InterpAsm-armv5te-vfp.S revision c35a2ef53d0cccd6f924eeba36633220ec67c32e
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* 25 * ARMv5 definitions and declarations. 26 */ 27 28/* 29ARM EABI general notes: 30 31r0-r3 hold first 4 args to a method; they are not preserved across method calls 32r4-r8 are available for general use 33r9 is given special treatment in some situations, but not for us 34r10 (sl) seems to be generally available 35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 36r12 (ip) is scratch -- not preserved across method calls 37r13 (sp) should be managed carefully in case a signal arrives 38r14 (lr) must be preserved 39r15 (pc) can be tinkered with directly 40 41r0 holds returns of <= 4 bytes 42r0-r1 hold returns of 8 bytes, low word in r0 43 44Callee must save/restore r4+ (except r12) if it modifies them. If VFP 45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 46s0-s15 (d0-d7, q0-a3) do not need to be. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59Mterp and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r4 rPC interpreted program counter, used for fetching instructions 65 r5 rFP interpreted frame pointer, used for accessing locals and args 66 r6 rGLUE MterpGlue pointer 67 r7 rINST first 16-bit code unit of current instruction 68 r8 rIBASE interpreted instruction base pointer, used for computed goto 69 70Macros are provided for common operations. Each macro MUST emit only 71one instruction to make instruction-counting easier. They MUST NOT alter 72unspecified registers or condition codes. 73*/ 74 75/* single-purpose registers, given names for clarity */ 76#define rPC r4 77#define rFP r5 78#define rGLUE r6 79#define rINST r7 80#define rIBASE r8 81 82/* save/restore the PC and/or FP from the glue struct */ 83#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 84#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 85#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 86#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 87#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 88#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 89 90/* 91 * "export" the PC to the stack frame, f/b/o future exception objects. Must 92 * be done *before* something calls dvmThrowException. 93 * 94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 96 * 97 * It's okay to do this more than once. 98 */ 99#define EXPORT_PC() \ 100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 101 102/* 103 * Given a frame pointer, find the stack save area. 104 * 105 * In C this is "((StackSaveArea*)(_fp) -1)". 106 */ 107#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 108 sub _reg, _fpreg, #sizeofStackSaveArea 109 110/* 111 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 112 */ 113#define FETCH_INST() ldrh rINST, [rPC] 114 115/* 116 * Fetch the next instruction from the specified offset. Advances rPC 117 * to point to the next instruction. "_count" is in 16-bit code units. 118 * 119 * Because of the limited size of immediate constants on ARM, this is only 120 * suitable for small forward movements (i.e. don't try to implement "goto" 121 * with this). 122 * 123 * This must come AFTER anything that can throw an exception, or the 124 * exception catch may miss. (This also implies that it must come after 125 * EXPORT_PC().) 126 */ 127#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 128 129/* 130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 131 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 132 */ 133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 134 ldrh _dreg, [_sreg, #(_count*2)]! 135 136/* 137 * Fetch the next instruction from an offset specified by _reg. Updates 138 * rPC to point to the next instruction. "_reg" must specify the distance 139 * in bytes, *not* 16-bit code units, and may be a signed value. 140 * 141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 142 * bits that hold the shift distance are used for the half/byte/sign flags. 143 * In some cases we can pre-double _reg for free, so we require a byte offset 144 * here. 145 */ 146#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 147 148/* 149 * Fetch a half-word code unit from an offset past the current PC. The 150 * "_count" value is in 16-bit code units. Does not advance rPC. 151 * 152 * The "_S" variant works the same but treats the value as signed. 153 */ 154#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 155#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 156 157/* 158 * Fetch one byte from an offset past the current PC. Pass in the same 159 * "_count" as you would for FETCH, and an additional 0/1 indicating which 160 * byte of the halfword you want (lo/hi). 161 */ 162#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 163 164/* 165 * Put the instruction's opcode field into the specified register. 166 */ 167#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 168 169/* 170 * Put the prefetched instruction's opcode field into the specified register. 171 */ 172#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 173 174/* 175 * Begin executing the opcode in _reg. Because this only jumps within the 176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 177 */ 178#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 180#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 181 182/* 183 * Get/set the 32-bit value from a Dalvik register. 184 */ 185#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 186#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 187 188#if defined(WITH_JIT) 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205#if defined(WITH_JIT) 206#include "../common/jit-config.h" 207#endif 208 209/* File: armv5te/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 218 * one-way branch. 219 * 220 * May modify IP. Does not modify LR. 221 */ 222.macro LDR_PC source 223 ldr pc, \source 224.endm 225 226/* 227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 228 * Jump to subroutine. 229 * 230 * May modify IP and LR. 231 */ 232.macro LDR_PC_LR source 233 mov lr, pc 234 ldr pc, \source 235.endm 236 237/* 238 * Macro for "LDMFD SP!, {...regs...,PC}". 239 * 240 * May modify IP and LR. 241 */ 242.macro LDMFD_PC regs 243 ldmfd sp!, {\regs,pc} 244.endm 245 246/* 247 * Macro for data memory barrier; not meaningful pre-ARMv6K. 248 */ 249.macro SMP_DMB gen 250.endm 251 252 253/* File: armv5te/entry.S */ 254/* 255 * Copyright (C) 2008 The Android Open Source Project 256 * 257 * Licensed under the Apache License, Version 2.0 (the "License"); 258 * you may not use this file except in compliance with the License. 259 * You may obtain a copy of the License at 260 * 261 * http://www.apache.org/licenses/LICENSE-2.0 262 * 263 * Unless required by applicable law or agreed to in writing, software 264 * distributed under the License is distributed on an "AS IS" BASIS, 265 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 266 * See the License for the specific language governing permissions and 267 * limitations under the License. 268 */ 269/* 270 * Interpreter entry point. 271 */ 272 273/* 274 * We don't have formal stack frames, so gdb scans upward in the code 275 * to find the start of the function (a label with the %function type), 276 * and then looks at the next few instructions to figure out what 277 * got pushed onto the stack. From this it figures out how to restore 278 * the registers, including PC, for the previous stack frame. If gdb 279 * sees a non-function label, it stops scanning, so either we need to 280 * have nothing but assembler-local labels between the entry point and 281 * the break, or we need to fake it out. 282 * 283 * When this is defined, we add some stuff to make gdb less confused. 284 */ 285#define ASSIST_DEBUGGER 1 286 287 .text 288 .align 2 289 .global dvmMterpStdRun 290 .type dvmMterpStdRun, %function 291 292/* 293 * On entry: 294 * r0 MterpGlue* glue 295 * 296 * This function returns a boolean "changeInterp" value. The return comes 297 * via a call to dvmMterpStdBail(). 298 */ 299dvmMterpStdRun: 300#define MTERP_ENTRY1 \ 301 .save {r4-r10,fp,lr}; \ 302 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 303#define MTERP_ENTRY2 \ 304 .pad #4; \ 305 sub sp, sp, #4 @ align 64 306 307 .fnstart 308 MTERP_ENTRY1 309 MTERP_ENTRY2 310 311 /* save stack pointer, add magic word for debuggerd */ 312 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 313 314 /* set up "named" registers, figure out entry point */ 315 mov rGLUE, r0 @ set rGLUE 316 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 317 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 318 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 319 cmp r1, #kInterpEntryInstr @ usual case? 320 bne .Lnot_instr @ no, handle it 321 322#if defined(WITH_JIT) 323.LentryInstr: 324 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 325 /* Entry is always a possible trace start */ 326 GET_JIT_PROF_TABLE(r0) 327 FETCH_INST() 328 mov r1, #0 @ prepare the value for the new state 329 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 330 cmp r0,#0 331 bne common_updateProfile 332 GET_INST_OPCODE(ip) 333 GOTO_OPCODE(ip) 334#else 335 /* start executing the instruction at rPC */ 336 FETCH_INST() @ load rINST from rPC 337 GET_INST_OPCODE(ip) @ extract opcode from rINST 338 GOTO_OPCODE(ip) @ jump to next instruction 339#endif 340 341.Lnot_instr: 342 cmp r1, #kInterpEntryReturn @ were we returning from a method? 343 beq common_returnFromMethod 344 345.Lnot_return: 346 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 347 beq common_exceptionThrown 348 349#if defined(WITH_JIT) 350.Lnot_throw: 351 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 352 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 353 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 354 bne .Lbad_arg 355 cmp rPC,r2 356 bne .LentryInstr @ must have branched, don't resume 357#if defined(WITH_SELF_VERIFICATION) 358 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 359 b jitSVShadowRunStart @ re-enter the translation after the 360 @ single-stepped instruction 361 @noreturn 362#endif 363 mov r1, #kInterpEntryInstr 364 str r1, [rGLUE, #offGlue_entryPoint] 365 bx r10 @ re-enter the translation 366#endif 367 368.Lbad_arg: 369 ldr r0, strBadEntryPoint 370 @ r1 holds value of entryPoint 371 bl printf 372 bl dvmAbort 373 .fnend 374 375 376 .global dvmMterpStdBail 377 .type dvmMterpStdBail, %function 378 379/* 380 * Restore the stack pointer and PC from the save point established on entry. 381 * This is essentially the same as a longjmp, but should be cheaper. The 382 * last instruction causes us to return to whoever called dvmMterpStdRun. 383 * 384 * We pushed some registers on the stack in dvmMterpStdRun, then saved 385 * SP and LR. Here we restore SP, restore the registers, and then restore 386 * LR to PC. 387 * 388 * On entry: 389 * r0 MterpGlue* glue 390 * r1 bool changeInterp 391 */ 392dvmMterpStdBail: 393 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 394 mov r0, r1 @ return the changeInterp value 395 add sp, sp, #4 @ un-align 64 396 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 397 398 399/* 400 * String references. 401 */ 402strBadEntryPoint: 403 .word .LstrBadEntryPoint 404 405 406 .global dvmAsmInstructionStart 407 .type dvmAsmInstructionStart, %function 408dvmAsmInstructionStart = .L_OP_NOP 409 .text 410 411/* ------------------------------ */ 412 .balign 64 413.L_OP_NOP: /* 0x00 */ 414/* File: armv5te/OP_NOP.S */ 415 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 416 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 417 GOTO_OPCODE(ip) @ execute it 418 419#ifdef ASSIST_DEBUGGER 420 /* insert fake function header to help gdb find the stack frame */ 421 .type dalvik_inst, %function 422dalvik_inst: 423 .fnstart 424 MTERP_ENTRY1 425 MTERP_ENTRY2 426 .fnend 427#endif 428 429/* ------------------------------ */ 430 .balign 64 431.L_OP_MOVE: /* 0x01 */ 432/* File: armv5te/OP_MOVE.S */ 433 /* for move, move-object, long-to-int */ 434 /* op vA, vB */ 435 mov r1, rINST, lsr #12 @ r1<- B from 15:12 436 mov r0, rINST, lsr #8 @ r0<- A from 11:8 437 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 438 GET_VREG(r2, r1) @ r2<- fp[B] 439 and r0, r0, #15 440 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 441 SET_VREG(r2, r0) @ fp[A]<- r2 442 GOTO_OPCODE(ip) @ execute next instruction 443 444/* ------------------------------ */ 445 .balign 64 446.L_OP_MOVE_FROM16: /* 0x02 */ 447/* File: armv5te/OP_MOVE_FROM16.S */ 448 /* for: move/from16, move-object/from16 */ 449 /* op vAA, vBBBB */ 450 FETCH(r1, 1) @ r1<- BBBB 451 mov r0, rINST, lsr #8 @ r0<- AA 452 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 453 GET_VREG(r2, r1) @ r2<- fp[BBBB] 454 GET_INST_OPCODE(ip) @ extract opcode from rINST 455 SET_VREG(r2, r0) @ fp[AA]<- r2 456 GOTO_OPCODE(ip) @ jump to next instruction 457 458/* ------------------------------ */ 459 .balign 64 460.L_OP_MOVE_16: /* 0x03 */ 461/* File: armv5te/OP_MOVE_16.S */ 462 /* for: move/16, move-object/16 */ 463 /* op vAAAA, vBBBB */ 464 FETCH(r1, 2) @ r1<- BBBB 465 FETCH(r0, 1) @ r0<- AAAA 466 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 467 GET_VREG(r2, r1) @ r2<- fp[BBBB] 468 GET_INST_OPCODE(ip) @ extract opcode from rINST 469 SET_VREG(r2, r0) @ fp[AAAA]<- r2 470 GOTO_OPCODE(ip) @ jump to next instruction 471 472/* ------------------------------ */ 473 .balign 64 474.L_OP_MOVE_WIDE: /* 0x04 */ 475/* File: armv5te/OP_MOVE_WIDE.S */ 476 /* move-wide vA, vB */ 477 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 478 mov r2, rINST, lsr #8 @ r2<- A(+) 479 mov r3, rINST, lsr #12 @ r3<- B 480 and r2, r2, #15 481 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 482 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 483 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 484 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 485 GET_INST_OPCODE(ip) @ extract opcode from rINST 486 stmia r2, {r0-r1} @ fp[A]<- r0/r1 487 GOTO_OPCODE(ip) @ jump to next instruction 488 489/* ------------------------------ */ 490 .balign 64 491.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 492/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 493 /* move-wide/from16 vAA, vBBBB */ 494 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 495 FETCH(r3, 1) @ r3<- BBBB 496 mov r2, rINST, lsr #8 @ r2<- AA 497 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 498 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 499 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 500 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 501 GET_INST_OPCODE(ip) @ extract opcode from rINST 502 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 503 GOTO_OPCODE(ip) @ jump to next instruction 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 .balign 64 523.L_OP_MOVE_OBJECT: /* 0x07 */ 524/* File: armv5te/OP_MOVE_OBJECT.S */ 525/* File: armv5te/OP_MOVE.S */ 526 /* for move, move-object, long-to-int */ 527 /* op vA, vB */ 528 mov r1, rINST, lsr #12 @ r1<- B from 15:12 529 mov r0, rINST, lsr #8 @ r0<- A from 11:8 530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 531 GET_VREG(r2, r1) @ r2<- fp[B] 532 and r0, r0, #15 533 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 534 SET_VREG(r2, r0) @ fp[A]<- r2 535 GOTO_OPCODE(ip) @ execute next instruction 536 537 538/* ------------------------------ */ 539 .balign 64 540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 542/* File: armv5te/OP_MOVE_FROM16.S */ 543 /* for: move/from16, move-object/from16 */ 544 /* op vAA, vBBBB */ 545 FETCH(r1, 1) @ r1<- BBBB 546 mov r0, rINST, lsr #8 @ r0<- AA 547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 548 GET_VREG(r2, r1) @ r2<- fp[BBBB] 549 GET_INST_OPCODE(ip) @ extract opcode from rINST 550 SET_VREG(r2, r0) @ fp[AA]<- r2 551 GOTO_OPCODE(ip) @ jump to next instruction 552 553 554/* ------------------------------ */ 555 .balign 64 556.L_OP_MOVE_OBJECT_16: /* 0x09 */ 557/* File: armv5te/OP_MOVE_OBJECT_16.S */ 558/* File: armv5te/OP_MOVE_16.S */ 559 /* for: move/16, move-object/16 */ 560 /* op vAAAA, vBBBB */ 561 FETCH(r1, 2) @ r1<- BBBB 562 FETCH(r0, 1) @ r0<- AAAA 563 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 564 GET_VREG(r2, r1) @ r2<- fp[BBBB] 565 GET_INST_OPCODE(ip) @ extract opcode from rINST 566 SET_VREG(r2, r0) @ fp[AAAA]<- r2 567 GOTO_OPCODE(ip) @ jump to next instruction 568 569 570/* ------------------------------ */ 571 .balign 64 572.L_OP_MOVE_RESULT: /* 0x0a */ 573/* File: armv5te/OP_MOVE_RESULT.S */ 574 /* for: move-result, move-result-object */ 575 /* op vAA */ 576 mov r2, rINST, lsr #8 @ r2<- AA 577 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 578 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 579 GET_INST_OPCODE(ip) @ extract opcode from rINST 580 SET_VREG(r0, r2) @ fp[AA]<- r0 581 GOTO_OPCODE(ip) @ jump to next instruction 582 583/* ------------------------------ */ 584 .balign 64 585.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 586/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 587 /* move-result-wide vAA */ 588 mov r2, rINST, lsr #8 @ r2<- AA 589 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 590 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 591 ldmia r3, {r0-r1} @ r0/r1<- retval.j 592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 593 GET_INST_OPCODE(ip) @ extract opcode from rINST 594 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 595 GOTO_OPCODE(ip) @ jump to next instruction 596 597/* ------------------------------ */ 598 .balign 64 599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 601/* File: armv5te/OP_MOVE_RESULT.S */ 602 /* for: move-result, move-result-object */ 603 /* op vAA */ 604 mov r2, rINST, lsr #8 @ r2<- AA 605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 606 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 607 GET_INST_OPCODE(ip) @ extract opcode from rINST 608 SET_VREG(r0, r2) @ fp[AA]<- r0 609 GOTO_OPCODE(ip) @ jump to next instruction 610 611 612/* ------------------------------ */ 613 .balign 64 614.L_OP_MOVE_EXCEPTION: /* 0x0d */ 615/* File: armv5te/OP_MOVE_EXCEPTION.S */ 616 /* move-exception vAA */ 617 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 618 mov r2, rINST, lsr #8 @ r2<- AA 619 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 620 mov r1, #0 @ r1<- 0 621 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 622 SET_VREG(r3, r2) @ fp[AA]<- exception obj 623 GET_INST_OPCODE(ip) @ extract opcode from rINST 624 str r1, [r0, #offThread_exception] @ dvmClearException bypass 625 GOTO_OPCODE(ip) @ jump to next instruction 626 627/* ------------------------------ */ 628 .balign 64 629.L_OP_RETURN_VOID: /* 0x0e */ 630/* File: armv5te/OP_RETURN_VOID.S */ 631 b common_returnFromMethod 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN: /* 0x0f */ 636/* File: armv5te/OP_RETURN.S */ 637 /* 638 * Return a 32-bit value. Copies the return value into the "glue" 639 * structure, then jumps to the return handler. 640 * 641 * for: return, return-object 642 */ 643 /* op vAA */ 644 mov r2, rINST, lsr #8 @ r2<- AA 645 GET_VREG(r0, r2) @ r0<- vAA 646 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 647 b common_returnFromMethod 648 649/* ------------------------------ */ 650 .balign 64 651.L_OP_RETURN_WIDE: /* 0x10 */ 652/* File: armv5te/OP_RETURN_WIDE.S */ 653 /* 654 * Return a 64-bit value. Copies the return value into the "glue" 655 * structure, then jumps to the return handler. 656 */ 657 /* return-wide vAA */ 658 mov r2, rINST, lsr #8 @ r2<- AA 659 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 660 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 661 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 662 stmia r3, {r0-r1} @ retval<- r0/r1 663 b common_returnFromMethod 664 665/* ------------------------------ */ 666 .balign 64 667.L_OP_RETURN_OBJECT: /* 0x11 */ 668/* File: armv5te/OP_RETURN_OBJECT.S */ 669/* File: armv5te/OP_RETURN.S */ 670 /* 671 * Return a 32-bit value. Copies the return value into the "glue" 672 * structure, then jumps to the return handler. 673 * 674 * for: return, return-object 675 */ 676 /* op vAA */ 677 mov r2, rINST, lsr #8 @ r2<- AA 678 GET_VREG(r0, r2) @ r0<- vAA 679 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 680 b common_returnFromMethod 681 682 683/* ------------------------------ */ 684 .balign 64 685.L_OP_CONST_4: /* 0x12 */ 686/* File: armv5te/OP_CONST_4.S */ 687 /* const/4 vA, #+B */ 688 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 689 mov r0, rINST, lsr #8 @ r0<- A+ 690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 691 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 692 and r0, r0, #15 693 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 694 SET_VREG(r1, r0) @ fp[A]<- r1 695 GOTO_OPCODE(ip) @ execute next instruction 696 697/* ------------------------------ */ 698 .balign 64 699.L_OP_CONST_16: /* 0x13 */ 700/* File: armv5te/OP_CONST_16.S */ 701 /* const/16 vAA, #+BBBB */ 702 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 703 mov r3, rINST, lsr #8 @ r3<- AA 704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 705 SET_VREG(r0, r3) @ vAA<- r0 706 GET_INST_OPCODE(ip) @ extract opcode from rINST 707 GOTO_OPCODE(ip) @ jump to next instruction 708 709/* ------------------------------ */ 710 .balign 64 711.L_OP_CONST: /* 0x14 */ 712/* File: armv5te/OP_CONST.S */ 713 /* const vAA, #+BBBBbbbb */ 714 mov r3, rINST, lsr #8 @ r3<- AA 715 FETCH(r0, 1) @ r0<- bbbb (low) 716 FETCH(r1, 2) @ r1<- BBBB (high) 717 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 718 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 719 GET_INST_OPCODE(ip) @ extract opcode from rINST 720 SET_VREG(r0, r3) @ vAA<- r0 721 GOTO_OPCODE(ip) @ jump to next instruction 722 723/* ------------------------------ */ 724 .balign 64 725.L_OP_CONST_HIGH16: /* 0x15 */ 726/* File: armv5te/OP_CONST_HIGH16.S */ 727 /* const/high16 vAA, #+BBBB0000 */ 728 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 729 mov r3, rINST, lsr #8 @ r3<- AA 730 mov r0, r0, lsl #16 @ r0<- BBBB0000 731 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 732 SET_VREG(r0, r3) @ vAA<- r0 733 GET_INST_OPCODE(ip) @ extract opcode from rINST 734 GOTO_OPCODE(ip) @ jump to next instruction 735 736/* ------------------------------ */ 737 .balign 64 738.L_OP_CONST_WIDE_16: /* 0x16 */ 739/* File: armv5te/OP_CONST_WIDE_16.S */ 740 /* const-wide/16 vAA, #+BBBB */ 741 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 742 mov r3, rINST, lsr #8 @ r3<- AA 743 mov r1, r0, asr #31 @ r1<- ssssssss 744 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 745 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 746 GET_INST_OPCODE(ip) @ extract opcode from rINST 747 stmia r3, {r0-r1} @ vAA<- r0/r1 748 GOTO_OPCODE(ip) @ jump to next instruction 749 750/* ------------------------------ */ 751 .balign 64 752.L_OP_CONST_WIDE_32: /* 0x17 */ 753/* File: armv5te/OP_CONST_WIDE_32.S */ 754 /* const-wide/32 vAA, #+BBBBbbbb */ 755 FETCH(r0, 1) @ r0<- 0000bbbb (low) 756 mov r3, rINST, lsr #8 @ r3<- AA 757 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 758 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 759 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 760 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 761 mov r1, r0, asr #31 @ r1<- ssssssss 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 .balign 64 768.L_OP_CONST_WIDE: /* 0x18 */ 769/* File: armv5te/OP_CONST_WIDE.S */ 770 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 771 FETCH(r0, 1) @ r0<- bbbb (low) 772 FETCH(r1, 2) @ r1<- BBBB (low middle) 773 FETCH(r2, 3) @ r2<- hhhh (high middle) 774 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 775 FETCH(r3, 4) @ r3<- HHHH (high) 776 mov r9, rINST, lsr #8 @ r9<- AA 777 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 778 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 779 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 780 GET_INST_OPCODE(ip) @ extract opcode from rINST 781 stmia r9, {r0-r1} @ vAA<- r0/r1 782 GOTO_OPCODE(ip) @ jump to next instruction 783 784/* ------------------------------ */ 785 .balign 64 786.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 787/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 788 /* const-wide/high16 vAA, #+BBBB000000000000 */ 789 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 790 mov r3, rINST, lsr #8 @ r3<- AA 791 mov r0, #0 @ r0<- 00000000 792 mov r1, r1, lsl #16 @ r1<- BBBB0000 793 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 794 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 795 GET_INST_OPCODE(ip) @ extract opcode from rINST 796 stmia r3, {r0-r1} @ vAA<- r0/r1 797 GOTO_OPCODE(ip) @ jump to next instruction 798 799/* ------------------------------ */ 800 .balign 64 801.L_OP_CONST_STRING: /* 0x1a */ 802/* File: armv5te/OP_CONST_STRING.S */ 803 /* const/string vAA, String@BBBB */ 804 FETCH(r1, 1) @ r1<- BBBB 805 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 806 mov r9, rINST, lsr #8 @ r9<- AA 807 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 808 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 809 cmp r0, #0 @ not yet resolved? 810 beq .LOP_CONST_STRING_resolve 811 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 812 GET_INST_OPCODE(ip) @ extract opcode from rINST 813 SET_VREG(r0, r9) @ vAA<- r0 814 GOTO_OPCODE(ip) @ jump to next instruction 815 816/* ------------------------------ */ 817 .balign 64 818.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 819/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 820 /* const/string vAA, String@BBBBBBBB */ 821 FETCH(r0, 1) @ r0<- bbbb (low) 822 FETCH(r1, 2) @ r1<- BBBB (high) 823 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 824 mov r9, rINST, lsr #8 @ r9<- AA 825 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 826 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 827 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 828 cmp r0, #0 829 beq .LOP_CONST_STRING_JUMBO_resolve 830 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 831 GET_INST_OPCODE(ip) @ extract opcode from rINST 832 SET_VREG(r0, r9) @ vAA<- r0 833 GOTO_OPCODE(ip) @ jump to next instruction 834 835/* ------------------------------ */ 836 .balign 64 837.L_OP_CONST_CLASS: /* 0x1c */ 838/* File: armv5te/OP_CONST_CLASS.S */ 839 /* const/class vAA, Class@BBBB */ 840 FETCH(r1, 1) @ r1<- BBBB 841 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 842 mov r9, rINST, lsr #8 @ r9<- AA 843 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 844 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 845 cmp r0, #0 @ not yet resolved? 846 beq .LOP_CONST_CLASS_resolve 847 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 848 GET_INST_OPCODE(ip) @ extract opcode from rINST 849 SET_VREG(r0, r9) @ vAA<- r0 850 GOTO_OPCODE(ip) @ jump to next instruction 851 852/* ------------------------------ */ 853 .balign 64 854.L_OP_MONITOR_ENTER: /* 0x1d */ 855/* File: armv5te/OP_MONITOR_ENTER.S */ 856 /* 857 * Synchronize on an object. 858 */ 859 /* monitor-enter vAA */ 860 mov r2, rINST, lsr #8 @ r2<- AA 861 GET_VREG(r1, r2) @ r1<- vAA (object) 862 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 863 cmp r1, #0 @ null object? 864 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 865 beq common_errNullObject @ null object, throw an exception 866 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 867 bl dvmLockObject @ call(self, obj) 868#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 869 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 870 ldr r1, [r0, #offThread_exception] @ check for exception 871 cmp r1, #0 872 bne common_exceptionThrown @ exception raised, bail out 873#endif 874 GET_INST_OPCODE(ip) @ extract opcode from rINST 875 GOTO_OPCODE(ip) @ jump to next instruction 876 877/* ------------------------------ */ 878 .balign 64 879.L_OP_MONITOR_EXIT: /* 0x1e */ 880/* File: armv5te/OP_MONITOR_EXIT.S */ 881 /* 882 * Unlock an object. 883 * 884 * Exceptions that occur when unlocking a monitor need to appear as 885 * if they happened at the following instruction. See the Dalvik 886 * instruction spec. 887 */ 888 /* monitor-exit vAA */ 889 mov r2, rINST, lsr #8 @ r2<- AA 890 EXPORT_PC() @ before fetch: export the PC 891 GET_VREG(r1, r2) @ r1<- vAA (object) 892 cmp r1, #0 @ null object? 893 beq 1f @ yes 894 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 895 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 896 cmp r0, #0 @ failed? 897 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 898 beq common_exceptionThrown @ yes, exception is pending 899 GET_INST_OPCODE(ip) @ extract opcode from rINST 900 GOTO_OPCODE(ip) @ jump to next instruction 9011: 902 FETCH_ADVANCE_INST(1) @ advance before throw 903 b common_errNullObject 904 905/* ------------------------------ */ 906 .balign 64 907.L_OP_CHECK_CAST: /* 0x1f */ 908/* File: armv5te/OP_CHECK_CAST.S */ 909 /* 910 * Check to see if a cast from one class to another is allowed. 911 */ 912 /* check-cast vAA, class@BBBB */ 913 mov r3, rINST, lsr #8 @ r3<- AA 914 FETCH(r2, 1) @ r2<- BBBB 915 GET_VREG(r9, r3) @ r9<- object 916 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 917 cmp r9, #0 @ is object null? 918 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 919 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 920 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 921 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 922 cmp r1, #0 @ have we resolved this before? 923 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 924.LOP_CHECK_CAST_resolved: 925 cmp r0, r1 @ same class (trivial success)? 926 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 927.LOP_CHECK_CAST_okay: 928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 929 GET_INST_OPCODE(ip) @ extract opcode from rINST 930 GOTO_OPCODE(ip) @ jump to next instruction 931 932/* ------------------------------ */ 933 .balign 64 934.L_OP_INSTANCE_OF: /* 0x20 */ 935/* File: armv5te/OP_INSTANCE_OF.S */ 936 /* 937 * Check to see if an object reference is an instance of a class. 938 * 939 * Most common situation is a non-null object, being compared against 940 * an already-resolved class. 941 */ 942 /* instance-of vA, vB, class@CCCC */ 943 mov r3, rINST, lsr #12 @ r3<- B 944 mov r9, rINST, lsr #8 @ r9<- A+ 945 GET_VREG(r0, r3) @ r0<- vB (object) 946 and r9, r9, #15 @ r9<- A 947 cmp r0, #0 @ is object null? 948 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 949 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 950 FETCH(r3, 1) @ r3<- CCCC 951 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 952 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 953 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 954 cmp r1, #0 @ have we resolved this before? 955 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 956.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 957 cmp r0, r1 @ same class (trivial success)? 958 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 959 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 960 961/* ------------------------------ */ 962 .balign 64 963.L_OP_ARRAY_LENGTH: /* 0x21 */ 964/* File: armv5te/OP_ARRAY_LENGTH.S */ 965 /* 966 * Return the length of an array. 967 */ 968 mov r1, rINST, lsr #12 @ r1<- B 969 mov r2, rINST, lsr #8 @ r2<- A+ 970 GET_VREG(r0, r1) @ r0<- vB (object ref) 971 and r2, r2, #15 @ r2<- A 972 cmp r0, #0 @ is object null? 973 beq common_errNullObject @ yup, fail 974 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 975 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 976 GET_INST_OPCODE(ip) @ extract opcode from rINST 977 SET_VREG(r3, r2) @ vB<- length 978 GOTO_OPCODE(ip) @ jump to next instruction 979 980/* ------------------------------ */ 981 .balign 64 982.L_OP_NEW_INSTANCE: /* 0x22 */ 983/* File: armv5te/OP_NEW_INSTANCE.S */ 984 /* 985 * Create a new instance of a class. 986 */ 987 /* new-instance vAA, class@BBBB */ 988 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 989 FETCH(r1, 1) @ r1<- BBBB 990 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 991 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 992 EXPORT_PC() @ req'd for init, resolve, alloc 993 cmp r0, #0 @ already resolved? 994 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 995.LOP_NEW_INSTANCE_resolved: @ r0=class 996 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 997 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 998 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 999.LOP_NEW_INSTANCE_initialized: @ r0=class 1000 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1001 bl dvmAllocObject @ r0<- new object 1002 b .LOP_NEW_INSTANCE_finish @ continue 1003 1004/* ------------------------------ */ 1005 .balign 64 1006.L_OP_NEW_ARRAY: /* 0x23 */ 1007/* File: armv5te/OP_NEW_ARRAY.S */ 1008 /* 1009 * Allocate an array of objects, specified with the array class 1010 * and a count. 1011 * 1012 * The verifier guarantees that this is an array class, so we don't 1013 * check for it here. 1014 */ 1015 /* new-array vA, vB, class@CCCC */ 1016 mov r0, rINST, lsr #12 @ r0<- B 1017 FETCH(r2, 1) @ r2<- CCCC 1018 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1019 GET_VREG(r1, r0) @ r1<- vB (array length) 1020 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1021 cmp r1, #0 @ check length 1022 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1023 bmi common_errNegativeArraySize @ negative length, bail 1024 cmp r0, #0 @ already resolved? 1025 EXPORT_PC() @ req'd for resolve, alloc 1026 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1027 b .LOP_NEW_ARRAY_resolve @ do resolve now 1028 1029/* ------------------------------ */ 1030 .balign 64 1031.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1032/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1033 /* 1034 * Create a new array with elements filled from registers. 1035 * 1036 * for: filled-new-array, filled-new-array/range 1037 */ 1038 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1039 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1040 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1041 FETCH(r1, 1) @ r1<- BBBB 1042 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1043 EXPORT_PC() @ need for resolve and alloc 1044 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1045 mov r10, rINST, lsr #8 @ r10<- AA or BA 1046 cmp r0, #0 @ already resolved? 1047 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10488: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1049 mov r2, #0 @ r2<- false 1050 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1051 bl dvmResolveClass @ r0<- call(clazz, ref) 1052 cmp r0, #0 @ got null? 1053 beq common_exceptionThrown @ yes, handle exception 1054 b .LOP_FILLED_NEW_ARRAY_continue 1055 1056/* ------------------------------ */ 1057 .balign 64 1058.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1059/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1060/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1061 /* 1062 * Create a new array with elements filled from registers. 1063 * 1064 * for: filled-new-array, filled-new-array/range 1065 */ 1066 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1067 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1068 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1069 FETCH(r1, 1) @ r1<- BBBB 1070 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1071 EXPORT_PC() @ need for resolve and alloc 1072 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1073 mov r10, rINST, lsr #8 @ r10<- AA or BA 1074 cmp r0, #0 @ already resolved? 1075 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10768: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1077 mov r2, #0 @ r2<- false 1078 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1079 bl dvmResolveClass @ r0<- call(clazz, ref) 1080 cmp r0, #0 @ got null? 1081 beq common_exceptionThrown @ yes, handle exception 1082 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1083 1084 1085/* ------------------------------ */ 1086 .balign 64 1087.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1088/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1089 /* fill-array-data vAA, +BBBBBBBB */ 1090 FETCH(r0, 1) @ r0<- bbbb (lo) 1091 FETCH(r1, 2) @ r1<- BBBB (hi) 1092 mov r3, rINST, lsr #8 @ r3<- AA 1093 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1094 GET_VREG(r0, r3) @ r0<- vAA (array object) 1095 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1096 EXPORT_PC(); 1097 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1098 cmp r0, #0 @ 0 means an exception is thrown 1099 beq common_exceptionThrown @ has exception 1100 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1101 GET_INST_OPCODE(ip) @ extract opcode from rINST 1102 GOTO_OPCODE(ip) @ jump to next instruction 1103 1104/* ------------------------------ */ 1105 .balign 64 1106.L_OP_THROW: /* 0x27 */ 1107/* File: armv5te/OP_THROW.S */ 1108 /* 1109 * Throw an exception object in the current thread. 1110 */ 1111 /* throw vAA */ 1112 mov r2, rINST, lsr #8 @ r2<- AA 1113 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1114 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1115 EXPORT_PC() @ exception handler can throw 1116 cmp r1, #0 @ null object? 1117 beq common_errNullObject @ yes, throw an NPE instead 1118 @ bypass dvmSetException, just store it 1119 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1120 b common_exceptionThrown 1121 1122/* ------------------------------ */ 1123 .balign 64 1124.L_OP_GOTO: /* 0x28 */ 1125/* File: armv5te/OP_GOTO.S */ 1126 /* 1127 * Unconditional branch, 8-bit offset. 1128 * 1129 * The branch distance is a signed code-unit offset, which we need to 1130 * double to get a byte offset. 1131 */ 1132 /* goto +AA */ 1133 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1134 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1135 mov r9, r9, lsl #1 @ r9<- byte offset 1136 bmi common_backwardBranch @ backward branch, do periodic checks 1137#if defined(WITH_JIT) 1138 GET_JIT_PROF_TABLE(r0) 1139 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1140 cmp r0,#0 1141 bne common_updateProfile 1142 GET_INST_OPCODE(ip) @ extract opcode from rINST 1143 GOTO_OPCODE(ip) @ jump to next instruction 1144#else 1145 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1146 GET_INST_OPCODE(ip) @ extract opcode from rINST 1147 GOTO_OPCODE(ip) @ jump to next instruction 1148#endif 1149 1150/* ------------------------------ */ 1151 .balign 64 1152.L_OP_GOTO_16: /* 0x29 */ 1153/* File: armv5te/OP_GOTO_16.S */ 1154 /* 1155 * Unconditional branch, 16-bit offset. 1156 * 1157 * The branch distance is a signed code-unit offset, which we need to 1158 * double to get a byte offset. 1159 */ 1160 /* goto/16 +AAAA */ 1161 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1162 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1163 bmi common_backwardBranch @ backward branch, do periodic checks 1164#if defined(WITH_JIT) 1165 GET_JIT_PROF_TABLE(r0) 1166 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1167 cmp r0,#0 1168 bne common_updateProfile 1169 GET_INST_OPCODE(ip) @ extract opcode from rINST 1170 GOTO_OPCODE(ip) @ jump to next instruction 1171#else 1172 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1173 GET_INST_OPCODE(ip) @ extract opcode from rINST 1174 GOTO_OPCODE(ip) @ jump to next instruction 1175#endif 1176 1177/* ------------------------------ */ 1178 .balign 64 1179.L_OP_GOTO_32: /* 0x2a */ 1180/* File: armv5te/OP_GOTO_32.S */ 1181 /* 1182 * Unconditional branch, 32-bit offset. 1183 * 1184 * The branch distance is a signed code-unit offset, which we need to 1185 * double to get a byte offset. 1186 * 1187 * Unlike most opcodes, this one is allowed to branch to itself, so 1188 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1189 * instruction doesn't affect the V flag, so we need to clear it 1190 * explicitly. 1191 */ 1192 /* goto/32 +AAAAAAAA */ 1193 FETCH(r0, 1) @ r0<- aaaa (lo) 1194 FETCH(r1, 2) @ r1<- AAAA (hi) 1195 cmp ip, ip @ (clear V flag during stall) 1196 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1197 mov r9, r0, asl #1 @ r9<- byte offset 1198 ble common_backwardBranch @ backward branch, do periodic checks 1199#if defined(WITH_JIT) 1200 GET_JIT_PROF_TABLE(r0) 1201 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1202 cmp r0,#0 1203 bne common_updateProfile 1204 GET_INST_OPCODE(ip) @ extract opcode from rINST 1205 GOTO_OPCODE(ip) @ jump to next instruction 1206#else 1207 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1208 GET_INST_OPCODE(ip) @ extract opcode from rINST 1209 GOTO_OPCODE(ip) @ jump to next instruction 1210#endif 1211 1212/* ------------------------------ */ 1213 .balign 64 1214.L_OP_PACKED_SWITCH: /* 0x2b */ 1215/* File: armv5te/OP_PACKED_SWITCH.S */ 1216 /* 1217 * Handle a packed-switch or sparse-switch instruction. In both cases 1218 * we decode it and hand it off to a helper function. 1219 * 1220 * We don't really expect backward branches in a switch statement, but 1221 * they're perfectly legal, so we check for them here. 1222 * 1223 * for: packed-switch, sparse-switch 1224 */ 1225 /* op vAA, +BBBB */ 1226 FETCH(r0, 1) @ r0<- bbbb (lo) 1227 FETCH(r1, 2) @ r1<- BBBB (hi) 1228 mov r3, rINST, lsr #8 @ r3<- AA 1229 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1230 GET_VREG(r1, r3) @ r1<- vAA 1231 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1232 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1233 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1234 bmi common_backwardBranch @ backward branch, do periodic checks 1235 beq common_backwardBranch @ (want to use BLE but V is unknown) 1236#if defined(WITH_JIT) 1237 GET_JIT_PROF_TABLE(r0) 1238 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1239 cmp r0,#0 1240 bne common_updateProfile 1241 GET_INST_OPCODE(ip) @ extract opcode from rINST 1242 GOTO_OPCODE(ip) @ jump to next instruction 1243#else 1244 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1245 GET_INST_OPCODE(ip) @ extract opcode from rINST 1246 GOTO_OPCODE(ip) @ jump to next instruction 1247#endif 1248 1249/* ------------------------------ */ 1250 .balign 64 1251.L_OP_SPARSE_SWITCH: /* 0x2c */ 1252/* File: armv5te/OP_SPARSE_SWITCH.S */ 1253/* File: armv5te/OP_PACKED_SWITCH.S */ 1254 /* 1255 * Handle a packed-switch or sparse-switch instruction. In both cases 1256 * we decode it and hand it off to a helper function. 1257 * 1258 * We don't really expect backward branches in a switch statement, but 1259 * they're perfectly legal, so we check for them here. 1260 * 1261 * for: packed-switch, sparse-switch 1262 */ 1263 /* op vAA, +BBBB */ 1264 FETCH(r0, 1) @ r0<- bbbb (lo) 1265 FETCH(r1, 2) @ r1<- BBBB (hi) 1266 mov r3, rINST, lsr #8 @ r3<- AA 1267 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1268 GET_VREG(r1, r3) @ r1<- vAA 1269 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1270 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1271 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1272 bmi common_backwardBranch @ backward branch, do periodic checks 1273 beq common_backwardBranch @ (want to use BLE but V is unknown) 1274#if defined(WITH_JIT) 1275 GET_JIT_PROF_TABLE(r0) 1276 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1277 cmp r0,#0 1278 bne common_updateProfile 1279 GET_INST_OPCODE(ip) @ extract opcode from rINST 1280 GOTO_OPCODE(ip) @ jump to next instruction 1281#else 1282 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1283 GET_INST_OPCODE(ip) @ extract opcode from rINST 1284 GOTO_OPCODE(ip) @ jump to next instruction 1285#endif 1286 1287 1288/* ------------------------------ */ 1289 .balign 64 1290.L_OP_CMPL_FLOAT: /* 0x2d */ 1291/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1292 /* 1293 * Compare two floating-point values. Puts 0, 1, or -1 into the 1294 * destination register based on the results of the comparison. 1295 * 1296 * int compare(x, y) { 1297 * if (x == y) { 1298 * return 0; 1299 * } else if (x > y) { 1300 * return 1; 1301 * } else if (x < y) { 1302 * return -1; 1303 * } else { 1304 * return -1; 1305 * } 1306 * } 1307 */ 1308 /* op vAA, vBB, vCC */ 1309 FETCH(r0, 1) @ r0<- CCBB 1310 mov r9, rINST, lsr #8 @ r9<- AA 1311 and r2, r0, #255 @ r2<- BB 1312 mov r3, r0, lsr #8 @ r3<- CC 1313 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1314 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1315 flds s0, [r2] @ s0<- vBB 1316 flds s1, [r3] @ s1<- vCC 1317 fcmpes s0, s1 @ compare (vBB, vCC) 1318 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1319 mvn r0, #0 @ r0<- -1 (default) 1320 GET_INST_OPCODE(ip) @ extract opcode from rINST 1321 fmstat @ export status flags 1322 movgt r0, #1 @ (greater than) r1<- 1 1323 moveq r0, #0 @ (equal) r1<- 0 1324 b .LOP_CMPL_FLOAT_finish @ argh 1325 1326 1327/* ------------------------------ */ 1328 .balign 64 1329.L_OP_CMPG_FLOAT: /* 0x2e */ 1330/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1331 /* 1332 * Compare two floating-point values. Puts 0, 1, or -1 into the 1333 * destination register based on the results of the comparison. 1334 * 1335 * int compare(x, y) { 1336 * if (x == y) { 1337 * return 0; 1338 * } else if (x < y) { 1339 * return -1; 1340 * } else if (x > y) { 1341 * return 1; 1342 * } else { 1343 * return 1; 1344 * } 1345 * } 1346 */ 1347 /* op vAA, vBB, vCC */ 1348 FETCH(r0, 1) @ r0<- CCBB 1349 mov r9, rINST, lsr #8 @ r9<- AA 1350 and r2, r0, #255 @ r2<- BB 1351 mov r3, r0, lsr #8 @ r3<- CC 1352 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1353 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1354 flds s0, [r2] @ s0<- vBB 1355 flds s1, [r3] @ s1<- vCC 1356 fcmpes s0, s1 @ compare (vBB, vCC) 1357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1358 mov r0, #1 @ r0<- 1 (default) 1359 GET_INST_OPCODE(ip) @ extract opcode from rINST 1360 fmstat @ export status flags 1361 mvnmi r0, #0 @ (less than) r1<- -1 1362 moveq r0, #0 @ (equal) r1<- 0 1363 b .LOP_CMPG_FLOAT_finish @ argh 1364 1365 1366/* ------------------------------ */ 1367 .balign 64 1368.L_OP_CMPL_DOUBLE: /* 0x2f */ 1369/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1370 /* 1371 * Compare two floating-point values. Puts 0, 1, or -1 into the 1372 * destination register based on the results of the comparison. 1373 * 1374 * int compare(x, y) { 1375 * if (x == y) { 1376 * return 0; 1377 * } else if (x > y) { 1378 * return 1; 1379 * } else if (x < y) { 1380 * return -1; 1381 * } else { 1382 * return -1; 1383 * } 1384 * } 1385 */ 1386 /* op vAA, vBB, vCC */ 1387 FETCH(r0, 1) @ r0<- CCBB 1388 mov r9, rINST, lsr #8 @ r9<- AA 1389 and r2, r0, #255 @ r2<- BB 1390 mov r3, r0, lsr #8 @ r3<- CC 1391 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1392 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1393 fldd d0, [r2] @ d0<- vBB 1394 fldd d1, [r3] @ d1<- vCC 1395 fcmped d0, d1 @ compare (vBB, vCC) 1396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1397 mvn r0, #0 @ r0<- -1 (default) 1398 GET_INST_OPCODE(ip) @ extract opcode from rINST 1399 fmstat @ export status flags 1400 movgt r0, #1 @ (greater than) r1<- 1 1401 moveq r0, #0 @ (equal) r1<- 0 1402 b .LOP_CMPL_DOUBLE_finish @ argh 1403 1404 1405/* ------------------------------ */ 1406 .balign 64 1407.L_OP_CMPG_DOUBLE: /* 0x30 */ 1408/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1409 /* 1410 * Compare two floating-point values. Puts 0, 1, or -1 into the 1411 * destination register based on the results of the comparison. 1412 * 1413 * int compare(x, y) { 1414 * if (x == y) { 1415 * return 0; 1416 * } else if (x < y) { 1417 * return -1; 1418 * } else if (x > y) { 1419 * return 1; 1420 * } else { 1421 * return 1; 1422 * } 1423 * } 1424 */ 1425 /* op vAA, vBB, vCC */ 1426 FETCH(r0, 1) @ r0<- CCBB 1427 mov r9, rINST, lsr #8 @ r9<- AA 1428 and r2, r0, #255 @ r2<- BB 1429 mov r3, r0, lsr #8 @ r3<- CC 1430 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1431 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1432 fldd d0, [r2] @ d0<- vBB 1433 fldd d1, [r3] @ d1<- vCC 1434 fcmped d0, d1 @ compare (vBB, vCC) 1435 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1436 mov r0, #1 @ r0<- 1 (default) 1437 GET_INST_OPCODE(ip) @ extract opcode from rINST 1438 fmstat @ export status flags 1439 mvnmi r0, #0 @ (less than) r1<- -1 1440 moveq r0, #0 @ (equal) r1<- 0 1441 b .LOP_CMPG_DOUBLE_finish @ argh 1442 1443 1444/* ------------------------------ */ 1445 .balign 64 1446.L_OP_CMP_LONG: /* 0x31 */ 1447/* File: armv5te/OP_CMP_LONG.S */ 1448 /* 1449 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1450 * register based on the results of the comparison. 1451 * 1452 * We load the full values with LDM, but in practice many values could 1453 * be resolved by only looking at the high word. This could be made 1454 * faster or slower by splitting the LDM into a pair of LDRs. 1455 * 1456 * If we just wanted to set condition flags, we could do this: 1457 * subs ip, r0, r2 1458 * sbcs ip, r1, r3 1459 * subeqs ip, r0, r2 1460 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1461 * integer value, which we can do with 2 conditional mov/mvn instructions 1462 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1463 * us a constant 5-cycle path plus a branch at the end to the 1464 * instruction epilogue code. The multi-compare approach below needs 1465 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1466 * in the worst case (the 64-bit values are equal). 1467 */ 1468 /* cmp-long vAA, vBB, vCC */ 1469 FETCH(r0, 1) @ r0<- CCBB 1470 mov r9, rINST, lsr #8 @ r9<- AA 1471 and r2, r0, #255 @ r2<- BB 1472 mov r3, r0, lsr #8 @ r3<- CC 1473 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1474 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1475 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1476 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1477 cmp r1, r3 @ compare (vBB+1, vCC+1) 1478 blt .LOP_CMP_LONG_less @ signed compare on high part 1479 bgt .LOP_CMP_LONG_greater 1480 subs r1, r0, r2 @ r1<- r0 - r2 1481 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1482 bne .LOP_CMP_LONG_less 1483 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1484 1485/* ------------------------------ */ 1486 .balign 64 1487.L_OP_IF_EQ: /* 0x32 */ 1488/* File: armv5te/OP_IF_EQ.S */ 1489/* File: armv5te/bincmp.S */ 1490 /* 1491 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1492 * fragment that specifies the *reverse* comparison to perform, e.g. 1493 * for "if-le" you would use "gt". 1494 * 1495 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1496 */ 1497 /* if-cmp vA, vB, +CCCC */ 1498 mov r0, rINST, lsr #8 @ r0<- A+ 1499 mov r1, rINST, lsr #12 @ r1<- B 1500 and r0, r0, #15 1501 GET_VREG(r3, r1) @ r3<- vB 1502 GET_VREG(r2, r0) @ r2<- vA 1503 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1504 cmp r2, r3 @ compare (vA, vB) 1505 bne 1f @ branch to 1 if comparison failed 1506 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1507 movs r9, r9, asl #1 @ convert to bytes, check sign 1508 bmi common_backwardBranch @ yes, do periodic checks 15091: 1510#if defined(WITH_JIT) 1511 GET_JIT_PROF_TABLE(r0) 1512 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1513 b common_testUpdateProfile 1514#else 1515 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1516 GET_INST_OPCODE(ip) @ extract opcode from rINST 1517 GOTO_OPCODE(ip) @ jump to next instruction 1518#endif 1519 1520 1521/* ------------------------------ */ 1522 .balign 64 1523.L_OP_IF_NE: /* 0x33 */ 1524/* File: armv5te/OP_IF_NE.S */ 1525/* File: armv5te/bincmp.S */ 1526 /* 1527 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1528 * fragment that specifies the *reverse* comparison to perform, e.g. 1529 * for "if-le" you would use "gt". 1530 * 1531 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1532 */ 1533 /* if-cmp vA, vB, +CCCC */ 1534 mov r0, rINST, lsr #8 @ r0<- A+ 1535 mov r1, rINST, lsr #12 @ r1<- B 1536 and r0, r0, #15 1537 GET_VREG(r3, r1) @ r3<- vB 1538 GET_VREG(r2, r0) @ r2<- vA 1539 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1540 cmp r2, r3 @ compare (vA, vB) 1541 beq 1f @ branch to 1 if comparison failed 1542 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1543 movs r9, r9, asl #1 @ convert to bytes, check sign 1544 bmi common_backwardBranch @ yes, do periodic checks 15451: 1546#if defined(WITH_JIT) 1547 GET_JIT_PROF_TABLE(r0) 1548 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1549 b common_testUpdateProfile 1550#else 1551 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1552 GET_INST_OPCODE(ip) @ extract opcode from rINST 1553 GOTO_OPCODE(ip) @ jump to next instruction 1554#endif 1555 1556 1557/* ------------------------------ */ 1558 .balign 64 1559.L_OP_IF_LT: /* 0x34 */ 1560/* File: armv5te/OP_IF_LT.S */ 1561/* File: armv5te/bincmp.S */ 1562 /* 1563 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1564 * fragment that specifies the *reverse* comparison to perform, e.g. 1565 * for "if-le" you would use "gt". 1566 * 1567 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1568 */ 1569 /* if-cmp vA, vB, +CCCC */ 1570 mov r0, rINST, lsr #8 @ r0<- A+ 1571 mov r1, rINST, lsr #12 @ r1<- B 1572 and r0, r0, #15 1573 GET_VREG(r3, r1) @ r3<- vB 1574 GET_VREG(r2, r0) @ r2<- vA 1575 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1576 cmp r2, r3 @ compare (vA, vB) 1577 bge 1f @ branch to 1 if comparison failed 1578 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1579 movs r9, r9, asl #1 @ convert to bytes, check sign 1580 bmi common_backwardBranch @ yes, do periodic checks 15811: 1582#if defined(WITH_JIT) 1583 GET_JIT_PROF_TABLE(r0) 1584 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1585 b common_testUpdateProfile 1586#else 1587 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1588 GET_INST_OPCODE(ip) @ extract opcode from rINST 1589 GOTO_OPCODE(ip) @ jump to next instruction 1590#endif 1591 1592 1593/* ------------------------------ */ 1594 .balign 64 1595.L_OP_IF_GE: /* 0x35 */ 1596/* File: armv5te/OP_IF_GE.S */ 1597/* File: armv5te/bincmp.S */ 1598 /* 1599 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1600 * fragment that specifies the *reverse* comparison to perform, e.g. 1601 * for "if-le" you would use "gt". 1602 * 1603 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1604 */ 1605 /* if-cmp vA, vB, +CCCC */ 1606 mov r0, rINST, lsr #8 @ r0<- A+ 1607 mov r1, rINST, lsr #12 @ r1<- B 1608 and r0, r0, #15 1609 GET_VREG(r3, r1) @ r3<- vB 1610 GET_VREG(r2, r0) @ r2<- vA 1611 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1612 cmp r2, r3 @ compare (vA, vB) 1613 blt 1f @ branch to 1 if comparison failed 1614 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1615 movs r9, r9, asl #1 @ convert to bytes, check sign 1616 bmi common_backwardBranch @ yes, do periodic checks 16171: 1618#if defined(WITH_JIT) 1619 GET_JIT_PROF_TABLE(r0) 1620 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1621 b common_testUpdateProfile 1622#else 1623 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1624 GET_INST_OPCODE(ip) @ extract opcode from rINST 1625 GOTO_OPCODE(ip) @ jump to next instruction 1626#endif 1627 1628 1629/* ------------------------------ */ 1630 .balign 64 1631.L_OP_IF_GT: /* 0x36 */ 1632/* File: armv5te/OP_IF_GT.S */ 1633/* File: armv5te/bincmp.S */ 1634 /* 1635 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1636 * fragment that specifies the *reverse* comparison to perform, e.g. 1637 * for "if-le" you would use "gt". 1638 * 1639 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1640 */ 1641 /* if-cmp vA, vB, +CCCC */ 1642 mov r0, rINST, lsr #8 @ r0<- A+ 1643 mov r1, rINST, lsr #12 @ r1<- B 1644 and r0, r0, #15 1645 GET_VREG(r3, r1) @ r3<- vB 1646 GET_VREG(r2, r0) @ r2<- vA 1647 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1648 cmp r2, r3 @ compare (vA, vB) 1649 ble 1f @ branch to 1 if comparison failed 1650 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1651 movs r9, r9, asl #1 @ convert to bytes, check sign 1652 bmi common_backwardBranch @ yes, do periodic checks 16531: 1654#if defined(WITH_JIT) 1655 GET_JIT_PROF_TABLE(r0) 1656 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1657 b common_testUpdateProfile 1658#else 1659 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1660 GET_INST_OPCODE(ip) @ extract opcode from rINST 1661 GOTO_OPCODE(ip) @ jump to next instruction 1662#endif 1663 1664 1665/* ------------------------------ */ 1666 .balign 64 1667.L_OP_IF_LE: /* 0x37 */ 1668/* File: armv5te/OP_IF_LE.S */ 1669/* File: armv5te/bincmp.S */ 1670 /* 1671 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1672 * fragment that specifies the *reverse* comparison to perform, e.g. 1673 * for "if-le" you would use "gt". 1674 * 1675 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1676 */ 1677 /* if-cmp vA, vB, +CCCC */ 1678 mov r0, rINST, lsr #8 @ r0<- A+ 1679 mov r1, rINST, lsr #12 @ r1<- B 1680 and r0, r0, #15 1681 GET_VREG(r3, r1) @ r3<- vB 1682 GET_VREG(r2, r0) @ r2<- vA 1683 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1684 cmp r2, r3 @ compare (vA, vB) 1685 bgt 1f @ branch to 1 if comparison failed 1686 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1687 movs r9, r9, asl #1 @ convert to bytes, check sign 1688 bmi common_backwardBranch @ yes, do periodic checks 16891: 1690#if defined(WITH_JIT) 1691 GET_JIT_PROF_TABLE(r0) 1692 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1693 b common_testUpdateProfile 1694#else 1695 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1696 GET_INST_OPCODE(ip) @ extract opcode from rINST 1697 GOTO_OPCODE(ip) @ jump to next instruction 1698#endif 1699 1700 1701/* ------------------------------ */ 1702 .balign 64 1703.L_OP_IF_EQZ: /* 0x38 */ 1704/* File: armv5te/OP_IF_EQZ.S */ 1705/* File: armv5te/zcmp.S */ 1706 /* 1707 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1708 * fragment that specifies the *reverse* comparison to perform, e.g. 1709 * for "if-le" you would use "gt". 1710 * 1711 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1712 */ 1713 /* if-cmp vAA, +BBBB */ 1714 mov r0, rINST, lsr #8 @ r0<- AA 1715 GET_VREG(r2, r0) @ r2<- vAA 1716 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1717 cmp r2, #0 @ compare (vA, 0) 1718 bne 1f @ branch to 1 if comparison failed 1719 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1720 movs r9, r9, asl #1 @ convert to bytes, check sign 1721 bmi common_backwardBranch @ backward branch, do periodic checks 17221: 1723#if defined(WITH_JIT) 1724 GET_JIT_PROF_TABLE(r0) 1725 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1726 cmp r0,#0 1727 bne common_updateProfile 1728 GET_INST_OPCODE(ip) @ extract opcode from rINST 1729 GOTO_OPCODE(ip) @ jump to next instruction 1730#else 1731 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1732 GET_INST_OPCODE(ip) @ extract opcode from rINST 1733 GOTO_OPCODE(ip) @ jump to next instruction 1734#endif 1735 1736 1737/* ------------------------------ */ 1738 .balign 64 1739.L_OP_IF_NEZ: /* 0x39 */ 1740/* File: armv5te/OP_IF_NEZ.S */ 1741/* File: armv5te/zcmp.S */ 1742 /* 1743 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1744 * fragment that specifies the *reverse* comparison to perform, e.g. 1745 * for "if-le" you would use "gt". 1746 * 1747 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1748 */ 1749 /* if-cmp vAA, +BBBB */ 1750 mov r0, rINST, lsr #8 @ r0<- AA 1751 GET_VREG(r2, r0) @ r2<- vAA 1752 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1753 cmp r2, #0 @ compare (vA, 0) 1754 beq 1f @ branch to 1 if comparison failed 1755 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1756 movs r9, r9, asl #1 @ convert to bytes, check sign 1757 bmi common_backwardBranch @ backward branch, do periodic checks 17581: 1759#if defined(WITH_JIT) 1760 GET_JIT_PROF_TABLE(r0) 1761 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1762 cmp r0,#0 1763 bne common_updateProfile 1764 GET_INST_OPCODE(ip) @ extract opcode from rINST 1765 GOTO_OPCODE(ip) @ jump to next instruction 1766#else 1767 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1768 GET_INST_OPCODE(ip) @ extract opcode from rINST 1769 GOTO_OPCODE(ip) @ jump to next instruction 1770#endif 1771 1772 1773/* ------------------------------ */ 1774 .balign 64 1775.L_OP_IF_LTZ: /* 0x3a */ 1776/* File: armv5te/OP_IF_LTZ.S */ 1777/* File: armv5te/zcmp.S */ 1778 /* 1779 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1780 * fragment that specifies the *reverse* comparison to perform, e.g. 1781 * for "if-le" you would use "gt". 1782 * 1783 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1784 */ 1785 /* if-cmp vAA, +BBBB */ 1786 mov r0, rINST, lsr #8 @ r0<- AA 1787 GET_VREG(r2, r0) @ r2<- vAA 1788 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1789 cmp r2, #0 @ compare (vA, 0) 1790 bge 1f @ branch to 1 if comparison failed 1791 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1792 movs r9, r9, asl #1 @ convert to bytes, check sign 1793 bmi common_backwardBranch @ backward branch, do periodic checks 17941: 1795#if defined(WITH_JIT) 1796 GET_JIT_PROF_TABLE(r0) 1797 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1798 cmp r0,#0 1799 bne common_updateProfile 1800 GET_INST_OPCODE(ip) @ extract opcode from rINST 1801 GOTO_OPCODE(ip) @ jump to next instruction 1802#else 1803 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1804 GET_INST_OPCODE(ip) @ extract opcode from rINST 1805 GOTO_OPCODE(ip) @ jump to next instruction 1806#endif 1807 1808 1809/* ------------------------------ */ 1810 .balign 64 1811.L_OP_IF_GEZ: /* 0x3b */ 1812/* File: armv5te/OP_IF_GEZ.S */ 1813/* File: armv5te/zcmp.S */ 1814 /* 1815 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1816 * fragment that specifies the *reverse* comparison to perform, e.g. 1817 * for "if-le" you would use "gt". 1818 * 1819 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1820 */ 1821 /* if-cmp vAA, +BBBB */ 1822 mov r0, rINST, lsr #8 @ r0<- AA 1823 GET_VREG(r2, r0) @ r2<- vAA 1824 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1825 cmp r2, #0 @ compare (vA, 0) 1826 blt 1f @ branch to 1 if comparison failed 1827 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1828 movs r9, r9, asl #1 @ convert to bytes, check sign 1829 bmi common_backwardBranch @ backward branch, do periodic checks 18301: 1831#if defined(WITH_JIT) 1832 GET_JIT_PROF_TABLE(r0) 1833 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1834 cmp r0,#0 1835 bne common_updateProfile 1836 GET_INST_OPCODE(ip) @ extract opcode from rINST 1837 GOTO_OPCODE(ip) @ jump to next instruction 1838#else 1839 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1840 GET_INST_OPCODE(ip) @ extract opcode from rINST 1841 GOTO_OPCODE(ip) @ jump to next instruction 1842#endif 1843 1844 1845/* ------------------------------ */ 1846 .balign 64 1847.L_OP_IF_GTZ: /* 0x3c */ 1848/* File: armv5te/OP_IF_GTZ.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 ble 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 .balign 64 1883.L_OP_IF_LEZ: /* 0x3d */ 1884/* File: armv5te/OP_IF_LEZ.S */ 1885/* File: armv5te/zcmp.S */ 1886 /* 1887 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1888 * fragment that specifies the *reverse* comparison to perform, e.g. 1889 * for "if-le" you would use "gt". 1890 * 1891 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1892 */ 1893 /* if-cmp vAA, +BBBB */ 1894 mov r0, rINST, lsr #8 @ r0<- AA 1895 GET_VREG(r2, r0) @ r2<- vAA 1896 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1897 cmp r2, #0 @ compare (vA, 0) 1898 bgt 1f @ branch to 1 if comparison failed 1899 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1900 movs r9, r9, asl #1 @ convert to bytes, check sign 1901 bmi common_backwardBranch @ backward branch, do periodic checks 19021: 1903#if defined(WITH_JIT) 1904 GET_JIT_PROF_TABLE(r0) 1905 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1906 cmp r0,#0 1907 bne common_updateProfile 1908 GET_INST_OPCODE(ip) @ extract opcode from rINST 1909 GOTO_OPCODE(ip) @ jump to next instruction 1910#else 1911 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1912 GET_INST_OPCODE(ip) @ extract opcode from rINST 1913 GOTO_OPCODE(ip) @ jump to next instruction 1914#endif 1915 1916 1917/* ------------------------------ */ 1918 .balign 64 1919.L_OP_UNUSED_3E: /* 0x3e */ 1920/* File: armv5te/OP_UNUSED_3E.S */ 1921/* File: armv5te/unused.S */ 1922 bl common_abort 1923 1924 1925/* ------------------------------ */ 1926 .balign 64 1927.L_OP_UNUSED_3F: /* 0x3f */ 1928/* File: armv5te/OP_UNUSED_3F.S */ 1929/* File: armv5te/unused.S */ 1930 bl common_abort 1931 1932 1933/* ------------------------------ */ 1934 .balign 64 1935.L_OP_UNUSED_40: /* 0x40 */ 1936/* File: armv5te/OP_UNUSED_40.S */ 1937/* File: armv5te/unused.S */ 1938 bl common_abort 1939 1940 1941/* ------------------------------ */ 1942 .balign 64 1943.L_OP_UNUSED_41: /* 0x41 */ 1944/* File: armv5te/OP_UNUSED_41.S */ 1945/* File: armv5te/unused.S */ 1946 bl common_abort 1947 1948 1949/* ------------------------------ */ 1950 .balign 64 1951.L_OP_UNUSED_42: /* 0x42 */ 1952/* File: armv5te/OP_UNUSED_42.S */ 1953/* File: armv5te/unused.S */ 1954 bl common_abort 1955 1956 1957/* ------------------------------ */ 1958 .balign 64 1959.L_OP_UNUSED_43: /* 0x43 */ 1960/* File: armv5te/OP_UNUSED_43.S */ 1961/* File: armv5te/unused.S */ 1962 bl common_abort 1963 1964 1965/* ------------------------------ */ 1966 .balign 64 1967.L_OP_AGET: /* 0x44 */ 1968/* File: armv5te/OP_AGET.S */ 1969 /* 1970 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1971 * 1972 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1973 * instructions. We use a pair of FETCH_Bs instead. 1974 * 1975 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1976 */ 1977 /* op vAA, vBB, vCC */ 1978 FETCH_B(r2, 1, 0) @ r2<- BB 1979 mov r9, rINST, lsr #8 @ r9<- AA 1980 FETCH_B(r3, 1, 1) @ r3<- CC 1981 GET_VREG(r0, r2) @ r0<- vBB (array object) 1982 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1983 cmp r0, #0 @ null array object? 1984 beq common_errNullObject @ yes, bail 1985 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1986 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1987 cmp r1, r3 @ compare unsigned index, length 1988 bcs common_errArrayIndex @ index >= length, bail 1989 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1990 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1991 GET_INST_OPCODE(ip) @ extract opcode from rINST 1992 SET_VREG(r2, r9) @ vAA<- r2 1993 GOTO_OPCODE(ip) @ jump to next instruction 1994 1995/* ------------------------------ */ 1996 .balign 64 1997.L_OP_AGET_WIDE: /* 0x45 */ 1998/* File: armv5te/OP_AGET_WIDE.S */ 1999 /* 2000 * Array get, 64 bits. vAA <- vBB[vCC]. 2001 * 2002 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2003 */ 2004 /* aget-wide vAA, vBB, vCC */ 2005 FETCH(r0, 1) @ r0<- CCBB 2006 mov r9, rINST, lsr #8 @ r9<- AA 2007 and r2, r0, #255 @ r2<- BB 2008 mov r3, r0, lsr #8 @ r3<- CC 2009 GET_VREG(r0, r2) @ r0<- vBB (array object) 2010 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2011 cmp r0, #0 @ null array object? 2012 beq common_errNullObject @ yes, bail 2013 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2014 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2015 cmp r1, r3 @ compare unsigned index, length 2016 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2017 b common_errArrayIndex @ index >= length, bail 2018 @ May want to swap the order of these two branches depending on how the 2019 @ branch prediction (if any) handles conditional forward branches vs. 2020 @ unconditional forward branches. 2021 2022/* ------------------------------ */ 2023 .balign 64 2024.L_OP_AGET_OBJECT: /* 0x46 */ 2025/* File: armv5te/OP_AGET_OBJECT.S */ 2026/* File: armv5te/OP_AGET.S */ 2027 /* 2028 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2029 * 2030 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2031 * instructions. We use a pair of FETCH_Bs instead. 2032 * 2033 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2034 */ 2035 /* op vAA, vBB, vCC */ 2036 FETCH_B(r2, 1, 0) @ r2<- BB 2037 mov r9, rINST, lsr #8 @ r9<- AA 2038 FETCH_B(r3, 1, 1) @ r3<- CC 2039 GET_VREG(r0, r2) @ r0<- vBB (array object) 2040 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2041 cmp r0, #0 @ null array object? 2042 beq common_errNullObject @ yes, bail 2043 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2044 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2045 cmp r1, r3 @ compare unsigned index, length 2046 bcs common_errArrayIndex @ index >= length, bail 2047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2048 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2049 GET_INST_OPCODE(ip) @ extract opcode from rINST 2050 SET_VREG(r2, r9) @ vAA<- r2 2051 GOTO_OPCODE(ip) @ jump to next instruction 2052 2053 2054/* ------------------------------ */ 2055 .balign 64 2056.L_OP_AGET_BOOLEAN: /* 0x47 */ 2057/* File: armv5te/OP_AGET_BOOLEAN.S */ 2058/* File: armv5te/OP_AGET.S */ 2059 /* 2060 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2061 * 2062 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2063 * instructions. We use a pair of FETCH_Bs instead. 2064 * 2065 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2066 */ 2067 /* op vAA, vBB, vCC */ 2068 FETCH_B(r2, 1, 0) @ r2<- BB 2069 mov r9, rINST, lsr #8 @ r9<- AA 2070 FETCH_B(r3, 1, 1) @ r3<- CC 2071 GET_VREG(r0, r2) @ r0<- vBB (array object) 2072 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2073 cmp r0, #0 @ null array object? 2074 beq common_errNullObject @ yes, bail 2075 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2076 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2077 cmp r1, r3 @ compare unsigned index, length 2078 bcs common_errArrayIndex @ index >= length, bail 2079 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2080 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2081 GET_INST_OPCODE(ip) @ extract opcode from rINST 2082 SET_VREG(r2, r9) @ vAA<- r2 2083 GOTO_OPCODE(ip) @ jump to next instruction 2084 2085 2086/* ------------------------------ */ 2087 .balign 64 2088.L_OP_AGET_BYTE: /* 0x48 */ 2089/* File: armv5te/OP_AGET_BYTE.S */ 2090/* File: armv5te/OP_AGET.S */ 2091 /* 2092 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2093 * 2094 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2095 * instructions. We use a pair of FETCH_Bs instead. 2096 * 2097 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2098 */ 2099 /* op vAA, vBB, vCC */ 2100 FETCH_B(r2, 1, 0) @ r2<- BB 2101 mov r9, rINST, lsr #8 @ r9<- AA 2102 FETCH_B(r3, 1, 1) @ r3<- CC 2103 GET_VREG(r0, r2) @ r0<- vBB (array object) 2104 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2105 cmp r0, #0 @ null array object? 2106 beq common_errNullObject @ yes, bail 2107 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2108 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2109 cmp r1, r3 @ compare unsigned index, length 2110 bcs common_errArrayIndex @ index >= length, bail 2111 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2112 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2113 GET_INST_OPCODE(ip) @ extract opcode from rINST 2114 SET_VREG(r2, r9) @ vAA<- r2 2115 GOTO_OPCODE(ip) @ jump to next instruction 2116 2117 2118/* ------------------------------ */ 2119 .balign 64 2120.L_OP_AGET_CHAR: /* 0x49 */ 2121/* File: armv5te/OP_AGET_CHAR.S */ 2122/* File: armv5te/OP_AGET.S */ 2123 /* 2124 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2125 * 2126 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2127 * instructions. We use a pair of FETCH_Bs instead. 2128 * 2129 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2130 */ 2131 /* op vAA, vBB, vCC */ 2132 FETCH_B(r2, 1, 0) @ r2<- BB 2133 mov r9, rINST, lsr #8 @ r9<- AA 2134 FETCH_B(r3, 1, 1) @ r3<- CC 2135 GET_VREG(r0, r2) @ r0<- vBB (array object) 2136 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2137 cmp r0, #0 @ null array object? 2138 beq common_errNullObject @ yes, bail 2139 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2140 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2141 cmp r1, r3 @ compare unsigned index, length 2142 bcs common_errArrayIndex @ index >= length, bail 2143 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2144 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2145 GET_INST_OPCODE(ip) @ extract opcode from rINST 2146 SET_VREG(r2, r9) @ vAA<- r2 2147 GOTO_OPCODE(ip) @ jump to next instruction 2148 2149 2150/* ------------------------------ */ 2151 .balign 64 2152.L_OP_AGET_SHORT: /* 0x4a */ 2153/* File: armv5te/OP_AGET_SHORT.S */ 2154/* File: armv5te/OP_AGET.S */ 2155 /* 2156 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2157 * 2158 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2159 * instructions. We use a pair of FETCH_Bs instead. 2160 * 2161 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2162 */ 2163 /* op vAA, vBB, vCC */ 2164 FETCH_B(r2, 1, 0) @ r2<- BB 2165 mov r9, rINST, lsr #8 @ r9<- AA 2166 FETCH_B(r3, 1, 1) @ r3<- CC 2167 GET_VREG(r0, r2) @ r0<- vBB (array object) 2168 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2169 cmp r0, #0 @ null array object? 2170 beq common_errNullObject @ yes, bail 2171 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2172 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2173 cmp r1, r3 @ compare unsigned index, length 2174 bcs common_errArrayIndex @ index >= length, bail 2175 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2176 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2177 GET_INST_OPCODE(ip) @ extract opcode from rINST 2178 SET_VREG(r2, r9) @ vAA<- r2 2179 GOTO_OPCODE(ip) @ jump to next instruction 2180 2181 2182/* ------------------------------ */ 2183 .balign 64 2184.L_OP_APUT: /* 0x4b */ 2185/* File: armv5te/OP_APUT.S */ 2186 /* 2187 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2188 * 2189 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2190 * instructions. We use a pair of FETCH_Bs instead. 2191 * 2192 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2193 */ 2194 /* op vAA, vBB, vCC */ 2195 FETCH_B(r2, 1, 0) @ r2<- BB 2196 mov r9, rINST, lsr #8 @ r9<- AA 2197 FETCH_B(r3, 1, 1) @ r3<- CC 2198 GET_VREG(r0, r2) @ r0<- vBB (array object) 2199 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2200 cmp r0, #0 @ null array object? 2201 beq common_errNullObject @ yes, bail 2202 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2203 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2204 cmp r1, r3 @ compare unsigned index, length 2205 bcs common_errArrayIndex @ index >= length, bail 2206 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2207 GET_VREG(r2, r9) @ r2<- vAA 2208 GET_INST_OPCODE(ip) @ extract opcode from rINST 2209 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2210 GOTO_OPCODE(ip) @ jump to next instruction 2211 2212/* ------------------------------ */ 2213 .balign 64 2214.L_OP_APUT_WIDE: /* 0x4c */ 2215/* File: armv5te/OP_APUT_WIDE.S */ 2216 /* 2217 * Array put, 64 bits. vBB[vCC] <- vAA. 2218 * 2219 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2220 */ 2221 /* aput-wide vAA, vBB, vCC */ 2222 FETCH(r0, 1) @ r0<- CCBB 2223 mov r9, rINST, lsr #8 @ r9<- AA 2224 and r2, r0, #255 @ r2<- BB 2225 mov r3, r0, lsr #8 @ r3<- CC 2226 GET_VREG(r0, r2) @ r0<- vBB (array object) 2227 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2228 cmp r0, #0 @ null array object? 2229 beq common_errNullObject @ yes, bail 2230 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2231 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2232 cmp r1, r3 @ compare unsigned index, length 2233 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2234 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2235 b common_errArrayIndex @ index >= length, bail 2236 @ May want to swap the order of these two branches depending on how the 2237 @ branch prediction (if any) handles conditional forward branches vs. 2238 @ unconditional forward branches. 2239 2240/* ------------------------------ */ 2241 .balign 64 2242.L_OP_APUT_OBJECT: /* 0x4d */ 2243/* File: armv5te/OP_APUT_OBJECT.S */ 2244 /* 2245 * Store an object into an array. vBB[vCC] <- vAA. 2246 * 2247 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2248 * instructions. We use a pair of FETCH_Bs instead. 2249 */ 2250 /* op vAA, vBB, vCC */ 2251 FETCH(r0, 1) @ r0<- CCBB 2252 mov r9, rINST, lsr #8 @ r9<- AA 2253 and r2, r0, #255 @ r2<- BB 2254 mov r3, r0, lsr #8 @ r3<- CC 2255 GET_VREG(r1, r2) @ r1<- vBB (array object) 2256 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2257 cmp r1, #0 @ null array object? 2258 GET_VREG(r9, r9) @ r9<- vAA 2259 beq common_errNullObject @ yes, bail 2260 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2261 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2262 cmp r0, r3 @ compare unsigned index, length 2263 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2264 b common_errArrayIndex @ index >= length, bail 2265 2266 2267/* ------------------------------ */ 2268 .balign 64 2269.L_OP_APUT_BOOLEAN: /* 0x4e */ 2270/* File: armv5te/OP_APUT_BOOLEAN.S */ 2271/* File: armv5te/OP_APUT.S */ 2272 /* 2273 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2274 * 2275 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2276 * instructions. We use a pair of FETCH_Bs instead. 2277 * 2278 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2279 */ 2280 /* op vAA, vBB, vCC */ 2281 FETCH_B(r2, 1, 0) @ r2<- BB 2282 mov r9, rINST, lsr #8 @ r9<- AA 2283 FETCH_B(r3, 1, 1) @ r3<- CC 2284 GET_VREG(r0, r2) @ r0<- vBB (array object) 2285 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2286 cmp r0, #0 @ null array object? 2287 beq common_errNullObject @ yes, bail 2288 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2289 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2290 cmp r1, r3 @ compare unsigned index, length 2291 bcs common_errArrayIndex @ index >= length, bail 2292 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2293 GET_VREG(r2, r9) @ r2<- vAA 2294 GET_INST_OPCODE(ip) @ extract opcode from rINST 2295 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2296 GOTO_OPCODE(ip) @ jump to next instruction 2297 2298 2299/* ------------------------------ */ 2300 .balign 64 2301.L_OP_APUT_BYTE: /* 0x4f */ 2302/* File: armv5te/OP_APUT_BYTE.S */ 2303/* File: armv5te/OP_APUT.S */ 2304 /* 2305 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2306 * 2307 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2308 * instructions. We use a pair of FETCH_Bs instead. 2309 * 2310 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2311 */ 2312 /* op vAA, vBB, vCC */ 2313 FETCH_B(r2, 1, 0) @ r2<- BB 2314 mov r9, rINST, lsr #8 @ r9<- AA 2315 FETCH_B(r3, 1, 1) @ r3<- CC 2316 GET_VREG(r0, r2) @ r0<- vBB (array object) 2317 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2318 cmp r0, #0 @ null array object? 2319 beq common_errNullObject @ yes, bail 2320 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2321 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2322 cmp r1, r3 @ compare unsigned index, length 2323 bcs common_errArrayIndex @ index >= length, bail 2324 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2325 GET_VREG(r2, r9) @ r2<- vAA 2326 GET_INST_OPCODE(ip) @ extract opcode from rINST 2327 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2328 GOTO_OPCODE(ip) @ jump to next instruction 2329 2330 2331/* ------------------------------ */ 2332 .balign 64 2333.L_OP_APUT_CHAR: /* 0x50 */ 2334/* File: armv5te/OP_APUT_CHAR.S */ 2335/* File: armv5te/OP_APUT.S */ 2336 /* 2337 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2338 * 2339 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2340 * instructions. We use a pair of FETCH_Bs instead. 2341 * 2342 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2343 */ 2344 /* op vAA, vBB, vCC */ 2345 FETCH_B(r2, 1, 0) @ r2<- BB 2346 mov r9, rINST, lsr #8 @ r9<- AA 2347 FETCH_B(r3, 1, 1) @ r3<- CC 2348 GET_VREG(r0, r2) @ r0<- vBB (array object) 2349 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2350 cmp r0, #0 @ null array object? 2351 beq common_errNullObject @ yes, bail 2352 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2353 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2354 cmp r1, r3 @ compare unsigned index, length 2355 bcs common_errArrayIndex @ index >= length, bail 2356 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2357 GET_VREG(r2, r9) @ r2<- vAA 2358 GET_INST_OPCODE(ip) @ extract opcode from rINST 2359 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2360 GOTO_OPCODE(ip) @ jump to next instruction 2361 2362 2363/* ------------------------------ */ 2364 .balign 64 2365.L_OP_APUT_SHORT: /* 0x51 */ 2366/* File: armv5te/OP_APUT_SHORT.S */ 2367/* File: armv5te/OP_APUT.S */ 2368 /* 2369 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2370 * 2371 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2372 * instructions. We use a pair of FETCH_Bs instead. 2373 * 2374 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2375 */ 2376 /* op vAA, vBB, vCC */ 2377 FETCH_B(r2, 1, 0) @ r2<- BB 2378 mov r9, rINST, lsr #8 @ r9<- AA 2379 FETCH_B(r3, 1, 1) @ r3<- CC 2380 GET_VREG(r0, r2) @ r0<- vBB (array object) 2381 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2382 cmp r0, #0 @ null array object? 2383 beq common_errNullObject @ yes, bail 2384 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2385 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2386 cmp r1, r3 @ compare unsigned index, length 2387 bcs common_errArrayIndex @ index >= length, bail 2388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2389 GET_VREG(r2, r9) @ r2<- vAA 2390 GET_INST_OPCODE(ip) @ extract opcode from rINST 2391 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2392 GOTO_OPCODE(ip) @ jump to next instruction 2393 2394 2395/* ------------------------------ */ 2396 .balign 64 2397.L_OP_IGET: /* 0x52 */ 2398/* File: armv5te/OP_IGET.S */ 2399 /* 2400 * General 32-bit instance field get. 2401 * 2402 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2403 */ 2404 /* op vA, vB, field@CCCC */ 2405 mov r0, rINST, lsr #12 @ r0<- B 2406 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2407 FETCH(r1, 1) @ r1<- field ref CCCC 2408 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2409 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2410 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2411 cmp r0, #0 @ is resolved entry null? 2412 bne .LOP_IGET_finish @ no, already resolved 24138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2414 EXPORT_PC() @ resolve() could throw 2415 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2416 bl dvmResolveInstField @ r0<- resolved InstField ptr 2417 cmp r0, #0 2418 bne .LOP_IGET_finish 2419 b common_exceptionThrown 2420 2421/* ------------------------------ */ 2422 .balign 64 2423.L_OP_IGET_WIDE: /* 0x53 */ 2424/* File: armv5te/OP_IGET_WIDE.S */ 2425 /* 2426 * Wide 32-bit instance field get. 2427 */ 2428 /* iget-wide vA, vB, field@CCCC */ 2429 mov r0, rINST, lsr #12 @ r0<- B 2430 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2431 FETCH(r1, 1) @ r1<- field ref CCCC 2432 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2433 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2434 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2435 cmp r0, #0 @ is resolved entry null? 2436 bne .LOP_IGET_WIDE_finish @ no, already resolved 24378: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2438 EXPORT_PC() @ resolve() could throw 2439 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2440 bl dvmResolveInstField @ r0<- resolved InstField ptr 2441 cmp r0, #0 2442 bne .LOP_IGET_WIDE_finish 2443 b common_exceptionThrown 2444 2445/* ------------------------------ */ 2446 .balign 64 2447.L_OP_IGET_OBJECT: /* 0x54 */ 2448/* File: armv5te/OP_IGET_OBJECT.S */ 2449/* File: armv5te/OP_IGET.S */ 2450 /* 2451 * General 32-bit instance field get. 2452 * 2453 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2454 */ 2455 /* op vA, vB, field@CCCC */ 2456 mov r0, rINST, lsr #12 @ r0<- B 2457 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2458 FETCH(r1, 1) @ r1<- field ref CCCC 2459 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2460 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2461 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2462 cmp r0, #0 @ is resolved entry null? 2463 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24648: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2465 EXPORT_PC() @ resolve() could throw 2466 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2467 bl dvmResolveInstField @ r0<- resolved InstField ptr 2468 cmp r0, #0 2469 bne .LOP_IGET_OBJECT_finish 2470 b common_exceptionThrown 2471 2472 2473/* ------------------------------ */ 2474 .balign 64 2475.L_OP_IGET_BOOLEAN: /* 0x55 */ 2476/* File: armv5te/OP_IGET_BOOLEAN.S */ 2477@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2478/* File: armv5te/OP_IGET.S */ 2479 /* 2480 * General 32-bit instance field get. 2481 * 2482 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2483 */ 2484 /* op 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<- pDvmDex->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_BOOLEAN_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_BOOLEAN_finish 2499 b common_exceptionThrown 2500 2501 2502/* ------------------------------ */ 2503 .balign 64 2504.L_OP_IGET_BYTE: /* 0x56 */ 2505/* File: armv5te/OP_IGET_BYTE.S */ 2506@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2507/* File: armv5te/OP_IGET.S */ 2508 /* 2509 * General 32-bit instance field get. 2510 * 2511 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2512 */ 2513 /* op vA, vB, field@CCCC */ 2514 mov r0, rINST, lsr #12 @ r0<- B 2515 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2516 FETCH(r1, 1) @ r1<- field ref CCCC 2517 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2518 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2519 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2520 cmp r0, #0 @ is resolved entry null? 2521 bne .LOP_IGET_BYTE_finish @ no, already resolved 25228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2523 EXPORT_PC() @ resolve() could throw 2524 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2525 bl dvmResolveInstField @ r0<- resolved InstField ptr 2526 cmp r0, #0 2527 bne .LOP_IGET_BYTE_finish 2528 b common_exceptionThrown 2529 2530 2531/* ------------------------------ */ 2532 .balign 64 2533.L_OP_IGET_CHAR: /* 0x57 */ 2534/* File: armv5te/OP_IGET_CHAR.S */ 2535@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2536/* File: armv5te/OP_IGET.S */ 2537 /* 2538 * General 32-bit instance field get. 2539 * 2540 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2541 */ 2542 /* op vA, vB, field@CCCC */ 2543 mov r0, rINST, lsr #12 @ r0<- B 2544 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2545 FETCH(r1, 1) @ r1<- field ref CCCC 2546 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2547 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2548 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2549 cmp r0, #0 @ is resolved entry null? 2550 bne .LOP_IGET_CHAR_finish @ no, already resolved 25518: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2552 EXPORT_PC() @ resolve() could throw 2553 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2554 bl dvmResolveInstField @ r0<- resolved InstField ptr 2555 cmp r0, #0 2556 bne .LOP_IGET_CHAR_finish 2557 b common_exceptionThrown 2558 2559 2560/* ------------------------------ */ 2561 .balign 64 2562.L_OP_IGET_SHORT: /* 0x58 */ 2563/* File: armv5te/OP_IGET_SHORT.S */ 2564@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2565/* File: armv5te/OP_IGET.S */ 2566 /* 2567 * General 32-bit instance field get. 2568 * 2569 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2570 */ 2571 /* op vA, vB, field@CCCC */ 2572 mov r0, rINST, lsr #12 @ r0<- B 2573 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2574 FETCH(r1, 1) @ r1<- field ref CCCC 2575 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2576 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2577 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2578 cmp r0, #0 @ is resolved entry null? 2579 bne .LOP_IGET_SHORT_finish @ no, already resolved 25808: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2581 EXPORT_PC() @ resolve() could throw 2582 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2583 bl dvmResolveInstField @ r0<- resolved InstField ptr 2584 cmp r0, #0 2585 bne .LOP_IGET_SHORT_finish 2586 b common_exceptionThrown 2587 2588 2589/* ------------------------------ */ 2590 .balign 64 2591.L_OP_IPUT: /* 0x59 */ 2592/* File: armv5te/OP_IPUT.S */ 2593 /* 2594 * General 32-bit instance field put. 2595 * 2596 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-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_IPUT_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 @ success? 2612 bne .LOP_IPUT_finish @ yes, finish up 2613 b common_exceptionThrown 2614 2615/* ------------------------------ */ 2616 .balign 64 2617.L_OP_IPUT_WIDE: /* 0x5a */ 2618/* File: armv5te/OP_IPUT_WIDE.S */ 2619 /* iput-wide vA, vB, field@CCCC */ 2620 mov r0, rINST, lsr #12 @ r0<- B 2621 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2622 FETCH(r1, 1) @ r1<- field ref CCCC 2623 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2624 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2625 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2626 cmp r0, #0 @ is resolved entry null? 2627 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26288: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2629 EXPORT_PC() @ resolve() could throw 2630 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2631 bl dvmResolveInstField @ r0<- resolved InstField ptr 2632 cmp r0, #0 @ success? 2633 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2634 b common_exceptionThrown 2635 2636/* ------------------------------ */ 2637 .balign 64 2638.L_OP_IPUT_OBJECT: /* 0x5b */ 2639/* File: armv5te/OP_IPUT_OBJECT.S */ 2640/* File: armv5te/OP_IPUT.S */ 2641 /* 2642 * General 32-bit instance field put. 2643 * 2644 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2645 */ 2646 /* op vA, vB, field@CCCC */ 2647 mov r0, rINST, lsr #12 @ r0<- B 2648 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2649 FETCH(r1, 1) @ r1<- field ref CCCC 2650 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2651 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2652 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2653 cmp r0, #0 @ is resolved entry null? 2654 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26558: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2656 EXPORT_PC() @ resolve() could throw 2657 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2658 bl dvmResolveInstField @ r0<- resolved InstField ptr 2659 cmp r0, #0 @ success? 2660 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2661 b common_exceptionThrown 2662 2663 2664/* ------------------------------ */ 2665 .balign 64 2666.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2667/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2668@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2669/* File: armv5te/OP_IPUT.S */ 2670 /* 2671 * General 32-bit instance field put. 2672 * 2673 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2674 */ 2675 /* op 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<- pDvmDex->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_BOOLEAN_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_BOOLEAN_finish @ yes, finish up 2690 b common_exceptionThrown 2691 2692 2693/* ------------------------------ */ 2694 .balign 64 2695.L_OP_IPUT_BYTE: /* 0x5d */ 2696/* File: armv5te/OP_IPUT_BYTE.S */ 2697@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2698/* File: armv5te/OP_IPUT.S */ 2699 /* 2700 * General 32-bit instance field put. 2701 * 2702 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2703 */ 2704 /* op vA, vB, field@CCCC */ 2705 mov r0, rINST, lsr #12 @ r0<- B 2706 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2707 FETCH(r1, 1) @ r1<- field ref CCCC 2708 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2709 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2710 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2711 cmp r0, #0 @ is resolved entry null? 2712 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2714 EXPORT_PC() @ resolve() could throw 2715 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2716 bl dvmResolveInstField @ r0<- resolved InstField ptr 2717 cmp r0, #0 @ success? 2718 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2719 b common_exceptionThrown 2720 2721 2722/* ------------------------------ */ 2723 .balign 64 2724.L_OP_IPUT_CHAR: /* 0x5e */ 2725/* File: armv5te/OP_IPUT_CHAR.S */ 2726@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2727/* File: armv5te/OP_IPUT.S */ 2728 /* 2729 * General 32-bit instance field put. 2730 * 2731 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2732 */ 2733 /* op vA, vB, field@CCCC */ 2734 mov r0, rINST, lsr #12 @ r0<- B 2735 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2736 FETCH(r1, 1) @ r1<- field ref CCCC 2737 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2738 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2739 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2740 cmp r0, #0 @ is resolved entry null? 2741 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27428: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2743 EXPORT_PC() @ resolve() could throw 2744 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2745 bl dvmResolveInstField @ r0<- resolved InstField ptr 2746 cmp r0, #0 @ success? 2747 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2748 b common_exceptionThrown 2749 2750 2751/* ------------------------------ */ 2752 .balign 64 2753.L_OP_IPUT_SHORT: /* 0x5f */ 2754/* File: armv5te/OP_IPUT_SHORT.S */ 2755@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2756/* File: armv5te/OP_IPUT.S */ 2757 /* 2758 * General 32-bit instance field put. 2759 * 2760 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2761 */ 2762 /* op vA, vB, field@CCCC */ 2763 mov r0, rINST, lsr #12 @ r0<- B 2764 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2765 FETCH(r1, 1) @ r1<- field ref CCCC 2766 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2767 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2768 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2769 cmp r0, #0 @ is resolved entry null? 2770 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2772 EXPORT_PC() @ resolve() could throw 2773 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2774 bl dvmResolveInstField @ r0<- resolved InstField ptr 2775 cmp r0, #0 @ success? 2776 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2777 b common_exceptionThrown 2778 2779 2780/* ------------------------------ */ 2781 .balign 64 2782.L_OP_SGET: /* 0x60 */ 2783/* File: armv5te/OP_SGET.S */ 2784 /* 2785 * General 32-bit SGET handler. 2786 * 2787 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2788 */ 2789 /* op vAA, field@BBBB */ 2790 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2791 FETCH(r1, 1) @ r1<- field ref BBBB 2792 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2793 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2794 cmp r0, #0 @ is resolved entry null? 2795 beq .LOP_SGET_resolve @ yes, do resolve 2796.LOP_SGET_finish: @ field ptr in r0 2797 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2798 SMP_DMB 0 @ acquiring load 2799 mov r2, rINST, lsr #8 @ r2<- AA 2800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2801 SET_VREG(r1, r2) @ fp[AA]<- r1 2802 GET_INST_OPCODE(ip) @ extract opcode from rINST 2803 GOTO_OPCODE(ip) @ jump to next instruction 2804 2805/* ------------------------------ */ 2806 .balign 64 2807.L_OP_SGET_WIDE: /* 0x61 */ 2808/* File: armv5te/OP_SGET_WIDE.S */ 2809 /* 2810 * 64-bit SGET handler. 2811 */ 2812 /* sget-wide vAA, field@BBBB */ 2813 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2814 FETCH(r1, 1) @ r1<- field ref BBBB 2815 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2816 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2817 cmp r0, #0 @ is resolved entry null? 2818 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2819.LOP_SGET_WIDE_finish: 2820 mov r9, rINST, lsr #8 @ r9<- AA 2821 .if 0 2822 add r0, r0, #offStaticField_value @ r0<- pointer to data 2823 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2824 .else 2825 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2826 .endif 2827 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2828 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2829 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2830 GET_INST_OPCODE(ip) @ extract opcode from rINST 2831 GOTO_OPCODE(ip) @ jump to next instruction 2832 2833/* ------------------------------ */ 2834 .balign 64 2835.L_OP_SGET_OBJECT: /* 0x62 */ 2836/* File: armv5te/OP_SGET_OBJECT.S */ 2837/* File: armv5te/OP_SGET.S */ 2838 /* 2839 * General 32-bit SGET handler. 2840 * 2841 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2842 */ 2843 /* op vAA, field@BBBB */ 2844 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2845 FETCH(r1, 1) @ r1<- field ref BBBB 2846 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2847 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2848 cmp r0, #0 @ is resolved entry null? 2849 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2850.LOP_SGET_OBJECT_finish: @ field ptr in r0 2851 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2852 SMP_DMB 0 @ acquiring load 2853 mov r2, rINST, lsr #8 @ r2<- AA 2854 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2855 SET_VREG(r1, r2) @ fp[AA]<- r1 2856 GET_INST_OPCODE(ip) @ extract opcode from rINST 2857 GOTO_OPCODE(ip) @ jump to next instruction 2858 2859 2860/* ------------------------------ */ 2861 .balign 64 2862.L_OP_SGET_BOOLEAN: /* 0x63 */ 2863/* File: armv5te/OP_SGET_BOOLEAN.S */ 2864/* File: armv5te/OP_SGET.S */ 2865 /* 2866 * General 32-bit SGET handler. 2867 * 2868 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2869 */ 2870 /* op vAA, field@BBBB */ 2871 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2872 FETCH(r1, 1) @ r1<- field ref BBBB 2873 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2874 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2875 cmp r0, #0 @ is resolved entry null? 2876 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2877.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2878 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2879 SMP_DMB 0 @ acquiring load 2880 mov r2, rINST, lsr #8 @ r2<- AA 2881 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2882 SET_VREG(r1, r2) @ fp[AA]<- r1 2883 GET_INST_OPCODE(ip) @ extract opcode from rINST 2884 GOTO_OPCODE(ip) @ jump to next instruction 2885 2886 2887/* ------------------------------ */ 2888 .balign 64 2889.L_OP_SGET_BYTE: /* 0x64 */ 2890/* File: armv5te/OP_SGET_BYTE.S */ 2891/* File: armv5te/OP_SGET.S */ 2892 /* 2893 * General 32-bit SGET handler. 2894 * 2895 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2896 */ 2897 /* op vAA, field@BBBB */ 2898 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2899 FETCH(r1, 1) @ r1<- field ref BBBB 2900 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2901 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2902 cmp r0, #0 @ is resolved entry null? 2903 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2904.LOP_SGET_BYTE_finish: @ field ptr in r0 2905 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2906 SMP_DMB 0 @ acquiring load 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_CHAR: /* 0x65 */ 2917/* File: armv5te/OP_SGET_CHAR.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_CHAR_resolve @ yes, do resolve 2931.LOP_SGET_CHAR_finish: @ field ptr in r0 2932 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2933 SMP_DMB 0 @ acquiring load 2934 mov r2, rINST, lsr #8 @ r2<- AA 2935 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2936 SET_VREG(r1, r2) @ fp[AA]<- r1 2937 GET_INST_OPCODE(ip) @ extract opcode from rINST 2938 GOTO_OPCODE(ip) @ jump to next instruction 2939 2940 2941/* ------------------------------ */ 2942 .balign 64 2943.L_OP_SGET_SHORT: /* 0x66 */ 2944/* File: armv5te/OP_SGET_SHORT.S */ 2945/* File: armv5te/OP_SGET.S */ 2946 /* 2947 * General 32-bit SGET handler. 2948 * 2949 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2950 */ 2951 /* op vAA, field@BBBB */ 2952 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2953 FETCH(r1, 1) @ r1<- field ref BBBB 2954 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2955 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2956 cmp r0, #0 @ is resolved entry null? 2957 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2958.LOP_SGET_SHORT_finish: @ field ptr in r0 2959 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2960 SMP_DMB 0 @ acquiring load 2961 mov r2, rINST, lsr #8 @ r2<- AA 2962 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2963 SET_VREG(r1, r2) @ fp[AA]<- r1 2964 GET_INST_OPCODE(ip) @ extract opcode from rINST 2965 GOTO_OPCODE(ip) @ jump to next instruction 2966 2967 2968/* ------------------------------ */ 2969 .balign 64 2970.L_OP_SPUT: /* 0x67 */ 2971/* File: armv5te/OP_SPUT.S */ 2972 /* 2973 * General 32-bit SPUT handler. 2974 * 2975 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2976 */ 2977 /* op vAA, field@BBBB */ 2978 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2979 FETCH(r1, 1) @ r1<- field ref BBBB 2980 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2981 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2982 cmp r0, #0 @ is resolved entry null? 2983 beq .LOP_SPUT_resolve @ yes, do resolve 2984.LOP_SPUT_finish: @ field ptr in r0 2985 mov r2, rINST, lsr #8 @ r2<- AA 2986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2987 GET_VREG(r1, r2) @ r1<- fp[AA] 2988 GET_INST_OPCODE(ip) @ extract opcode from rINST 2989 SMP_DMB 0 @ releasing store 2990 str r1, [r0, #offStaticField_value] @ field<- vAA 2991 GOTO_OPCODE(ip) @ jump to next instruction 2992 2993/* ------------------------------ */ 2994 .balign 64 2995.L_OP_SPUT_WIDE: /* 0x68 */ 2996/* File: armv5te/OP_SPUT_WIDE.S */ 2997 /* 2998 * 64-bit SPUT handler. 2999 */ 3000 /* sput-wide vAA, field@BBBB */ 3001 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3002 FETCH(r1, 1) @ r1<- field ref BBBB 3003 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3004 mov r9, rINST, lsr #8 @ r9<- AA 3005 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3006 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3007 cmp r2, #0 @ is resolved entry null? 3008 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3009.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3010 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3011 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3012 GET_INST_OPCODE(r10) @ extract opcode from rINST 3013 .if 0 3014 add r2, r2, #offStaticField_value @ r2<- pointer to data 3015 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3016 .else 3017 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3018 .endif 3019 GOTO_OPCODE(r10) @ jump to next instruction 3020 3021/* ------------------------------ */ 3022 .balign 64 3023.L_OP_SPUT_OBJECT: /* 0x69 */ 3024/* File: armv5te/OP_SPUT_OBJECT.S */ 3025/* File: armv5te/OP_SPUT.S */ 3026 /* 3027 * General 32-bit SPUT handler. 3028 * 3029 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3030 */ 3031 /* op vAA, field@BBBB */ 3032 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3033 FETCH(r1, 1) @ r1<- field ref BBBB 3034 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3035 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3036 cmp r0, #0 @ is resolved entry null? 3037 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3038.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3039 mov r2, rINST, lsr #8 @ r2<- AA 3040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3041 GET_VREG(r1, r2) @ r1<- fp[AA] 3042 GET_INST_OPCODE(ip) @ extract opcode from rINST 3043 SMP_DMB 0 @ releasing store 3044 str r1, [r0, #offStaticField_value] @ field<- vAA 3045 GOTO_OPCODE(ip) @ jump to next instruction 3046 3047 3048/* ------------------------------ */ 3049 .balign 64 3050.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3051/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3052/* File: armv5te/OP_SPUT.S */ 3053 /* 3054 * General 32-bit SPUT handler. 3055 * 3056 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3057 */ 3058 /* op vAA, field@BBBB */ 3059 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3060 FETCH(r1, 1) @ r1<- field ref BBBB 3061 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3062 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3063 cmp r0, #0 @ is resolved entry null? 3064 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3065.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3066 mov r2, rINST, lsr #8 @ r2<- AA 3067 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3068 GET_VREG(r1, r2) @ r1<- fp[AA] 3069 GET_INST_OPCODE(ip) @ extract opcode from rINST 3070 SMP_DMB 0 @ releasing store 3071 str r1, [r0, #offStaticField_value] @ field<- vAA 3072 GOTO_OPCODE(ip) @ jump to next instruction 3073 3074 3075/* ------------------------------ */ 3076 .balign 64 3077.L_OP_SPUT_BYTE: /* 0x6b */ 3078/* File: armv5te/OP_SPUT_BYTE.S */ 3079/* File: armv5te/OP_SPUT.S */ 3080 /* 3081 * General 32-bit SPUT handler. 3082 * 3083 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3084 */ 3085 /* op vAA, field@BBBB */ 3086 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3087 FETCH(r1, 1) @ r1<- field ref BBBB 3088 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3089 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3090 cmp r0, #0 @ is resolved entry null? 3091 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3092.LOP_SPUT_BYTE_finish: @ field ptr in r0 3093 mov r2, rINST, lsr #8 @ r2<- AA 3094 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3095 GET_VREG(r1, r2) @ r1<- fp[AA] 3096 GET_INST_OPCODE(ip) @ extract opcode from rINST 3097 SMP_DMB 0 @ releasing store 3098 str r1, [r0, #offStaticField_value] @ field<- vAA 3099 GOTO_OPCODE(ip) @ jump to next instruction 3100 3101 3102/* ------------------------------ */ 3103 .balign 64 3104.L_OP_SPUT_CHAR: /* 0x6c */ 3105/* File: armv5te/OP_SPUT_CHAR.S */ 3106/* File: armv5te/OP_SPUT.S */ 3107 /* 3108 * General 32-bit SPUT handler. 3109 * 3110 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3111 */ 3112 /* op vAA, field@BBBB */ 3113 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3114 FETCH(r1, 1) @ r1<- field ref BBBB 3115 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3116 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3117 cmp r0, #0 @ is resolved entry null? 3118 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3119.LOP_SPUT_CHAR_finish: @ field ptr in r0 3120 mov r2, rINST, lsr #8 @ r2<- AA 3121 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3122 GET_VREG(r1, r2) @ r1<- fp[AA] 3123 GET_INST_OPCODE(ip) @ extract opcode from rINST 3124 SMP_DMB 0 @ releasing store 3125 str r1, [r0, #offStaticField_value] @ field<- vAA 3126 GOTO_OPCODE(ip) @ jump to next instruction 3127 3128 3129/* ------------------------------ */ 3130 .balign 64 3131.L_OP_SPUT_SHORT: /* 0x6d */ 3132/* File: armv5te/OP_SPUT_SHORT.S */ 3133/* File: armv5te/OP_SPUT.S */ 3134 /* 3135 * General 32-bit SPUT handler. 3136 * 3137 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3138 */ 3139 /* op vAA, field@BBBB */ 3140 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3141 FETCH(r1, 1) @ r1<- field ref BBBB 3142 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3143 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3144 cmp r0, #0 @ is resolved entry null? 3145 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3146.LOP_SPUT_SHORT_finish: @ field ptr in r0 3147 mov r2, rINST, lsr #8 @ r2<- AA 3148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3149 GET_VREG(r1, r2) @ r1<- fp[AA] 3150 GET_INST_OPCODE(ip) @ extract opcode from rINST 3151 SMP_DMB 0 @ releasing store 3152 str r1, [r0, #offStaticField_value] @ field<- vAA 3153 GOTO_OPCODE(ip) @ jump to next instruction 3154 3155 3156/* ------------------------------ */ 3157 .balign 64 3158.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3159/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3160 /* 3161 * Handle a virtual method call. 3162 * 3163 * for: invoke-virtual, invoke-virtual/range 3164 */ 3165 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3166 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3167 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3168 FETCH(r1, 1) @ r1<- BBBB 3169 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3170 FETCH(r10, 2) @ r10<- GFED or CCCC 3171 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3172 .if (!0) 3173 and r10, r10, #15 @ r10<- D (or stays CCCC) 3174 .endif 3175 cmp r0, #0 @ already resolved? 3176 EXPORT_PC() @ must export for invoke 3177 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3178 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3179 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3180 mov r2, #METHOD_VIRTUAL @ resolver method type 3181 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3182 cmp r0, #0 @ got null? 3183 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3184 b common_exceptionThrown @ yes, handle exception 3185 3186/* ------------------------------ */ 3187 .balign 64 3188.L_OP_INVOKE_SUPER: /* 0x6f */ 3189/* File: armv5te/OP_INVOKE_SUPER.S */ 3190 /* 3191 * Handle a "super" method call. 3192 * 3193 * for: invoke-super, invoke-super/range 3194 */ 3195 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3196 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3197 FETCH(r10, 2) @ r10<- GFED or CCCC 3198 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3199 .if (!0) 3200 and r10, r10, #15 @ r10<- D (or stays CCCC) 3201 .endif 3202 FETCH(r1, 1) @ r1<- BBBB 3203 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3204 GET_VREG(r2, r10) @ r2<- "this" ptr 3205 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3206 cmp r2, #0 @ null "this"? 3207 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3208 beq common_errNullObject @ null "this", throw exception 3209 cmp r0, #0 @ already resolved? 3210 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3211 EXPORT_PC() @ must export for invoke 3212 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3213 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3214 3215/* ------------------------------ */ 3216 .balign 64 3217.L_OP_INVOKE_DIRECT: /* 0x70 */ 3218/* File: armv5te/OP_INVOKE_DIRECT.S */ 3219 /* 3220 * Handle a direct method call. 3221 * 3222 * (We could defer the "is 'this' pointer null" test to the common 3223 * method invocation code, and use a flag to indicate that static 3224 * calls don't count. If we do this as part of copying the arguments 3225 * out we could avoiding loading the first arg twice.) 3226 * 3227 * for: invoke-direct, invoke-direct/range 3228 */ 3229 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3230 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3231 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3232 FETCH(r1, 1) @ r1<- BBBB 3233 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3234 FETCH(r10, 2) @ r10<- GFED or CCCC 3235 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3236 .if (!0) 3237 and r10, r10, #15 @ r10<- D (or stays CCCC) 3238 .endif 3239 cmp r0, #0 @ already resolved? 3240 EXPORT_PC() @ must export for invoke 3241 GET_VREG(r2, r10) @ r2<- "this" ptr 3242 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3243.LOP_INVOKE_DIRECT_finish: 3244 cmp r2, #0 @ null "this" ref? 3245 bne common_invokeMethodNoRange @ no, continue on 3246 b common_errNullObject @ yes, throw exception 3247 3248/* ------------------------------ */ 3249 .balign 64 3250.L_OP_INVOKE_STATIC: /* 0x71 */ 3251/* File: armv5te/OP_INVOKE_STATIC.S */ 3252 /* 3253 * Handle a static method call. 3254 * 3255 * for: invoke-static, invoke-static/range 3256 */ 3257 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3258 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3259 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3260 FETCH(r1, 1) @ r1<- BBBB 3261 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3262 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3263 cmp r0, #0 @ already resolved? 3264 EXPORT_PC() @ must export for invoke 3265 bne common_invokeMethodNoRange @ yes, continue on 32660: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3267 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3268 mov r2, #METHOD_STATIC @ resolver method type 3269 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3270 cmp r0, #0 @ got null? 3271 bne common_invokeMethodNoRange @ no, continue 3272 b common_exceptionThrown @ yes, handle exception 3273 3274/* ------------------------------ */ 3275 .balign 64 3276.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3277/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3278 /* 3279 * Handle an interface method call. 3280 * 3281 * for: invoke-interface, invoke-interface/range 3282 */ 3283 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3284 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3285 FETCH(r2, 2) @ r2<- FEDC or CCCC 3286 FETCH(r1, 1) @ r1<- BBBB 3287 .if (!0) 3288 and r2, r2, #15 @ r2<- C (or stays CCCC) 3289 .endif 3290 EXPORT_PC() @ must export for invoke 3291 GET_VREG(r0, r2) @ r0<- first arg ("this") 3292 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3293 cmp r0, #0 @ null obj? 3294 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3295 beq common_errNullObject @ yes, fail 3296 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3297 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3298 cmp r0, #0 @ failed? 3299 beq common_exceptionThrown @ yes, handle exception 3300 b common_invokeMethodNoRange @ jump to common handler 3301 3302/* ------------------------------ */ 3303 .balign 64 3304.L_OP_UNUSED_73: /* 0x73 */ 3305/* File: armv5te/OP_UNUSED_73.S */ 3306/* File: armv5te/unused.S */ 3307 bl common_abort 3308 3309 3310/* ------------------------------ */ 3311 .balign 64 3312.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3313/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3314/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3315 /* 3316 * Handle a virtual method call. 3317 * 3318 * for: invoke-virtual, invoke-virtual/range 3319 */ 3320 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3321 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3322 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3323 FETCH(r1, 1) @ r1<- BBBB 3324 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3325 FETCH(r10, 2) @ r10<- GFED or CCCC 3326 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3327 .if (!1) 3328 and r10, r10, #15 @ r10<- D (or stays CCCC) 3329 .endif 3330 cmp r0, #0 @ already resolved? 3331 EXPORT_PC() @ must export for invoke 3332 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3333 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3334 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3335 mov r2, #METHOD_VIRTUAL @ resolver method type 3336 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3337 cmp r0, #0 @ got null? 3338 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3339 b common_exceptionThrown @ yes, handle exception 3340 3341 3342/* ------------------------------ */ 3343 .balign 64 3344.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3345/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3346/* File: armv5te/OP_INVOKE_SUPER.S */ 3347 /* 3348 * Handle a "super" method call. 3349 * 3350 * for: invoke-super, invoke-super/range 3351 */ 3352 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3353 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3354 FETCH(r10, 2) @ r10<- GFED or CCCC 3355 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3356 .if (!1) 3357 and r10, r10, #15 @ r10<- D (or stays CCCC) 3358 .endif 3359 FETCH(r1, 1) @ r1<- BBBB 3360 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3361 GET_VREG(r2, r10) @ r2<- "this" ptr 3362 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3363 cmp r2, #0 @ null "this"? 3364 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3365 beq common_errNullObject @ null "this", throw exception 3366 cmp r0, #0 @ already resolved? 3367 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3368 EXPORT_PC() @ must export for invoke 3369 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3370 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3371 3372 3373/* ------------------------------ */ 3374 .balign 64 3375.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3376/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3377/* File: armv5te/OP_INVOKE_DIRECT.S */ 3378 /* 3379 * Handle a direct method call. 3380 * 3381 * (We could defer the "is 'this' pointer null" test to the common 3382 * method invocation code, and use a flag to indicate that static 3383 * calls don't count. If we do this as part of copying the arguments 3384 * out we could avoiding loading the first arg twice.) 3385 * 3386 * for: invoke-direct, invoke-direct/range 3387 */ 3388 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3389 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3390 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3391 FETCH(r1, 1) @ r1<- BBBB 3392 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3393 FETCH(r10, 2) @ r10<- GFED or CCCC 3394 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3395 .if (!1) 3396 and r10, r10, #15 @ r10<- D (or stays CCCC) 3397 .endif 3398 cmp r0, #0 @ already resolved? 3399 EXPORT_PC() @ must export for invoke 3400 GET_VREG(r2, r10) @ r2<- "this" ptr 3401 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3402.LOP_INVOKE_DIRECT_RANGE_finish: 3403 cmp r2, #0 @ null "this" ref? 3404 bne common_invokeMethodRange @ no, continue on 3405 b common_errNullObject @ yes, throw exception 3406 3407 3408/* ------------------------------ */ 3409 .balign 64 3410.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3411/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3412/* File: armv5te/OP_INVOKE_STATIC.S */ 3413 /* 3414 * Handle a static method call. 3415 * 3416 * for: invoke-static, invoke-static/range 3417 */ 3418 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3419 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3420 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3421 FETCH(r1, 1) @ r1<- BBBB 3422 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3423 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3424 cmp r0, #0 @ already resolved? 3425 EXPORT_PC() @ must export for invoke 3426 bne common_invokeMethodRange @ yes, continue on 34270: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3428 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3429 mov r2, #METHOD_STATIC @ resolver method type 3430 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3431 cmp r0, #0 @ got null? 3432 bne common_invokeMethodRange @ no, continue 3433 b common_exceptionThrown @ yes, handle exception 3434 3435 3436/* ------------------------------ */ 3437 .balign 64 3438.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3439/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3440/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3441 /* 3442 * Handle an interface method call. 3443 * 3444 * for: invoke-interface, invoke-interface/range 3445 */ 3446 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3447 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3448 FETCH(r2, 2) @ r2<- FEDC or CCCC 3449 FETCH(r1, 1) @ r1<- BBBB 3450 .if (!1) 3451 and r2, r2, #15 @ r2<- C (or stays CCCC) 3452 .endif 3453 EXPORT_PC() @ must export for invoke 3454 GET_VREG(r0, r2) @ r0<- first arg ("this") 3455 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3456 cmp r0, #0 @ null obj? 3457 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3458 beq common_errNullObject @ yes, fail 3459 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3460 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3461 cmp r0, #0 @ failed? 3462 beq common_exceptionThrown @ yes, handle exception 3463 b common_invokeMethodRange @ jump to common handler 3464 3465 3466/* ------------------------------ */ 3467 .balign 64 3468.L_OP_UNUSED_79: /* 0x79 */ 3469/* File: armv5te/OP_UNUSED_79.S */ 3470/* File: armv5te/unused.S */ 3471 bl common_abort 3472 3473 3474/* ------------------------------ */ 3475 .balign 64 3476.L_OP_UNUSED_7A: /* 0x7a */ 3477/* File: armv5te/OP_UNUSED_7A.S */ 3478/* File: armv5te/unused.S */ 3479 bl common_abort 3480 3481 3482/* ------------------------------ */ 3483 .balign 64 3484.L_OP_NEG_INT: /* 0x7b */ 3485/* File: armv5te/OP_NEG_INT.S */ 3486/* File: armv5te/unop.S */ 3487 /* 3488 * Generic 32-bit unary operation. Provide an "instr" line that 3489 * specifies an instruction that performs "result = op r0". 3490 * This could be an ARM instruction or a function call. 3491 * 3492 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3493 * int-to-byte, int-to-char, int-to-short 3494 */ 3495 /* unop vA, vB */ 3496 mov r3, rINST, lsr #12 @ r3<- B 3497 mov r9, rINST, lsr #8 @ r9<- A+ 3498 GET_VREG(r0, r3) @ r0<- vB 3499 and r9, r9, #15 3500 @ optional op; may set condition codes 3501 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3502 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3503 GET_INST_OPCODE(ip) @ extract opcode from rINST 3504 SET_VREG(r0, r9) @ vAA<- r0 3505 GOTO_OPCODE(ip) @ jump to next instruction 3506 /* 9-10 instructions */ 3507 3508 3509/* ------------------------------ */ 3510 .balign 64 3511.L_OP_NOT_INT: /* 0x7c */ 3512/* File: armv5te/OP_NOT_INT.S */ 3513/* File: armv5te/unop.S */ 3514 /* 3515 * Generic 32-bit unary operation. Provide an "instr" line that 3516 * specifies an instruction that performs "result = op r0". 3517 * This could be an ARM instruction or a function call. 3518 * 3519 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3520 * int-to-byte, int-to-char, int-to-short 3521 */ 3522 /* unop vA, vB */ 3523 mov r3, rINST, lsr #12 @ r3<- B 3524 mov r9, rINST, lsr #8 @ r9<- A+ 3525 GET_VREG(r0, r3) @ r0<- vB 3526 and r9, r9, #15 3527 @ optional op; may set condition codes 3528 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3529 mvn r0, r0 @ r0<- op, r0-r3 changed 3530 GET_INST_OPCODE(ip) @ extract opcode from rINST 3531 SET_VREG(r0, r9) @ vAA<- r0 3532 GOTO_OPCODE(ip) @ jump to next instruction 3533 /* 9-10 instructions */ 3534 3535 3536/* ------------------------------ */ 3537 .balign 64 3538.L_OP_NEG_LONG: /* 0x7d */ 3539/* File: armv5te/OP_NEG_LONG.S */ 3540/* File: armv5te/unopWide.S */ 3541 /* 3542 * Generic 64-bit unary operation. Provide an "instr" line that 3543 * specifies an instruction that performs "result = op r0/r1". 3544 * This could be an ARM instruction or a function call. 3545 * 3546 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3547 */ 3548 /* unop vA, vB */ 3549 mov r9, rINST, lsr #8 @ r9<- A+ 3550 mov r3, rINST, lsr #12 @ r3<- B 3551 and r9, r9, #15 3552 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3553 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3554 ldmia r3, {r0-r1} @ r0/r1<- vAA 3555 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3556 rsbs r0, r0, #0 @ optional op; may set condition codes 3557 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3558 GET_INST_OPCODE(ip) @ extract opcode from rINST 3559 stmia r9, {r0-r1} @ vAA<- r0/r1 3560 GOTO_OPCODE(ip) @ jump to next instruction 3561 /* 12-13 instructions */ 3562 3563 3564/* ------------------------------ */ 3565 .balign 64 3566.L_OP_NOT_LONG: /* 0x7e */ 3567/* File: armv5te/OP_NOT_LONG.S */ 3568/* File: armv5te/unopWide.S */ 3569 /* 3570 * Generic 64-bit unary operation. Provide an "instr" line that 3571 * specifies an instruction that performs "result = op r0/r1". 3572 * This could be an ARM instruction or a function call. 3573 * 3574 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3575 */ 3576 /* unop vA, vB */ 3577 mov r9, rINST, lsr #8 @ r9<- A+ 3578 mov r3, rINST, lsr #12 @ r3<- B 3579 and r9, r9, #15 3580 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3581 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3582 ldmia r3, {r0-r1} @ r0/r1<- vAA 3583 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3584 mvn r0, r0 @ optional op; may set condition codes 3585 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3586 GET_INST_OPCODE(ip) @ extract opcode from rINST 3587 stmia r9, {r0-r1} @ vAA<- r0/r1 3588 GOTO_OPCODE(ip) @ jump to next instruction 3589 /* 12-13 instructions */ 3590 3591 3592/* ------------------------------ */ 3593 .balign 64 3594.L_OP_NEG_FLOAT: /* 0x7f */ 3595/* File: armv5te/OP_NEG_FLOAT.S */ 3596/* File: armv5te/unop.S */ 3597 /* 3598 * Generic 32-bit unary operation. Provide an "instr" line that 3599 * specifies an instruction that performs "result = op r0". 3600 * This could be an ARM instruction or a function call. 3601 * 3602 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3603 * int-to-byte, int-to-char, int-to-short 3604 */ 3605 /* unop vA, vB */ 3606 mov r3, rINST, lsr #12 @ r3<- B 3607 mov r9, rINST, lsr #8 @ r9<- A+ 3608 GET_VREG(r0, r3) @ r0<- vB 3609 and r9, r9, #15 3610 @ optional op; may set condition codes 3611 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3612 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3613 GET_INST_OPCODE(ip) @ extract opcode from rINST 3614 SET_VREG(r0, r9) @ vAA<- r0 3615 GOTO_OPCODE(ip) @ jump to next instruction 3616 /* 9-10 instructions */ 3617 3618 3619/* ------------------------------ */ 3620 .balign 64 3621.L_OP_NEG_DOUBLE: /* 0x80 */ 3622/* File: armv5te/OP_NEG_DOUBLE.S */ 3623/* File: armv5te/unopWide.S */ 3624 /* 3625 * Generic 64-bit unary operation. Provide an "instr" line that 3626 * specifies an instruction that performs "result = op r0/r1". 3627 * This could be an ARM instruction or a function call. 3628 * 3629 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3630 */ 3631 /* unop vA, vB */ 3632 mov r9, rINST, lsr #8 @ r9<- A+ 3633 mov r3, rINST, lsr #12 @ r3<- B 3634 and r9, r9, #15 3635 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3636 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3637 ldmia r3, {r0-r1} @ r0/r1<- vAA 3638 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3639 @ optional op; may set condition codes 3640 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3641 GET_INST_OPCODE(ip) @ extract opcode from rINST 3642 stmia r9, {r0-r1} @ vAA<- r0/r1 3643 GOTO_OPCODE(ip) @ jump to next instruction 3644 /* 12-13 instructions */ 3645 3646 3647/* ------------------------------ */ 3648 .balign 64 3649.L_OP_INT_TO_LONG: /* 0x81 */ 3650/* File: armv5te/OP_INT_TO_LONG.S */ 3651/* File: armv5te/unopWider.S */ 3652 /* 3653 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3654 * that specifies an instruction that performs "result = op r0", where 3655 * "result" is a 64-bit quantity in r0/r1. 3656 * 3657 * For: int-to-long, int-to-double, float-to-long, float-to-double 3658 */ 3659 /* unop vA, vB */ 3660 mov r9, rINST, lsr #8 @ r9<- A+ 3661 mov r3, rINST, lsr #12 @ r3<- B 3662 and r9, r9, #15 3663 GET_VREG(r0, r3) @ r0<- vB 3664 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3665 @ optional op; may set condition codes 3666 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3667 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3668 GET_INST_OPCODE(ip) @ extract opcode from rINST 3669 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3670 GOTO_OPCODE(ip) @ jump to next instruction 3671 /* 10-11 instructions */ 3672 3673 3674/* ------------------------------ */ 3675 .balign 64 3676.L_OP_INT_TO_FLOAT: /* 0x82 */ 3677/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3678/* File: arm-vfp/funop.S */ 3679 /* 3680 * Generic 32-bit unary floating-point operation. Provide an "instr" 3681 * line that specifies an instruction that performs "s1 = op s0". 3682 * 3683 * for: int-to-float, float-to-int 3684 */ 3685 /* unop vA, vB */ 3686 mov r3, rINST, lsr #12 @ r3<- B 3687 mov r9, rINST, lsr #8 @ r9<- A+ 3688 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3689 flds s0, [r3] @ s0<- vB 3690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3691 and r9, r9, #15 @ r9<- A 3692 fsitos s1, s0 @ s1<- op 3693 GET_INST_OPCODE(ip) @ extract opcode from rINST 3694 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3695 fsts s1, [r9] @ vA<- s1 3696 GOTO_OPCODE(ip) @ jump to next instruction 3697 3698 3699/* ------------------------------ */ 3700 .balign 64 3701.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3702/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3703/* File: arm-vfp/funopWider.S */ 3704 /* 3705 * Generic 32bit-to-64bit floating point unary operation. Provide an 3706 * "instr" line that specifies an instruction that performs "d0 = op s0". 3707 * 3708 * For: int-to-double, float-to-double 3709 */ 3710 /* unop vA, vB */ 3711 mov r3, rINST, lsr #12 @ r3<- B 3712 mov r9, rINST, lsr #8 @ r9<- A+ 3713 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3714 flds s0, [r3] @ s0<- vB 3715 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3716 and r9, r9, #15 @ r9<- A 3717 fsitod d0, s0 @ d0<- op 3718 GET_INST_OPCODE(ip) @ extract opcode from rINST 3719 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3720 fstd d0, [r9] @ vA<- d0 3721 GOTO_OPCODE(ip) @ jump to next instruction 3722 3723 3724/* ------------------------------ */ 3725 .balign 64 3726.L_OP_LONG_TO_INT: /* 0x84 */ 3727/* File: armv5te/OP_LONG_TO_INT.S */ 3728/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3729/* File: armv5te/OP_MOVE.S */ 3730 /* for move, move-object, long-to-int */ 3731 /* op vA, vB */ 3732 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3733 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3734 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3735 GET_VREG(r2, r1) @ r2<- fp[B] 3736 and r0, r0, #15 3737 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3738 SET_VREG(r2, r0) @ fp[A]<- r2 3739 GOTO_OPCODE(ip) @ execute next instruction 3740 3741 3742/* ------------------------------ */ 3743 .balign 64 3744.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3745/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3746/* File: armv5te/unopNarrower.S */ 3747 /* 3748 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3749 * that specifies an instruction that performs "result = op r0/r1", where 3750 * "result" is a 32-bit quantity in r0. 3751 * 3752 * For: long-to-float, double-to-int, double-to-float 3753 * 3754 * (This would work for long-to-int, but that instruction is actually 3755 * an exact match for OP_MOVE.) 3756 */ 3757 /* unop vA, vB */ 3758 mov r3, rINST, lsr #12 @ r3<- B 3759 mov r9, rINST, lsr #8 @ r9<- A+ 3760 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3761 and r9, r9, #15 3762 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3763 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3764 @ optional op; may set condition codes 3765 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3766 GET_INST_OPCODE(ip) @ extract opcode from rINST 3767 SET_VREG(r0, r9) @ vA<- r0 3768 GOTO_OPCODE(ip) @ jump to next instruction 3769 /* 10-11 instructions */ 3770 3771 3772/* ------------------------------ */ 3773 .balign 64 3774.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3775/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3776/* File: armv5te/unopWide.S */ 3777 /* 3778 * Generic 64-bit unary operation. Provide an "instr" line that 3779 * specifies an instruction that performs "result = op r0/r1". 3780 * This could be an ARM instruction or a function call. 3781 * 3782 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3783 */ 3784 /* unop vA, vB */ 3785 mov r9, rINST, lsr #8 @ r9<- A+ 3786 mov r3, rINST, lsr #12 @ r3<- B 3787 and r9, r9, #15 3788 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3789 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3790 ldmia r3, {r0-r1} @ r0/r1<- vAA 3791 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3792 @ optional op; may set condition codes 3793 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3794 GET_INST_OPCODE(ip) @ extract opcode from rINST 3795 stmia r9, {r0-r1} @ vAA<- r0/r1 3796 GOTO_OPCODE(ip) @ jump to next instruction 3797 /* 12-13 instructions */ 3798 3799 3800/* ------------------------------ */ 3801 .balign 64 3802.L_OP_FLOAT_TO_INT: /* 0x87 */ 3803/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3804/* File: arm-vfp/funop.S */ 3805 /* 3806 * Generic 32-bit unary floating-point operation. Provide an "instr" 3807 * line that specifies an instruction that performs "s1 = op s0". 3808 * 3809 * for: int-to-float, float-to-int 3810 */ 3811 /* unop vA, vB */ 3812 mov r3, rINST, lsr #12 @ r3<- B 3813 mov r9, rINST, lsr #8 @ r9<- A+ 3814 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3815 flds s0, [r3] @ s0<- vB 3816 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3817 and r9, r9, #15 @ r9<- A 3818 ftosizs s1, s0 @ s1<- op 3819 GET_INST_OPCODE(ip) @ extract opcode from rINST 3820 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3821 fsts s1, [r9] @ vA<- s1 3822 GOTO_OPCODE(ip) @ jump to next instruction 3823 3824 3825/* ------------------------------ */ 3826 .balign 64 3827.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3828/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3829@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3830/* File: armv5te/unopWider.S */ 3831 /* 3832 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3833 * that specifies an instruction that performs "result = op r0", where 3834 * "result" is a 64-bit quantity in r0/r1. 3835 * 3836 * For: int-to-long, int-to-double, float-to-long, float-to-double 3837 */ 3838 /* unop vA, vB */ 3839 mov r9, rINST, lsr #8 @ r9<- A+ 3840 mov r3, rINST, lsr #12 @ r3<- B 3841 and r9, r9, #15 3842 GET_VREG(r0, r3) @ r0<- vB 3843 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3844 @ optional op; may set condition codes 3845 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3846 bl f2l_doconv @ r0<- op, r0-r3 changed 3847 GET_INST_OPCODE(ip) @ extract opcode from rINST 3848 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3849 GOTO_OPCODE(ip) @ jump to next instruction 3850 /* 10-11 instructions */ 3851 3852 3853 3854/* ------------------------------ */ 3855 .balign 64 3856.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3857/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3858/* File: arm-vfp/funopWider.S */ 3859 /* 3860 * Generic 32bit-to-64bit floating point unary operation. Provide an 3861 * "instr" line that specifies an instruction that performs "d0 = op s0". 3862 * 3863 * For: int-to-double, float-to-double 3864 */ 3865 /* unop vA, vB */ 3866 mov r3, rINST, lsr #12 @ r3<- B 3867 mov r9, rINST, lsr #8 @ r9<- A+ 3868 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3869 flds s0, [r3] @ s0<- vB 3870 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3871 and r9, r9, #15 @ r9<- A 3872 fcvtds d0, s0 @ d0<- op 3873 GET_INST_OPCODE(ip) @ extract opcode from rINST 3874 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3875 fstd d0, [r9] @ vA<- d0 3876 GOTO_OPCODE(ip) @ jump to next instruction 3877 3878 3879/* ------------------------------ */ 3880 .balign 64 3881.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3882/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3883/* File: arm-vfp/funopNarrower.S */ 3884 /* 3885 * Generic 64bit-to-32bit unary floating point operation. Provide an 3886 * "instr" line that specifies an instruction that performs "s0 = op d0". 3887 * 3888 * For: double-to-int, double-to-float 3889 */ 3890 /* unop vA, vB */ 3891 mov r3, rINST, lsr #12 @ r3<- B 3892 mov r9, rINST, lsr #8 @ r9<- A+ 3893 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3894 fldd d0, [r3] @ d0<- vB 3895 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3896 and r9, r9, #15 @ r9<- A 3897 ftosizd s0, d0 @ s0<- op 3898 GET_INST_OPCODE(ip) @ extract opcode from rINST 3899 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3900 fsts s0, [r9] @ vA<- s0 3901 GOTO_OPCODE(ip) @ jump to next instruction 3902 3903 3904/* ------------------------------ */ 3905 .balign 64 3906.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3907/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3908@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3909/* File: armv5te/unopWide.S */ 3910 /* 3911 * Generic 64-bit unary operation. Provide an "instr" line that 3912 * specifies an instruction that performs "result = op r0/r1". 3913 * This could be an ARM instruction or a function call. 3914 * 3915 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3916 */ 3917 /* unop vA, vB */ 3918 mov r9, rINST, lsr #8 @ r9<- A+ 3919 mov r3, rINST, lsr #12 @ r3<- B 3920 and r9, r9, #15 3921 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3922 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3923 ldmia r3, {r0-r1} @ r0/r1<- vAA 3924 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3925 @ optional op; may set condition codes 3926 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3927 GET_INST_OPCODE(ip) @ extract opcode from rINST 3928 stmia r9, {r0-r1} @ vAA<- r0/r1 3929 GOTO_OPCODE(ip) @ jump to next instruction 3930 /* 12-13 instructions */ 3931 3932 3933 3934/* ------------------------------ */ 3935 .balign 64 3936.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3937/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3938/* File: arm-vfp/funopNarrower.S */ 3939 /* 3940 * Generic 64bit-to-32bit unary floating point operation. Provide an 3941 * "instr" line that specifies an instruction that performs "s0 = op d0". 3942 * 3943 * For: double-to-int, double-to-float 3944 */ 3945 /* unop vA, vB */ 3946 mov r3, rINST, lsr #12 @ r3<- B 3947 mov r9, rINST, lsr #8 @ r9<- A+ 3948 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3949 fldd d0, [r3] @ d0<- vB 3950 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3951 and r9, r9, #15 @ r9<- A 3952 fcvtsd s0, d0 @ s0<- op 3953 GET_INST_OPCODE(ip) @ extract opcode from rINST 3954 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3955 fsts s0, [r9] @ vA<- s0 3956 GOTO_OPCODE(ip) @ jump to next instruction 3957 3958 3959/* ------------------------------ */ 3960 .balign 64 3961.L_OP_INT_TO_BYTE: /* 0x8d */ 3962/* File: armv5te/OP_INT_TO_BYTE.S */ 3963/* File: armv5te/unop.S */ 3964 /* 3965 * Generic 32-bit unary operation. Provide an "instr" line that 3966 * specifies an instruction that performs "result = op r0". 3967 * This could be an ARM instruction or a function call. 3968 * 3969 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3970 * int-to-byte, int-to-char, int-to-short 3971 */ 3972 /* unop vA, vB */ 3973 mov r3, rINST, lsr #12 @ r3<- B 3974 mov r9, rINST, lsr #8 @ r9<- A+ 3975 GET_VREG(r0, r3) @ r0<- vB 3976 and r9, r9, #15 3977 mov r0, r0, asl #24 @ optional op; may set condition codes 3978 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3979 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3980 GET_INST_OPCODE(ip) @ extract opcode from rINST 3981 SET_VREG(r0, r9) @ vAA<- r0 3982 GOTO_OPCODE(ip) @ jump to next instruction 3983 /* 9-10 instructions */ 3984 3985 3986/* ------------------------------ */ 3987 .balign 64 3988.L_OP_INT_TO_CHAR: /* 0x8e */ 3989/* File: armv5te/OP_INT_TO_CHAR.S */ 3990/* File: armv5te/unop.S */ 3991 /* 3992 * Generic 32-bit unary operation. Provide an "instr" line that 3993 * specifies an instruction that performs "result = op r0". 3994 * This could be an ARM instruction or a function call. 3995 * 3996 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3997 * int-to-byte, int-to-char, int-to-short 3998 */ 3999 /* unop vA, vB */ 4000 mov r3, rINST, lsr #12 @ r3<- B 4001 mov r9, rINST, lsr #8 @ r9<- A+ 4002 GET_VREG(r0, r3) @ r0<- vB 4003 and r9, r9, #15 4004 mov r0, r0, asl #16 @ optional op; may set condition codes 4005 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4006 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4007 GET_INST_OPCODE(ip) @ extract opcode from rINST 4008 SET_VREG(r0, r9) @ vAA<- r0 4009 GOTO_OPCODE(ip) @ jump to next instruction 4010 /* 9-10 instructions */ 4011 4012 4013/* ------------------------------ */ 4014 .balign 64 4015.L_OP_INT_TO_SHORT: /* 0x8f */ 4016/* File: armv5te/OP_INT_TO_SHORT.S */ 4017/* File: armv5te/unop.S */ 4018 /* 4019 * Generic 32-bit unary operation. Provide an "instr" line that 4020 * specifies an instruction that performs "result = op r0". 4021 * This could be an ARM instruction or a function call. 4022 * 4023 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4024 * int-to-byte, int-to-char, int-to-short 4025 */ 4026 /* unop vA, vB */ 4027 mov r3, rINST, lsr #12 @ r3<- B 4028 mov r9, rINST, lsr #8 @ r9<- A+ 4029 GET_VREG(r0, r3) @ r0<- vB 4030 and r9, r9, #15 4031 mov r0, r0, asl #16 @ optional op; may set condition codes 4032 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4033 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4034 GET_INST_OPCODE(ip) @ extract opcode from rINST 4035 SET_VREG(r0, r9) @ vAA<- r0 4036 GOTO_OPCODE(ip) @ jump to next instruction 4037 /* 9-10 instructions */ 4038 4039 4040/* ------------------------------ */ 4041 .balign 64 4042.L_OP_ADD_INT: /* 0x90 */ 4043/* File: armv5te/OP_ADD_INT.S */ 4044/* File: armv5te/binop.S */ 4045 /* 4046 * Generic 32-bit binary operation. Provide an "instr" line that 4047 * specifies an instruction that performs "result = r0 op r1". 4048 * This could be an ARM instruction or a function call. (If the result 4049 * comes back in a register other than r0, you can override "result".) 4050 * 4051 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4052 * vCC (r1). Useful for integer division and modulus. Note that we 4053 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4054 * handles it correctly. 4055 * 4056 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4057 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4058 * mul-float, div-float, rem-float 4059 */ 4060 /* binop vAA, vBB, vCC */ 4061 FETCH(r0, 1) @ r0<- CCBB 4062 mov r9, rINST, lsr #8 @ r9<- AA 4063 mov r3, r0, lsr #8 @ r3<- CC 4064 and r2, r0, #255 @ r2<- BB 4065 GET_VREG(r1, r3) @ r1<- vCC 4066 GET_VREG(r0, r2) @ r0<- vBB 4067 .if 0 4068 cmp r1, #0 @ is second operand zero? 4069 beq common_errDivideByZero 4070 .endif 4071 4072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4073 @ optional op; may set condition codes 4074 add r0, r0, r1 @ r0<- op, r0-r3 changed 4075 GET_INST_OPCODE(ip) @ extract opcode from rINST 4076 SET_VREG(r0, r9) @ vAA<- r0 4077 GOTO_OPCODE(ip) @ jump to next instruction 4078 /* 11-14 instructions */ 4079 4080 4081/* ------------------------------ */ 4082 .balign 64 4083.L_OP_SUB_INT: /* 0x91 */ 4084/* File: armv5te/OP_SUB_INT.S */ 4085/* File: armv5te/binop.S */ 4086 /* 4087 * Generic 32-bit binary operation. Provide an "instr" line that 4088 * specifies an instruction that performs "result = r0 op r1". 4089 * This could be an ARM instruction or a function call. (If the result 4090 * comes back in a register other than r0, you can override "result".) 4091 * 4092 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4093 * vCC (r1). Useful for integer division and modulus. Note that we 4094 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4095 * handles it correctly. 4096 * 4097 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4098 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4099 * mul-float, div-float, rem-float 4100 */ 4101 /* binop vAA, vBB, vCC */ 4102 FETCH(r0, 1) @ r0<- CCBB 4103 mov r9, rINST, lsr #8 @ r9<- AA 4104 mov r3, r0, lsr #8 @ r3<- CC 4105 and r2, r0, #255 @ r2<- BB 4106 GET_VREG(r1, r3) @ r1<- vCC 4107 GET_VREG(r0, r2) @ r0<- vBB 4108 .if 0 4109 cmp r1, #0 @ is second operand zero? 4110 beq common_errDivideByZero 4111 .endif 4112 4113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4114 @ optional op; may set condition codes 4115 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4116 GET_INST_OPCODE(ip) @ extract opcode from rINST 4117 SET_VREG(r0, r9) @ vAA<- r0 4118 GOTO_OPCODE(ip) @ jump to next instruction 4119 /* 11-14 instructions */ 4120 4121 4122/* ------------------------------ */ 4123 .balign 64 4124.L_OP_MUL_INT: /* 0x92 */ 4125/* File: armv5te/OP_MUL_INT.S */ 4126/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4127/* File: armv5te/binop.S */ 4128 /* 4129 * Generic 32-bit binary operation. Provide an "instr" line that 4130 * specifies an instruction that performs "result = r0 op r1". 4131 * This could be an ARM instruction or a function call. (If the result 4132 * comes back in a register other than r0, you can override "result".) 4133 * 4134 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4135 * vCC (r1). Useful for integer division and modulus. Note that we 4136 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4137 * handles it correctly. 4138 * 4139 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4140 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4141 * mul-float, div-float, rem-float 4142 */ 4143 /* binop vAA, vBB, vCC */ 4144 FETCH(r0, 1) @ r0<- CCBB 4145 mov r9, rINST, lsr #8 @ r9<- AA 4146 mov r3, r0, lsr #8 @ r3<- CC 4147 and r2, r0, #255 @ r2<- BB 4148 GET_VREG(r1, r3) @ r1<- vCC 4149 GET_VREG(r0, r2) @ r0<- vBB 4150 .if 0 4151 cmp r1, #0 @ is second operand zero? 4152 beq common_errDivideByZero 4153 .endif 4154 4155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4156 @ optional op; may set condition codes 4157 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4158 GET_INST_OPCODE(ip) @ extract opcode from rINST 4159 SET_VREG(r0, r9) @ vAA<- r0 4160 GOTO_OPCODE(ip) @ jump to next instruction 4161 /* 11-14 instructions */ 4162 4163 4164/* ------------------------------ */ 4165 .balign 64 4166.L_OP_DIV_INT: /* 0x93 */ 4167/* File: armv5te/OP_DIV_INT.S */ 4168/* File: armv5te/binop.S */ 4169 /* 4170 * Generic 32-bit binary operation. Provide an "instr" line that 4171 * specifies an instruction that performs "result = r0 op r1". 4172 * This could be an ARM instruction or a function call. (If the result 4173 * comes back in a register other than r0, you can override "result".) 4174 * 4175 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4176 * vCC (r1). Useful for integer division and modulus. Note that we 4177 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4178 * handles it correctly. 4179 * 4180 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4181 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4182 * mul-float, div-float, rem-float 4183 */ 4184 /* binop vAA, vBB, vCC */ 4185 FETCH(r0, 1) @ r0<- CCBB 4186 mov r9, rINST, lsr #8 @ r9<- AA 4187 mov r3, r0, lsr #8 @ r3<- CC 4188 and r2, r0, #255 @ r2<- BB 4189 GET_VREG(r1, r3) @ r1<- vCC 4190 GET_VREG(r0, r2) @ r0<- vBB 4191 .if 1 4192 cmp r1, #0 @ is second operand zero? 4193 beq common_errDivideByZero 4194 .endif 4195 4196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4197 @ optional op; may set condition codes 4198 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4199 GET_INST_OPCODE(ip) @ extract opcode from rINST 4200 SET_VREG(r0, r9) @ vAA<- r0 4201 GOTO_OPCODE(ip) @ jump to next instruction 4202 /* 11-14 instructions */ 4203 4204 4205/* ------------------------------ */ 4206 .balign 64 4207.L_OP_REM_INT: /* 0x94 */ 4208/* File: armv5te/OP_REM_INT.S */ 4209/* idivmod returns quotient in r0 and remainder in r1 */ 4210/* File: armv5te/binop.S */ 4211 /* 4212 * Generic 32-bit binary operation. Provide an "instr" line that 4213 * specifies an instruction that performs "result = r0 op r1". 4214 * This could be an ARM instruction or a function call. (If the result 4215 * comes back in a register other than r0, you can override "result".) 4216 * 4217 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4218 * vCC (r1). Useful for integer division and modulus. Note that we 4219 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4220 * handles it correctly. 4221 * 4222 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4223 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4224 * mul-float, div-float, rem-float 4225 */ 4226 /* binop vAA, vBB, vCC */ 4227 FETCH(r0, 1) @ r0<- CCBB 4228 mov r9, rINST, lsr #8 @ r9<- AA 4229 mov r3, r0, lsr #8 @ r3<- CC 4230 and r2, r0, #255 @ r2<- BB 4231 GET_VREG(r1, r3) @ r1<- vCC 4232 GET_VREG(r0, r2) @ r0<- vBB 4233 .if 1 4234 cmp r1, #0 @ is second operand zero? 4235 beq common_errDivideByZero 4236 .endif 4237 4238 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4239 @ optional op; may set condition codes 4240 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4241 GET_INST_OPCODE(ip) @ extract opcode from rINST 4242 SET_VREG(r1, r9) @ vAA<- r1 4243 GOTO_OPCODE(ip) @ jump to next instruction 4244 /* 11-14 instructions */ 4245 4246 4247/* ------------------------------ */ 4248 .balign 64 4249.L_OP_AND_INT: /* 0x95 */ 4250/* File: armv5te/OP_AND_INT.S */ 4251/* File: armv5te/binop.S */ 4252 /* 4253 * Generic 32-bit binary operation. Provide an "instr" line that 4254 * specifies an instruction that performs "result = r0 op r1". 4255 * This could be an ARM instruction or a function call. (If the result 4256 * comes back in a register other than r0, you can override "result".) 4257 * 4258 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4259 * vCC (r1). Useful for integer division and modulus. Note that we 4260 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4261 * handles it correctly. 4262 * 4263 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4264 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4265 * mul-float, div-float, rem-float 4266 */ 4267 /* binop vAA, vBB, vCC */ 4268 FETCH(r0, 1) @ r0<- CCBB 4269 mov r9, rINST, lsr #8 @ r9<- AA 4270 mov r3, r0, lsr #8 @ r3<- CC 4271 and r2, r0, #255 @ r2<- BB 4272 GET_VREG(r1, r3) @ r1<- vCC 4273 GET_VREG(r0, r2) @ r0<- vBB 4274 .if 0 4275 cmp r1, #0 @ is second operand zero? 4276 beq common_errDivideByZero 4277 .endif 4278 4279 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4280 @ optional op; may set condition codes 4281 and r0, r0, r1 @ r0<- op, r0-r3 changed 4282 GET_INST_OPCODE(ip) @ extract opcode from rINST 4283 SET_VREG(r0, r9) @ vAA<- r0 4284 GOTO_OPCODE(ip) @ jump to next instruction 4285 /* 11-14 instructions */ 4286 4287 4288/* ------------------------------ */ 4289 .balign 64 4290.L_OP_OR_INT: /* 0x96 */ 4291/* File: armv5te/OP_OR_INT.S */ 4292/* File: armv5te/binop.S */ 4293 /* 4294 * Generic 32-bit binary operation. Provide an "instr" line that 4295 * specifies an instruction that performs "result = r0 op r1". 4296 * This could be an ARM instruction or a function call. (If the result 4297 * comes back in a register other than r0, you can override "result".) 4298 * 4299 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4300 * vCC (r1). Useful for integer division and modulus. Note that we 4301 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4302 * handles it correctly. 4303 * 4304 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4305 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4306 * mul-float, div-float, rem-float 4307 */ 4308 /* binop vAA, vBB, vCC */ 4309 FETCH(r0, 1) @ r0<- CCBB 4310 mov r9, rINST, lsr #8 @ r9<- AA 4311 mov r3, r0, lsr #8 @ r3<- CC 4312 and r2, r0, #255 @ r2<- BB 4313 GET_VREG(r1, r3) @ r1<- vCC 4314 GET_VREG(r0, r2) @ r0<- vBB 4315 .if 0 4316 cmp r1, #0 @ is second operand zero? 4317 beq common_errDivideByZero 4318 .endif 4319 4320 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4321 @ optional op; may set condition codes 4322 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4323 GET_INST_OPCODE(ip) @ extract opcode from rINST 4324 SET_VREG(r0, r9) @ vAA<- r0 4325 GOTO_OPCODE(ip) @ jump to next instruction 4326 /* 11-14 instructions */ 4327 4328 4329/* ------------------------------ */ 4330 .balign 64 4331.L_OP_XOR_INT: /* 0x97 */ 4332/* File: armv5te/OP_XOR_INT.S */ 4333/* File: armv5te/binop.S */ 4334 /* 4335 * Generic 32-bit binary operation. Provide an "instr" line that 4336 * specifies an instruction that performs "result = r0 op r1". 4337 * This could be an ARM instruction or a function call. (If the result 4338 * comes back in a register other than r0, you can override "result".) 4339 * 4340 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4341 * vCC (r1). Useful for integer division and modulus. Note that we 4342 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4343 * handles it correctly. 4344 * 4345 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4346 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4347 * mul-float, div-float, rem-float 4348 */ 4349 /* binop vAA, vBB, vCC */ 4350 FETCH(r0, 1) @ r0<- CCBB 4351 mov r9, rINST, lsr #8 @ r9<- AA 4352 mov r3, r0, lsr #8 @ r3<- CC 4353 and r2, r0, #255 @ r2<- BB 4354 GET_VREG(r1, r3) @ r1<- vCC 4355 GET_VREG(r0, r2) @ r0<- vBB 4356 .if 0 4357 cmp r1, #0 @ is second operand zero? 4358 beq common_errDivideByZero 4359 .endif 4360 4361 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4362 @ optional op; may set condition codes 4363 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4364 GET_INST_OPCODE(ip) @ extract opcode from rINST 4365 SET_VREG(r0, r9) @ vAA<- r0 4366 GOTO_OPCODE(ip) @ jump to next instruction 4367 /* 11-14 instructions */ 4368 4369 4370/* ------------------------------ */ 4371 .balign 64 4372.L_OP_SHL_INT: /* 0x98 */ 4373/* File: armv5te/OP_SHL_INT.S */ 4374/* File: armv5te/binop.S */ 4375 /* 4376 * Generic 32-bit binary operation. Provide an "instr" line that 4377 * specifies an instruction that performs "result = r0 op r1". 4378 * This could be an ARM instruction or a function call. (If the result 4379 * comes back in a register other than r0, you can override "result".) 4380 * 4381 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4382 * vCC (r1). Useful for integer division and modulus. Note that we 4383 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4384 * handles it correctly. 4385 * 4386 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4387 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4388 * mul-float, div-float, rem-float 4389 */ 4390 /* binop vAA, vBB, vCC */ 4391 FETCH(r0, 1) @ r0<- CCBB 4392 mov r9, rINST, lsr #8 @ r9<- AA 4393 mov r3, r0, lsr #8 @ r3<- CC 4394 and r2, r0, #255 @ r2<- BB 4395 GET_VREG(r1, r3) @ r1<- vCC 4396 GET_VREG(r0, r2) @ r0<- vBB 4397 .if 0 4398 cmp r1, #0 @ is second operand zero? 4399 beq common_errDivideByZero 4400 .endif 4401 4402 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4403 and r1, r1, #31 @ optional op; may set condition codes 4404 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4405 GET_INST_OPCODE(ip) @ extract opcode from rINST 4406 SET_VREG(r0, r9) @ vAA<- r0 4407 GOTO_OPCODE(ip) @ jump to next instruction 4408 /* 11-14 instructions */ 4409 4410 4411/* ------------------------------ */ 4412 .balign 64 4413.L_OP_SHR_INT: /* 0x99 */ 4414/* File: armv5te/OP_SHR_INT.S */ 4415/* File: armv5te/binop.S */ 4416 /* 4417 * Generic 32-bit binary operation. Provide an "instr" line that 4418 * specifies an instruction that performs "result = r0 op r1". 4419 * This could be an ARM instruction or a function call. (If the result 4420 * comes back in a register other than r0, you can override "result".) 4421 * 4422 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4423 * vCC (r1). Useful for integer division and modulus. Note that we 4424 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4425 * handles it correctly. 4426 * 4427 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4428 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4429 * mul-float, div-float, rem-float 4430 */ 4431 /* binop vAA, vBB, vCC */ 4432 FETCH(r0, 1) @ r0<- CCBB 4433 mov r9, rINST, lsr #8 @ r9<- AA 4434 mov r3, r0, lsr #8 @ r3<- CC 4435 and r2, r0, #255 @ r2<- BB 4436 GET_VREG(r1, r3) @ r1<- vCC 4437 GET_VREG(r0, r2) @ r0<- vBB 4438 .if 0 4439 cmp r1, #0 @ is second operand zero? 4440 beq common_errDivideByZero 4441 .endif 4442 4443 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4444 and r1, r1, #31 @ optional op; may set condition codes 4445 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4446 GET_INST_OPCODE(ip) @ extract opcode from rINST 4447 SET_VREG(r0, r9) @ vAA<- r0 4448 GOTO_OPCODE(ip) @ jump to next instruction 4449 /* 11-14 instructions */ 4450 4451 4452/* ------------------------------ */ 4453 .balign 64 4454.L_OP_USHR_INT: /* 0x9a */ 4455/* File: armv5te/OP_USHR_INT.S */ 4456/* File: armv5te/binop.S */ 4457 /* 4458 * Generic 32-bit binary operation. Provide an "instr" line that 4459 * specifies an instruction that performs "result = r0 op r1". 4460 * This could be an ARM instruction or a function call. (If the result 4461 * comes back in a register other than r0, you can override "result".) 4462 * 4463 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4464 * vCC (r1). Useful for integer division and modulus. Note that we 4465 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4466 * handles it correctly. 4467 * 4468 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4469 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4470 * mul-float, div-float, rem-float 4471 */ 4472 /* binop vAA, vBB, vCC */ 4473 FETCH(r0, 1) @ r0<- CCBB 4474 mov r9, rINST, lsr #8 @ r9<- AA 4475 mov r3, r0, lsr #8 @ r3<- CC 4476 and r2, r0, #255 @ r2<- BB 4477 GET_VREG(r1, r3) @ r1<- vCC 4478 GET_VREG(r0, r2) @ r0<- vBB 4479 .if 0 4480 cmp r1, #0 @ is second operand zero? 4481 beq common_errDivideByZero 4482 .endif 4483 4484 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4485 and r1, r1, #31 @ optional op; may set condition codes 4486 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4487 GET_INST_OPCODE(ip) @ extract opcode from rINST 4488 SET_VREG(r0, r9) @ vAA<- r0 4489 GOTO_OPCODE(ip) @ jump to next instruction 4490 /* 11-14 instructions */ 4491 4492 4493/* ------------------------------ */ 4494 .balign 64 4495.L_OP_ADD_LONG: /* 0x9b */ 4496/* File: armv5te/OP_ADD_LONG.S */ 4497/* File: armv5te/binopWide.S */ 4498 /* 4499 * Generic 64-bit binary operation. Provide an "instr" line that 4500 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4501 * This could be an ARM instruction or a function call. (If the result 4502 * comes back in a register other than r0, you can override "result".) 4503 * 4504 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4505 * vCC (r1). Useful for integer division and modulus. 4506 * 4507 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4508 * xor-long, add-double, sub-double, mul-double, div-double, 4509 * rem-double 4510 * 4511 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4512 */ 4513 /* binop vAA, vBB, vCC */ 4514 FETCH(r0, 1) @ r0<- CCBB 4515 mov r9, rINST, lsr #8 @ r9<- AA 4516 and r2, r0, #255 @ r2<- BB 4517 mov r3, r0, lsr #8 @ r3<- CC 4518 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4519 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4520 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4521 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4522 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4523 .if 0 4524 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4525 beq common_errDivideByZero 4526 .endif 4527 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4528 4529 adds r0, r0, r2 @ optional op; may set condition codes 4530 adc r1, r1, r3 @ result<- op, r0-r3 changed 4531 GET_INST_OPCODE(ip) @ extract opcode from rINST 4532 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4533 GOTO_OPCODE(ip) @ jump to next instruction 4534 /* 14-17 instructions */ 4535 4536 4537/* ------------------------------ */ 4538 .balign 64 4539.L_OP_SUB_LONG: /* 0x9c */ 4540/* File: armv5te/OP_SUB_LONG.S */ 4541/* File: armv5te/binopWide.S */ 4542 /* 4543 * Generic 64-bit binary operation. Provide an "instr" line that 4544 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4545 * This could be an ARM instruction or a function call. (If the result 4546 * comes back in a register other than r0, you can override "result".) 4547 * 4548 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4549 * vCC (r1). Useful for integer division and modulus. 4550 * 4551 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4552 * xor-long, add-double, sub-double, mul-double, div-double, 4553 * rem-double 4554 * 4555 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4556 */ 4557 /* binop vAA, vBB, vCC */ 4558 FETCH(r0, 1) @ r0<- CCBB 4559 mov r9, rINST, lsr #8 @ r9<- AA 4560 and r2, r0, #255 @ r2<- BB 4561 mov r3, r0, lsr #8 @ r3<- CC 4562 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4563 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4564 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4565 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4566 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4567 .if 0 4568 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4569 beq common_errDivideByZero 4570 .endif 4571 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4572 4573 subs r0, r0, r2 @ optional op; may set condition codes 4574 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4575 GET_INST_OPCODE(ip) @ extract opcode from rINST 4576 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4577 GOTO_OPCODE(ip) @ jump to next instruction 4578 /* 14-17 instructions */ 4579 4580 4581/* ------------------------------ */ 4582 .balign 64 4583.L_OP_MUL_LONG: /* 0x9d */ 4584/* File: armv5te/OP_MUL_LONG.S */ 4585 /* 4586 * Signed 64-bit integer multiply. 4587 * 4588 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4589 * WX 4590 * x YZ 4591 * -------- 4592 * ZW ZX 4593 * YW YX 4594 * 4595 * The low word of the result holds ZX, the high word holds 4596 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4597 * it doesn't fit in the low 64 bits. 4598 * 4599 * Unlike most ARM math operations, multiply instructions have 4600 * restrictions on using the same register more than once (Rd and Rm 4601 * cannot be the same). 4602 */ 4603 /* mul-long vAA, vBB, vCC */ 4604 FETCH(r0, 1) @ r0<- CCBB 4605 and r2, r0, #255 @ r2<- BB 4606 mov r3, r0, lsr #8 @ r3<- CC 4607 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4608 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4609 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4610 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4611 mul ip, r2, r1 @ ip<- ZxW 4612 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4613 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4614 mov r0, rINST, lsr #8 @ r0<- AA 4615 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4616 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4617 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4618 b .LOP_MUL_LONG_finish 4619 4620/* ------------------------------ */ 4621 .balign 64 4622.L_OP_DIV_LONG: /* 0x9e */ 4623/* File: armv5te/OP_DIV_LONG.S */ 4624/* File: armv5te/binopWide.S */ 4625 /* 4626 * Generic 64-bit binary operation. Provide an "instr" line that 4627 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4628 * This could be an ARM instruction or a function call. (If the result 4629 * comes back in a register other than r0, you can override "result".) 4630 * 4631 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4632 * vCC (r1). Useful for integer division and modulus. 4633 * 4634 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4635 * xor-long, add-double, sub-double, mul-double, div-double, 4636 * rem-double 4637 * 4638 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4639 */ 4640 /* binop vAA, vBB, vCC */ 4641 FETCH(r0, 1) @ r0<- CCBB 4642 mov r9, rINST, lsr #8 @ r9<- AA 4643 and r2, r0, #255 @ r2<- BB 4644 mov r3, r0, lsr #8 @ r3<- CC 4645 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4646 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4647 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4648 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4649 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4650 .if 1 4651 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4652 beq common_errDivideByZero 4653 .endif 4654 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4655 4656 @ optional op; may set condition codes 4657 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4658 GET_INST_OPCODE(ip) @ extract opcode from rINST 4659 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4660 GOTO_OPCODE(ip) @ jump to next instruction 4661 /* 14-17 instructions */ 4662 4663 4664/* ------------------------------ */ 4665 .balign 64 4666.L_OP_REM_LONG: /* 0x9f */ 4667/* File: armv5te/OP_REM_LONG.S */ 4668/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4669/* File: armv5te/binopWide.S */ 4670 /* 4671 * Generic 64-bit binary operation. Provide an "instr" line that 4672 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4673 * This could be an ARM instruction or a function call. (If the result 4674 * comes back in a register other than r0, you can override "result".) 4675 * 4676 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4677 * vCC (r1). Useful for integer division and modulus. 4678 * 4679 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4680 * xor-long, add-double, sub-double, mul-double, div-double, 4681 * rem-double 4682 * 4683 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4684 */ 4685 /* binop vAA, vBB, vCC */ 4686 FETCH(r0, 1) @ r0<- CCBB 4687 mov r9, rINST, lsr #8 @ r9<- AA 4688 and r2, r0, #255 @ r2<- BB 4689 mov r3, r0, lsr #8 @ r3<- CC 4690 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4691 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4692 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4693 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4694 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4695 .if 1 4696 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4697 beq common_errDivideByZero 4698 .endif 4699 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4700 4701 @ optional op; may set condition codes 4702 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4703 GET_INST_OPCODE(ip) @ extract opcode from rINST 4704 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4705 GOTO_OPCODE(ip) @ jump to next instruction 4706 /* 14-17 instructions */ 4707 4708 4709/* ------------------------------ */ 4710 .balign 64 4711.L_OP_AND_LONG: /* 0xa0 */ 4712/* File: armv5te/OP_AND_LONG.S */ 4713/* File: armv5te/binopWide.S */ 4714 /* 4715 * Generic 64-bit binary operation. Provide an "instr" line that 4716 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4717 * This could be an ARM instruction or a function call. (If the result 4718 * comes back in a register other than r0, you can override "result".) 4719 * 4720 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4721 * vCC (r1). Useful for integer division and modulus. 4722 * 4723 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4724 * xor-long, add-double, sub-double, mul-double, div-double, 4725 * rem-double 4726 * 4727 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4728 */ 4729 /* binop vAA, vBB, vCC */ 4730 FETCH(r0, 1) @ r0<- CCBB 4731 mov r9, rINST, lsr #8 @ r9<- AA 4732 and r2, r0, #255 @ r2<- BB 4733 mov r3, r0, lsr #8 @ r3<- CC 4734 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4735 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4736 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4737 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4738 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4739 .if 0 4740 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4741 beq common_errDivideByZero 4742 .endif 4743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4744 4745 and r0, r0, r2 @ optional op; may set condition codes 4746 and r1, r1, r3 @ result<- op, r0-r3 changed 4747 GET_INST_OPCODE(ip) @ extract opcode from rINST 4748 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4749 GOTO_OPCODE(ip) @ jump to next instruction 4750 /* 14-17 instructions */ 4751 4752 4753/* ------------------------------ */ 4754 .balign 64 4755.L_OP_OR_LONG: /* 0xa1 */ 4756/* File: armv5te/OP_OR_LONG.S */ 4757/* File: armv5te/binopWide.S */ 4758 /* 4759 * Generic 64-bit binary operation. Provide an "instr" line that 4760 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4761 * This could be an ARM instruction or a function call. (If the result 4762 * comes back in a register other than r0, you can override "result".) 4763 * 4764 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4765 * vCC (r1). Useful for integer division and modulus. 4766 * 4767 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4768 * xor-long, add-double, sub-double, mul-double, div-double, 4769 * rem-double 4770 * 4771 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4772 */ 4773 /* binop vAA, vBB, vCC */ 4774 FETCH(r0, 1) @ r0<- CCBB 4775 mov r9, rINST, lsr #8 @ r9<- AA 4776 and r2, r0, #255 @ r2<- BB 4777 mov r3, r0, lsr #8 @ r3<- CC 4778 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4779 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4780 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4781 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4782 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4783 .if 0 4784 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4785 beq common_errDivideByZero 4786 .endif 4787 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4788 4789 orr r0, r0, r2 @ optional op; may set condition codes 4790 orr r1, r1, r3 @ result<- op, r0-r3 changed 4791 GET_INST_OPCODE(ip) @ extract opcode from rINST 4792 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4793 GOTO_OPCODE(ip) @ jump to next instruction 4794 /* 14-17 instructions */ 4795 4796 4797/* ------------------------------ */ 4798 .balign 64 4799.L_OP_XOR_LONG: /* 0xa2 */ 4800/* File: armv5te/OP_XOR_LONG.S */ 4801/* File: armv5te/binopWide.S */ 4802 /* 4803 * Generic 64-bit binary operation. Provide an "instr" line that 4804 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4805 * This could be an ARM instruction or a function call. (If the result 4806 * comes back in a register other than r0, you can override "result".) 4807 * 4808 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4809 * vCC (r1). Useful for integer division and modulus. 4810 * 4811 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4812 * xor-long, add-double, sub-double, mul-double, div-double, 4813 * rem-double 4814 * 4815 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4816 */ 4817 /* binop vAA, vBB, vCC */ 4818 FETCH(r0, 1) @ r0<- CCBB 4819 mov r9, rINST, lsr #8 @ r9<- AA 4820 and r2, r0, #255 @ r2<- BB 4821 mov r3, r0, lsr #8 @ r3<- CC 4822 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4823 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4824 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4825 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4826 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4827 .if 0 4828 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4829 beq common_errDivideByZero 4830 .endif 4831 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4832 4833 eor r0, r0, r2 @ optional op; may set condition codes 4834 eor r1, r1, r3 @ result<- op, r0-r3 changed 4835 GET_INST_OPCODE(ip) @ extract opcode from rINST 4836 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4837 GOTO_OPCODE(ip) @ jump to next instruction 4838 /* 14-17 instructions */ 4839 4840 4841/* ------------------------------ */ 4842 .balign 64 4843.L_OP_SHL_LONG: /* 0xa3 */ 4844/* File: armv5te/OP_SHL_LONG.S */ 4845 /* 4846 * Long integer shift. This is different from the generic 32/64-bit 4847 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4848 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4849 * 6 bits of the shift distance. 4850 */ 4851 /* shl-long vAA, vBB, vCC */ 4852 FETCH(r0, 1) @ r0<- CCBB 4853 mov r9, rINST, lsr #8 @ r9<- AA 4854 and r3, r0, #255 @ r3<- BB 4855 mov r0, r0, lsr #8 @ r0<- CC 4856 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4857 GET_VREG(r2, r0) @ r2<- vCC 4858 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4859 and r2, r2, #63 @ r2<- r2 & 0x3f 4860 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4861 4862 mov r1, r1, asl r2 @ r1<- r1 << r2 4863 rsb r3, r2, #32 @ r3<- 32 - r2 4864 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4865 subs ip, r2, #32 @ ip<- r2 - 32 4866 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4868 b .LOP_SHL_LONG_finish 4869 4870/* ------------------------------ */ 4871 .balign 64 4872.L_OP_SHR_LONG: /* 0xa4 */ 4873/* File: armv5te/OP_SHR_LONG.S */ 4874 /* 4875 * Long integer shift. This is different from the generic 32/64-bit 4876 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4877 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4878 * 6 bits of the shift distance. 4879 */ 4880 /* shr-long vAA, vBB, vCC */ 4881 FETCH(r0, 1) @ r0<- CCBB 4882 mov r9, rINST, lsr #8 @ r9<- AA 4883 and r3, r0, #255 @ r3<- BB 4884 mov r0, r0, lsr #8 @ r0<- CC 4885 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4886 GET_VREG(r2, r0) @ r2<- vCC 4887 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4888 and r2, r2, #63 @ r0<- r0 & 0x3f 4889 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4890 4891 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4892 rsb r3, r2, #32 @ r3<- 32 - r2 4893 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4894 subs ip, r2, #32 @ ip<- r2 - 32 4895 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4897 b .LOP_SHR_LONG_finish 4898 4899/* ------------------------------ */ 4900 .balign 64 4901.L_OP_USHR_LONG: /* 0xa5 */ 4902/* File: armv5te/OP_USHR_LONG.S */ 4903 /* 4904 * Long integer shift. This is different from the generic 32/64-bit 4905 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4906 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4907 * 6 bits of the shift distance. 4908 */ 4909 /* ushr-long vAA, vBB, vCC */ 4910 FETCH(r0, 1) @ r0<- CCBB 4911 mov r9, rINST, lsr #8 @ r9<- AA 4912 and r3, r0, #255 @ r3<- BB 4913 mov r0, r0, lsr #8 @ r0<- CC 4914 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4915 GET_VREG(r2, r0) @ r2<- vCC 4916 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4917 and r2, r2, #63 @ r0<- r0 & 0x3f 4918 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4919 4920 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4921 rsb r3, r2, #32 @ r3<- 32 - r2 4922 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4923 subs ip, r2, #32 @ ip<- r2 - 32 4924 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4925 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4926 b .LOP_USHR_LONG_finish 4927 4928/* ------------------------------ */ 4929 .balign 64 4930.L_OP_ADD_FLOAT: /* 0xa6 */ 4931/* File: arm-vfp/OP_ADD_FLOAT.S */ 4932/* File: arm-vfp/fbinop.S */ 4933 /* 4934 * Generic 32-bit floating-point operation. Provide an "instr" line that 4935 * specifies an instruction that performs "s2 = s0 op s1". Because we 4936 * use the "softfp" ABI, this must be an instruction, not a function call. 4937 * 4938 * For: add-float, sub-float, mul-float, div-float 4939 */ 4940 /* floatop vAA, vBB, vCC */ 4941 FETCH(r0, 1) @ r0<- CCBB 4942 mov r9, rINST, lsr #8 @ r9<- AA 4943 mov r3, r0, lsr #8 @ r3<- CC 4944 and r2, r0, #255 @ r2<- BB 4945 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4946 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4947 flds s1, [r3] @ s1<- vCC 4948 flds s0, [r2] @ s0<- vBB 4949 4950 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4951 fadds s2, s0, s1 @ s2<- op 4952 GET_INST_OPCODE(ip) @ extract opcode from rINST 4953 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4954 fsts s2, [r9] @ vAA<- s2 4955 GOTO_OPCODE(ip) @ jump to next instruction 4956 4957 4958/* ------------------------------ */ 4959 .balign 64 4960.L_OP_SUB_FLOAT: /* 0xa7 */ 4961/* File: arm-vfp/OP_SUB_FLOAT.S */ 4962/* File: arm-vfp/fbinop.S */ 4963 /* 4964 * Generic 32-bit floating-point operation. Provide an "instr" line that 4965 * specifies an instruction that performs "s2 = s0 op s1". Because we 4966 * use the "softfp" ABI, this must be an instruction, not a function call. 4967 * 4968 * For: add-float, sub-float, mul-float, div-float 4969 */ 4970 /* floatop vAA, vBB, vCC */ 4971 FETCH(r0, 1) @ r0<- CCBB 4972 mov r9, rINST, lsr #8 @ r9<- AA 4973 mov r3, r0, lsr #8 @ r3<- CC 4974 and r2, r0, #255 @ r2<- BB 4975 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4976 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4977 flds s1, [r3] @ s1<- vCC 4978 flds s0, [r2] @ s0<- vBB 4979 4980 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4981 fsubs s2, s0, s1 @ s2<- op 4982 GET_INST_OPCODE(ip) @ extract opcode from rINST 4983 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4984 fsts s2, [r9] @ vAA<- s2 4985 GOTO_OPCODE(ip) @ jump to next instruction 4986 4987 4988/* ------------------------------ */ 4989 .balign 64 4990.L_OP_MUL_FLOAT: /* 0xa8 */ 4991/* File: arm-vfp/OP_MUL_FLOAT.S */ 4992/* File: arm-vfp/fbinop.S */ 4993 /* 4994 * Generic 32-bit floating-point operation. Provide an "instr" line that 4995 * specifies an instruction that performs "s2 = s0 op s1". Because we 4996 * use the "softfp" ABI, this must be an instruction, not a function call. 4997 * 4998 * For: add-float, sub-float, mul-float, div-float 4999 */ 5000 /* floatop vAA, vBB, vCC */ 5001 FETCH(r0, 1) @ r0<- CCBB 5002 mov r9, rINST, lsr #8 @ r9<- AA 5003 mov r3, r0, lsr #8 @ r3<- CC 5004 and r2, r0, #255 @ r2<- BB 5005 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5006 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5007 flds s1, [r3] @ s1<- vCC 5008 flds s0, [r2] @ s0<- vBB 5009 5010 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5011 fmuls s2, s0, s1 @ s2<- op 5012 GET_INST_OPCODE(ip) @ extract opcode from rINST 5013 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5014 fsts s2, [r9] @ vAA<- s2 5015 GOTO_OPCODE(ip) @ jump to next instruction 5016 5017 5018/* ------------------------------ */ 5019 .balign 64 5020.L_OP_DIV_FLOAT: /* 0xa9 */ 5021/* File: arm-vfp/OP_DIV_FLOAT.S */ 5022/* File: arm-vfp/fbinop.S */ 5023 /* 5024 * Generic 32-bit floating-point operation. Provide an "instr" line that 5025 * specifies an instruction that performs "s2 = s0 op s1". Because we 5026 * use the "softfp" ABI, this must be an instruction, not a function call. 5027 * 5028 * For: add-float, sub-float, mul-float, div-float 5029 */ 5030 /* floatop vAA, vBB, vCC */ 5031 FETCH(r0, 1) @ r0<- CCBB 5032 mov r9, rINST, lsr #8 @ r9<- AA 5033 mov r3, r0, lsr #8 @ r3<- CC 5034 and r2, r0, #255 @ r2<- BB 5035 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5036 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5037 flds s1, [r3] @ s1<- vCC 5038 flds s0, [r2] @ s0<- vBB 5039 5040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5041 fdivs s2, s0, s1 @ s2<- op 5042 GET_INST_OPCODE(ip) @ extract opcode from rINST 5043 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5044 fsts s2, [r9] @ vAA<- s2 5045 GOTO_OPCODE(ip) @ jump to next instruction 5046 5047 5048/* ------------------------------ */ 5049 .balign 64 5050.L_OP_REM_FLOAT: /* 0xaa */ 5051/* File: armv5te/OP_REM_FLOAT.S */ 5052/* EABI doesn't define a float remainder function, but libm does */ 5053/* File: armv5te/binop.S */ 5054 /* 5055 * Generic 32-bit binary operation. Provide an "instr" line that 5056 * specifies an instruction that performs "result = r0 op r1". 5057 * This could be an ARM instruction or a function call. (If the result 5058 * comes back in a register other than r0, you can override "result".) 5059 * 5060 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5061 * vCC (r1). Useful for integer division and modulus. Note that we 5062 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5063 * handles it correctly. 5064 * 5065 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5066 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5067 * mul-float, div-float, rem-float 5068 */ 5069 /* binop vAA, vBB, vCC */ 5070 FETCH(r0, 1) @ r0<- CCBB 5071 mov r9, rINST, lsr #8 @ r9<- AA 5072 mov r3, r0, lsr #8 @ r3<- CC 5073 and r2, r0, #255 @ r2<- BB 5074 GET_VREG(r1, r3) @ r1<- vCC 5075 GET_VREG(r0, r2) @ r0<- vBB 5076 .if 0 5077 cmp r1, #0 @ is second operand zero? 5078 beq common_errDivideByZero 5079 .endif 5080 5081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5082 @ optional op; may set condition codes 5083 bl fmodf @ r0<- op, r0-r3 changed 5084 GET_INST_OPCODE(ip) @ extract opcode from rINST 5085 SET_VREG(r0, r9) @ vAA<- r0 5086 GOTO_OPCODE(ip) @ jump to next instruction 5087 /* 11-14 instructions */ 5088 5089 5090/* ------------------------------ */ 5091 .balign 64 5092.L_OP_ADD_DOUBLE: /* 0xab */ 5093/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5094/* File: arm-vfp/fbinopWide.S */ 5095 /* 5096 * Generic 64-bit double-precision floating point binary operation. 5097 * Provide an "instr" line that specifies an instruction that performs 5098 * "d2 = d0 op d1". 5099 * 5100 * for: add-double, sub-double, mul-double, div-double 5101 */ 5102 /* doubleop vAA, vBB, vCC */ 5103 FETCH(r0, 1) @ r0<- CCBB 5104 mov r9, rINST, lsr #8 @ r9<- AA 5105 mov r3, r0, lsr #8 @ r3<- CC 5106 and r2, r0, #255 @ r2<- BB 5107 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5108 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5109 fldd d1, [r3] @ d1<- vCC 5110 fldd d0, [r2] @ d0<- vBB 5111 5112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5113 faddd d2, d0, d1 @ s2<- op 5114 GET_INST_OPCODE(ip) @ extract opcode from rINST 5115 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5116 fstd d2, [r9] @ vAA<- d2 5117 GOTO_OPCODE(ip) @ jump to next instruction 5118 5119 5120/* ------------------------------ */ 5121 .balign 64 5122.L_OP_SUB_DOUBLE: /* 0xac */ 5123/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5124/* File: arm-vfp/fbinopWide.S */ 5125 /* 5126 * Generic 64-bit double-precision floating point binary operation. 5127 * Provide an "instr" line that specifies an instruction that performs 5128 * "d2 = d0 op d1". 5129 * 5130 * for: add-double, sub-double, mul-double, div-double 5131 */ 5132 /* doubleop vAA, vBB, vCC */ 5133 FETCH(r0, 1) @ r0<- CCBB 5134 mov r9, rINST, lsr #8 @ r9<- AA 5135 mov r3, r0, lsr #8 @ r3<- CC 5136 and r2, r0, #255 @ r2<- BB 5137 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5138 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5139 fldd d1, [r3] @ d1<- vCC 5140 fldd d0, [r2] @ d0<- vBB 5141 5142 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5143 fsubd d2, d0, d1 @ s2<- op 5144 GET_INST_OPCODE(ip) @ extract opcode from rINST 5145 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5146 fstd d2, [r9] @ vAA<- d2 5147 GOTO_OPCODE(ip) @ jump to next instruction 5148 5149 5150/* ------------------------------ */ 5151 .balign 64 5152.L_OP_MUL_DOUBLE: /* 0xad */ 5153/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5154/* File: arm-vfp/fbinopWide.S */ 5155 /* 5156 * Generic 64-bit double-precision floating point binary operation. 5157 * Provide an "instr" line that specifies an instruction that performs 5158 * "d2 = d0 op d1". 5159 * 5160 * for: add-double, sub-double, mul-double, div-double 5161 */ 5162 /* doubleop vAA, vBB, vCC */ 5163 FETCH(r0, 1) @ r0<- CCBB 5164 mov r9, rINST, lsr #8 @ r9<- AA 5165 mov r3, r0, lsr #8 @ r3<- CC 5166 and r2, r0, #255 @ r2<- BB 5167 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5168 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5169 fldd d1, [r3] @ d1<- vCC 5170 fldd d0, [r2] @ d0<- vBB 5171 5172 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5173 fmuld d2, d0, d1 @ s2<- op 5174 GET_INST_OPCODE(ip) @ extract opcode from rINST 5175 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5176 fstd d2, [r9] @ vAA<- d2 5177 GOTO_OPCODE(ip) @ jump to next instruction 5178 5179 5180/* ------------------------------ */ 5181 .balign 64 5182.L_OP_DIV_DOUBLE: /* 0xae */ 5183/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5184/* File: arm-vfp/fbinopWide.S */ 5185 /* 5186 * Generic 64-bit double-precision floating point binary operation. 5187 * Provide an "instr" line that specifies an instruction that performs 5188 * "d2 = d0 op d1". 5189 * 5190 * for: add-double, sub-double, mul-double, div-double 5191 */ 5192 /* doubleop vAA, vBB, vCC */ 5193 FETCH(r0, 1) @ r0<- CCBB 5194 mov r9, rINST, lsr #8 @ r9<- AA 5195 mov r3, r0, lsr #8 @ r3<- CC 5196 and r2, r0, #255 @ r2<- BB 5197 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5198 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5199 fldd d1, [r3] @ d1<- vCC 5200 fldd d0, [r2] @ d0<- vBB 5201 5202 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5203 fdivd d2, d0, d1 @ s2<- op 5204 GET_INST_OPCODE(ip) @ extract opcode from rINST 5205 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5206 fstd d2, [r9] @ vAA<- d2 5207 GOTO_OPCODE(ip) @ jump to next instruction 5208 5209 5210/* ------------------------------ */ 5211 .balign 64 5212.L_OP_REM_DOUBLE: /* 0xaf */ 5213/* File: armv5te/OP_REM_DOUBLE.S */ 5214/* EABI doesn't define a double remainder function, but libm does */ 5215/* File: armv5te/binopWide.S */ 5216 /* 5217 * Generic 64-bit binary operation. Provide an "instr" line that 5218 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5219 * This could be an ARM instruction or a function call. (If the result 5220 * comes back in a register other than r0, you can override "result".) 5221 * 5222 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5223 * vCC (r1). Useful for integer division and modulus. 5224 * 5225 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5226 * xor-long, add-double, sub-double, mul-double, div-double, 5227 * rem-double 5228 * 5229 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5230 */ 5231 /* binop vAA, vBB, vCC */ 5232 FETCH(r0, 1) @ r0<- CCBB 5233 mov r9, rINST, lsr #8 @ r9<- AA 5234 and r2, r0, #255 @ r2<- BB 5235 mov r3, r0, lsr #8 @ r3<- CC 5236 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5237 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5238 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5239 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5240 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5241 .if 0 5242 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5243 beq common_errDivideByZero 5244 .endif 5245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5246 5247 @ optional op; may set condition codes 5248 bl fmod @ result<- op, r0-r3 changed 5249 GET_INST_OPCODE(ip) @ extract opcode from rINST 5250 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5251 GOTO_OPCODE(ip) @ jump to next instruction 5252 /* 14-17 instructions */ 5253 5254 5255/* ------------------------------ */ 5256 .balign 64 5257.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5258/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5259/* File: armv5te/binop2addr.S */ 5260 /* 5261 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5262 * that specifies an instruction that performs "result = r0 op r1". 5263 * This could be an ARM instruction or a function call. (If the result 5264 * comes back in a register other than r0, you can override "result".) 5265 * 5266 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5267 * vCC (r1). Useful for integer division and modulus. 5268 * 5269 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5270 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5271 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5272 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5273 */ 5274 /* binop/2addr vA, vB */ 5275 mov r9, rINST, lsr #8 @ r9<- A+ 5276 mov r3, rINST, lsr #12 @ r3<- B 5277 and r9, r9, #15 5278 GET_VREG(r1, r3) @ r1<- vB 5279 GET_VREG(r0, r9) @ r0<- vA 5280 .if 0 5281 cmp r1, #0 @ is second operand zero? 5282 beq common_errDivideByZero 5283 .endif 5284 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5285 5286 @ optional op; may set condition codes 5287 add r0, r0, r1 @ r0<- op, r0-r3 changed 5288 GET_INST_OPCODE(ip) @ extract opcode from rINST 5289 SET_VREG(r0, r9) @ vAA<- r0 5290 GOTO_OPCODE(ip) @ jump to next instruction 5291 /* 10-13 instructions */ 5292 5293 5294/* ------------------------------ */ 5295 .balign 64 5296.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5297/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5298/* File: armv5te/binop2addr.S */ 5299 /* 5300 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5301 * that specifies an instruction that performs "result = r0 op r1". 5302 * This could be an ARM instruction or a function call. (If the result 5303 * comes back in a register other than r0, you can override "result".) 5304 * 5305 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5306 * vCC (r1). Useful for integer division and modulus. 5307 * 5308 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5309 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5310 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5311 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5312 */ 5313 /* binop/2addr vA, vB */ 5314 mov r9, rINST, lsr #8 @ r9<- A+ 5315 mov r3, rINST, lsr #12 @ r3<- B 5316 and r9, r9, #15 5317 GET_VREG(r1, r3) @ r1<- vB 5318 GET_VREG(r0, r9) @ r0<- vA 5319 .if 0 5320 cmp r1, #0 @ is second operand zero? 5321 beq common_errDivideByZero 5322 .endif 5323 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5324 5325 @ optional op; may set condition codes 5326 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5327 GET_INST_OPCODE(ip) @ extract opcode from rINST 5328 SET_VREG(r0, r9) @ vAA<- r0 5329 GOTO_OPCODE(ip) @ jump to next instruction 5330 /* 10-13 instructions */ 5331 5332 5333/* ------------------------------ */ 5334 .balign 64 5335.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5336/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5337/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5338/* File: armv5te/binop2addr.S */ 5339 /* 5340 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5341 * that specifies an instruction that performs "result = r0 op r1". 5342 * This could be an ARM instruction or a function call. (If the result 5343 * comes back in a register other than r0, you can override "result".) 5344 * 5345 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5346 * vCC (r1). Useful for integer division and modulus. 5347 * 5348 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5349 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5350 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5351 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5352 */ 5353 /* binop/2addr vA, vB */ 5354 mov r9, rINST, lsr #8 @ r9<- A+ 5355 mov r3, rINST, lsr #12 @ r3<- B 5356 and r9, r9, #15 5357 GET_VREG(r1, r3) @ r1<- vB 5358 GET_VREG(r0, r9) @ r0<- vA 5359 .if 0 5360 cmp r1, #0 @ is second operand zero? 5361 beq common_errDivideByZero 5362 .endif 5363 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5364 5365 @ optional op; may set condition codes 5366 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5367 GET_INST_OPCODE(ip) @ extract opcode from rINST 5368 SET_VREG(r0, r9) @ vAA<- r0 5369 GOTO_OPCODE(ip) @ jump to next instruction 5370 /* 10-13 instructions */ 5371 5372 5373/* ------------------------------ */ 5374 .balign 64 5375.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5376/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5377/* File: armv5te/binop2addr.S */ 5378 /* 5379 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5380 * that specifies an instruction that performs "result = r0 op r1". 5381 * This could be an ARM instruction or a function call. (If the result 5382 * comes back in a register other than r0, you can override "result".) 5383 * 5384 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5385 * vCC (r1). Useful for integer division and modulus. 5386 * 5387 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5388 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5389 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5390 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5391 */ 5392 /* binop/2addr vA, vB */ 5393 mov r9, rINST, lsr #8 @ r9<- A+ 5394 mov r3, rINST, lsr #12 @ r3<- B 5395 and r9, r9, #15 5396 GET_VREG(r1, r3) @ r1<- vB 5397 GET_VREG(r0, r9) @ r0<- vA 5398 .if 1 5399 cmp r1, #0 @ is second operand zero? 5400 beq common_errDivideByZero 5401 .endif 5402 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5403 5404 @ optional op; may set condition codes 5405 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5406 GET_INST_OPCODE(ip) @ extract opcode from rINST 5407 SET_VREG(r0, r9) @ vAA<- r0 5408 GOTO_OPCODE(ip) @ jump to next instruction 5409 /* 10-13 instructions */ 5410 5411 5412/* ------------------------------ */ 5413 .balign 64 5414.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5415/* File: armv5te/OP_REM_INT_2ADDR.S */ 5416/* idivmod returns quotient in r0 and remainder in r1 */ 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 1 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 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5446 GET_INST_OPCODE(ip) @ extract opcode from rINST 5447 SET_VREG(r1, r9) @ vAA<- r1 5448 GOTO_OPCODE(ip) @ jump to next instruction 5449 /* 10-13 instructions */ 5450 5451 5452/* ------------------------------ */ 5453 .balign 64 5454.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5455/* File: armv5te/OP_AND_INT_2ADDR.S */ 5456/* File: armv5te/binop2addr.S */ 5457 /* 5458 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5459 * that specifies an instruction that performs "result = r0 op r1". 5460 * This could be an ARM instruction or a function call. (If the result 5461 * comes back in a register other than r0, you can override "result".) 5462 * 5463 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5464 * vCC (r1). Useful for integer division and modulus. 5465 * 5466 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5467 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5468 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5469 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5470 */ 5471 /* binop/2addr vA, vB */ 5472 mov r9, rINST, lsr #8 @ r9<- A+ 5473 mov r3, rINST, lsr #12 @ r3<- B 5474 and r9, r9, #15 5475 GET_VREG(r1, r3) @ r1<- vB 5476 GET_VREG(r0, r9) @ r0<- vA 5477 .if 0 5478 cmp r1, #0 @ is second operand zero? 5479 beq common_errDivideByZero 5480 .endif 5481 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5482 5483 @ optional op; may set condition codes 5484 and r0, r0, r1 @ r0<- op, r0-r3 changed 5485 GET_INST_OPCODE(ip) @ extract opcode from rINST 5486 SET_VREG(r0, r9) @ vAA<- r0 5487 GOTO_OPCODE(ip) @ jump to next instruction 5488 /* 10-13 instructions */ 5489 5490 5491/* ------------------------------ */ 5492 .balign 64 5493.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5494/* File: armv5te/OP_OR_INT_2ADDR.S */ 5495/* File: armv5te/binop2addr.S */ 5496 /* 5497 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5498 * that specifies an instruction that performs "result = r0 op r1". 5499 * This could be an ARM instruction or a function call. (If the result 5500 * comes back in a register other than r0, you can override "result".) 5501 * 5502 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5503 * vCC (r1). Useful for integer division and modulus. 5504 * 5505 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5506 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5507 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5508 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5509 */ 5510 /* binop/2addr vA, vB */ 5511 mov r9, rINST, lsr #8 @ r9<- A+ 5512 mov r3, rINST, lsr #12 @ r3<- B 5513 and r9, r9, #15 5514 GET_VREG(r1, r3) @ r1<- vB 5515 GET_VREG(r0, r9) @ r0<- vA 5516 .if 0 5517 cmp r1, #0 @ is second operand zero? 5518 beq common_errDivideByZero 5519 .endif 5520 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5521 5522 @ optional op; may set condition codes 5523 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5524 GET_INST_OPCODE(ip) @ extract opcode from rINST 5525 SET_VREG(r0, r9) @ vAA<- r0 5526 GOTO_OPCODE(ip) @ jump to next instruction 5527 /* 10-13 instructions */ 5528 5529 5530/* ------------------------------ */ 5531 .balign 64 5532.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5533/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5534/* File: armv5te/binop2addr.S */ 5535 /* 5536 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5537 * that specifies an instruction that performs "result = r0 op r1". 5538 * This could be an ARM instruction or a function call. (If the result 5539 * comes back in a register other than r0, you can override "result".) 5540 * 5541 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5542 * vCC (r1). Useful for integer division and modulus. 5543 * 5544 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5545 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5546 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5547 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5548 */ 5549 /* binop/2addr vA, vB */ 5550 mov r9, rINST, lsr #8 @ r9<- A+ 5551 mov r3, rINST, lsr #12 @ r3<- B 5552 and r9, r9, #15 5553 GET_VREG(r1, r3) @ r1<- vB 5554 GET_VREG(r0, r9) @ r0<- vA 5555 .if 0 5556 cmp r1, #0 @ is second operand zero? 5557 beq common_errDivideByZero 5558 .endif 5559 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5560 5561 @ optional op; may set condition codes 5562 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5563 GET_INST_OPCODE(ip) @ extract opcode from rINST 5564 SET_VREG(r0, r9) @ vAA<- r0 5565 GOTO_OPCODE(ip) @ jump to next instruction 5566 /* 10-13 instructions */ 5567 5568 5569/* ------------------------------ */ 5570 .balign 64 5571.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5572/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5573/* File: armv5te/binop2addr.S */ 5574 /* 5575 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5576 * that specifies an instruction that performs "result = r0 op r1". 5577 * This could be an ARM instruction or a function call. (If the result 5578 * comes back in a register other than r0, you can override "result".) 5579 * 5580 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5581 * vCC (r1). Useful for integer division and modulus. 5582 * 5583 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5584 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5585 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5586 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5587 */ 5588 /* binop/2addr vA, vB */ 5589 mov r9, rINST, lsr #8 @ r9<- A+ 5590 mov r3, rINST, lsr #12 @ r3<- B 5591 and r9, r9, #15 5592 GET_VREG(r1, r3) @ r1<- vB 5593 GET_VREG(r0, r9) @ r0<- vA 5594 .if 0 5595 cmp r1, #0 @ is second operand zero? 5596 beq common_errDivideByZero 5597 .endif 5598 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5599 5600 and r1, r1, #31 @ optional op; may set condition codes 5601 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5602 GET_INST_OPCODE(ip) @ extract opcode from rINST 5603 SET_VREG(r0, r9) @ vAA<- r0 5604 GOTO_OPCODE(ip) @ jump to next instruction 5605 /* 10-13 instructions */ 5606 5607 5608/* ------------------------------ */ 5609 .balign 64 5610.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5611/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5612/* File: armv5te/binop2addr.S */ 5613 /* 5614 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5615 * that specifies an instruction that performs "result = r0 op r1". 5616 * This could be an ARM instruction or a function call. (If the result 5617 * comes back in a register other than r0, you can override "result".) 5618 * 5619 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5620 * vCC (r1). Useful for integer division and modulus. 5621 * 5622 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5623 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5624 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5625 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5626 */ 5627 /* binop/2addr vA, vB */ 5628 mov r9, rINST, lsr #8 @ r9<- A+ 5629 mov r3, rINST, lsr #12 @ r3<- B 5630 and r9, r9, #15 5631 GET_VREG(r1, r3) @ r1<- vB 5632 GET_VREG(r0, r9) @ r0<- vA 5633 .if 0 5634 cmp r1, #0 @ is second operand zero? 5635 beq common_errDivideByZero 5636 .endif 5637 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5638 5639 and r1, r1, #31 @ optional op; may set condition codes 5640 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5641 GET_INST_OPCODE(ip) @ extract opcode from rINST 5642 SET_VREG(r0, r9) @ vAA<- r0 5643 GOTO_OPCODE(ip) @ jump to next instruction 5644 /* 10-13 instructions */ 5645 5646 5647/* ------------------------------ */ 5648 .balign 64 5649.L_OP_USHR_INT_2ADDR: /* 0xba */ 5650/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5651/* File: armv5te/binop2addr.S */ 5652 /* 5653 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5654 * that specifies an instruction that performs "result = r0 op r1". 5655 * This could be an ARM instruction or a function call. (If the result 5656 * comes back in a register other than r0, you can override "result".) 5657 * 5658 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5659 * vCC (r1). Useful for integer division and modulus. 5660 * 5661 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5662 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5663 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5664 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5665 */ 5666 /* binop/2addr vA, vB */ 5667 mov r9, rINST, lsr #8 @ r9<- A+ 5668 mov r3, rINST, lsr #12 @ r3<- B 5669 and r9, r9, #15 5670 GET_VREG(r1, r3) @ r1<- vB 5671 GET_VREG(r0, r9) @ r0<- vA 5672 .if 0 5673 cmp r1, #0 @ is second operand zero? 5674 beq common_errDivideByZero 5675 .endif 5676 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5677 5678 and r1, r1, #31 @ optional op; may set condition codes 5679 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5680 GET_INST_OPCODE(ip) @ extract opcode from rINST 5681 SET_VREG(r0, r9) @ vAA<- r0 5682 GOTO_OPCODE(ip) @ jump to next instruction 5683 /* 10-13 instructions */ 5684 5685 5686/* ------------------------------ */ 5687 .balign 64 5688.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5689/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5690/* File: armv5te/binopWide2addr.S */ 5691 /* 5692 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5693 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5694 * This could be an ARM instruction or a function call. (If the result 5695 * comes back in a register other than r0, you can override "result".) 5696 * 5697 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5698 * vCC (r1). Useful for integer division and modulus. 5699 * 5700 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5701 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5702 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5703 * rem-double/2addr 5704 */ 5705 /* binop/2addr vA, vB */ 5706 mov r9, rINST, lsr #8 @ r9<- A+ 5707 mov r1, rINST, lsr #12 @ r1<- B 5708 and r9, r9, #15 5709 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5710 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5711 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5712 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5713 .if 0 5714 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5715 beq common_errDivideByZero 5716 .endif 5717 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5718 5719 adds r0, r0, r2 @ optional op; may set condition codes 5720 adc r1, r1, r3 @ result<- op, r0-r3 changed 5721 GET_INST_OPCODE(ip) @ extract opcode from rINST 5722 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5723 GOTO_OPCODE(ip) @ jump to next instruction 5724 /* 12-15 instructions */ 5725 5726 5727/* ------------------------------ */ 5728 .balign 64 5729.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5730/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5731/* File: armv5te/binopWide2addr.S */ 5732 /* 5733 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5734 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5735 * This could be an ARM instruction or a function call. (If the result 5736 * comes back in a register other than r0, you can override "result".) 5737 * 5738 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5739 * vCC (r1). Useful for integer division and modulus. 5740 * 5741 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5742 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5743 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5744 * rem-double/2addr 5745 */ 5746 /* binop/2addr vA, vB */ 5747 mov r9, rINST, lsr #8 @ r9<- A+ 5748 mov r1, rINST, lsr #12 @ r1<- B 5749 and r9, r9, #15 5750 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5751 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5752 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5753 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5754 .if 0 5755 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5756 beq common_errDivideByZero 5757 .endif 5758 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5759 5760 subs r0, r0, r2 @ optional op; may set condition codes 5761 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5762 GET_INST_OPCODE(ip) @ extract opcode from rINST 5763 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5764 GOTO_OPCODE(ip) @ jump to next instruction 5765 /* 12-15 instructions */ 5766 5767 5768/* ------------------------------ */ 5769 .balign 64 5770.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5771/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5772 /* 5773 * Signed 64-bit integer multiply, "/2addr" version. 5774 * 5775 * See OP_MUL_LONG for an explanation. 5776 * 5777 * We get a little tight on registers, so to avoid looking up &fp[A] 5778 * again we stuff it into rINST. 5779 */ 5780 /* mul-long/2addr vA, vB */ 5781 mov r9, rINST, lsr #8 @ r9<- A+ 5782 mov r1, rINST, lsr #12 @ r1<- B 5783 and r9, r9, #15 5784 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5785 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5786 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5787 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5788 mul ip, r2, r1 @ ip<- ZxW 5789 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5790 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5791 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5792 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5793 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5794 GET_INST_OPCODE(ip) @ extract opcode from rINST 5795 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5796 GOTO_OPCODE(ip) @ jump to next instruction 5797 5798/* ------------------------------ */ 5799 .balign 64 5800.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5801/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5802/* File: armv5te/binopWide2addr.S */ 5803 /* 5804 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5805 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5806 * This could be an ARM instruction or a function call. (If the result 5807 * comes back in a register other than r0, you can override "result".) 5808 * 5809 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5810 * vCC (r1). Useful for integer division and modulus. 5811 * 5812 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5813 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5814 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5815 * rem-double/2addr 5816 */ 5817 /* binop/2addr vA, vB */ 5818 mov r9, rINST, lsr #8 @ r9<- A+ 5819 mov r1, rINST, lsr #12 @ r1<- B 5820 and r9, r9, #15 5821 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5822 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5823 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5824 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5825 .if 1 5826 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5827 beq common_errDivideByZero 5828 .endif 5829 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5830 5831 @ optional op; may set condition codes 5832 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5833 GET_INST_OPCODE(ip) @ extract opcode from rINST 5834 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5835 GOTO_OPCODE(ip) @ jump to next instruction 5836 /* 12-15 instructions */ 5837 5838 5839/* ------------------------------ */ 5840 .balign 64 5841.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5842/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5843/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5844/* File: armv5te/binopWide2addr.S */ 5845 /* 5846 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5847 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5848 * This could be an ARM instruction or a function call. (If the result 5849 * comes back in a register other than r0, you can override "result".) 5850 * 5851 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5852 * vCC (r1). Useful for integer division and modulus. 5853 * 5854 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5855 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5856 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5857 * rem-double/2addr 5858 */ 5859 /* binop/2addr vA, vB */ 5860 mov r9, rINST, lsr #8 @ r9<- A+ 5861 mov r1, rINST, lsr #12 @ r1<- B 5862 and r9, r9, #15 5863 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5864 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5865 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5866 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5867 .if 1 5868 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5869 beq common_errDivideByZero 5870 .endif 5871 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5872 5873 @ optional op; may set condition codes 5874 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5875 GET_INST_OPCODE(ip) @ extract opcode from rINST 5876 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5877 GOTO_OPCODE(ip) @ jump to next instruction 5878 /* 12-15 instructions */ 5879 5880 5881/* ------------------------------ */ 5882 .balign 64 5883.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5884/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5885/* File: armv5te/binopWide2addr.S */ 5886 /* 5887 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5888 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5889 * This could be an ARM instruction or a function call. (If the result 5890 * comes back in a register other than r0, you can override "result".) 5891 * 5892 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5893 * vCC (r1). Useful for integer division and modulus. 5894 * 5895 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5896 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5897 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5898 * rem-double/2addr 5899 */ 5900 /* binop/2addr vA, vB */ 5901 mov r9, rINST, lsr #8 @ r9<- A+ 5902 mov r1, rINST, lsr #12 @ r1<- B 5903 and r9, r9, #15 5904 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5905 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5906 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5907 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5908 .if 0 5909 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5910 beq common_errDivideByZero 5911 .endif 5912 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5913 5914 and r0, r0, r2 @ optional op; may set condition codes 5915 and r1, r1, r3 @ result<- op, r0-r3 changed 5916 GET_INST_OPCODE(ip) @ extract opcode from rINST 5917 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5918 GOTO_OPCODE(ip) @ jump to next instruction 5919 /* 12-15 instructions */ 5920 5921 5922/* ------------------------------ */ 5923 .balign 64 5924.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5925/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5926/* File: armv5te/binopWide2addr.S */ 5927 /* 5928 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5929 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5930 * This could be an ARM instruction or a function call. (If the result 5931 * comes back in a register other than r0, you can override "result".) 5932 * 5933 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5934 * vCC (r1). Useful for integer division and modulus. 5935 * 5936 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5937 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5938 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5939 * rem-double/2addr 5940 */ 5941 /* binop/2addr vA, vB */ 5942 mov r9, rINST, lsr #8 @ r9<- A+ 5943 mov r1, rINST, lsr #12 @ r1<- B 5944 and r9, r9, #15 5945 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5946 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5947 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5948 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5949 .if 0 5950 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5951 beq common_errDivideByZero 5952 .endif 5953 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5954 5955 orr r0, r0, r2 @ optional op; may set condition codes 5956 orr r1, r1, r3 @ result<- op, r0-r3 changed 5957 GET_INST_OPCODE(ip) @ extract opcode from rINST 5958 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5959 GOTO_OPCODE(ip) @ jump to next instruction 5960 /* 12-15 instructions */ 5961 5962 5963/* ------------------------------ */ 5964 .balign 64 5965.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5966/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5967/* File: armv5te/binopWide2addr.S */ 5968 /* 5969 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5970 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5971 * This could be an ARM instruction or a function call. (If the result 5972 * comes back in a register other than r0, you can override "result".) 5973 * 5974 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5975 * vCC (r1). Useful for integer division and modulus. 5976 * 5977 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5978 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5979 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5980 * rem-double/2addr 5981 */ 5982 /* binop/2addr vA, vB */ 5983 mov r9, rINST, lsr #8 @ r9<- A+ 5984 mov r1, rINST, lsr #12 @ r1<- B 5985 and r9, r9, #15 5986 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5987 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5988 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5989 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5990 .if 0 5991 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5992 beq common_errDivideByZero 5993 .endif 5994 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5995 5996 eor r0, r0, r2 @ optional op; may set condition codes 5997 eor r1, r1, r3 @ result<- op, r0-r3 changed 5998 GET_INST_OPCODE(ip) @ extract opcode from rINST 5999 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6000 GOTO_OPCODE(ip) @ jump to next instruction 6001 /* 12-15 instructions */ 6002 6003 6004/* ------------------------------ */ 6005 .balign 64 6006.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6007/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6008 /* 6009 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6010 * 32-bit shift distance. 6011 */ 6012 /* shl-long/2addr vA, vB */ 6013 mov r9, rINST, lsr #8 @ r9<- A+ 6014 mov r3, rINST, lsr #12 @ r3<- B 6015 and r9, r9, #15 6016 GET_VREG(r2, r3) @ r2<- vB 6017 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6018 and r2, r2, #63 @ r2<- r2 & 0x3f 6019 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6020 6021 mov r1, r1, asl r2 @ r1<- r1 << r2 6022 rsb r3, r2, #32 @ r3<- 32 - r2 6023 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6024 subs ip, r2, #32 @ ip<- r2 - 32 6025 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6026 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6027 mov r0, r0, asl r2 @ r0<- r0 << r2 6028 b .LOP_SHL_LONG_2ADDR_finish 6029 6030/* ------------------------------ */ 6031 .balign 64 6032.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6033/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6034 /* 6035 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6036 * 32-bit shift distance. 6037 */ 6038 /* shr-long/2addr vA, vB */ 6039 mov r9, rINST, lsr #8 @ r9<- A+ 6040 mov r3, rINST, lsr #12 @ r3<- B 6041 and r9, r9, #15 6042 GET_VREG(r2, r3) @ r2<- vB 6043 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6044 and r2, r2, #63 @ r2<- r2 & 0x3f 6045 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6046 6047 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6048 rsb r3, r2, #32 @ r3<- 32 - r2 6049 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6050 subs ip, r2, #32 @ ip<- r2 - 32 6051 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6052 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6053 mov r1, r1, asr r2 @ r1<- r1 >> r2 6054 b .LOP_SHR_LONG_2ADDR_finish 6055 6056/* ------------------------------ */ 6057 .balign 64 6058.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6059/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6060 /* 6061 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6062 * 32-bit shift distance. 6063 */ 6064 /* ushr-long/2addr vA, vB */ 6065 mov r9, rINST, lsr #8 @ r9<- A+ 6066 mov r3, rINST, lsr #12 @ r3<- B 6067 and r9, r9, #15 6068 GET_VREG(r2, r3) @ r2<- vB 6069 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6070 and r2, r2, #63 @ r2<- r2 & 0x3f 6071 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6072 6073 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6074 rsb r3, r2, #32 @ r3<- 32 - r2 6075 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6076 subs ip, r2, #32 @ ip<- r2 - 32 6077 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6078 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6079 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6080 b .LOP_USHR_LONG_2ADDR_finish 6081 6082/* ------------------------------ */ 6083 .balign 64 6084.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6085/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6086/* File: arm-vfp/fbinop2addr.S */ 6087 /* 6088 * Generic 32-bit floating point "/2addr" binary operation. Provide 6089 * an "instr" line that specifies an instruction that performs 6090 * "s2 = s0 op s1". 6091 * 6092 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6093 */ 6094 /* binop/2addr vA, vB */ 6095 mov r3, rINST, lsr #12 @ r3<- B 6096 mov r9, rINST, lsr #8 @ r9<- A+ 6097 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6098 and r9, r9, #15 @ r9<- A 6099 flds s1, [r3] @ s1<- vB 6100 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6101 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6102 flds s0, [r9] @ s0<- vA 6103 6104 fadds s2, s0, s1 @ s2<- op 6105 GET_INST_OPCODE(ip) @ extract opcode from rINST 6106 fsts s2, [r9] @ vAA<- s2 6107 GOTO_OPCODE(ip) @ jump to next instruction 6108 6109 6110/* ------------------------------ */ 6111 .balign 64 6112.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6113/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6114/* File: arm-vfp/fbinop2addr.S */ 6115 /* 6116 * Generic 32-bit floating point "/2addr" binary operation. Provide 6117 * an "instr" line that specifies an instruction that performs 6118 * "s2 = s0 op s1". 6119 * 6120 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6121 */ 6122 /* binop/2addr vA, vB */ 6123 mov r3, rINST, lsr #12 @ r3<- B 6124 mov r9, rINST, lsr #8 @ r9<- A+ 6125 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6126 and r9, r9, #15 @ r9<- A 6127 flds s1, [r3] @ s1<- vB 6128 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6129 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6130 flds s0, [r9] @ s0<- vA 6131 6132 fsubs s2, s0, s1 @ s2<- op 6133 GET_INST_OPCODE(ip) @ extract opcode from rINST 6134 fsts s2, [r9] @ vAA<- s2 6135 GOTO_OPCODE(ip) @ jump to next instruction 6136 6137 6138/* ------------------------------ */ 6139 .balign 64 6140.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6141/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6142/* File: arm-vfp/fbinop2addr.S */ 6143 /* 6144 * Generic 32-bit floating point "/2addr" binary operation. Provide 6145 * an "instr" line that specifies an instruction that performs 6146 * "s2 = s0 op s1". 6147 * 6148 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6149 */ 6150 /* binop/2addr vA, vB */ 6151 mov r3, rINST, lsr #12 @ r3<- B 6152 mov r9, rINST, lsr #8 @ r9<- A+ 6153 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6154 and r9, r9, #15 @ r9<- A 6155 flds s1, [r3] @ s1<- vB 6156 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6157 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6158 flds s0, [r9] @ s0<- vA 6159 6160 fmuls s2, s0, s1 @ s2<- op 6161 GET_INST_OPCODE(ip) @ extract opcode from rINST 6162 fsts s2, [r9] @ vAA<- s2 6163 GOTO_OPCODE(ip) @ jump to next instruction 6164 6165 6166/* ------------------------------ */ 6167 .balign 64 6168.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6169/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6170/* File: arm-vfp/fbinop2addr.S */ 6171 /* 6172 * Generic 32-bit floating point "/2addr" binary operation. Provide 6173 * an "instr" line that specifies an instruction that performs 6174 * "s2 = s0 op s1". 6175 * 6176 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6177 */ 6178 /* binop/2addr vA, vB */ 6179 mov r3, rINST, lsr #12 @ r3<- B 6180 mov r9, rINST, lsr #8 @ r9<- A+ 6181 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6182 and r9, r9, #15 @ r9<- A 6183 flds s1, [r3] @ s1<- vB 6184 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6185 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6186 flds s0, [r9] @ s0<- vA 6187 6188 fdivs s2, s0, s1 @ s2<- op 6189 GET_INST_OPCODE(ip) @ extract opcode from rINST 6190 fsts s2, [r9] @ vAA<- s2 6191 GOTO_OPCODE(ip) @ jump to next instruction 6192 6193 6194/* ------------------------------ */ 6195 .balign 64 6196.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6197/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6198/* EABI doesn't define a float remainder function, but libm does */ 6199/* File: armv5te/binop2addr.S */ 6200 /* 6201 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6202 * that specifies an instruction that performs "result = r0 op r1". 6203 * This could be an ARM instruction or a function call. (If the result 6204 * comes back in a register other than r0, you can override "result".) 6205 * 6206 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6207 * vCC (r1). Useful for integer division and modulus. 6208 * 6209 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6210 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6211 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6212 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6213 */ 6214 /* binop/2addr vA, vB */ 6215 mov r9, rINST, lsr #8 @ r9<- A+ 6216 mov r3, rINST, lsr #12 @ r3<- B 6217 and r9, r9, #15 6218 GET_VREG(r1, r3) @ r1<- vB 6219 GET_VREG(r0, r9) @ r0<- vA 6220 .if 0 6221 cmp r1, #0 @ is second operand zero? 6222 beq common_errDivideByZero 6223 .endif 6224 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6225 6226 @ optional op; may set condition codes 6227 bl fmodf @ r0<- op, r0-r3 changed 6228 GET_INST_OPCODE(ip) @ extract opcode from rINST 6229 SET_VREG(r0, r9) @ vAA<- r0 6230 GOTO_OPCODE(ip) @ jump to next instruction 6231 /* 10-13 instructions */ 6232 6233 6234/* ------------------------------ */ 6235 .balign 64 6236.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6237/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6238/* File: arm-vfp/fbinopWide2addr.S */ 6239 /* 6240 * Generic 64-bit floating point "/2addr" binary operation. Provide 6241 * an "instr" line that specifies an instruction that performs 6242 * "d2 = d0 op d1". 6243 * 6244 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6245 * div-double/2addr 6246 */ 6247 /* binop/2addr vA, vB */ 6248 mov r3, rINST, lsr #12 @ r3<- B 6249 mov r9, rINST, lsr #8 @ r9<- A+ 6250 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6251 and r9, r9, #15 @ r9<- A 6252 fldd d1, [r3] @ d1<- vB 6253 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6254 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6255 fldd d0, [r9] @ d0<- vA 6256 6257 faddd d2, d0, d1 @ d2<- op 6258 GET_INST_OPCODE(ip) @ extract opcode from rINST 6259 fstd d2, [r9] @ vAA<- d2 6260 GOTO_OPCODE(ip) @ jump to next instruction 6261 6262 6263/* ------------------------------ */ 6264 .balign 64 6265.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6266/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6267/* File: arm-vfp/fbinopWide2addr.S */ 6268 /* 6269 * Generic 64-bit floating point "/2addr" binary operation. Provide 6270 * an "instr" line that specifies an instruction that performs 6271 * "d2 = d0 op d1". 6272 * 6273 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6274 * div-double/2addr 6275 */ 6276 /* binop/2addr vA, vB */ 6277 mov r3, rINST, lsr #12 @ r3<- B 6278 mov r9, rINST, lsr #8 @ r9<- A+ 6279 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6280 and r9, r9, #15 @ r9<- A 6281 fldd d1, [r3] @ d1<- vB 6282 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6283 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6284 fldd d0, [r9] @ d0<- vA 6285 6286 fsubd d2, d0, d1 @ d2<- op 6287 GET_INST_OPCODE(ip) @ extract opcode from rINST 6288 fstd d2, [r9] @ vAA<- d2 6289 GOTO_OPCODE(ip) @ jump to next instruction 6290 6291 6292/* ------------------------------ */ 6293 .balign 64 6294.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6295/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6296/* File: arm-vfp/fbinopWide2addr.S */ 6297 /* 6298 * Generic 64-bit floating point "/2addr" binary operation. Provide 6299 * an "instr" line that specifies an instruction that performs 6300 * "d2 = d0 op d1". 6301 * 6302 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6303 * div-double/2addr 6304 */ 6305 /* binop/2addr vA, vB */ 6306 mov r3, rINST, lsr #12 @ r3<- B 6307 mov r9, rINST, lsr #8 @ r9<- A+ 6308 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6309 and r9, r9, #15 @ r9<- A 6310 fldd d1, [r3] @ d1<- vB 6311 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6312 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6313 fldd d0, [r9] @ d0<- vA 6314 6315 fmuld d2, d0, d1 @ d2<- op 6316 GET_INST_OPCODE(ip) @ extract opcode from rINST 6317 fstd d2, [r9] @ vAA<- d2 6318 GOTO_OPCODE(ip) @ jump to next instruction 6319 6320 6321/* ------------------------------ */ 6322 .balign 64 6323.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6324/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6325/* File: arm-vfp/fbinopWide2addr.S */ 6326 /* 6327 * Generic 64-bit floating point "/2addr" binary operation. Provide 6328 * an "instr" line that specifies an instruction that performs 6329 * "d2 = d0 op d1". 6330 * 6331 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6332 * div-double/2addr 6333 */ 6334 /* binop/2addr vA, vB */ 6335 mov r3, rINST, lsr #12 @ r3<- B 6336 mov r9, rINST, lsr #8 @ r9<- A+ 6337 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6338 and r9, r9, #15 @ r9<- A 6339 fldd d1, [r3] @ d1<- vB 6340 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6341 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6342 fldd d0, [r9] @ d0<- vA 6343 6344 fdivd d2, d0, d1 @ d2<- op 6345 GET_INST_OPCODE(ip) @ extract opcode from rINST 6346 fstd d2, [r9] @ vAA<- d2 6347 GOTO_OPCODE(ip) @ jump to next instruction 6348 6349 6350/* ------------------------------ */ 6351 .balign 64 6352.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6353/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6354/* EABI doesn't define a double remainder function, but libm does */ 6355/* File: armv5te/binopWide2addr.S */ 6356 /* 6357 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6358 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6359 * This could be an ARM instruction or a function call. (If the result 6360 * comes back in a register other than r0, you can override "result".) 6361 * 6362 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6363 * vCC (r1). Useful for integer division and modulus. 6364 * 6365 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6366 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6367 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6368 * rem-double/2addr 6369 */ 6370 /* binop/2addr vA, vB */ 6371 mov r9, rINST, lsr #8 @ r9<- A+ 6372 mov r1, rINST, lsr #12 @ r1<- B 6373 and r9, r9, #15 6374 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6375 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6376 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6377 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6378 .if 0 6379 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6380 beq common_errDivideByZero 6381 .endif 6382 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6383 6384 @ optional op; may set condition codes 6385 bl fmod @ result<- op, r0-r3 changed 6386 GET_INST_OPCODE(ip) @ extract opcode from rINST 6387 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6388 GOTO_OPCODE(ip) @ jump to next instruction 6389 /* 12-15 instructions */ 6390 6391 6392/* ------------------------------ */ 6393 .balign 64 6394.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6395/* File: armv5te/OP_ADD_INT_LIT16.S */ 6396/* File: armv5te/binopLit16.S */ 6397 /* 6398 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6399 * that specifies an instruction that performs "result = r0 op r1". 6400 * This could be an ARM instruction or a function call. (If the result 6401 * comes back in a register other than r0, you can override "result".) 6402 * 6403 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6404 * vCC (r1). Useful for integer division and modulus. 6405 * 6406 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6407 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6408 */ 6409 /* binop/lit16 vA, vB, #+CCCC */ 6410 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6411 mov r2, rINST, lsr #12 @ r2<- B 6412 mov r9, rINST, lsr #8 @ r9<- A+ 6413 GET_VREG(r0, r2) @ r0<- vB 6414 and r9, r9, #15 6415 .if 0 6416 cmp r1, #0 @ is second operand zero? 6417 beq common_errDivideByZero 6418 .endif 6419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6420 6421 add r0, r0, r1 @ r0<- op, r0-r3 changed 6422 GET_INST_OPCODE(ip) @ extract opcode from rINST 6423 SET_VREG(r0, r9) @ vAA<- r0 6424 GOTO_OPCODE(ip) @ jump to next instruction 6425 /* 10-13 instructions */ 6426 6427 6428/* ------------------------------ */ 6429 .balign 64 6430.L_OP_RSUB_INT: /* 0xd1 */ 6431/* File: armv5te/OP_RSUB_INT.S */ 6432/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6433/* File: armv5te/binopLit16.S */ 6434 /* 6435 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6436 * that specifies an instruction that performs "result = r0 op r1". 6437 * This could be an ARM instruction or a function call. (If the result 6438 * comes back in a register other than r0, you can override "result".) 6439 * 6440 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6441 * vCC (r1). Useful for integer division and modulus. 6442 * 6443 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6444 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6445 */ 6446 /* binop/lit16 vA, vB, #+CCCC */ 6447 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6448 mov r2, rINST, lsr #12 @ r2<- B 6449 mov r9, rINST, lsr #8 @ r9<- A+ 6450 GET_VREG(r0, r2) @ r0<- vB 6451 and r9, r9, #15 6452 .if 0 6453 cmp r1, #0 @ is second operand zero? 6454 beq common_errDivideByZero 6455 .endif 6456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6457 6458 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6459 GET_INST_OPCODE(ip) @ extract opcode from rINST 6460 SET_VREG(r0, r9) @ vAA<- r0 6461 GOTO_OPCODE(ip) @ jump to next instruction 6462 /* 10-13 instructions */ 6463 6464 6465/* ------------------------------ */ 6466 .balign 64 6467.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6468/* File: armv5te/OP_MUL_INT_LIT16.S */ 6469/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6470/* File: armv5te/binopLit16.S */ 6471 /* 6472 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6473 * that specifies an instruction that performs "result = r0 op r1". 6474 * This could be an ARM instruction or a function call. (If the result 6475 * comes back in a register other than r0, you can override "result".) 6476 * 6477 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6478 * vCC (r1). Useful for integer division and modulus. 6479 * 6480 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6481 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6482 */ 6483 /* binop/lit16 vA, vB, #+CCCC */ 6484 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6485 mov r2, rINST, lsr #12 @ r2<- B 6486 mov r9, rINST, lsr #8 @ r9<- A+ 6487 GET_VREG(r0, r2) @ r0<- vB 6488 and r9, r9, #15 6489 .if 0 6490 cmp r1, #0 @ is second operand zero? 6491 beq common_errDivideByZero 6492 .endif 6493 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6494 6495 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6496 GET_INST_OPCODE(ip) @ extract opcode from rINST 6497 SET_VREG(r0, r9) @ vAA<- r0 6498 GOTO_OPCODE(ip) @ jump to next instruction 6499 /* 10-13 instructions */ 6500 6501 6502/* ------------------------------ */ 6503 .balign 64 6504.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6505/* File: armv5te/OP_DIV_INT_LIT16.S */ 6506/* File: armv5te/binopLit16.S */ 6507 /* 6508 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6509 * that specifies an instruction that performs "result = r0 op r1". 6510 * This could be an ARM instruction or a function call. (If the result 6511 * comes back in a register other than r0, you can override "result".) 6512 * 6513 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6514 * vCC (r1). Useful for integer division and modulus. 6515 * 6516 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6517 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6518 */ 6519 /* binop/lit16 vA, vB, #+CCCC */ 6520 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6521 mov r2, rINST, lsr #12 @ r2<- B 6522 mov r9, rINST, lsr #8 @ r9<- A+ 6523 GET_VREG(r0, r2) @ r0<- vB 6524 and r9, r9, #15 6525 .if 1 6526 cmp r1, #0 @ is second operand zero? 6527 beq common_errDivideByZero 6528 .endif 6529 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6530 6531 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6532 GET_INST_OPCODE(ip) @ extract opcode from rINST 6533 SET_VREG(r0, r9) @ vAA<- r0 6534 GOTO_OPCODE(ip) @ jump to next instruction 6535 /* 10-13 instructions */ 6536 6537 6538/* ------------------------------ */ 6539 .balign 64 6540.L_OP_REM_INT_LIT16: /* 0xd4 */ 6541/* File: armv5te/OP_REM_INT_LIT16.S */ 6542/* idivmod returns quotient in r0 and remainder in r1 */ 6543/* File: armv5te/binopLit16.S */ 6544 /* 6545 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6546 * that specifies an instruction that performs "result = r0 op r1". 6547 * This could be an ARM instruction or a function call. (If the result 6548 * comes back in a register other than r0, you can override "result".) 6549 * 6550 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6551 * vCC (r1). Useful for integer division and modulus. 6552 * 6553 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6554 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6555 */ 6556 /* binop/lit16 vA, vB, #+CCCC */ 6557 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6558 mov r2, rINST, lsr #12 @ r2<- B 6559 mov r9, rINST, lsr #8 @ r9<- A+ 6560 GET_VREG(r0, r2) @ r0<- vB 6561 and r9, r9, #15 6562 .if 1 6563 cmp r1, #0 @ is second operand zero? 6564 beq common_errDivideByZero 6565 .endif 6566 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6567 6568 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6569 GET_INST_OPCODE(ip) @ extract opcode from rINST 6570 SET_VREG(r1, r9) @ vAA<- r1 6571 GOTO_OPCODE(ip) @ jump to next instruction 6572 /* 10-13 instructions */ 6573 6574 6575/* ------------------------------ */ 6576 .balign 64 6577.L_OP_AND_INT_LIT16: /* 0xd5 */ 6578/* File: armv5te/OP_AND_INT_LIT16.S */ 6579/* File: armv5te/binopLit16.S */ 6580 /* 6581 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6582 * that specifies an instruction that performs "result = r0 op r1". 6583 * This could be an ARM instruction or a function call. (If the result 6584 * comes back in a register other than r0, you can override "result".) 6585 * 6586 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6587 * vCC (r1). Useful for integer division and modulus. 6588 * 6589 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6590 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6591 */ 6592 /* binop/lit16 vA, vB, #+CCCC */ 6593 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6594 mov r2, rINST, lsr #12 @ r2<- B 6595 mov r9, rINST, lsr #8 @ r9<- A+ 6596 GET_VREG(r0, r2) @ r0<- vB 6597 and r9, r9, #15 6598 .if 0 6599 cmp r1, #0 @ is second operand zero? 6600 beq common_errDivideByZero 6601 .endif 6602 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6603 6604 and r0, r0, r1 @ r0<- op, r0-r3 changed 6605 GET_INST_OPCODE(ip) @ extract opcode from rINST 6606 SET_VREG(r0, r9) @ vAA<- r0 6607 GOTO_OPCODE(ip) @ jump to next instruction 6608 /* 10-13 instructions */ 6609 6610 6611/* ------------------------------ */ 6612 .balign 64 6613.L_OP_OR_INT_LIT16: /* 0xd6 */ 6614/* File: armv5te/OP_OR_INT_LIT16.S */ 6615/* File: armv5te/binopLit16.S */ 6616 /* 6617 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6618 * that specifies an instruction that performs "result = r0 op r1". 6619 * This could be an ARM instruction or a function call. (If the result 6620 * comes back in a register other than r0, you can override "result".) 6621 * 6622 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6623 * vCC (r1). Useful for integer division and modulus. 6624 * 6625 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6626 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6627 */ 6628 /* binop/lit16 vA, vB, #+CCCC */ 6629 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6630 mov r2, rINST, lsr #12 @ r2<- B 6631 mov r9, rINST, lsr #8 @ r9<- A+ 6632 GET_VREG(r0, r2) @ r0<- vB 6633 and r9, r9, #15 6634 .if 0 6635 cmp r1, #0 @ is second operand zero? 6636 beq common_errDivideByZero 6637 .endif 6638 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6639 6640 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6641 GET_INST_OPCODE(ip) @ extract opcode from rINST 6642 SET_VREG(r0, r9) @ vAA<- r0 6643 GOTO_OPCODE(ip) @ jump to next instruction 6644 /* 10-13 instructions */ 6645 6646 6647/* ------------------------------ */ 6648 .balign 64 6649.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6650/* File: armv5te/OP_XOR_INT_LIT16.S */ 6651/* File: armv5te/binopLit16.S */ 6652 /* 6653 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6654 * that specifies an instruction that performs "result = r0 op r1". 6655 * This could be an ARM instruction or a function call. (If the result 6656 * comes back in a register other than r0, you can override "result".) 6657 * 6658 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6659 * vCC (r1). Useful for integer division and modulus. 6660 * 6661 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6662 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6663 */ 6664 /* binop/lit16 vA, vB, #+CCCC */ 6665 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6666 mov r2, rINST, lsr #12 @ r2<- B 6667 mov r9, rINST, lsr #8 @ r9<- A+ 6668 GET_VREG(r0, r2) @ r0<- vB 6669 and r9, r9, #15 6670 .if 0 6671 cmp r1, #0 @ is second operand zero? 6672 beq common_errDivideByZero 6673 .endif 6674 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6675 6676 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6677 GET_INST_OPCODE(ip) @ extract opcode from rINST 6678 SET_VREG(r0, r9) @ vAA<- r0 6679 GOTO_OPCODE(ip) @ jump to next instruction 6680 /* 10-13 instructions */ 6681 6682 6683/* ------------------------------ */ 6684 .balign 64 6685.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6686/* File: armv5te/OP_ADD_INT_LIT8.S */ 6687/* File: armv5te/binopLit8.S */ 6688 /* 6689 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6690 * that specifies an instruction that performs "result = r0 op r1". 6691 * This could be an ARM instruction or a function call. (If the result 6692 * comes back in a register other than r0, you can override "result".) 6693 * 6694 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6695 * vCC (r1). Useful for integer division and modulus. 6696 * 6697 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6698 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6699 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6700 */ 6701 /* binop/lit8 vAA, vBB, #+CC */ 6702 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6703 mov r9, rINST, lsr #8 @ r9<- AA 6704 and r2, r3, #255 @ r2<- BB 6705 GET_VREG(r0, r2) @ r0<- vBB 6706 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6707 .if 0 6708 @cmp r1, #0 @ is second operand zero? 6709 beq common_errDivideByZero 6710 .endif 6711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6712 6713 @ optional op; may set condition codes 6714 add r0, r0, r1 @ r0<- op, r0-r3 changed 6715 GET_INST_OPCODE(ip) @ extract opcode from rINST 6716 SET_VREG(r0, r9) @ vAA<- r0 6717 GOTO_OPCODE(ip) @ jump to next instruction 6718 /* 10-12 instructions */ 6719 6720 6721/* ------------------------------ */ 6722 .balign 64 6723.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6724/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6725/* File: armv5te/binopLit8.S */ 6726 /* 6727 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6728 * that specifies an instruction that performs "result = r0 op r1". 6729 * This could be an ARM instruction or a function call. (If the result 6730 * comes back in a register other than r0, you can override "result".) 6731 * 6732 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6733 * vCC (r1). Useful for integer division and modulus. 6734 * 6735 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6736 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6737 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6738 */ 6739 /* binop/lit8 vAA, vBB, #+CC */ 6740 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6741 mov r9, rINST, lsr #8 @ r9<- AA 6742 and r2, r3, #255 @ r2<- BB 6743 GET_VREG(r0, r2) @ r0<- vBB 6744 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6745 .if 0 6746 @cmp r1, #0 @ is second operand zero? 6747 beq common_errDivideByZero 6748 .endif 6749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6750 6751 @ optional op; may set condition codes 6752 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6753 GET_INST_OPCODE(ip) @ extract opcode from rINST 6754 SET_VREG(r0, r9) @ vAA<- r0 6755 GOTO_OPCODE(ip) @ jump to next instruction 6756 /* 10-12 instructions */ 6757 6758 6759/* ------------------------------ */ 6760 .balign 64 6761.L_OP_MUL_INT_LIT8: /* 0xda */ 6762/* File: armv5te/OP_MUL_INT_LIT8.S */ 6763/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6764/* File: armv5te/binopLit8.S */ 6765 /* 6766 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6767 * that specifies an instruction that performs "result = r0 op r1". 6768 * This could be an ARM instruction or a function call. (If the result 6769 * comes back in a register other than r0, you can override "result".) 6770 * 6771 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6772 * vCC (r1). Useful for integer division and modulus. 6773 * 6774 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6775 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6776 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6777 */ 6778 /* binop/lit8 vAA, vBB, #+CC */ 6779 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6780 mov r9, rINST, lsr #8 @ r9<- AA 6781 and r2, r3, #255 @ r2<- BB 6782 GET_VREG(r0, r2) @ r0<- vBB 6783 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6784 .if 0 6785 @cmp r1, #0 @ is second operand zero? 6786 beq common_errDivideByZero 6787 .endif 6788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6789 6790 @ optional op; may set condition codes 6791 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6792 GET_INST_OPCODE(ip) @ extract opcode from rINST 6793 SET_VREG(r0, r9) @ vAA<- r0 6794 GOTO_OPCODE(ip) @ jump to next instruction 6795 /* 10-12 instructions */ 6796 6797 6798/* ------------------------------ */ 6799 .balign 64 6800.L_OP_DIV_INT_LIT8: /* 0xdb */ 6801/* File: armv5te/OP_DIV_INT_LIT8.S */ 6802/* File: armv5te/binopLit8.S */ 6803 /* 6804 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6805 * that specifies an instruction that performs "result = r0 op r1". 6806 * This could be an ARM instruction or a function call. (If the result 6807 * comes back in a register other than r0, you can override "result".) 6808 * 6809 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6810 * vCC (r1). Useful for integer division and modulus. 6811 * 6812 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6813 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6814 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6815 */ 6816 /* binop/lit8 vAA, vBB, #+CC */ 6817 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6818 mov r9, rINST, lsr #8 @ r9<- AA 6819 and r2, r3, #255 @ r2<- BB 6820 GET_VREG(r0, r2) @ r0<- vBB 6821 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6822 .if 1 6823 @cmp r1, #0 @ is second operand zero? 6824 beq common_errDivideByZero 6825 .endif 6826 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6827 6828 @ optional op; may set condition codes 6829 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6830 GET_INST_OPCODE(ip) @ extract opcode from rINST 6831 SET_VREG(r0, r9) @ vAA<- r0 6832 GOTO_OPCODE(ip) @ jump to next instruction 6833 /* 10-12 instructions */ 6834 6835 6836/* ------------------------------ */ 6837 .balign 64 6838.L_OP_REM_INT_LIT8: /* 0xdc */ 6839/* File: armv5te/OP_REM_INT_LIT8.S */ 6840/* idivmod returns quotient in r0 and remainder in r1 */ 6841/* File: armv5te/binopLit8.S */ 6842 /* 6843 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6844 * that specifies an instruction that performs "result = r0 op r1". 6845 * This could be an ARM instruction or a function call. (If the result 6846 * comes back in a register other than r0, you can override "result".) 6847 * 6848 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6849 * vCC (r1). Useful for integer division and modulus. 6850 * 6851 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6852 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6853 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6854 */ 6855 /* binop/lit8 vAA, vBB, #+CC */ 6856 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6857 mov r9, rINST, lsr #8 @ r9<- AA 6858 and r2, r3, #255 @ r2<- BB 6859 GET_VREG(r0, r2) @ r0<- vBB 6860 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6861 .if 1 6862 @cmp r1, #0 @ is second operand zero? 6863 beq common_errDivideByZero 6864 .endif 6865 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6866 6867 @ optional op; may set condition codes 6868 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6869 GET_INST_OPCODE(ip) @ extract opcode from rINST 6870 SET_VREG(r1, r9) @ vAA<- r1 6871 GOTO_OPCODE(ip) @ jump to next instruction 6872 /* 10-12 instructions */ 6873 6874 6875/* ------------------------------ */ 6876 .balign 64 6877.L_OP_AND_INT_LIT8: /* 0xdd */ 6878/* File: armv5te/OP_AND_INT_LIT8.S */ 6879/* File: armv5te/binopLit8.S */ 6880 /* 6881 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6882 * that specifies an instruction that performs "result = r0 op r1". 6883 * This could be an ARM instruction or a function call. (If the result 6884 * comes back in a register other than r0, you can override "result".) 6885 * 6886 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6887 * vCC (r1). Useful for integer division and modulus. 6888 * 6889 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6890 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6891 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6892 */ 6893 /* binop/lit8 vAA, vBB, #+CC */ 6894 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6895 mov r9, rINST, lsr #8 @ r9<- AA 6896 and r2, r3, #255 @ r2<- BB 6897 GET_VREG(r0, r2) @ r0<- vBB 6898 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6899 .if 0 6900 @cmp r1, #0 @ is second operand zero? 6901 beq common_errDivideByZero 6902 .endif 6903 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6904 6905 @ optional op; may set condition codes 6906 and r0, r0, r1 @ r0<- op, r0-r3 changed 6907 GET_INST_OPCODE(ip) @ extract opcode from rINST 6908 SET_VREG(r0, r9) @ vAA<- r0 6909 GOTO_OPCODE(ip) @ jump to next instruction 6910 /* 10-12 instructions */ 6911 6912 6913/* ------------------------------ */ 6914 .balign 64 6915.L_OP_OR_INT_LIT8: /* 0xde */ 6916/* File: armv5te/OP_OR_INT_LIT8.S */ 6917/* File: armv5te/binopLit8.S */ 6918 /* 6919 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6920 * that specifies an instruction that performs "result = r0 op r1". 6921 * This could be an ARM instruction or a function call. (If the result 6922 * comes back in a register other than r0, you can override "result".) 6923 * 6924 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6925 * vCC (r1). Useful for integer division and modulus. 6926 * 6927 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6928 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6929 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6930 */ 6931 /* binop/lit8 vAA, vBB, #+CC */ 6932 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6933 mov r9, rINST, lsr #8 @ r9<- AA 6934 and r2, r3, #255 @ r2<- BB 6935 GET_VREG(r0, r2) @ r0<- vBB 6936 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6937 .if 0 6938 @cmp r1, #0 @ is second operand zero? 6939 beq common_errDivideByZero 6940 .endif 6941 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6942 6943 @ optional op; may set condition codes 6944 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6945 GET_INST_OPCODE(ip) @ extract opcode from rINST 6946 SET_VREG(r0, r9) @ vAA<- r0 6947 GOTO_OPCODE(ip) @ jump to next instruction 6948 /* 10-12 instructions */ 6949 6950 6951/* ------------------------------ */ 6952 .balign 64 6953.L_OP_XOR_INT_LIT8: /* 0xdf */ 6954/* File: armv5te/OP_XOR_INT_LIT8.S */ 6955/* File: armv5te/binopLit8.S */ 6956 /* 6957 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6958 * that specifies an instruction that performs "result = r0 op r1". 6959 * This could be an ARM instruction or a function call. (If the result 6960 * comes back in a register other than r0, you can override "result".) 6961 * 6962 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6963 * vCC (r1). Useful for integer division and modulus. 6964 * 6965 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6966 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6967 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6968 */ 6969 /* binop/lit8 vAA, vBB, #+CC */ 6970 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6971 mov r9, rINST, lsr #8 @ r9<- AA 6972 and r2, r3, #255 @ r2<- BB 6973 GET_VREG(r0, r2) @ r0<- vBB 6974 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6975 .if 0 6976 @cmp r1, #0 @ is second operand zero? 6977 beq common_errDivideByZero 6978 .endif 6979 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6980 6981 @ optional op; may set condition codes 6982 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6983 GET_INST_OPCODE(ip) @ extract opcode from rINST 6984 SET_VREG(r0, r9) @ vAA<- r0 6985 GOTO_OPCODE(ip) @ jump to next instruction 6986 /* 10-12 instructions */ 6987 6988 6989/* ------------------------------ */ 6990 .balign 64 6991.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6992/* File: armv5te/OP_SHL_INT_LIT8.S */ 6993/* File: armv5te/binopLit8.S */ 6994 /* 6995 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6996 * that specifies an instruction that performs "result = r0 op r1". 6997 * This could be an ARM instruction or a function call. (If the result 6998 * comes back in a register other than r0, you can override "result".) 6999 * 7000 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7001 * vCC (r1). Useful for integer division and modulus. 7002 * 7003 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7004 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7005 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7006 */ 7007 /* binop/lit8 vAA, vBB, #+CC */ 7008 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7009 mov r9, rINST, lsr #8 @ r9<- AA 7010 and r2, r3, #255 @ r2<- BB 7011 GET_VREG(r0, r2) @ r0<- vBB 7012 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7013 .if 0 7014 @cmp r1, #0 @ is second operand zero? 7015 beq common_errDivideByZero 7016 .endif 7017 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7018 7019 and r1, r1, #31 @ optional op; may set condition codes 7020 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7021 GET_INST_OPCODE(ip) @ extract opcode from rINST 7022 SET_VREG(r0, r9) @ vAA<- r0 7023 GOTO_OPCODE(ip) @ jump to next instruction 7024 /* 10-12 instructions */ 7025 7026 7027/* ------------------------------ */ 7028 .balign 64 7029.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7030/* File: armv5te/OP_SHR_INT_LIT8.S */ 7031/* File: armv5te/binopLit8.S */ 7032 /* 7033 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7034 * that specifies an instruction that performs "result = r0 op r1". 7035 * This could be an ARM instruction or a function call. (If the result 7036 * comes back in a register other than r0, you can override "result".) 7037 * 7038 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7039 * vCC (r1). Useful for integer division and modulus. 7040 * 7041 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7042 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7043 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7044 */ 7045 /* binop/lit8 vAA, vBB, #+CC */ 7046 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7047 mov r9, rINST, lsr #8 @ r9<- AA 7048 and r2, r3, #255 @ r2<- BB 7049 GET_VREG(r0, r2) @ r0<- vBB 7050 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7051 .if 0 7052 @cmp r1, #0 @ is second operand zero? 7053 beq common_errDivideByZero 7054 .endif 7055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7056 7057 and r1, r1, #31 @ optional op; may set condition codes 7058 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7059 GET_INST_OPCODE(ip) @ extract opcode from rINST 7060 SET_VREG(r0, r9) @ vAA<- r0 7061 GOTO_OPCODE(ip) @ jump to next instruction 7062 /* 10-12 instructions */ 7063 7064 7065/* ------------------------------ */ 7066 .balign 64 7067.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7068/* File: armv5te/OP_USHR_INT_LIT8.S */ 7069/* File: armv5te/binopLit8.S */ 7070 /* 7071 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7072 * that specifies an instruction that performs "result = r0 op r1". 7073 * This could be an ARM instruction or a function call. (If the result 7074 * comes back in a register other than r0, you can override "result".) 7075 * 7076 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7077 * vCC (r1). Useful for integer division and modulus. 7078 * 7079 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7080 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7081 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7082 */ 7083 /* binop/lit8 vAA, vBB, #+CC */ 7084 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7085 mov r9, rINST, lsr #8 @ r9<- AA 7086 and r2, r3, #255 @ r2<- BB 7087 GET_VREG(r0, r2) @ r0<- vBB 7088 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7089 .if 0 7090 @cmp r1, #0 @ is second operand zero? 7091 beq common_errDivideByZero 7092 .endif 7093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7094 7095 and r1, r1, #31 @ optional op; may set condition codes 7096 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7097 GET_INST_OPCODE(ip) @ extract opcode from rINST 7098 SET_VREG(r0, r9) @ vAA<- r0 7099 GOTO_OPCODE(ip) @ jump to next instruction 7100 /* 10-12 instructions */ 7101 7102 7103/* ------------------------------ */ 7104 .balign 64 7105.L_OP_IGET_VOLATILE: /* 0xe3 */ 7106/* File: armv5te/OP_IGET_VOLATILE.S */ 7107/* File: armv5te/OP_IGET.S */ 7108 /* 7109 * General 32-bit instance field get. 7110 * 7111 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7112 */ 7113 /* op vA, vB, field@CCCC */ 7114 mov r0, rINST, lsr #12 @ r0<- B 7115 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7116 FETCH(r1, 1) @ r1<- field ref CCCC 7117 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7118 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7119 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7120 cmp r0, #0 @ is resolved entry null? 7121 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 71228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7123 EXPORT_PC() @ resolve() could throw 7124 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7125 bl dvmResolveInstField @ r0<- resolved InstField ptr 7126 cmp r0, #0 7127 bne .LOP_IGET_VOLATILE_finish 7128 b common_exceptionThrown 7129 7130 7131/* ------------------------------ */ 7132 .balign 64 7133.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7134/* File: armv5te/OP_IPUT_VOLATILE.S */ 7135/* File: armv5te/OP_IPUT.S */ 7136 /* 7137 * General 32-bit instance field put. 7138 * 7139 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 7140 */ 7141 /* op vA, vB, field@CCCC */ 7142 mov r0, rINST, lsr #12 @ r0<- B 7143 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7144 FETCH(r1, 1) @ r1<- field ref CCCC 7145 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7146 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7147 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7148 cmp r0, #0 @ is resolved entry null? 7149 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71508: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7151 EXPORT_PC() @ resolve() could throw 7152 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7153 bl dvmResolveInstField @ r0<- resolved InstField ptr 7154 cmp r0, #0 @ success? 7155 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7156 b common_exceptionThrown 7157 7158 7159/* ------------------------------ */ 7160 .balign 64 7161.L_OP_SGET_VOLATILE: /* 0xe5 */ 7162/* File: armv5te/OP_SGET_VOLATILE.S */ 7163/* File: armv5te/OP_SGET.S */ 7164 /* 7165 * General 32-bit SGET handler. 7166 * 7167 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7168 */ 7169 /* op vAA, field@BBBB */ 7170 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7171 FETCH(r1, 1) @ r1<- field ref BBBB 7172 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7173 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7174 cmp r0, #0 @ is resolved entry null? 7175 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7176.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7177 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7178 SMP_DMB 1 @ acquiring load 7179 mov r2, rINST, lsr #8 @ r2<- AA 7180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7181 SET_VREG(r1, r2) @ fp[AA]<- r1 7182 GET_INST_OPCODE(ip) @ extract opcode from rINST 7183 GOTO_OPCODE(ip) @ jump to next instruction 7184 7185 7186/* ------------------------------ */ 7187 .balign 64 7188.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7189/* File: armv5te/OP_SPUT_VOLATILE.S */ 7190/* File: armv5te/OP_SPUT.S */ 7191 /* 7192 * General 32-bit SPUT handler. 7193 * 7194 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 7195 */ 7196 /* op vAA, field@BBBB */ 7197 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7198 FETCH(r1, 1) @ r1<- field ref BBBB 7199 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7200 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7201 cmp r0, #0 @ is resolved entry null? 7202 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7203.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7204 mov r2, rINST, lsr #8 @ r2<- AA 7205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7206 GET_VREG(r1, r2) @ r1<- fp[AA] 7207 GET_INST_OPCODE(ip) @ extract opcode from rINST 7208 SMP_DMB 1 @ releasing store 7209 str r1, [r0, #offStaticField_value] @ field<- vAA 7210 GOTO_OPCODE(ip) @ jump to next instruction 7211 7212 7213/* ------------------------------ */ 7214 .balign 64 7215.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7216/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7217/* File: armv5te/OP_IGET.S */ 7218 /* 7219 * General 32-bit instance field get. 7220 * 7221 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7222 */ 7223 /* op vA, vB, field@CCCC */ 7224 mov r0, rINST, lsr #12 @ r0<- B 7225 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7226 FETCH(r1, 1) @ r1<- field ref CCCC 7227 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7228 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7229 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7230 cmp r0, #0 @ is resolved entry null? 7231 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72328: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7233 EXPORT_PC() @ resolve() could throw 7234 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7235 bl dvmResolveInstField @ r0<- resolved InstField ptr 7236 cmp r0, #0 7237 bne .LOP_IGET_OBJECT_VOLATILE_finish 7238 b common_exceptionThrown 7239 7240 7241/* ------------------------------ */ 7242 .balign 64 7243.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7244/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7245/* File: armv5te/OP_IGET_WIDE.S */ 7246 /* 7247 * Wide 32-bit instance field get. 7248 */ 7249 /* iget-wide vA, vB, field@CCCC */ 7250 mov r0, rINST, lsr #12 @ r0<- B 7251 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7252 FETCH(r1, 1) @ r1<- field ref CCCC 7253 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7254 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7255 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7256 cmp r0, #0 @ is resolved entry null? 7257 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7259 EXPORT_PC() @ resolve() could throw 7260 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7261 bl dvmResolveInstField @ r0<- resolved InstField ptr 7262 cmp r0, #0 7263 bne .LOP_IGET_WIDE_VOLATILE_finish 7264 b common_exceptionThrown 7265 7266 7267/* ------------------------------ */ 7268 .balign 64 7269.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7270/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7271/* File: armv5te/OP_IPUT_WIDE.S */ 7272 /* iput-wide vA, vB, field@CCCC */ 7273 mov r0, rINST, lsr #12 @ r0<- B 7274 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7275 FETCH(r1, 1) @ r1<- field ref CCCC 7276 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7277 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7278 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7279 cmp r0, #0 @ is resolved entry null? 7280 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7282 EXPORT_PC() @ resolve() could throw 7283 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7284 bl dvmResolveInstField @ r0<- resolved InstField ptr 7285 cmp r0, #0 @ success? 7286 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7287 b common_exceptionThrown 7288 7289 7290/* ------------------------------ */ 7291 .balign 64 7292.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7293/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7294/* File: armv5te/OP_SGET_WIDE.S */ 7295 /* 7296 * 64-bit SGET handler. 7297 */ 7298 /* sget-wide vAA, field@BBBB */ 7299 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7300 FETCH(r1, 1) @ r1<- field ref BBBB 7301 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7302 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7303 cmp r0, #0 @ is resolved entry null? 7304 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7305.LOP_SGET_WIDE_VOLATILE_finish: 7306 mov r9, rINST, lsr #8 @ r9<- AA 7307 .if 1 7308 add r0, r0, #offStaticField_value @ r0<- pointer to data 7309 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7310 .else 7311 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7312 .endif 7313 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7314 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7315 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7316 GET_INST_OPCODE(ip) @ extract opcode from rINST 7317 GOTO_OPCODE(ip) @ jump to next instruction 7318 7319 7320/* ------------------------------ */ 7321 .balign 64 7322.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7323/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7324/* File: armv5te/OP_SPUT_WIDE.S */ 7325 /* 7326 * 64-bit SPUT handler. 7327 */ 7328 /* sput-wide vAA, field@BBBB */ 7329 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7330 FETCH(r1, 1) @ r1<- field ref BBBB 7331 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7332 mov r9, rINST, lsr #8 @ r9<- AA 7333 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7334 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7335 cmp r2, #0 @ is resolved entry null? 7336 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7337.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7338 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7339 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7340 GET_INST_OPCODE(r10) @ extract opcode from rINST 7341 .if 1 7342 add r2, r2, #offStaticField_value @ r2<- pointer to data 7343 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7344 .else 7345 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7346 .endif 7347 GOTO_OPCODE(r10) @ jump to next instruction 7348 7349 7350/* ------------------------------ */ 7351 .balign 64 7352.L_OP_BREAKPOINT: /* 0xec */ 7353/* File: armv5te/OP_BREAKPOINT.S */ 7354/* File: armv5te/unused.S */ 7355 bl common_abort 7356 7357 7358/* ------------------------------ */ 7359 .balign 64 7360.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7361/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7362 /* 7363 * Handle a throw-verification-error instruction. This throws an 7364 * exception for an error discovered during verification. The 7365 * exception is indicated by AA, with some detail provided by BBBB. 7366 */ 7367 /* op AA, ref@BBBB */ 7368 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7369 FETCH(r2, 1) @ r2<- BBBB 7370 EXPORT_PC() @ export the PC 7371 mov r1, rINST, lsr #8 @ r1<- AA 7372 bl dvmThrowVerificationError @ always throws 7373 b common_exceptionThrown @ handle exception 7374 7375/* ------------------------------ */ 7376 .balign 64 7377.L_OP_EXECUTE_INLINE: /* 0xee */ 7378/* File: armv5te/OP_EXECUTE_INLINE.S */ 7379 /* 7380 * Execute a "native inline" instruction. 7381 * 7382 * We need to call an InlineOp4Func: 7383 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7384 * 7385 * The first four args are in r0-r3, pointer to return value storage 7386 * is on the stack. The function's return value is a flag that tells 7387 * us if an exception was thrown. 7388 */ 7389 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7390 FETCH(r10, 1) @ r10<- BBBB 7391 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7392 EXPORT_PC() @ can throw 7393 sub sp, sp, #8 @ make room for arg, +64 bit align 7394 mov r0, rINST, lsr #12 @ r0<- B 7395 str r1, [sp] @ push &glue->retval 7396 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7397 add sp, sp, #8 @ pop stack 7398 cmp r0, #0 @ test boolean result of inline 7399 beq common_exceptionThrown @ returned false, handle exception 7400 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7401 GET_INST_OPCODE(ip) @ extract opcode from rINST 7402 GOTO_OPCODE(ip) @ jump to next instruction 7403 7404/* ------------------------------ */ 7405 .balign 64 7406.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7407/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7408 /* 7409 * Execute a "native inline" instruction, using "/range" semantics. 7410 * Same idea as execute-inline, but we get the args differently. 7411 * 7412 * We need to call an InlineOp4Func: 7413 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7414 * 7415 * The first four args are in r0-r3, pointer to return value storage 7416 * is on the stack. The function's return value is a flag that tells 7417 * us if an exception was thrown. 7418 */ 7419 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7420 FETCH(r10, 1) @ r10<- BBBB 7421 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7422 EXPORT_PC() @ can throw 7423 sub sp, sp, #8 @ make room for arg, +64 bit align 7424 mov r0, rINST, lsr #8 @ r0<- AA 7425 str r1, [sp] @ push &glue->retval 7426 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7427 add sp, sp, #8 @ pop stack 7428 cmp r0, #0 @ test boolean result of inline 7429 beq common_exceptionThrown @ returned false, handle exception 7430 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7431 GET_INST_OPCODE(ip) @ extract opcode from rINST 7432 GOTO_OPCODE(ip) @ jump to next instruction 7433 7434/* ------------------------------ */ 7435 .balign 64 7436.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7437/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7438 /* 7439 * invoke-direct-empty is a no-op in a "standard" interpreter. 7440 */ 7441 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7442 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7443 GOTO_OPCODE(ip) @ execute it 7444 7445/* ------------------------------ */ 7446 .balign 64 7447.L_OP_UNUSED_F1: /* 0xf1 */ 7448/* File: armv5te/OP_UNUSED_F1.S */ 7449/* File: armv5te/unused.S */ 7450 bl common_abort 7451 7452 7453/* ------------------------------ */ 7454 .balign 64 7455.L_OP_IGET_QUICK: /* 0xf2 */ 7456/* File: armv5te/OP_IGET_QUICK.S */ 7457 /* For: iget-quick, iget-object-quick */ 7458 /* op vA, vB, offset@CCCC */ 7459 mov r2, rINST, lsr #12 @ r2<- B 7460 GET_VREG(r3, r2) @ r3<- object we're operating on 7461 FETCH(r1, 1) @ r1<- field byte offset 7462 cmp r3, #0 @ check object for null 7463 mov r2, rINST, lsr #8 @ r2<- A(+) 7464 beq common_errNullObject @ object was null 7465 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7466 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7467 and r2, r2, #15 7468 GET_INST_OPCODE(ip) @ extract opcode from rINST 7469 SET_VREG(r0, r2) @ fp[A]<- r0 7470 GOTO_OPCODE(ip) @ jump to next instruction 7471 7472/* ------------------------------ */ 7473 .balign 64 7474.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7475/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7476 /* iget-wide-quick vA, vB, offset@CCCC */ 7477 mov r2, rINST, lsr #12 @ r2<- B 7478 GET_VREG(r3, r2) @ r3<- object we're operating on 7479 FETCH(ip, 1) @ ip<- field byte offset 7480 cmp r3, #0 @ check object for null 7481 mov r2, rINST, lsr #8 @ r2<- A(+) 7482 beq common_errNullObject @ object was null 7483 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7484 and r2, r2, #15 7485 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7486 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7487 GET_INST_OPCODE(ip) @ extract opcode from rINST 7488 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7489 GOTO_OPCODE(ip) @ jump to next instruction 7490 7491/* ------------------------------ */ 7492 .balign 64 7493.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7494/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7495/* File: armv5te/OP_IGET_QUICK.S */ 7496 /* For: iget-quick, iget-object-quick */ 7497 /* op vA, vB, offset@CCCC */ 7498 mov r2, rINST, lsr #12 @ r2<- B 7499 GET_VREG(r3, r2) @ r3<- object we're operating on 7500 FETCH(r1, 1) @ r1<- field byte offset 7501 cmp r3, #0 @ check object for null 7502 mov r2, rINST, lsr #8 @ r2<- A(+) 7503 beq common_errNullObject @ object was null 7504 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7505 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7506 and r2, r2, #15 7507 GET_INST_OPCODE(ip) @ extract opcode from rINST 7508 SET_VREG(r0, r2) @ fp[A]<- r0 7509 GOTO_OPCODE(ip) @ jump to next instruction 7510 7511 7512/* ------------------------------ */ 7513 .balign 64 7514.L_OP_IPUT_QUICK: /* 0xf5 */ 7515/* File: armv5te/OP_IPUT_QUICK.S */ 7516 /* For: iput-quick, iput-object-quick */ 7517 /* op vA, vB, offset@CCCC */ 7518 mov r2, rINST, lsr #12 @ r2<- B 7519 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7520 FETCH(r1, 1) @ r1<- field byte offset 7521 cmp r3, #0 @ check object for null 7522 mov r2, rINST, lsr #8 @ r2<- A(+) 7523 beq common_errNullObject @ object was null 7524 and r2, r2, #15 7525 GET_VREG(r0, r2) @ r0<- fp[A] 7526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7527 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7528 GET_INST_OPCODE(ip) @ extract opcode from rINST 7529 GOTO_OPCODE(ip) @ jump to next instruction 7530 7531/* ------------------------------ */ 7532 .balign 64 7533.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7534/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7535 /* iput-wide-quick vA, vB, offset@CCCC */ 7536 mov r0, rINST, lsr #8 @ r0<- A(+) 7537 mov r1, rINST, lsr #12 @ r1<- B 7538 and r0, r0, #15 7539 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7540 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7541 cmp r2, #0 @ check object for null 7542 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7543 beq common_errNullObject @ object was null 7544 FETCH(r3, 1) @ r3<- field byte offset 7545 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7546 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7547 GET_INST_OPCODE(ip) @ extract opcode from rINST 7548 GOTO_OPCODE(ip) @ jump to next instruction 7549 7550/* ------------------------------ */ 7551 .balign 64 7552.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7553/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7554/* File: armv5te/OP_IPUT_QUICK.S */ 7555 /* For: iput-quick, iput-object-quick */ 7556 /* op vA, vB, offset@CCCC */ 7557 mov r2, rINST, lsr #12 @ r2<- B 7558 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7559 FETCH(r1, 1) @ r1<- field byte offset 7560 cmp r3, #0 @ check object for null 7561 mov r2, rINST, lsr #8 @ r2<- A(+) 7562 beq common_errNullObject @ object was null 7563 and r2, r2, #15 7564 GET_VREG(r0, r2) @ r0<- fp[A] 7565 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7566 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7567 GET_INST_OPCODE(ip) @ extract opcode from rINST 7568 GOTO_OPCODE(ip) @ jump to next instruction 7569 7570 7571/* ------------------------------ */ 7572 .balign 64 7573.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7574/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7575 /* 7576 * Handle an optimized virtual method call. 7577 * 7578 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7579 */ 7580 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7581 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7582 FETCH(r3, 2) @ r3<- FEDC or CCCC 7583 FETCH(r1, 1) @ r1<- BBBB 7584 .if (!0) 7585 and r3, r3, #15 @ r3<- C (or stays CCCC) 7586 .endif 7587 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7588 cmp r2, #0 @ is "this" null? 7589 beq common_errNullObject @ null "this", throw exception 7590 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7591 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7592 EXPORT_PC() @ invoke must export 7593 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7594 bl common_invokeMethodNoRange @ continue on 7595 7596/* ------------------------------ */ 7597 .balign 64 7598.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7599/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7600/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7601 /* 7602 * Handle an optimized virtual method call. 7603 * 7604 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7605 */ 7606 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7607 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7608 FETCH(r3, 2) @ r3<- FEDC or CCCC 7609 FETCH(r1, 1) @ r1<- BBBB 7610 .if (!1) 7611 and r3, r3, #15 @ r3<- C (or stays CCCC) 7612 .endif 7613 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7614 cmp r2, #0 @ is "this" null? 7615 beq common_errNullObject @ null "this", throw exception 7616 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7617 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7618 EXPORT_PC() @ invoke must export 7619 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7620 bl common_invokeMethodRange @ continue on 7621 7622 7623/* ------------------------------ */ 7624 .balign 64 7625.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7626/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7627 /* 7628 * Handle an optimized "super" method call. 7629 * 7630 * for: [opt] invoke-super-quick, invoke-super-quick/range 7631 */ 7632 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7633 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7634 FETCH(r10, 2) @ r10<- GFED or CCCC 7635 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7636 .if (!0) 7637 and r10, r10, #15 @ r10<- D (or stays CCCC) 7638 .endif 7639 FETCH(r1, 1) @ r1<- BBBB 7640 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7641 EXPORT_PC() @ must export for invoke 7642 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7643 GET_VREG(r3, r10) @ r3<- "this" 7644 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7645 cmp r3, #0 @ null "this" ref? 7646 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7647 beq common_errNullObject @ "this" is null, throw exception 7648 bl common_invokeMethodNoRange @ continue on 7649 7650/* ------------------------------ */ 7651 .balign 64 7652.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7653/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7654/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7655 /* 7656 * Handle an optimized "super" method call. 7657 * 7658 * for: [opt] invoke-super-quick, invoke-super-quick/range 7659 */ 7660 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7661 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7662 FETCH(r10, 2) @ r10<- GFED or CCCC 7663 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7664 .if (!1) 7665 and r10, r10, #15 @ r10<- D (or stays CCCC) 7666 .endif 7667 FETCH(r1, 1) @ r1<- BBBB 7668 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7669 EXPORT_PC() @ must export for invoke 7670 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7671 GET_VREG(r3, r10) @ r3<- "this" 7672 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7673 cmp r3, #0 @ null "this" ref? 7674 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7675 beq common_errNullObject @ "this" is null, throw exception 7676 bl common_invokeMethodRange @ continue on 7677 7678 7679/* ------------------------------ */ 7680 .balign 64 7681.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7682/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7683/* File: armv5te/OP_IPUT.S */ 7684 /* 7685 * General 32-bit instance field put. 7686 * 7687 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 7688 */ 7689 /* op vA, vB, field@CCCC */ 7690 mov r0, rINST, lsr #12 @ r0<- B 7691 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7692 FETCH(r1, 1) @ r1<- field ref CCCC 7693 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7694 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7695 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7696 cmp r0, #0 @ is resolved entry null? 7697 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7699 EXPORT_PC() @ resolve() could throw 7700 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7701 bl dvmResolveInstField @ r0<- resolved InstField ptr 7702 cmp r0, #0 @ success? 7703 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7704 b common_exceptionThrown 7705 7706 7707/* ------------------------------ */ 7708 .balign 64 7709.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7710/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7711/* File: armv5te/OP_SGET.S */ 7712 /* 7713 * General 32-bit SGET handler. 7714 * 7715 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7716 */ 7717 /* op vAA, field@BBBB */ 7718 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7719 FETCH(r1, 1) @ r1<- field ref BBBB 7720 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7721 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7722 cmp r0, #0 @ is resolved entry null? 7723 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7724.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7725 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7726 SMP_DMB 1 @ acquiring load 7727 mov r2, rINST, lsr #8 @ r2<- AA 7728 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7729 SET_VREG(r1, r2) @ fp[AA]<- r1 7730 GET_INST_OPCODE(ip) @ extract opcode from rINST 7731 GOTO_OPCODE(ip) @ jump to next instruction 7732 7733 7734/* ------------------------------ */ 7735 .balign 64 7736.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7737/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7738/* File: armv5te/OP_SPUT.S */ 7739 /* 7740 * General 32-bit SPUT handler. 7741 * 7742 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 7743 */ 7744 /* op vAA, field@BBBB */ 7745 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7746 FETCH(r1, 1) @ r1<- field ref BBBB 7747 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7748 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7749 cmp r0, #0 @ is resolved entry null? 7750 beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve 7751.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 7752 mov r2, rINST, lsr #8 @ r2<- AA 7753 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7754 GET_VREG(r1, r2) @ r1<- fp[AA] 7755 GET_INST_OPCODE(ip) @ extract opcode from rINST 7756 SMP_DMB 1 @ releasing store 7757 str r1, [r0, #offStaticField_value] @ field<- vAA 7758 GOTO_OPCODE(ip) @ jump to next instruction 7759 7760 7761/* ------------------------------ */ 7762 .balign 64 7763.L_OP_UNUSED_FF: /* 0xff */ 7764/* File: armv5te/OP_UNUSED_FF.S */ 7765/* File: armv5te/unused.S */ 7766 bl common_abort 7767 7768 7769 7770 .balign 64 7771 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7772 .global dvmAsmInstructionEnd 7773dvmAsmInstructionEnd: 7774 7775/* 7776 * =========================================================================== 7777 * Sister implementations 7778 * =========================================================================== 7779 */ 7780 .global dvmAsmSisterStart 7781 .type dvmAsmSisterStart, %function 7782 .text 7783 .balign 4 7784dvmAsmSisterStart: 7785 7786/* continuation for OP_CONST_STRING */ 7787 7788 /* 7789 * Continuation if the String has not yet been resolved. 7790 * r1: BBBB (String ref) 7791 * r9: target register 7792 */ 7793.LOP_CONST_STRING_resolve: 7794 EXPORT_PC() 7795 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7796 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7797 bl dvmResolveString @ r0<- String reference 7798 cmp r0, #0 @ failed? 7799 beq common_exceptionThrown @ yup, handle the exception 7800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7801 GET_INST_OPCODE(ip) @ extract opcode from rINST 7802 SET_VREG(r0, r9) @ vAA<- r0 7803 GOTO_OPCODE(ip) @ jump to next instruction 7804 7805/* continuation for OP_CONST_STRING_JUMBO */ 7806 7807 /* 7808 * Continuation if the String has not yet been resolved. 7809 * r1: BBBBBBBB (String ref) 7810 * r9: target register 7811 */ 7812.LOP_CONST_STRING_JUMBO_resolve: 7813 EXPORT_PC() 7814 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7815 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7816 bl dvmResolveString @ r0<- String reference 7817 cmp r0, #0 @ failed? 7818 beq common_exceptionThrown @ yup, handle the exception 7819 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7820 GET_INST_OPCODE(ip) @ extract opcode from rINST 7821 SET_VREG(r0, r9) @ vAA<- r0 7822 GOTO_OPCODE(ip) @ jump to next instruction 7823 7824/* continuation for OP_CONST_CLASS */ 7825 7826 /* 7827 * Continuation if the Class has not yet been resolved. 7828 * r1: BBBB (Class ref) 7829 * r9: target register 7830 */ 7831.LOP_CONST_CLASS_resolve: 7832 EXPORT_PC() 7833 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7834 mov r2, #1 @ r2<- true 7835 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7836 bl dvmResolveClass @ r0<- Class reference 7837 cmp r0, #0 @ failed? 7838 beq common_exceptionThrown @ yup, handle the exception 7839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7840 GET_INST_OPCODE(ip) @ extract opcode from rINST 7841 SET_VREG(r0, r9) @ vAA<- r0 7842 GOTO_OPCODE(ip) @ jump to next instruction 7843 7844/* continuation for OP_CHECK_CAST */ 7845 7846 /* 7847 * Trivial test failed, need to perform full check. This is common. 7848 * r0 holds obj->clazz 7849 * r1 holds class resolved from BBBB 7850 * r9 holds object 7851 */ 7852.LOP_CHECK_CAST_fullcheck: 7853 bl dvmInstanceofNonTrivial @ r0<- boolean result 7854 cmp r0, #0 @ failed? 7855 bne .LOP_CHECK_CAST_okay @ no, success 7856 7857 @ A cast has failed. We need to throw a ClassCastException with the 7858 @ class of the object that failed to be cast. 7859 EXPORT_PC() @ about to throw 7860 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7861 ldr r0, .LstrClassCastExceptionPtr 7862 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7863 bl dvmThrowExceptionWithClassMessage 7864 b common_exceptionThrown 7865 7866 /* 7867 * Resolution required. This is the least-likely path. 7868 * 7869 * r2 holds BBBB 7870 * r9 holds object 7871 */ 7872.LOP_CHECK_CAST_resolve: 7873 EXPORT_PC() @ resolve() could throw 7874 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7875 mov r1, r2 @ r1<- BBBB 7876 mov r2, #0 @ r2<- false 7877 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7878 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7879 cmp r0, #0 @ got null? 7880 beq common_exceptionThrown @ yes, handle exception 7881 mov r1, r0 @ r1<- class resolved from BBB 7882 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7883 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7884 7885.LstrClassCastExceptionPtr: 7886 .word .LstrClassCastException 7887 7888/* continuation for OP_INSTANCE_OF */ 7889 7890 /* 7891 * Trivial test failed, need to perform full check. This is common. 7892 * r0 holds obj->clazz 7893 * r1 holds class resolved from BBBB 7894 * r9 holds A 7895 */ 7896.LOP_INSTANCE_OF_fullcheck: 7897 bl dvmInstanceofNonTrivial @ r0<- boolean result 7898 @ fall through to OP_INSTANCE_OF_store 7899 7900 /* 7901 * r0 holds boolean result 7902 * r9 holds A 7903 */ 7904.LOP_INSTANCE_OF_store: 7905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7906 SET_VREG(r0, r9) @ vA<- r0 7907 GET_INST_OPCODE(ip) @ extract opcode from rINST 7908 GOTO_OPCODE(ip) @ jump to next instruction 7909 7910 /* 7911 * Trivial test succeeded, save and bail. 7912 * r9 holds A 7913 */ 7914.LOP_INSTANCE_OF_trivial: 7915 mov r0, #1 @ indicate success 7916 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7918 SET_VREG(r0, r9) @ vA<- r0 7919 GET_INST_OPCODE(ip) @ extract opcode from rINST 7920 GOTO_OPCODE(ip) @ jump to next instruction 7921 7922 /* 7923 * Resolution required. This is the least-likely path. 7924 * 7925 * r3 holds BBBB 7926 * r9 holds A 7927 */ 7928.LOP_INSTANCE_OF_resolve: 7929 EXPORT_PC() @ resolve() could throw 7930 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7931 mov r1, r3 @ r1<- BBBB 7932 mov r2, #1 @ r2<- true 7933 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7934 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7935 cmp r0, #0 @ got null? 7936 beq common_exceptionThrown @ yes, handle exception 7937 mov r1, r0 @ r1<- class resolved from BBB 7938 mov r3, rINST, lsr #12 @ r3<- B 7939 GET_VREG(r0, r3) @ r0<- vB (object) 7940 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7941 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7942 7943/* continuation for OP_NEW_INSTANCE */ 7944 7945 .balign 32 @ minimize cache lines 7946.LOP_NEW_INSTANCE_finish: @ r0=new object 7947 mov r3, rINST, lsr #8 @ r3<- AA 7948 cmp r0, #0 @ failed? 7949 beq common_exceptionThrown @ yes, handle the exception 7950 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7951 GET_INST_OPCODE(ip) @ extract opcode from rINST 7952 SET_VREG(r0, r3) @ vAA<- r0 7953 GOTO_OPCODE(ip) @ jump to next instruction 7954 7955 /* 7956 * Class initialization required. 7957 * 7958 * r0 holds class object 7959 */ 7960.LOP_NEW_INSTANCE_needinit: 7961 mov r9, r0 @ save r0 7962 bl dvmInitClass @ initialize class 7963 cmp r0, #0 @ check boolean result 7964 mov r0, r9 @ restore r0 7965 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7966 b common_exceptionThrown @ failed, deal with init exception 7967 7968 /* 7969 * Resolution required. This is the least-likely path. 7970 * 7971 * r1 holds BBBB 7972 */ 7973.LOP_NEW_INSTANCE_resolve: 7974 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7975 mov r2, #0 @ r2<- false 7976 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7977 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7978 cmp r0, #0 @ got null? 7979 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7980 b common_exceptionThrown @ yes, handle exception 7981 7982.LstrInstantiationErrorPtr: 7983 .word .LstrInstantiationError 7984 7985/* continuation for OP_NEW_ARRAY */ 7986 7987 7988 /* 7989 * Resolve class. (This is an uncommon case.) 7990 * 7991 * r1 holds array length 7992 * r2 holds class ref CCCC 7993 */ 7994.LOP_NEW_ARRAY_resolve: 7995 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7996 mov r9, r1 @ r9<- length (save) 7997 mov r1, r2 @ r1<- CCCC 7998 mov r2, #0 @ r2<- false 7999 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8000 bl dvmResolveClass @ r0<- call(clazz, ref) 8001 cmp r0, #0 @ got null? 8002 mov r1, r9 @ r1<- length (restore) 8003 beq common_exceptionThrown @ yes, handle exception 8004 @ fall through to OP_NEW_ARRAY_finish 8005 8006 /* 8007 * Finish allocation. 8008 * 8009 * r0 holds class 8010 * r1 holds array length 8011 */ 8012.LOP_NEW_ARRAY_finish: 8013 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8014 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8015 cmp r0, #0 @ failed? 8016 mov r2, rINST, lsr #8 @ r2<- A+ 8017 beq common_exceptionThrown @ yes, handle the exception 8018 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8019 and r2, r2, #15 @ r2<- A 8020 GET_INST_OPCODE(ip) @ extract opcode from rINST 8021 SET_VREG(r0, r2) @ vA<- r0 8022 GOTO_OPCODE(ip) @ jump to next instruction 8023 8024/* continuation for OP_FILLED_NEW_ARRAY */ 8025 8026 /* 8027 * On entry: 8028 * r0 holds array class 8029 * r10 holds AA or BA 8030 */ 8031.LOP_FILLED_NEW_ARRAY_continue: 8032 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8033 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8034 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8035 .if 0 8036 mov r1, r10 @ r1<- AA (length) 8037 .else 8038 mov r1, r10, lsr #4 @ r1<- B (length) 8039 .endif 8040 cmp r3, #'I' @ array of ints? 8041 cmpne r3, #'L' @ array of objects? 8042 cmpne r3, #'[' @ array of arrays? 8043 mov r9, r1 @ save length in r9 8044 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8045 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8046 cmp r0, #0 @ null return? 8047 beq common_exceptionThrown @ alloc failed, handle exception 8048 8049 FETCH(r1, 2) @ r1<- FEDC or CCCC 8050 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8051 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8052 subs r9, r9, #1 @ length--, check for neg 8053 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8054 bmi 2f @ was zero, bail 8055 8056 @ copy values from registers into the array 8057 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8058 .if 0 8059 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80601: ldr r3, [r2], #4 @ r3<- *r2++ 8061 subs r9, r9, #1 @ count-- 8062 str r3, [r0], #4 @ *contents++ = vX 8063 bpl 1b 8064 @ continue at 2 8065 .else 8066 cmp r9, #4 @ length was initially 5? 8067 and r2, r10, #15 @ r2<- A 8068 bne 1f @ <= 4 args, branch 8069 GET_VREG(r3, r2) @ r3<- vA 8070 sub r9, r9, #1 @ count-- 8071 str r3, [r0, #16] @ contents[4] = vA 80721: and r2, r1, #15 @ r2<- F/E/D/C 8073 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8074 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8075 subs r9, r9, #1 @ count-- 8076 str r3, [r0], #4 @ *contents++ = vX 8077 bpl 1b 8078 @ continue at 2 8079 .endif 8080 80812: 8082 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8083 GOTO_OPCODE(ip) @ execute it 8084 8085 /* 8086 * Throw an exception indicating that we have not implemented this 8087 * mode of filled-new-array. 8088 */ 8089.LOP_FILLED_NEW_ARRAY_notimpl: 8090 ldr r0, .L_strInternalError 8091 ldr r1, .L_strFilledNewArrayNotImpl 8092 bl dvmThrowException 8093 b common_exceptionThrown 8094 8095 .if (!0) @ define in one or the other, not both 8096.L_strFilledNewArrayNotImpl: 8097 .word .LstrFilledNewArrayNotImpl 8098.L_strInternalError: 8099 .word .LstrInternalError 8100 .endif 8101 8102/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8103 8104 /* 8105 * On entry: 8106 * r0 holds array class 8107 * r10 holds AA or BA 8108 */ 8109.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8110 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8111 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8112 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8113 .if 1 8114 mov r1, r10 @ r1<- AA (length) 8115 .else 8116 mov r1, r10, lsr #4 @ r1<- B (length) 8117 .endif 8118 cmp r3, #'I' @ array of ints? 8119 cmpne r3, #'L' @ array of objects? 8120 cmpne r3, #'[' @ array of arrays? 8121 mov r9, r1 @ save length in r9 8122 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8123 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8124 cmp r0, #0 @ null return? 8125 beq common_exceptionThrown @ alloc failed, handle exception 8126 8127 FETCH(r1, 2) @ r1<- FEDC or CCCC 8128 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8129 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8130 subs r9, r9, #1 @ length--, check for neg 8131 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8132 bmi 2f @ was zero, bail 8133 8134 @ copy values from registers into the array 8135 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8136 .if 1 8137 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81381: ldr r3, [r2], #4 @ r3<- *r2++ 8139 subs r9, r9, #1 @ count-- 8140 str r3, [r0], #4 @ *contents++ = vX 8141 bpl 1b 8142 @ continue at 2 8143 .else 8144 cmp r9, #4 @ length was initially 5? 8145 and r2, r10, #15 @ r2<- A 8146 bne 1f @ <= 4 args, branch 8147 GET_VREG(r3, r2) @ r3<- vA 8148 sub r9, r9, #1 @ count-- 8149 str r3, [r0, #16] @ contents[4] = vA 81501: and r2, r1, #15 @ r2<- F/E/D/C 8151 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8152 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8153 subs r9, r9, #1 @ count-- 8154 str r3, [r0], #4 @ *contents++ = vX 8155 bpl 1b 8156 @ continue at 2 8157 .endif 8158 81592: 8160 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8161 GOTO_OPCODE(ip) @ execute it 8162 8163 /* 8164 * Throw an exception indicating that we have not implemented this 8165 * mode of filled-new-array. 8166 */ 8167.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8168 ldr r0, .L_strInternalError 8169 ldr r1, .L_strFilledNewArrayNotImpl 8170 bl dvmThrowException 8171 b common_exceptionThrown 8172 8173 .if (!1) @ define in one or the other, not both 8174.L_strFilledNewArrayNotImpl: 8175 .word .LstrFilledNewArrayNotImpl 8176.L_strInternalError: 8177 .word .LstrInternalError 8178 .endif 8179 8180/* continuation for OP_CMPL_FLOAT */ 8181.LOP_CMPL_FLOAT_finish: 8182 SET_VREG(r0, r9) @ vAA<- r0 8183 GOTO_OPCODE(ip) @ jump to next instruction 8184 8185/* continuation for OP_CMPG_FLOAT */ 8186.LOP_CMPG_FLOAT_finish: 8187 SET_VREG(r0, r9) @ vAA<- r0 8188 GOTO_OPCODE(ip) @ jump to next instruction 8189 8190/* continuation for OP_CMPL_DOUBLE */ 8191.LOP_CMPL_DOUBLE_finish: 8192 SET_VREG(r0, r9) @ vAA<- r0 8193 GOTO_OPCODE(ip) @ jump to next instruction 8194 8195/* continuation for OP_CMPG_DOUBLE */ 8196.LOP_CMPG_DOUBLE_finish: 8197 SET_VREG(r0, r9) @ vAA<- r0 8198 GOTO_OPCODE(ip) @ jump to next instruction 8199 8200/* continuation for OP_CMP_LONG */ 8201 8202.LOP_CMP_LONG_less: 8203 mvn r1, #0 @ r1<- -1 8204 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8205 @ instead, we just replicate the tail end. 8206 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8207 SET_VREG(r1, r9) @ vAA<- r1 8208 GET_INST_OPCODE(ip) @ extract opcode from rINST 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210 8211.LOP_CMP_LONG_greater: 8212 mov r1, #1 @ r1<- 1 8213 @ fall through to _finish 8214 8215.LOP_CMP_LONG_finish: 8216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8217 SET_VREG(r1, r9) @ vAA<- r1 8218 GET_INST_OPCODE(ip) @ extract opcode from rINST 8219 GOTO_OPCODE(ip) @ jump to next instruction 8220 8221/* continuation for OP_AGET_WIDE */ 8222 8223.LOP_AGET_WIDE_finish: 8224 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8225 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8226 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8227 GET_INST_OPCODE(ip) @ extract opcode from rINST 8228 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8229 GOTO_OPCODE(ip) @ jump to next instruction 8230 8231/* continuation for OP_APUT_WIDE */ 8232 8233.LOP_APUT_WIDE_finish: 8234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8235 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8236 GET_INST_OPCODE(ip) @ extract opcode from rINST 8237 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8238 GOTO_OPCODE(ip) @ jump to next instruction 8239 8240/* continuation for OP_APUT_OBJECT */ 8241 /* 8242 * On entry: 8243 * r1 = vBB (arrayObj) 8244 * r9 = vAA (obj) 8245 * r10 = offset into array (vBB + vCC * width) 8246 */ 8247.LOP_APUT_OBJECT_finish: 8248 cmp r9, #0 @ storing null reference? 8249 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8250 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8251 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8252 bl dvmCanPutArrayElement @ test object type vs. array type 8253 cmp r0, #0 @ okay? 8254 beq common_errArrayStore @ no 8255.LOP_APUT_OBJECT_skip_check: 8256 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8257 GET_INST_OPCODE(ip) @ extract opcode from rINST 8258 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8259 GOTO_OPCODE(ip) @ jump to next instruction 8260 8261/* continuation for OP_IGET */ 8262 8263 /* 8264 * Currently: 8265 * r0 holds resolved field 8266 * r9 holds object 8267 */ 8268.LOP_IGET_finish: 8269 @bl common_squeak0 8270 cmp r9, #0 @ check object for null 8271 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8272 beq common_errNullObject @ object was null 8273 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8274 SMP_DMB 0 @ acquiring load 8275 mov r2, rINST, lsr #8 @ r2<- A+ 8276 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8277 and r2, r2, #15 @ r2<- A 8278 GET_INST_OPCODE(ip) @ extract opcode from rINST 8279 SET_VREG(r0, r2) @ fp[A]<- r0 8280 GOTO_OPCODE(ip) @ jump to next instruction 8281 8282/* continuation for OP_IGET_WIDE */ 8283 8284 /* 8285 * Currently: 8286 * r0 holds resolved field 8287 * r9 holds object 8288 */ 8289.LOP_IGET_WIDE_finish: 8290 cmp r9, #0 @ check object for null 8291 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8292 beq common_errNullObject @ object was null 8293 .if 0 8294 add r0, r9, r3 @ r0<- address of field 8295 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8296 .else 8297 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8298 .endif 8299 mov r2, rINST, lsr #8 @ r2<- A+ 8300 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8301 and r2, r2, #15 @ r2<- A 8302 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8303 GET_INST_OPCODE(ip) @ extract opcode from rINST 8304 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8305 GOTO_OPCODE(ip) @ jump to next instruction 8306 8307/* continuation for OP_IGET_OBJECT */ 8308 8309 /* 8310 * Currently: 8311 * r0 holds resolved field 8312 * r9 holds object 8313 */ 8314.LOP_IGET_OBJECT_finish: 8315 @bl common_squeak0 8316 cmp r9, #0 @ check object for null 8317 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8318 beq common_errNullObject @ object was null 8319 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8320 SMP_DMB 0 @ acquiring load 8321 mov r2, rINST, lsr #8 @ r2<- A+ 8322 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8323 and r2, r2, #15 @ r2<- A 8324 GET_INST_OPCODE(ip) @ extract opcode from rINST 8325 SET_VREG(r0, r2) @ fp[A]<- r0 8326 GOTO_OPCODE(ip) @ jump to next instruction 8327 8328/* continuation for OP_IGET_BOOLEAN */ 8329 8330 /* 8331 * Currently: 8332 * r0 holds resolved field 8333 * r9 holds object 8334 */ 8335.LOP_IGET_BOOLEAN_finish: 8336 @bl common_squeak1 8337 cmp r9, #0 @ check object for null 8338 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8339 beq common_errNullObject @ object was null 8340 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8341 SMP_DMB 0 @ acquiring load 8342 mov r2, rINST, lsr #8 @ r2<- A+ 8343 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8344 and r2, r2, #15 @ r2<- A 8345 GET_INST_OPCODE(ip) @ extract opcode from rINST 8346 SET_VREG(r0, r2) @ fp[A]<- r0 8347 GOTO_OPCODE(ip) @ jump to next instruction 8348 8349/* continuation for OP_IGET_BYTE */ 8350 8351 /* 8352 * Currently: 8353 * r0 holds resolved field 8354 * r9 holds object 8355 */ 8356.LOP_IGET_BYTE_finish: 8357 @bl common_squeak2 8358 cmp r9, #0 @ check object for null 8359 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8360 beq common_errNullObject @ object was null 8361 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8362 SMP_DMB 0 @ acquiring load 8363 mov r2, rINST, lsr #8 @ r2<- A+ 8364 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8365 and r2, r2, #15 @ r2<- A 8366 GET_INST_OPCODE(ip) @ extract opcode from rINST 8367 SET_VREG(r0, r2) @ fp[A]<- r0 8368 GOTO_OPCODE(ip) @ jump to next instruction 8369 8370/* continuation for OP_IGET_CHAR */ 8371 8372 /* 8373 * Currently: 8374 * r0 holds resolved field 8375 * r9 holds object 8376 */ 8377.LOP_IGET_CHAR_finish: 8378 @bl common_squeak3 8379 cmp r9, #0 @ check object for null 8380 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8381 beq common_errNullObject @ object was null 8382 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8383 SMP_DMB 0 @ acquiring load 8384 mov r2, rINST, lsr #8 @ r2<- A+ 8385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8386 and r2, r2, #15 @ r2<- A 8387 GET_INST_OPCODE(ip) @ extract opcode from rINST 8388 SET_VREG(r0, r2) @ fp[A]<- r0 8389 GOTO_OPCODE(ip) @ jump to next instruction 8390 8391/* continuation for OP_IGET_SHORT */ 8392 8393 /* 8394 * Currently: 8395 * r0 holds resolved field 8396 * r9 holds object 8397 */ 8398.LOP_IGET_SHORT_finish: 8399 @bl common_squeak4 8400 cmp r9, #0 @ check object for null 8401 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8402 beq common_errNullObject @ object was null 8403 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8404 SMP_DMB 0 @ acquiring load 8405 mov r2, rINST, lsr #8 @ r2<- A+ 8406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8407 and r2, r2, #15 @ r2<- A 8408 GET_INST_OPCODE(ip) @ extract opcode from rINST 8409 SET_VREG(r0, r2) @ fp[A]<- r0 8410 GOTO_OPCODE(ip) @ jump to next instruction 8411 8412/* continuation for OP_IPUT */ 8413 8414 /* 8415 * Currently: 8416 * r0 holds resolved field 8417 * r9 holds object 8418 */ 8419.LOP_IPUT_finish: 8420 @bl common_squeak0 8421 mov r1, rINST, lsr #8 @ r1<- A+ 8422 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8423 and r1, r1, #15 @ r1<- A 8424 cmp r9, #0 @ check object for null 8425 GET_VREG(r0, r1) @ r0<- fp[A] 8426 beq common_errNullObject @ object was null 8427 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8428 GET_INST_OPCODE(ip) @ extract opcode from rINST 8429 SMP_DMB 0 @ releasing store 8430 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8431 GOTO_OPCODE(ip) @ jump to next instruction 8432 8433/* continuation for OP_IPUT_WIDE */ 8434 8435 /* 8436 * Currently: 8437 * r0 holds resolved field 8438 * r9 holds object 8439 */ 8440.LOP_IPUT_WIDE_finish: 8441 mov r2, rINST, lsr #8 @ r2<- A+ 8442 cmp r9, #0 @ check object for null 8443 and r2, r2, #15 @ r2<- A 8444 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8445 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8446 beq common_errNullObject @ object was null 8447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8448 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8449 GET_INST_OPCODE(r10) @ extract opcode from rINST 8450 .if 0 8451 add r2, r9, r3 @ r2<- target address 8452 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8453 .else 8454 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8455 .endif 8456 GOTO_OPCODE(r10) @ jump to next instruction 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 SMP_DMB 0 @ releasing store 8476 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8477 GOTO_OPCODE(ip) @ jump to next instruction 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 SMP_DMB 0 @ releasing store 8497 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8498 GOTO_OPCODE(ip) @ jump to next instruction 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 SMP_DMB 0 @ releasing store 8518 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8519 GOTO_OPCODE(ip) @ jump to next instruction 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 SMP_DMB 0 @ releasing store 8539 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8540 GOTO_OPCODE(ip) @ jump to next instruction 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 SMP_DMB 0 @ releasing store 8560 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8561 GOTO_OPCODE(ip) @ jump to next instruction 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/* continuation for OP_SGET_WIDE */ 8579 8580 /* 8581 * Continuation if the field has not yet been resolved. 8582 * r1: BBBB field ref 8583 * 8584 * Returns StaticField pointer in r0. 8585 */ 8586.LOP_SGET_WIDE_resolve: 8587 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8588 EXPORT_PC() @ resolve() could throw, so export now 8589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8590 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8591 cmp r0, #0 @ success? 8592 bne .LOP_SGET_WIDE_finish @ yes, finish 8593 b common_exceptionThrown @ no, handle exception 8594 8595/* continuation for OP_SGET_OBJECT */ 8596 8597 /* 8598 * Continuation if the field has not yet been resolved. 8599 * r1: BBBB field ref 8600 */ 8601.LOP_SGET_OBJECT_resolve: 8602 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8603 EXPORT_PC() @ resolve() could throw, so export now 8604 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8605 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8606 cmp r0, #0 @ success? 8607 bne .LOP_SGET_OBJECT_finish @ yes, finish 8608 b common_exceptionThrown @ no, handle exception 8609 8610/* continuation for OP_SGET_BOOLEAN */ 8611 8612 /* 8613 * Continuation if the field has not yet been resolved. 8614 * r1: BBBB field ref 8615 */ 8616.LOP_SGET_BOOLEAN_resolve: 8617 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8618 EXPORT_PC() @ resolve() could throw, so export now 8619 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8620 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8621 cmp r0, #0 @ success? 8622 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8623 b common_exceptionThrown @ no, handle exception 8624 8625/* continuation for OP_SGET_BYTE */ 8626 8627 /* 8628 * Continuation if the field has not yet been resolved. 8629 * r1: BBBB field ref 8630 */ 8631.LOP_SGET_BYTE_resolve: 8632 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8633 EXPORT_PC() @ resolve() could throw, so export now 8634 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8635 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8636 cmp r0, #0 @ success? 8637 bne .LOP_SGET_BYTE_finish @ yes, finish 8638 b common_exceptionThrown @ no, handle exception 8639 8640/* continuation for OP_SGET_CHAR */ 8641 8642 /* 8643 * Continuation if the field has not yet been resolved. 8644 * r1: BBBB field ref 8645 */ 8646.LOP_SGET_CHAR_resolve: 8647 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8648 EXPORT_PC() @ resolve() could throw, so export now 8649 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8650 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8651 cmp r0, #0 @ success? 8652 bne .LOP_SGET_CHAR_finish @ yes, finish 8653 b common_exceptionThrown @ no, handle exception 8654 8655/* continuation for OP_SGET_SHORT */ 8656 8657 /* 8658 * Continuation if the field has not yet been resolved. 8659 * r1: BBBB field ref 8660 */ 8661.LOP_SGET_SHORT_resolve: 8662 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8663 EXPORT_PC() @ resolve() could throw, so export now 8664 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8665 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8666 cmp r0, #0 @ success? 8667 bne .LOP_SGET_SHORT_finish @ yes, finish 8668 b common_exceptionThrown @ no, handle exception 8669 8670/* continuation for OP_SPUT */ 8671 8672 /* 8673 * Continuation if the field has not yet been resolved. 8674 * r1: BBBB field ref 8675 */ 8676.LOP_SPUT_resolve: 8677 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8678 EXPORT_PC() @ resolve() could throw, so export now 8679 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8680 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8681 cmp r0, #0 @ success? 8682 bne .LOP_SPUT_finish @ yes, finish 8683 b common_exceptionThrown @ no, handle exception 8684 8685/* continuation for OP_SPUT_WIDE */ 8686 8687 /* 8688 * Continuation if the field has not yet been resolved. 8689 * r1: BBBB field ref 8690 * r9: &fp[AA] 8691 * 8692 * Returns StaticField pointer in r2. 8693 */ 8694.LOP_SPUT_WIDE_resolve: 8695 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8696 EXPORT_PC() @ resolve() could throw, so export now 8697 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8698 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8699 cmp r0, #0 @ success? 8700 mov r2, r0 @ copy to r2 8701 bne .LOP_SPUT_WIDE_finish @ yes, finish 8702 b common_exceptionThrown @ no, handle exception 8703 8704/* continuation for OP_SPUT_OBJECT */ 8705 8706 /* 8707 * Continuation if the field has not yet been resolved. 8708 * r1: BBBB field ref 8709 */ 8710.LOP_SPUT_OBJECT_resolve: 8711 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8712 EXPORT_PC() @ resolve() could throw, so export now 8713 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8714 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8715 cmp r0, #0 @ success? 8716 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8717 b common_exceptionThrown @ no, handle exception 8718 8719/* continuation for OP_SPUT_BOOLEAN */ 8720 8721 /* 8722 * Continuation if the field has not yet been resolved. 8723 * r1: BBBB field ref 8724 */ 8725.LOP_SPUT_BOOLEAN_resolve: 8726 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8727 EXPORT_PC() @ resolve() could throw, so export now 8728 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8729 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8730 cmp r0, #0 @ success? 8731 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8732 b common_exceptionThrown @ no, handle exception 8733 8734/* continuation for OP_SPUT_BYTE */ 8735 8736 /* 8737 * Continuation if the field has not yet been resolved. 8738 * r1: BBBB field ref 8739 */ 8740.LOP_SPUT_BYTE_resolve: 8741 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8742 EXPORT_PC() @ resolve() could throw, so export now 8743 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8744 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8745 cmp r0, #0 @ success? 8746 bne .LOP_SPUT_BYTE_finish @ yes, finish 8747 b common_exceptionThrown @ no, handle exception 8748 8749/* continuation for OP_SPUT_CHAR */ 8750 8751 /* 8752 * Continuation if the field has not yet been resolved. 8753 * r1: BBBB field ref 8754 */ 8755.LOP_SPUT_CHAR_resolve: 8756 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8757 EXPORT_PC() @ resolve() could throw, so export now 8758 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8759 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8760 cmp r0, #0 @ success? 8761 bne .LOP_SPUT_CHAR_finish @ yes, finish 8762 b common_exceptionThrown @ no, handle exception 8763 8764/* continuation for OP_SPUT_SHORT */ 8765 8766 /* 8767 * Continuation if the field has not yet been resolved. 8768 * r1: BBBB field ref 8769 */ 8770.LOP_SPUT_SHORT_resolve: 8771 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8772 EXPORT_PC() @ resolve() could throw, so export now 8773 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8774 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8775 cmp r0, #0 @ success? 8776 bne .LOP_SPUT_SHORT_finish @ yes, finish 8777 b common_exceptionThrown @ no, handle exception 8778 8779/* continuation for OP_INVOKE_VIRTUAL */ 8780 8781 /* 8782 * At this point: 8783 * r0 = resolved base method 8784 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8785 */ 8786.LOP_INVOKE_VIRTUAL_continue: 8787 GET_VREG(r1, r10) @ r1<- "this" ptr 8788 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8789 cmp r1, #0 @ is "this" null? 8790 beq common_errNullObject @ null "this", throw exception 8791 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8792 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8793 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8794 bl common_invokeMethodNoRange @ continue on 8795 8796/* continuation for OP_INVOKE_SUPER */ 8797 8798 /* 8799 * At this point: 8800 * r0 = resolved base method 8801 * r9 = method->clazz 8802 */ 8803.LOP_INVOKE_SUPER_continue: 8804 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8805 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8806 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8807 EXPORT_PC() @ must export for invoke 8808 cmp r2, r3 @ compare (methodIndex, vtableCount) 8809 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8810 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8811 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8812 bl common_invokeMethodNoRange @ continue on 8813 8814.LOP_INVOKE_SUPER_resolve: 8815 mov r0, r9 @ r0<- method->clazz 8816 mov r2, #METHOD_VIRTUAL @ resolver method type 8817 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8818 cmp r0, #0 @ got null? 8819 bne .LOP_INVOKE_SUPER_continue @ no, continue 8820 b common_exceptionThrown @ yes, handle exception 8821 8822 /* 8823 * Throw a NoSuchMethodError with the method name as the message. 8824 * r0 = resolved base method 8825 */ 8826.LOP_INVOKE_SUPER_nsm: 8827 ldr r1, [r0, #offMethod_name] @ r1<- method name 8828 b common_errNoSuchMethod 8829 8830/* continuation for OP_INVOKE_DIRECT */ 8831 8832 /* 8833 * On entry: 8834 * r1 = reference (BBBB or CCCC) 8835 * r10 = "this" register 8836 */ 8837.LOP_INVOKE_DIRECT_resolve: 8838 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8839 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8840 mov r2, #METHOD_DIRECT @ resolver method type 8841 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8842 cmp r0, #0 @ got null? 8843 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8844 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8845 b common_exceptionThrown @ yes, handle exception 8846 8847/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8848 8849 /* 8850 * At this point: 8851 * r0 = resolved base method 8852 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8853 */ 8854.LOP_INVOKE_VIRTUAL_RANGE_continue: 8855 GET_VREG(r1, r10) @ r1<- "this" ptr 8856 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8857 cmp r1, #0 @ is "this" null? 8858 beq common_errNullObject @ null "this", throw exception 8859 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8860 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8861 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8862 bl common_invokeMethodRange @ continue on 8863 8864/* continuation for OP_INVOKE_SUPER_RANGE */ 8865 8866 /* 8867 * At this point: 8868 * r0 = resolved base method 8869 * r9 = method->clazz 8870 */ 8871.LOP_INVOKE_SUPER_RANGE_continue: 8872 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8873 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8874 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8875 EXPORT_PC() @ must export for invoke 8876 cmp r2, r3 @ compare (methodIndex, vtableCount) 8877 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8878 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8879 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8880 bl common_invokeMethodRange @ continue on 8881 8882.LOP_INVOKE_SUPER_RANGE_resolve: 8883 mov r0, r9 @ r0<- method->clazz 8884 mov r2, #METHOD_VIRTUAL @ resolver method type 8885 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8886 cmp r0, #0 @ got null? 8887 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8888 b common_exceptionThrown @ yes, handle exception 8889 8890 /* 8891 * Throw a NoSuchMethodError with the method name as the message. 8892 * r0 = resolved base method 8893 */ 8894.LOP_INVOKE_SUPER_RANGE_nsm: 8895 ldr r1, [r0, #offMethod_name] @ r1<- method name 8896 b common_errNoSuchMethod 8897 8898/* continuation for OP_INVOKE_DIRECT_RANGE */ 8899 8900 /* 8901 * On entry: 8902 * r1 = reference (BBBB or CCCC) 8903 * r10 = "this" register 8904 */ 8905.LOP_INVOKE_DIRECT_RANGE_resolve: 8906 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8907 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8908 mov r2, #METHOD_DIRECT @ resolver method type 8909 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8910 cmp r0, #0 @ got null? 8911 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8912 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8913 b common_exceptionThrown @ yes, handle exception 8914 8915/* continuation for OP_FLOAT_TO_LONG */ 8916/* 8917 * Convert the float in r0 to a long in r0/r1. 8918 * 8919 * We have to clip values to long min/max per the specification. The 8920 * expected common case is a "reasonable" value that converts directly 8921 * to modest integer. The EABI convert function isn't doing this for us. 8922 */ 8923f2l_doconv: 8924 stmfd sp!, {r4, lr} 8925 mov r1, #0x5f000000 @ (float)maxlong 8926 mov r4, r0 8927 bl __aeabi_fcmpge @ is arg >= maxlong? 8928 cmp r0, #0 @ nonzero == yes 8929 mvnne r0, #0 @ return maxlong (7fffffff) 8930 mvnne r1, #0x80000000 8931 ldmnefd sp!, {r4, pc} 8932 8933 mov r0, r4 @ recover arg 8934 mov r1, #0xdf000000 @ (float)minlong 8935 bl __aeabi_fcmple @ is arg <= minlong? 8936 cmp r0, #0 @ nonzero == yes 8937 movne r0, #0 @ return minlong (80000000) 8938 movne r1, #0x80000000 8939 ldmnefd sp!, {r4, pc} 8940 8941 mov r0, r4 @ recover arg 8942 mov r1, r4 8943 bl __aeabi_fcmpeq @ is arg == self? 8944 cmp r0, #0 @ zero == no 8945 moveq r1, #0 @ return zero for NaN 8946 ldmeqfd sp!, {r4, pc} 8947 8948 mov r0, r4 @ recover arg 8949 bl __aeabi_f2lz @ convert float to long 8950 ldmfd sp!, {r4, pc} 8951 8952/* continuation for OP_DOUBLE_TO_LONG */ 8953/* 8954 * Convert the double in r0/r1 to a long in r0/r1. 8955 * 8956 * We have to clip values to long min/max per the specification. The 8957 * expected common case is a "reasonable" value that converts directly 8958 * to modest integer. The EABI convert function isn't doing this for us. 8959 */ 8960d2l_doconv: 8961 stmfd sp!, {r4, r5, lr} @ save regs 8962 mov r3, #0x43000000 @ maxlong, as a double (high word) 8963 add r3, #0x00e00000 @ 0x43e00000 8964 mov r2, #0 @ maxlong, as a double (low word) 8965 sub sp, sp, #4 @ align for EABI 8966 mov r4, r0 @ save a copy of r0 8967 mov r5, r1 @ and r1 8968 bl __aeabi_dcmpge @ is arg >= maxlong? 8969 cmp r0, #0 @ nonzero == yes 8970 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8971 mvnne r1, #0x80000000 8972 bne 1f 8973 8974 mov r0, r4 @ recover arg 8975 mov r1, r5 8976 mov r3, #0xc3000000 @ minlong, as a double (high word) 8977 add r3, #0x00e00000 @ 0xc3e00000 8978 mov r2, #0 @ minlong, as a double (low word) 8979 bl __aeabi_dcmple @ is arg <= minlong? 8980 cmp r0, #0 @ nonzero == yes 8981 movne r0, #0 @ return minlong (8000000000000000) 8982 movne r1, #0x80000000 8983 bne 1f 8984 8985 mov r0, r4 @ recover arg 8986 mov r1, r5 8987 mov r2, r4 @ compare against self 8988 mov r3, r5 8989 bl __aeabi_dcmpeq @ is arg == self? 8990 cmp r0, #0 @ zero == no 8991 moveq r1, #0 @ return zero for NaN 8992 beq 1f 8993 8994 mov r0, r4 @ recover arg 8995 mov r1, r5 8996 bl __aeabi_d2lz @ convert double to long 8997 89981: 8999 add sp, sp, #4 9000 ldmfd sp!, {r4, r5, pc} 9001 9002/* continuation for OP_MUL_LONG */ 9003 9004.LOP_MUL_LONG_finish: 9005 GET_INST_OPCODE(ip) @ extract opcode from rINST 9006 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9007 GOTO_OPCODE(ip) @ jump to next instruction 9008 9009/* continuation for OP_SHL_LONG */ 9010 9011.LOP_SHL_LONG_finish: 9012 mov r0, r0, asl r2 @ r0<- r0 << r2 9013 GET_INST_OPCODE(ip) @ extract opcode from rINST 9014 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9015 GOTO_OPCODE(ip) @ jump to next instruction 9016 9017/* continuation for OP_SHR_LONG */ 9018 9019.LOP_SHR_LONG_finish: 9020 mov r1, r1, asr r2 @ r1<- r1 >> r2 9021 GET_INST_OPCODE(ip) @ extract opcode from rINST 9022 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9023 GOTO_OPCODE(ip) @ jump to next instruction 9024 9025/* continuation for OP_USHR_LONG */ 9026 9027.LOP_USHR_LONG_finish: 9028 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9029 GET_INST_OPCODE(ip) @ extract opcode from rINST 9030 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9031 GOTO_OPCODE(ip) @ jump to next instruction 9032 9033/* continuation for OP_SHL_LONG_2ADDR */ 9034 9035.LOP_SHL_LONG_2ADDR_finish: 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/* continuation for OP_SHR_LONG_2ADDR */ 9041 9042.LOP_SHR_LONG_2ADDR_finish: 9043 GET_INST_OPCODE(ip) @ extract opcode from rINST 9044 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9045 GOTO_OPCODE(ip) @ jump to next instruction 9046 9047/* continuation for OP_USHR_LONG_2ADDR */ 9048 9049.LOP_USHR_LONG_2ADDR_finish: 9050 GET_INST_OPCODE(ip) @ extract opcode from rINST 9051 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9052 GOTO_OPCODE(ip) @ jump to next instruction 9053 9054/* continuation for OP_IGET_VOLATILE */ 9055 9056 /* 9057 * Currently: 9058 * r0 holds resolved field 9059 * r9 holds object 9060 */ 9061.LOP_IGET_VOLATILE_finish: 9062 @bl common_squeak0 9063 cmp r9, #0 @ check object for null 9064 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9065 beq common_errNullObject @ object was null 9066 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9067 SMP_DMB 1 @ acquiring load 9068 mov r2, rINST, lsr #8 @ r2<- A+ 9069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9070 and r2, r2, #15 @ r2<- A 9071 GET_INST_OPCODE(ip) @ extract opcode from rINST 9072 SET_VREG(r0, r2) @ fp[A]<- r0 9073 GOTO_OPCODE(ip) @ jump to next instruction 9074 9075/* continuation for OP_IPUT_VOLATILE */ 9076 9077 /* 9078 * Currently: 9079 * r0 holds resolved field 9080 * r9 holds object 9081 */ 9082.LOP_IPUT_VOLATILE_finish: 9083 @bl common_squeak0 9084 mov r1, rINST, lsr #8 @ r1<- A+ 9085 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9086 and r1, r1, #15 @ r1<- A 9087 cmp r9, #0 @ check object for null 9088 GET_VREG(r0, r1) @ r0<- fp[A] 9089 beq common_errNullObject @ object was null 9090 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9091 GET_INST_OPCODE(ip) @ extract opcode from rINST 9092 SMP_DMB 1 @ releasing store 9093 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9094 GOTO_OPCODE(ip) @ jump to next instruction 9095 9096/* continuation for OP_SGET_VOLATILE */ 9097 9098 /* 9099 * Continuation if the field has not yet been resolved. 9100 * r1: BBBB field ref 9101 */ 9102.LOP_SGET_VOLATILE_resolve: 9103 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9104 EXPORT_PC() @ resolve() could throw, so export now 9105 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9106 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9107 cmp r0, #0 @ success? 9108 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9109 b common_exceptionThrown @ no, handle exception 9110 9111/* continuation for OP_SPUT_VOLATILE */ 9112 9113 /* 9114 * Continuation if the field has not yet been resolved. 9115 * r1: BBBB field ref 9116 */ 9117.LOP_SPUT_VOLATILE_resolve: 9118 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9119 EXPORT_PC() @ resolve() could throw, so export now 9120 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9121 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9122 cmp r0, #0 @ success? 9123 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9124 b common_exceptionThrown @ no, handle exception 9125 9126/* continuation for OP_IGET_OBJECT_VOLATILE */ 9127 9128 /* 9129 * Currently: 9130 * r0 holds resolved field 9131 * r9 holds object 9132 */ 9133.LOP_IGET_OBJECT_VOLATILE_finish: 9134 @bl common_squeak0 9135 cmp r9, #0 @ check object for null 9136 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9137 beq common_errNullObject @ object was null 9138 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9139 SMP_DMB 1 @ acquiring load 9140 mov r2, rINST, lsr #8 @ r2<- A+ 9141 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9142 and r2, r2, #15 @ r2<- A 9143 GET_INST_OPCODE(ip) @ extract opcode from rINST 9144 SET_VREG(r0, r2) @ fp[A]<- r0 9145 GOTO_OPCODE(ip) @ jump to next instruction 9146 9147/* continuation for OP_IGET_WIDE_VOLATILE */ 9148 9149 /* 9150 * Currently: 9151 * r0 holds resolved field 9152 * r9 holds object 9153 */ 9154.LOP_IGET_WIDE_VOLATILE_finish: 9155 cmp r9, #0 @ check object for null 9156 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9157 beq common_errNullObject @ object was null 9158 .if 1 9159 add r0, r9, r3 @ r0<- address of field 9160 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9161 .else 9162 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9163 .endif 9164 mov r2, rINST, lsr #8 @ r2<- A+ 9165 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9166 and r2, r2, #15 @ r2<- A 9167 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9168 GET_INST_OPCODE(ip) @ extract opcode from rINST 9169 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9170 GOTO_OPCODE(ip) @ jump to next instruction 9171 9172/* continuation for OP_IPUT_WIDE_VOLATILE */ 9173 9174 /* 9175 * Currently: 9176 * r0 holds resolved field 9177 * r9 holds object 9178 */ 9179.LOP_IPUT_WIDE_VOLATILE_finish: 9180 mov r2, rINST, lsr #8 @ r2<- A+ 9181 cmp r9, #0 @ check object for null 9182 and r2, r2, #15 @ r2<- A 9183 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9184 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9185 beq common_errNullObject @ object was null 9186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9187 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9188 GET_INST_OPCODE(r10) @ extract opcode from rINST 9189 .if 1 9190 add r2, r9, r3 @ r2<- target address 9191 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9192 .else 9193 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9194 .endif 9195 GOTO_OPCODE(r10) @ jump to next instruction 9196 9197/* continuation for OP_SGET_WIDE_VOLATILE */ 9198 9199 /* 9200 * Continuation if the field has not yet been resolved. 9201 * r1: BBBB field ref 9202 * 9203 * Returns StaticField pointer in r0. 9204 */ 9205.LOP_SGET_WIDE_VOLATILE_resolve: 9206 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9207 EXPORT_PC() @ resolve() could throw, so export now 9208 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9209 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9210 cmp r0, #0 @ success? 9211 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9212 b common_exceptionThrown @ no, handle exception 9213 9214/* continuation for OP_SPUT_WIDE_VOLATILE */ 9215 9216 /* 9217 * Continuation if the field has not yet been resolved. 9218 * r1: BBBB field ref 9219 * r9: &fp[AA] 9220 * 9221 * Returns StaticField pointer in r2. 9222 */ 9223.LOP_SPUT_WIDE_VOLATILE_resolve: 9224 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9225 EXPORT_PC() @ resolve() could throw, so export now 9226 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9227 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9228 cmp r0, #0 @ success? 9229 mov r2, r0 @ copy to r2 9230 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9231 b common_exceptionThrown @ no, handle exception 9232 9233/* continuation for OP_EXECUTE_INLINE */ 9234 9235 /* 9236 * Extract args, call function. 9237 * r0 = #of args (0-4) 9238 * r10 = call index 9239 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9240 * 9241 * Other ideas: 9242 * - Use a jump table from the main piece to jump directly into the 9243 * AND/LDR pairs. Costs a data load, saves a branch. 9244 * - Have five separate pieces that do the loading, so we can work the 9245 * interleave a little better. Increases code size. 9246 */ 9247.LOP_EXECUTE_INLINE_continue: 9248 rsb r0, r0, #4 @ r0<- 4-r0 9249 FETCH(r9, 2) @ r9<- FEDC 9250 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9251 bl common_abort @ (skipped due to ARM prefetch) 92524: and ip, r9, #0xf000 @ isolate F 9253 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92543: and ip, r9, #0x0f00 @ isolate E 9255 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92562: and ip, r9, #0x00f0 @ isolate D 9257 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92581: and ip, r9, #0x000f @ isolate C 9259 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92600: 9261 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9262 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9263 @ (not reached) 9264 9265.LOP_EXECUTE_INLINE_table: 9266 .word gDvmInlineOpsTable 9267 9268/* continuation for OP_EXECUTE_INLINE_RANGE */ 9269 9270 /* 9271 * Extract args, call function. 9272 * r0 = #of args (0-4) 9273 * r10 = call index 9274 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9275 */ 9276.LOP_EXECUTE_INLINE_RANGE_continue: 9277 rsb r0, r0, #4 @ r0<- 4-r0 9278 FETCH(r9, 2) @ r9<- CCCC 9279 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9280 bl common_abort @ (skipped due to ARM prefetch) 92814: add ip, r9, #3 @ base+3 9282 GET_VREG(r3, ip) @ r3<- vBase[3] 92833: add ip, r9, #2 @ base+2 9284 GET_VREG(r2, ip) @ r2<- vBase[2] 92852: add ip, r9, #1 @ base+1 9286 GET_VREG(r1, ip) @ r1<- vBase[1] 92871: add ip, r9, #0 @ (nop) 9288 GET_VREG(r0, ip) @ r0<- vBase[0] 92890: 9290 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9291 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9292 @ (not reached) 9293 9294.LOP_EXECUTE_INLINE_RANGE_table: 9295 .word gDvmInlineOpsTable 9296 9297/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9298 9299 /* 9300 * Currently: 9301 * r0 holds resolved field 9302 * r9 holds object 9303 */ 9304.LOP_IPUT_OBJECT_VOLATILE_finish: 9305 @bl common_squeak0 9306 mov r1, rINST, lsr #8 @ r1<- A+ 9307 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9308 and r1, r1, #15 @ r1<- A 9309 cmp r9, #0 @ check object for null 9310 GET_VREG(r0, r1) @ r0<- fp[A] 9311 beq common_errNullObject @ object was null 9312 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9313 GET_INST_OPCODE(ip) @ extract opcode from rINST 9314 SMP_DMB 1 @ releasing store 9315 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9316 GOTO_OPCODE(ip) @ jump to next instruction 9317 9318/* continuation for OP_SGET_OBJECT_VOLATILE */ 9319 9320 /* 9321 * Continuation if the field has not yet been resolved. 9322 * r1: BBBB field ref 9323 */ 9324.LOP_SGET_OBJECT_VOLATILE_resolve: 9325 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9326 EXPORT_PC() @ resolve() could throw, so export now 9327 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9328 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9329 cmp r0, #0 @ success? 9330 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9331 b common_exceptionThrown @ no, handle exception 9332 9333/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9334 9335 /* 9336 * Continuation if the field has not yet been resolved. 9337 * r1: BBBB field ref 9338 */ 9339.LOP_SPUT_OBJECT_VOLATILE_resolve: 9340 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9341 EXPORT_PC() @ resolve() could throw, so export now 9342 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9343 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9344 cmp r0, #0 @ success? 9345 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 9346 b common_exceptionThrown @ no, handle exception 9347 9348 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9349 .global dvmAsmSisterEnd 9350dvmAsmSisterEnd: 9351 9352/* File: armv5te/footer.S */ 9353 9354/* 9355 * =========================================================================== 9356 * Common subroutines and data 9357 * =========================================================================== 9358 */ 9359 9360 9361 9362 .text 9363 .align 2 9364 9365#if defined(WITH_JIT) 9366#if defined(WITH_SELF_VERIFICATION) 9367 .global dvmJitToInterpPunt 9368dvmJitToInterpPunt: 9369 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9370 mov r2,#kSVSPunt @ r2<- interpreter entry point 9371 mov r3, #0 9372 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9373 b jitSVShadowRunEnd @ doesn't return 9374 9375 .global dvmJitToInterpSingleStep 9376dvmJitToInterpSingleStep: 9377 str lr,[rGLUE,#offGlue_jitResumeNPC] 9378 str r1,[rGLUE,#offGlue_jitResumeDPC] 9379 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9380 b jitSVShadowRunEnd @ doesn't return 9381 9382 .global dvmJitToInterpTraceSelectNoChain 9383dvmJitToInterpTraceSelectNoChain: 9384 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9385 mov r0,rPC @ pass our target PC 9386 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point 9387 mov r3, #0 9388 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9389 b jitSVShadowRunEnd @ doesn't return 9390 9391 .global dvmJitToInterpTraceSelect 9392dvmJitToInterpTraceSelect: 9393 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9394 ldr r0,[lr, #-1] @ pass our target PC 9395 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9396 mov r3, #0 9397 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9398 b jitSVShadowRunEnd @ doesn't return 9399 9400 .global dvmJitToInterpBackwardBranch 9401dvmJitToInterpBackwardBranch: 9402 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9403 ldr r0,[lr, #-1] @ pass our target PC 9404 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9405 mov r3, #0 9406 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9407 b jitSVShadowRunEnd @ doesn't return 9408 9409 .global dvmJitToInterpNormal 9410dvmJitToInterpNormal: 9411 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9412 ldr r0,[lr, #-1] @ pass our target PC 9413 mov r2,#kSVSNormal @ r2<- interpreter entry point 9414 mov r3, #0 9415 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9416 b jitSVShadowRunEnd @ doesn't return 9417 9418 .global dvmJitToInterpNoChain 9419dvmJitToInterpNoChain: 9420 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9421 mov r0,rPC @ pass our target PC 9422 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9423 mov r3, #0 9424 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9425 b jitSVShadowRunEnd @ doesn't return 9426#else 9427/* 9428 * Return from the translation cache to the interpreter when the compiler is 9429 * having issues translating/executing a Dalvik instruction. We have to skip 9430 * the code cache lookup otherwise it is possible to indefinitely bouce 9431 * between the interpreter and the code cache if the instruction that fails 9432 * to be compiled happens to be at a trace start. 9433 */ 9434 .global dvmJitToInterpPunt 9435dvmJitToInterpPunt: 9436 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9437 mov rPC, r0 9438#if defined(WITH_JIT_TUNING) 9439 mov r0,lr 9440 bl dvmBumpPunt; 9441#endif 9442 EXPORT_PC() 9443 mov r0, #0 9444 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9445 adrl rIBASE, dvmAsmInstructionStart 9446 FETCH_INST() 9447 GET_INST_OPCODE(ip) 9448 GOTO_OPCODE(ip) 9449 9450/* 9451 * Return to the interpreter to handle a single instruction. 9452 * On entry: 9453 * r0 <= PC 9454 * r1 <= PC of resume instruction 9455 * lr <= resume point in translation 9456 */ 9457 .global dvmJitToInterpSingleStep 9458dvmJitToInterpSingleStep: 9459 str lr,[rGLUE,#offGlue_jitResumeNPC] 9460 str r1,[rGLUE,#offGlue_jitResumeDPC] 9461 mov r1,#kInterpEntryInstr 9462 @ enum is 4 byte in aapcs-EABI 9463 str r1, [rGLUE, #offGlue_entryPoint] 9464 mov rPC,r0 9465 EXPORT_PC() 9466 9467 adrl rIBASE, dvmAsmInstructionStart 9468 mov r2,#kJitSingleStep @ Ask for single step and then revert 9469 str r2,[rGLUE,#offGlue_jitState] 9470 mov r1,#1 @ set changeInterp to bail to debug interp 9471 b common_gotoBail 9472 9473/* 9474 * Return from the translation cache and immediately request 9475 * a translation for the exit target. Commonly used for callees. 9476 */ 9477 .global dvmJitToInterpTraceSelectNoChain 9478dvmJitToInterpTraceSelectNoChain: 9479#if defined(WITH_JIT_TUNING) 9480 bl dvmBumpNoChain 9481#endif 9482 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9483 mov r0,rPC 9484 bl dvmJitGetCodeAddr @ Is there a translation? 9485 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9486 mov r1, rPC @ arg1 of translation may need this 9487 mov lr, #0 @ in case target is HANDLER_INTERPRET 9488 cmp r0,#0 9489 bxne r0 @ continue native execution if so 9490 b 2f 9491 9492/* 9493 * Return from the translation cache and immediately request 9494 * a translation for the exit target. Commonly used following 9495 * invokes. 9496 */ 9497 .global dvmJitToInterpTraceSelect 9498dvmJitToInterpTraceSelect: 9499 ldr rPC,[lr, #-1] @ get our target PC 9500 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9501 add rINST,lr,#-5 @ save start of chain branch 9502 add rINST, #-4 @ .. which is 9 bytes back 9503 mov r0,rPC 9504 bl dvmJitGetCodeAddr @ Is there a translation? 9505 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9506 cmp r0,#0 9507 beq 2f 9508 mov r1,rINST 9509 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9510 mov r1, rPC @ arg1 of translation may need this 9511 mov lr, #0 @ in case target is HANDLER_INTERPRET 9512 cmp r0,#0 @ successful chain? 9513 bxne r0 @ continue native execution 9514 b toInterpreter @ didn't chain - resume with interpreter 9515 9516/* No translation, so request one if profiling isn't disabled*/ 95172: 9518 adrl rIBASE, dvmAsmInstructionStart 9519 GET_JIT_PROF_TABLE(r0) 9520 FETCH_INST() 9521 cmp r0, #0 9522 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9523 bne common_selectTrace 9524 GET_INST_OPCODE(ip) 9525 GOTO_OPCODE(ip) 9526 9527/* 9528 * Return from the translation cache to the interpreter. 9529 * The return was done with a BLX from thumb mode, and 9530 * the following 32-bit word contains the target rPC value. 9531 * Note that lr (r14) will have its low-order bit set to denote 9532 * its thumb-mode origin. 9533 * 9534 * We'll need to stash our lr origin away, recover the new 9535 * target and then check to see if there is a translation available 9536 * for our new target. If so, we do a translation chain and 9537 * go back to native execution. Otherwise, it's back to the 9538 * interpreter (after treating this entry as a potential 9539 * trace start). 9540 */ 9541 .global dvmJitToInterpNormal 9542dvmJitToInterpNormal: 9543 ldr rPC,[lr, #-1] @ get our target PC 9544 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9545 add rINST,lr,#-5 @ save start of chain branch 9546 add rINST,#-4 @ .. which is 9 bytes back 9547#if defined(WITH_JIT_TUNING) 9548 bl dvmBumpNormal 9549#endif 9550 mov r0,rPC 9551 bl dvmJitGetCodeAddr @ Is there a translation? 9552 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9553 cmp r0,#0 9554 beq toInterpreter @ go if not, otherwise do chain 9555 mov r1,rINST 9556 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9557 mov r1, rPC @ arg1 of translation may need this 9558 mov lr, #0 @ in case target is HANDLER_INTERPRET 9559 cmp r0,#0 @ successful chain? 9560 bxne r0 @ continue native execution 9561 b toInterpreter @ didn't chain - resume with interpreter 9562 9563/* 9564 * Return from the translation cache to the interpreter to do method invocation. 9565 * Check if translation exists for the callee, but don't chain to it. 9566 */ 9567 .global dvmJitToInterpNoChain 9568dvmJitToInterpNoChain: 9569#if defined(WITH_JIT_TUNING) 9570 bl dvmBumpNoChain 9571#endif 9572 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9573 mov r0,rPC 9574 bl dvmJitGetCodeAddr @ Is there a translation? 9575 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9576 mov r1, rPC @ arg1 of translation may need this 9577 mov lr, #0 @ in case target is HANDLER_INTERPRET 9578 cmp r0,#0 9579 bxne r0 @ continue native execution if so 9580#endif 9581 9582/* 9583 * No translation, restore interpreter regs and start interpreting. 9584 * rGLUE & rFP were preserved in the translated code, and rPC has 9585 * already been restored by the time we get here. We'll need to set 9586 * up rIBASE & rINST, and load the address of the JitTable into r0. 9587 */ 9588toInterpreter: 9589 EXPORT_PC() 9590 adrl rIBASE, dvmAsmInstructionStart 9591 FETCH_INST() 9592 GET_JIT_PROF_TABLE(r0) 9593 @ NOTE: intended fallthrough 9594/* 9595 * Common code to update potential trace start counter, and initiate 9596 * a trace-build if appropriate. On entry, rPC should point to the 9597 * next instruction to execute, and rINST should be already loaded with 9598 * the next opcode word, and r0 holds a pointer to the jit profile 9599 * table (pJitProfTable). 9600 */ 9601common_testUpdateProfile: 9602 cmp r0,#0 9603 GET_INST_OPCODE(ip) 9604 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9605 9606common_updateProfile: 9607 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9608 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9609 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9610 GET_INST_OPCODE(ip) 9611 subs r1,r1,#1 @ decrement counter 9612 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9613 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9614 9615/* 9616 * Here, we switch to the debug interpreter to request 9617 * trace selection. First, though, check to see if there 9618 * is already a native translation in place (and, if so, 9619 * jump to it now). 9620 */ 9621 GET_JIT_THRESHOLD(r1) 9622 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9623 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9624 EXPORT_PC() 9625 mov r0,rPC 9626 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9627 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9628 mov r1, rPC @ arg1 of translation may need this 9629 mov lr, #0 @ in case target is HANDLER_INTERPRET 9630 cmp r0,#0 9631#if !defined(WITH_SELF_VERIFICATION) 9632 bxne r0 @ jump to the translation 9633 mov r2,#kJitTSelectRequest @ ask for trace selection 9634 @ fall-through to common_selectTrace 9635#else 9636 moveq r2,#kJitTSelectRequest @ ask for trace selection 9637 beq common_selectTrace 9638 /* 9639 * At this point, we have a target translation. However, if 9640 * that translation is actually the interpret-only pseudo-translation 9641 * we want to treat it the same as no translation. 9642 */ 9643 mov r10, r0 @ save target 9644 bl dvmCompilerGetInterpretTemplate 9645 cmp r0, r10 @ special case? 9646 bne jitSVShadowRunStart @ set up self verification shadow space 9647 GET_INST_OPCODE(ip) 9648 GOTO_OPCODE(ip) 9649 /* no return */ 9650#endif 9651 9652/* 9653 * On entry: 9654 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9655 */ 9656common_selectTrace: 9657 str r2,[rGLUE,#offGlue_jitState] 9658 mov r2,#kInterpEntryInstr @ normal entry reason 9659 str r2,[rGLUE,#offGlue_entryPoint] 9660 mov r1,#1 @ set changeInterp 9661 b common_gotoBail 9662 9663#if defined(WITH_SELF_VERIFICATION) 9664/* 9665 * Save PC and registers to shadow memory for self verification mode 9666 * before jumping to native translation. 9667 * On entry: 9668 * rPC, rFP, rGLUE: the values that they should contain 9669 * r10: the address of the target translation. 9670 */ 9671jitSVShadowRunStart: 9672 mov r0,rPC @ r0<- program counter 9673 mov r1,rFP @ r1<- frame pointer 9674 mov r2,rGLUE @ r2<- InterpState pointer 9675 mov r3,r10 @ r3<- target translation 9676 bl dvmSelfVerificationSaveState @ save registers to shadow space 9677 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9678 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9679 bx r10 @ jump to the translation 9680 9681/* 9682 * Restore PC, registers, and interpState to original values 9683 * before jumping back to the interpreter. 9684 */ 9685jitSVShadowRunEnd: 9686 mov r1,rFP @ pass ending fp 9687 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9688 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9689 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9690 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9691 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9692 cmp r1,#0 @ check for punt condition 9693 beq 1f 9694 mov r2,#kJitSelfVerification @ ask for self verification 9695 str r2,[rGLUE,#offGlue_jitState] 9696 mov r2,#kInterpEntryInstr @ normal entry reason 9697 str r2,[rGLUE,#offGlue_entryPoint] 9698 mov r1,#1 @ set changeInterp 9699 b common_gotoBail 9700 97011: @ exit to interpreter without check 9702 EXPORT_PC() 9703 adrl rIBASE, dvmAsmInstructionStart 9704 FETCH_INST() 9705 GET_INST_OPCODE(ip) 9706 GOTO_OPCODE(ip) 9707#endif 9708 9709#endif 9710 9711/* 9712 * Common code when a backward branch is taken. 9713 * 9714 * TODO: we could avoid a branch by just setting r0 and falling through 9715 * into the common_periodicChecks code, and having a test on r0 at the 9716 * end determine if we should return to the caller or update & branch to 9717 * the next instr. 9718 * 9719 * On entry: 9720 * r9 is PC adjustment *in bytes* 9721 */ 9722common_backwardBranch: 9723 mov r0, #kInterpEntryInstr 9724 bl common_periodicChecks 9725#if defined(WITH_JIT) 9726 GET_JIT_PROF_TABLE(r0) 9727 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9728 cmp r0,#0 9729 bne common_updateProfile 9730 GET_INST_OPCODE(ip) 9731 GOTO_OPCODE(ip) 9732#else 9733 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9734 GET_INST_OPCODE(ip) @ extract opcode from rINST 9735 GOTO_OPCODE(ip) @ jump to next instruction 9736#endif 9737 9738 9739/* 9740 * Need to see if the thread needs to be suspended or debugger/profiler 9741 * activity has begun. If so, we suspend the thread or side-exit to 9742 * the debug interpreter as appropriate. 9743 * 9744 * The common case is no activity on any of these, so we want to figure 9745 * that out quickly. If something is up, we can then sort out what. 9746 * 9747 * We want to be fast if the VM was built without debugger or profiler 9748 * support, but we also need to recognize that the system is usually 9749 * shipped with both of these enabled. 9750 * 9751 * TODO: reduce this so we're just checking a single location. 9752 * 9753 * On entry: 9754 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9755 * r9 is trampoline PC adjustment *in bytes* 9756 */ 9757common_periodicChecks: 9758 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9759 9760#if defined(WITH_DEBUGGER) 9761 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9762#endif 9763#if defined(WITH_PROFILER) 9764 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9765#endif 9766 9767 ldr ip, [r3] @ ip<- suspendCount (int) 9768 9769#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9770 cmp r1, #0 @ debugger enabled? 9771 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9772 ldr r2, [r2] @ r2<- activeProfilers (int) 9773 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 9774 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9775#elif defined(WITH_DEBUGGER) 9776 cmp r1, #0 @ debugger enabled? 9777 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9778 orrsne ip, ip, r1 @ yes, ip<- suspend | debugger; set Z 9779 @ (if not enabled, Z was set by test for r1==0, which is what we want) 9780#elif defined (WITH_PROFILER) 9781 ldr r2, [r2] @ r2<- activeProfilers (int) 9782 orrs ip, ip, r2 @ ip<- suspendCount | activeProfilers 9783#else 9784 cmp ip, #0 @ not ORing anything in; set Z 9785#endif 9786 9787 bxeq lr @ all zero, return 9788 9789 /* 9790 * One or more interesting events have happened. Figure out what. 9791 * 9792 * If debugging or profiling are compiled in, we need to disambiguate. 9793 * 9794 * r0 still holds the reentry type. 9795 */ 9796#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9797 ldr ip, [r3] @ ip<- suspendCount (int) 9798 cmp ip, #0 @ want suspend? 9799 beq 1f @ no, must be debugger/profiler 9800#endif 9801 9802 stmfd sp!, {r0, lr} @ preserve r0 and lr 9803#if defined(WITH_JIT) 9804 /* 9805 * Refresh the Jit's cached copy of profile table pointer. This pointer 9806 * doubles as the Jit's on/off switch. 9807 */ 9808 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9809 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9810 ldr r3, [r3] @ r3 <- pJitProfTable 9811 EXPORT_PC() @ need for precise GC 9812 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9813#else 9814 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9815 EXPORT_PC() @ need for precise GC 9816#endif 9817 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9818 ldmfd sp!, {r0, lr} @ restore r0 and lr 9819 9820#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9821 9822 /* 9823 * Reload the debugger/profiler enable flags. We're checking to see 9824 * if either of these got set while we were suspended. 9825 * 9826 * We can't really avoid the #ifdefs here, because the fields don't 9827 * exist when the feature is disabled. 9828 */ 9829#if defined(WITH_DEBUGGER) 9830 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9831 cmp r1, #0 @ debugger enabled? 9832 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9833#else 9834 mov r1, #0 9835#endif 9836#if defined(WITH_PROFILER) 9837 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9838 ldr r2, [r2] @ r2<- activeProfilers (int) 9839#else 9840 mov r2, #0 9841#endif 9842 9843 orrs r1, r1, r2 9844 beq 2f 9845 98461: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9847 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9848 add rPC, rPC, r9 @ update rPC 9849 mov r1, #1 @ "want switch" = true 9850 b common_gotoBail @ side exit 9851 9852#endif /*WITH_DEBUGGER || WITH_PROFILER*/ 9853 98542: 9855 bx lr @ nothing to do, return 9856 9857 9858/* 9859 * The equivalent of "goto bail", this calls through the "bail handler". 9860 * 9861 * State registers will be saved to the "glue" area before bailing. 9862 * 9863 * On entry: 9864 * r1 is "bool changeInterp", indicating if we want to switch to the 9865 * other interpreter or just bail all the way out 9866 */ 9867common_gotoBail: 9868 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9869 mov r0, rGLUE @ r0<- glue ptr 9870 b dvmMterpStdBail @ call(glue, changeInterp) 9871 9872 @add r1, r1, #1 @ using (boolean+1) 9873 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9874 @bl _longjmp @ does not return 9875 @bl common_abort 9876 9877 9878/* 9879 * Common code for method invocation with range. 9880 * 9881 * On entry: 9882 * r0 is "Method* methodToCall", the method we're trying to call 9883 */ 9884common_invokeMethodRange: 9885.LinvokeNewRange: 9886 @ prepare to copy args to "outs" area of current frame 9887 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9888 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9889 beq .LinvokeArgsDone @ if no args, skip the rest 9890 FETCH(r1, 2) @ r1<- CCCC 9891 9892 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9893 @ (very few methods have > 10 args; could unroll for common cases) 9894 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9895 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9896 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98971: ldr r1, [r3], #4 @ val = *fp++ 9898 subs r2, r2, #1 @ count-- 9899 str r1, [r10], #4 @ *outs++ = val 9900 bne 1b @ ...while count != 0 9901 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9902 b .LinvokeArgsDone 9903 9904/* 9905 * Common code for method invocation without range. 9906 * 9907 * On entry: 9908 * r0 is "Method* methodToCall", the method we're trying to call 9909 */ 9910common_invokeMethodNoRange: 9911.LinvokeNewNoRange: 9912 @ prepare to copy args to "outs" area of current frame 9913 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9914 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9915 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9916 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9917 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9918 beq .LinvokeArgsDone 9919 9920 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9921.LinvokeNonRange: 9922 rsb r2, r2, #5 @ r2<- 5-r2 9923 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9924 bl common_abort @ (skipped due to ARM prefetch) 99255: and ip, rINST, #0x0f00 @ isolate A 9926 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9927 mov r0, r0 @ nop 9928 str r2, [r10, #-4]! @ *--outs = vA 99294: and ip, r1, #0xf000 @ isolate G 9930 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9931 mov r0, r0 @ nop 9932 str r2, [r10, #-4]! @ *--outs = vG 99333: and ip, r1, #0x0f00 @ isolate F 9934 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9935 mov r0, r0 @ nop 9936 str r2, [r10, #-4]! @ *--outs = vF 99372: and ip, r1, #0x00f0 @ isolate E 9938 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9939 mov r0, r0 @ nop 9940 str r2, [r10, #-4]! @ *--outs = vE 99411: and ip, r1, #0x000f @ isolate D 9942 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9943 mov r0, r0 @ nop 9944 str r2, [r10, #-4]! @ *--outs = vD 99450: @ fall through to .LinvokeArgsDone 9946 9947.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9948 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9949 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9950 @ find space for the new stack frame, check for overflow 9951 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9952 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9953 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9954@ bl common_dumpRegs 9955 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9956 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9957 cmp r3, r9 @ bottom < interpStackEnd? 9958 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9959 blo .LstackOverflow @ yes, this frame will overflow stack 9960 9961 @ set up newSaveArea 9962#ifdef EASY_GDB 9963 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9964 str ip, [r10, #offStackSaveArea_prevSave] 9965#endif 9966 str rFP, [r10, #offStackSaveArea_prevFrame] 9967 str rPC, [r10, #offStackSaveArea_savedPc] 9968#if defined(WITH_JIT) 9969 mov r9, #0 9970 str r9, [r10, #offStackSaveArea_returnAddr] 9971#endif 9972 str r0, [r10, #offStackSaveArea_method] 9973 tst r3, #ACC_NATIVE 9974 bne .LinvokeNative 9975 9976 /* 9977 stmfd sp!, {r0-r3} 9978 bl common_printNewline 9979 mov r0, rFP 9980 mov r1, #0 9981 bl dvmDumpFp 9982 ldmfd sp!, {r0-r3} 9983 stmfd sp!, {r0-r3} 9984 mov r0, r1 9985 mov r1, r10 9986 bl dvmDumpFp 9987 bl common_printNewline 9988 ldmfd sp!, {r0-r3} 9989 */ 9990 9991 ldrh r9, [r2] @ r9 <- load INST from new PC 9992 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9993 mov rPC, r2 @ publish new rPC 9994 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9995 9996 @ Update "glue" values for the new method 9997 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9998 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9999 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10000#if defined(WITH_JIT) 10001 GET_JIT_PROF_TABLE(r0) 10002 mov rFP, r1 @ fp = newFp 10003 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10004 mov rINST, r9 @ publish new rINST 10005 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10006 cmp r0,#0 10007 bne common_updateProfile 10008 GOTO_OPCODE(ip) @ jump to next instruction 10009#else 10010 mov rFP, r1 @ fp = newFp 10011 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10012 mov rINST, r9 @ publish new rINST 10013 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10014 GOTO_OPCODE(ip) @ jump to next instruction 10015#endif 10016 10017.LinvokeNative: 10018 @ Prep for the native call 10019 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10020 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10021 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10022 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10023 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10024 mov r9, r3 @ r9<- glue->self (preserve) 10025 10026 mov r2, r0 @ r2<- methodToCall 10027 mov r0, r1 @ r0<- newFp (points to args) 10028 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10029 10030#ifdef ASSIST_DEBUGGER 10031 /* insert fake function header to help gdb find the stack frame */ 10032 b .Lskip 10033 .type dalvik_mterp, %function 10034dalvik_mterp: 10035 .fnstart 10036 MTERP_ENTRY1 10037 MTERP_ENTRY2 10038.Lskip: 10039#endif 10040 10041 @mov lr, pc @ set return addr 10042 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10043 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10044 10045#if defined(WITH_JIT) 10046 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10047#endif 10048 10049 @ native return; r9=self, r10=newSaveArea 10050 @ equivalent to dvmPopJniLocals 10051 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10052 ldr r1, [r9, #offThread_exception] @ check for exception 10053#if defined(WITH_JIT) 10054 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10055#endif 10056 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10057 cmp r1, #0 @ null? 10058 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10059#if defined(WITH_JIT) 10060 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10061#endif 10062 bne common_exceptionThrown @ no, handle exception 10063 10064 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10065 GET_INST_OPCODE(ip) @ extract opcode from rINST 10066 GOTO_OPCODE(ip) @ jump to next instruction 10067 10068.LstackOverflow: @ r0=methodToCall 10069 mov r1, r0 @ r1<- methodToCall 10070 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10071 bl dvmHandleStackOverflow 10072 b common_exceptionThrown 10073#ifdef ASSIST_DEBUGGER 10074 .fnend 10075#endif 10076 10077 10078 /* 10079 * Common code for method invocation, calling through "glue code". 10080 * 10081 * TODO: now that we have range and non-range invoke handlers, this 10082 * needs to be split into two. Maybe just create entry points 10083 * that set r9 and jump here? 10084 * 10085 * On entry: 10086 * r0 is "Method* methodToCall", the method we're trying to call 10087 * r9 is "bool methodCallRange", indicating if this is a /range variant 10088 */ 10089 .if 0 10090.LinvokeOld: 10091 sub sp, sp, #8 @ space for args + pad 10092 FETCH(ip, 2) @ ip<- FEDC or CCCC 10093 mov r2, r0 @ A2<- methodToCall 10094 mov r0, rGLUE @ A0<- glue 10095 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10096 mov r1, r9 @ A1<- methodCallRange 10097 mov r3, rINST, lsr #8 @ A3<- AA 10098 str ip, [sp, #0] @ A4<- ip 10099 bl dvmMterp_invokeMethod @ call the C invokeMethod 10100 add sp, sp, #8 @ remove arg area 10101 b common_resumeAfterGlueCall @ continue to next instruction 10102 .endif 10103 10104 10105 10106/* 10107 * Common code for handling a return instruction. 10108 * 10109 * This does not return. 10110 */ 10111common_returnFromMethod: 10112.LreturnNew: 10113 mov r0, #kInterpEntryReturn 10114 mov r9, #0 10115 bl common_periodicChecks 10116 10117 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10118 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10119 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10120 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10121 @ r2<- method we're returning to 10122 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10123 cmp r2, #0 @ is this a break frame? 10124 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10125 mov r1, #0 @ "want switch" = false 10126 beq common_gotoBail @ break frame, bail out completely 10127 10128 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10129 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10130 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10131 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10132#if defined(WITH_JIT) 10133 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10134 GET_JIT_PROF_TABLE(r0) 10135 mov rPC, r9 @ publish new rPC 10136 str r1, [rGLUE, #offGlue_methodClassDex] 10137 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10138 cmp r10, #0 @ caller is compiled code 10139 blxne r10 10140 GET_INST_OPCODE(ip) @ extract opcode from rINST 10141 cmp r0,#0 10142 bne common_updateProfile 10143 GOTO_OPCODE(ip) @ jump to next instruction 10144#else 10145 GET_INST_OPCODE(ip) @ extract opcode from rINST 10146 mov rPC, r9 @ publish new rPC 10147 str r1, [rGLUE, #offGlue_methodClassDex] 10148 GOTO_OPCODE(ip) @ jump to next instruction 10149#endif 10150 10151 /* 10152 * Return handling, calls through "glue code". 10153 */ 10154 .if 0 10155.LreturnOld: 10156 SAVE_PC_FP_TO_GLUE() @ export state 10157 mov r0, rGLUE @ arg to function 10158 bl dvmMterp_returnFromMethod 10159 b common_resumeAfterGlueCall 10160 .endif 10161 10162 10163/* 10164 * Somebody has thrown an exception. Handle it. 10165 * 10166 * If the exception processing code returns to us (instead of falling 10167 * out of the interpreter), continue with whatever the next instruction 10168 * now happens to be. 10169 * 10170 * This does not return. 10171 */ 10172 .global dvmMterpCommonExceptionThrown 10173dvmMterpCommonExceptionThrown: 10174common_exceptionThrown: 10175.LexceptionNew: 10176 mov r0, #kInterpEntryThrow 10177 mov r9, #0 10178 bl common_periodicChecks 10179 10180 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10181 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10182 mov r1, r10 @ r1<- self 10183 mov r0, r9 @ r0<- exception 10184 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10185 mov r3, #0 @ r3<- NULL 10186 str r3, [r10, #offThread_exception] @ self->exception = NULL 10187 10188 /* set up args and a local for "&fp" */ 10189 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10190 str rFP, [sp, #-4]! @ *--sp = fp 10191 mov ip, sp @ ip<- &fp 10192 mov r3, #0 @ r3<- false 10193 str ip, [sp, #-4]! @ *--sp = &fp 10194 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10195 mov r0, r10 @ r0<- self 10196 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10197 mov r2, r9 @ r2<- exception 10198 sub r1, rPC, r1 @ r1<- pc - method->insns 10199 mov r1, r1, asr #1 @ r1<- offset in code units 10200 10201 /* call, r0 gets catchRelPc (a code-unit offset) */ 10202 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10203 10204 /* fix earlier stack overflow if necessary; may trash rFP */ 10205 ldrb r1, [r10, #offThread_stackOverflowed] 10206 cmp r1, #0 @ did we overflow earlier? 10207 beq 1f @ no, skip ahead 10208 mov rFP, r0 @ save relPc result in rFP 10209 mov r0, r10 @ r0<- self 10210 mov r1, r9 @ r1<- exception 10211 bl dvmCleanupStackOverflow @ call(self) 10212 mov r0, rFP @ restore result 102131: 10214 10215 /* update frame pointer and check result from dvmFindCatchBlock */ 10216 ldr rFP, [sp, #4] @ retrieve the updated rFP 10217 cmp r0, #0 @ is catchRelPc < 0? 10218 add sp, sp, #8 @ restore stack 10219 bmi .LnotCaughtLocally 10220 10221 /* adjust locals to match self->curFrame and updated PC */ 10222 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10223 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10224 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10225 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10226 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10227 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10228 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10229 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10230 10231 /* release the tracked alloc on the exception */ 10232 mov r0, r9 @ r0<- exception 10233 mov r1, r10 @ r1<- self 10234 bl dvmReleaseTrackedAlloc @ release the exception 10235 10236 /* restore the exception if the handler wants it */ 10237 FETCH_INST() @ load rINST from rPC 10238 GET_INST_OPCODE(ip) @ extract opcode from rINST 10239 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10240 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10241 GOTO_OPCODE(ip) @ jump to next instruction 10242 10243.LnotCaughtLocally: @ r9=exception, r10=self 10244 /* fix stack overflow if necessary */ 10245 ldrb r1, [r10, #offThread_stackOverflowed] 10246 cmp r1, #0 @ did we overflow earlier? 10247 movne r0, r10 @ if yes: r0<- self 10248 movne r1, r9 @ if yes: r1<- exception 10249 blne dvmCleanupStackOverflow @ if yes: call(self) 10250 10251 @ may want to show "not caught locally" debug messages here 10252#if DVM_SHOW_EXCEPTION >= 2 10253 /* call __android_log_print(prio, tag, format, ...) */ 10254 /* "Exception %s from %s:%d not caught locally" */ 10255 @ dvmLineNumFromPC(method, pc - method->insns) 10256 ldr r0, [rGLUE, #offGlue_method] 10257 ldr r1, [r0, #offMethod_insns] 10258 sub r1, rPC, r1 10259 asr r1, r1, #1 10260 bl dvmLineNumFromPC 10261 str r0, [sp, #-4]! 10262 @ dvmGetMethodSourceFile(method) 10263 ldr r0, [rGLUE, #offGlue_method] 10264 bl dvmGetMethodSourceFile 10265 str r0, [sp, #-4]! 10266 @ exception->clazz->descriptor 10267 ldr r3, [r9, #offObject_clazz] 10268 ldr r3, [r3, #offClassObject_descriptor] 10269 @ 10270 ldr r2, strExceptionNotCaughtLocally 10271 ldr r1, strLogTag 10272 mov r0, #3 @ LOG_DEBUG 10273 bl __android_log_print 10274#endif 10275 str r9, [r10, #offThread_exception] @ restore exception 10276 mov r0, r9 @ r0<- exception 10277 mov r1, r10 @ r1<- self 10278 bl dvmReleaseTrackedAlloc @ release the exception 10279 mov r1, #0 @ "want switch" = false 10280 b common_gotoBail @ bail out 10281 10282 10283 /* 10284 * Exception handling, calls through "glue code". 10285 */ 10286 .if 0 10287.LexceptionOld: 10288 SAVE_PC_FP_TO_GLUE() @ export state 10289 mov r0, rGLUE @ arg to function 10290 bl dvmMterp_exceptionThrown 10291 b common_resumeAfterGlueCall 10292 .endif 10293 10294 10295/* 10296 * After returning from a "glued" function, pull out the updated 10297 * values and start executing at the next instruction. 10298 */ 10299common_resumeAfterGlueCall: 10300 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10301 FETCH_INST() @ load rINST from rPC 10302 GET_INST_OPCODE(ip) @ extract opcode from rINST 10303 GOTO_OPCODE(ip) @ jump to next instruction 10304 10305/* 10306 * Invalid array index. 10307 */ 10308common_errArrayIndex: 10309 EXPORT_PC() 10310 ldr r0, strArrayIndexException 10311 mov r1, #0 10312 bl dvmThrowException 10313 b common_exceptionThrown 10314 10315/* 10316 * Invalid array value. 10317 */ 10318common_errArrayStore: 10319 EXPORT_PC() 10320 ldr r0, strArrayStoreException 10321 mov r1, #0 10322 bl dvmThrowException 10323 b common_exceptionThrown 10324 10325/* 10326 * Integer divide or mod by zero. 10327 */ 10328common_errDivideByZero: 10329 EXPORT_PC() 10330 ldr r0, strArithmeticException 10331 ldr r1, strDivideByZero 10332 bl dvmThrowException 10333 b common_exceptionThrown 10334 10335/* 10336 * Attempt to allocate an array with a negative size. 10337 */ 10338common_errNegativeArraySize: 10339 EXPORT_PC() 10340 ldr r0, strNegativeArraySizeException 10341 mov r1, #0 10342 bl dvmThrowException 10343 b common_exceptionThrown 10344 10345/* 10346 * Invocation of a non-existent method. 10347 */ 10348common_errNoSuchMethod: 10349 EXPORT_PC() 10350 ldr r0, strNoSuchMethodError 10351 mov r1, #0 10352 bl dvmThrowException 10353 b common_exceptionThrown 10354 10355/* 10356 * We encountered a null object when we weren't expecting one. We 10357 * export the PC, throw a NullPointerException, and goto the exception 10358 * processing code. 10359 */ 10360common_errNullObject: 10361 EXPORT_PC() 10362 ldr r0, strNullPointerException 10363 mov r1, #0 10364 bl dvmThrowException 10365 b common_exceptionThrown 10366 10367/* 10368 * For debugging, cause an immediate fault. The source address will 10369 * be in lr (use a bl instruction to jump here). 10370 */ 10371common_abort: 10372 ldr pc, .LdeadFood 10373.LdeadFood: 10374 .word 0xdeadf00d 10375 10376/* 10377 * Spit out a "we were here", preserving all registers. (The attempt 10378 * to save ip won't work, but we need to save an even number of 10379 * registers for EABI 64-bit stack alignment.) 10380 */ 10381 .macro SQUEAK num 10382common_squeak\num: 10383 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10384 ldr r0, strSqueak 10385 mov r1, #\num 10386 bl printf 10387 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10388 bx lr 10389 .endm 10390 10391 SQUEAK 0 10392 SQUEAK 1 10393 SQUEAK 2 10394 SQUEAK 3 10395 SQUEAK 4 10396 SQUEAK 5 10397 10398/* 10399 * Spit out the number in r0, preserving registers. 10400 */ 10401common_printNum: 10402 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10403 mov r1, r0 10404 ldr r0, strSqueak 10405 bl printf 10406 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10407 bx lr 10408 10409/* 10410 * Print a newline, preserving registers. 10411 */ 10412common_printNewline: 10413 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10414 ldr r0, strNewline 10415 bl printf 10416 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10417 bx lr 10418 10419 /* 10420 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10421 */ 10422common_printHex: 10423 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10424 mov r1, r0 10425 ldr r0, strPrintHex 10426 bl printf 10427 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10428 bx lr 10429 10430/* 10431 * Print the 64-bit quantity in r0-r1, preserving registers. 10432 */ 10433common_printLong: 10434 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10435 mov r3, r1 10436 mov r2, r0 10437 ldr r0, strPrintLong 10438 bl printf 10439 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10440 bx lr 10441 10442/* 10443 * Print full method info. Pass the Method* in r0. Preserves regs. 10444 */ 10445common_printMethod: 10446 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10447 bl dvmMterpPrintMethod 10448 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10449 bx lr 10450 10451/* 10452 * Call a C helper function that dumps regs and possibly some 10453 * additional info. Requires the C function to be compiled in. 10454 */ 10455 .if 0 10456common_dumpRegs: 10457 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10458 bl dvmMterpDumpArmRegs 10459 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10460 bx lr 10461 .endif 10462 10463#if 0 10464/* 10465 * Experiment on VFP mode. 10466 * 10467 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10468 * 10469 * Updates the bits specified by "mask", setting them to the values in "val". 10470 */ 10471setFPSCR: 10472 and r0, r0, r1 @ make sure no stray bits are set 10473 fmrx r2, fpscr @ get VFP reg 10474 mvn r1, r1 @ bit-invert mask 10475 and r2, r2, r1 @ clear masked bits 10476 orr r2, r2, r0 @ set specified bits 10477 fmxr fpscr, r2 @ set VFP reg 10478 mov r0, r2 @ return new value 10479 bx lr 10480 10481 .align 2 10482 .global dvmConfigureFP 10483 .type dvmConfigureFP, %function 10484dvmConfigureFP: 10485 stmfd sp!, {ip, lr} 10486 /* 0x03000000 sets DN/FZ */ 10487 /* 0x00009f00 clears the six exception enable flags */ 10488 bl common_squeak0 10489 mov r0, #0x03000000 @ r0<- 0x03000000 10490 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10491 bl setFPSCR 10492 ldmfd sp!, {ip, pc} 10493#endif 10494 10495 10496/* 10497 * String references, must be close to the code that uses them. 10498 */ 10499 .align 2 10500strArithmeticException: 10501 .word .LstrArithmeticException 10502strArrayIndexException: 10503 .word .LstrArrayIndexException 10504strArrayStoreException: 10505 .word .LstrArrayStoreException 10506strDivideByZero: 10507 .word .LstrDivideByZero 10508strNegativeArraySizeException: 10509 .word .LstrNegativeArraySizeException 10510strNoSuchMethodError: 10511 .word .LstrNoSuchMethodError 10512strNullPointerException: 10513 .word .LstrNullPointerException 10514 10515strLogTag: 10516 .word .LstrLogTag 10517strExceptionNotCaughtLocally: 10518 .word .LstrExceptionNotCaughtLocally 10519 10520strNewline: 10521 .word .LstrNewline 10522strSqueak: 10523 .word .LstrSqueak 10524strPrintHex: 10525 .word .LstrPrintHex 10526strPrintLong: 10527 .word .LstrPrintLong 10528 10529/* 10530 * Zero-terminated ASCII string data. 10531 * 10532 * On ARM we have two choices: do like gcc does, and LDR from a .word 10533 * with the address, or use an ADR pseudo-op to get the address 10534 * directly. ADR saves 4 bytes and an indirection, but it's using a 10535 * PC-relative addressing mode and hence has a limited range, which 10536 * makes it not work well with mergeable string sections. 10537 */ 10538 .section .rodata.str1.4,"aMS",%progbits,1 10539 10540.LstrBadEntryPoint: 10541 .asciz "Bad entry point %d\n" 10542.LstrArithmeticException: 10543 .asciz "Ljava/lang/ArithmeticException;" 10544.LstrArrayIndexException: 10545 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10546.LstrArrayStoreException: 10547 .asciz "Ljava/lang/ArrayStoreException;" 10548.LstrClassCastException: 10549 .asciz "Ljava/lang/ClassCastException;" 10550.LstrDivideByZero: 10551 .asciz "divide by zero" 10552.LstrFilledNewArrayNotImpl: 10553 .asciz "filled-new-array only implemented for objects and 'int'" 10554.LstrInternalError: 10555 .asciz "Ljava/lang/InternalError;" 10556.LstrInstantiationError: 10557 .asciz "Ljava/lang/InstantiationError;" 10558.LstrNegativeArraySizeException: 10559 .asciz "Ljava/lang/NegativeArraySizeException;" 10560.LstrNoSuchMethodError: 10561 .asciz "Ljava/lang/NoSuchMethodError;" 10562.LstrNullPointerException: 10563 .asciz "Ljava/lang/NullPointerException;" 10564 10565.LstrLogTag: 10566 .asciz "mterp" 10567.LstrExceptionNotCaughtLocally: 10568 .asciz "Exception %s from %s:%d not caught locally\n" 10569 10570.LstrNewline: 10571 .asciz "\n" 10572.LstrSqueak: 10573 .asciz "<%d>" 10574.LstrPrintHex: 10575 .asciz "<0x%x>" 10576.LstrPrintLong: 10577 .asciz "<%lld>" 10578 10579