InterpAsm-armv7-a.S revision 51ae442fa9ed49e081e58e5127d1805789dbb196
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv7-a'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204#if defined(WITH_JIT) 205#include "../common/jit-config.h" 206#endif 207 208/* File: armv5te/platform.S */ 209/* 210 * =========================================================================== 211 * CPU-version-specific defines 212 * =========================================================================== 213 */ 214 215/* 216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 217 * one-way branch. 218 * 219 * May modify IP. Does not modify LR. 220 */ 221.macro LDR_PC source 222 ldr pc, \source 223.endm 224 225/* 226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 227 * Jump to subroutine. 228 * 229 * May modify IP and LR. 230 */ 231.macro LDR_PC_LR source 232 mov lr, pc 233 ldr pc, \source 234.endm 235 236/* 237 * Macro for "LDMFD SP!, {...regs...,PC}". 238 * 239 * May modify IP and LR. 240 */ 241.macro LDMFD_PC regs 242 ldmfd sp!, {\regs,pc} 243.endm 244 245 246/* File: armv5te/entry.S */ 247/* 248 * Copyright (C) 2008 The Android Open Source Project 249 * 250 * Licensed under the Apache License, Version 2.0 (the "License"); 251 * you may not use this file except in compliance with the License. 252 * You may obtain a copy of the License at 253 * 254 * http://www.apache.org/licenses/LICENSE-2.0 255 * 256 * Unless required by applicable law or agreed to in writing, software 257 * distributed under the License is distributed on an "AS IS" BASIS, 258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 259 * See the License for the specific language governing permissions and 260 * limitations under the License. 261 */ 262/* 263 * Interpreter entry point. 264 */ 265 266/* 267 * We don't have formal stack frames, so gdb scans upward in the code 268 * to find the start of the function (a label with the %function type), 269 * and then looks at the next few instructions to figure out what 270 * got pushed onto the stack. From this it figures out how to restore 271 * the registers, including PC, for the previous stack frame. If gdb 272 * sees a non-function label, it stops scanning, so either we need to 273 * have nothing but assembler-local labels between the entry point and 274 * the break, or we need to fake it out. 275 * 276 * When this is defined, we add some stuff to make gdb less confused. 277 */ 278#define ASSIST_DEBUGGER 1 279 280 .text 281 .align 2 282 .global dvmMterpStdRun 283 .type dvmMterpStdRun, %function 284 285/* 286 * On entry: 287 * r0 MterpGlue* glue 288 * 289 * This function returns a boolean "changeInterp" value. The return comes 290 * via a call to dvmMterpStdBail(). 291 */ 292dvmMterpStdRun: 293#define MTERP_ENTRY1 \ 294 .save {r4-r10,fp,lr}; \ 295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 296#define MTERP_ENTRY2 \ 297 .pad #4; \ 298 sub sp, sp, #4 @ align 64 299 300 .fnstart 301 MTERP_ENTRY1 302 MTERP_ENTRY2 303 304 /* save stack pointer, add magic word for debuggerd */ 305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 306 307 /* set up "named" registers, figure out entry point */ 308 mov rGLUE, r0 @ set rGLUE 309 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 312 cmp r1, #kInterpEntryInstr @ usual case? 313 bne .Lnot_instr @ no, handle it 314 315#if defined(WITH_JIT) 316.Lno_singleStep: 317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 318 /* Entry is always a possible trace start */ 319 GET_JIT_PROF_TABLE(r0) 320 FETCH_INST() 321 mov r1, #0 @ prepare the value for the new state 322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 323 cmp r0,#0 324 bne common_updateProfile 325 GET_INST_OPCODE(ip) 326 GOTO_OPCODE(ip) 327#else 328 /* start executing the instruction at rPC */ 329 FETCH_INST() @ load rINST from rPC 330 GET_INST_OPCODE(ip) @ extract opcode from rINST 331 GOTO_OPCODE(ip) @ jump to next instruction 332#endif 333 334.Lnot_instr: 335 cmp r1, #kInterpEntryReturn @ were we returning from a method? 336 beq common_returnFromMethod 337 338.Lnot_return: 339 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 340 beq common_exceptionThrown 341 342#if defined(WITH_JIT) 343.Lnot_throw: 344 ldr r0,[rGLUE, #offGlue_jitResume] 345 ldr r2,[rGLUE, #offGlue_jitResumePC] 346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 347 bne .Lbad_arg 348 cmp rPC,r2 349 bne .Lno_singleStep @ must have branched, don't resume 350 mov r1, #kInterpEntryInstr 351 str r1, [rGLUE, #offGlue_entryPoint] 352 ldr rINST, .LdvmCompilerTemplate 353 bx r0 @ re-enter the translation 354.LdvmCompilerTemplate: 355 .word dvmCompilerTemplateStart 356#endif 357 358.Lbad_arg: 359 ldr r0, strBadEntryPoint 360 @ r1 holds value of entryPoint 361 bl printf 362 bl dvmAbort 363 .fnend 364 365 366 .global dvmMterpStdBail 367 .type dvmMterpStdBail, %function 368 369/* 370 * Restore the stack pointer and PC from the save point established on entry. 371 * This is essentially the same as a longjmp, but should be cheaper. The 372 * last instruction causes us to return to whoever called dvmMterpStdRun. 373 * 374 * We pushed some registers on the stack in dvmMterpStdRun, then saved 375 * SP and LR. Here we restore SP, restore the registers, and then restore 376 * LR to PC. 377 * 378 * On entry: 379 * r0 MterpGlue* glue 380 * r1 bool changeInterp 381 */ 382dvmMterpStdBail: 383 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 384 mov r0, r1 @ return the changeInterp value 385 add sp, sp, #4 @ un-align 64 386 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 387 388 389/* 390 * String references. 391 */ 392strBadEntryPoint: 393 .word .LstrBadEntryPoint 394 395 396 397 .global dvmAsmInstructionStart 398 .type dvmAsmInstructionStart, %function 399dvmAsmInstructionStart = .L_OP_NOP 400 .text 401 402/* ------------------------------ */ 403 .balign 64 404.L_OP_NOP: /* 0x00 */ 405/* File: armv5te/OP_NOP.S */ 406 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 407 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 408 GOTO_OPCODE(ip) @ execute it 409 410#ifdef ASSIST_DEBUGGER 411 /* insert fake function header to help gdb find the stack frame */ 412 .type dalvik_inst, %function 413dalvik_inst: 414 .fnstart 415 MTERP_ENTRY1 416 MTERP_ENTRY2 417 .fnend 418#endif 419 420 421/* ------------------------------ */ 422 .balign 64 423.L_OP_MOVE: /* 0x01 */ 424/* File: armv6t2/OP_MOVE.S */ 425 /* for move, move-object, long-to-int */ 426 /* op vA, vB */ 427 mov r1, rINST, lsr #12 @ r1<- B from 15:12 428 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 429 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 430 GET_VREG(r2, r1) @ r2<- fp[B] 431 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 432 SET_VREG(r2, r0) @ fp[A]<- r2 433 GOTO_OPCODE(ip) @ execute next instruction 434 435 436/* ------------------------------ */ 437 .balign 64 438.L_OP_MOVE_FROM16: /* 0x02 */ 439/* File: armv5te/OP_MOVE_FROM16.S */ 440 /* for: move/from16, move-object/from16 */ 441 /* op vAA, vBBBB */ 442 FETCH(r1, 1) @ r1<- BBBB 443 mov r0, rINST, lsr #8 @ r0<- AA 444 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 445 GET_VREG(r2, r1) @ r2<- fp[BBBB] 446 GET_INST_OPCODE(ip) @ extract opcode from rINST 447 SET_VREG(r2, r0) @ fp[AA]<- r2 448 GOTO_OPCODE(ip) @ jump to next instruction 449 450 451/* ------------------------------ */ 452 .balign 64 453.L_OP_MOVE_16: /* 0x03 */ 454/* File: armv5te/OP_MOVE_16.S */ 455 /* for: move/16, move-object/16 */ 456 /* op vAAAA, vBBBB */ 457 FETCH(r1, 2) @ r1<- BBBB 458 FETCH(r0, 1) @ r0<- AAAA 459 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 460 GET_VREG(r2, r1) @ r2<- fp[BBBB] 461 GET_INST_OPCODE(ip) @ extract opcode from rINST 462 SET_VREG(r2, r0) @ fp[AAAA]<- r2 463 GOTO_OPCODE(ip) @ jump to next instruction 464 465 466/* ------------------------------ */ 467 .balign 64 468.L_OP_MOVE_WIDE: /* 0x04 */ 469/* File: armv6t2/OP_MOVE_WIDE.S */ 470 /* move-wide vA, vB */ 471 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 472 mov r3, rINST, lsr #12 @ r3<- B 473 ubfx r2, rINST, #8, #4 @ r2<- A 474 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 475 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 476 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 477 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 478 GET_INST_OPCODE(ip) @ extract opcode from rINST 479 stmia r2, {r0-r1} @ fp[A]<- r0/r1 480 GOTO_OPCODE(ip) @ jump to next instruction 481 482 483/* ------------------------------ */ 484 .balign 64 485.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 486/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 487 /* move-wide/from16 vAA, vBBBB */ 488 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 489 FETCH(r3, 1) @ r3<- BBBB 490 mov r2, rINST, lsr #8 @ r2<- AA 491 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 492 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 493 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 494 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 495 GET_INST_OPCODE(ip) @ extract opcode from rINST 496 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 497 GOTO_OPCODE(ip) @ jump to next instruction 498 499 500/* ------------------------------ */ 501 .balign 64 502.L_OP_MOVE_WIDE_16: /* 0x06 */ 503/* File: armv5te/OP_MOVE_WIDE_16.S */ 504 /* move-wide/16 vAAAA, vBBBB */ 505 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 506 FETCH(r3, 2) @ r3<- BBBB 507 FETCH(r2, 1) @ r2<- AAAA 508 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 509 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 510 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 511 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 512 GET_INST_OPCODE(ip) @ extract opcode from rINST 513 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 514 GOTO_OPCODE(ip) @ jump to next instruction 515 516 517/* ------------------------------ */ 518 .balign 64 519.L_OP_MOVE_OBJECT: /* 0x07 */ 520/* File: armv5te/OP_MOVE_OBJECT.S */ 521/* File: armv5te/OP_MOVE.S */ 522 /* for move, move-object, long-to-int */ 523 /* op vA, vB */ 524 mov r1, rINST, lsr #12 @ r1<- B from 15:12 525 mov r0, rINST, lsr #8 @ r0<- A from 11:8 526 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 527 GET_VREG(r2, r1) @ r2<- fp[B] 528 and r0, r0, #15 529 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 530 SET_VREG(r2, r0) @ fp[A]<- r2 531 GOTO_OPCODE(ip) @ execute next instruction 532 533 534 535/* ------------------------------ */ 536 .balign 64 537.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 538/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 539/* File: armv5te/OP_MOVE_FROM16.S */ 540 /* for: move/from16, move-object/from16 */ 541 /* op vAA, vBBBB */ 542 FETCH(r1, 1) @ r1<- BBBB 543 mov r0, rINST, lsr #8 @ r0<- AA 544 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 545 GET_VREG(r2, r1) @ r2<- fp[BBBB] 546 GET_INST_OPCODE(ip) @ extract opcode from rINST 547 SET_VREG(r2, r0) @ fp[AA]<- r2 548 GOTO_OPCODE(ip) @ jump to next instruction 549 550 551 552/* ------------------------------ */ 553 .balign 64 554.L_OP_MOVE_OBJECT_16: /* 0x09 */ 555/* File: armv5te/OP_MOVE_OBJECT_16.S */ 556/* File: armv5te/OP_MOVE_16.S */ 557 /* for: move/16, move-object/16 */ 558 /* op vAAAA, vBBBB */ 559 FETCH(r1, 2) @ r1<- BBBB 560 FETCH(r0, 1) @ r0<- AAAA 561 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 562 GET_VREG(r2, r1) @ r2<- fp[BBBB] 563 GET_INST_OPCODE(ip) @ extract opcode from rINST 564 SET_VREG(r2, r0) @ fp[AAAA]<- r2 565 GOTO_OPCODE(ip) @ jump to next instruction 566 567 568 569/* ------------------------------ */ 570 .balign 64 571.L_OP_MOVE_RESULT: /* 0x0a */ 572/* File: armv5te/OP_MOVE_RESULT.S */ 573 /* for: move-result, move-result-object */ 574 /* op vAA */ 575 mov r2, rINST, lsr #8 @ r2<- AA 576 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 577 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 578 GET_INST_OPCODE(ip) @ extract opcode from rINST 579 SET_VREG(r0, r2) @ fp[AA]<- r0 580 GOTO_OPCODE(ip) @ jump to next instruction 581 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/* ------------------------------ */ 599 .balign 64 600.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 601/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 602/* File: armv5te/OP_MOVE_RESULT.S */ 603 /* for: move-result, move-result-object */ 604 /* op vAA */ 605 mov r2, rINST, lsr #8 @ r2<- AA 606 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 607 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 608 GET_INST_OPCODE(ip) @ extract opcode from rINST 609 SET_VREG(r0, r2) @ fp[AA]<- r0 610 GOTO_OPCODE(ip) @ jump to next instruction 611 612 613 614/* ------------------------------ */ 615 .balign 64 616.L_OP_MOVE_EXCEPTION: /* 0x0d */ 617/* File: armv5te/OP_MOVE_EXCEPTION.S */ 618 /* move-exception vAA */ 619 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 620 mov r2, rINST, lsr #8 @ r2<- AA 621 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 622 mov r1, #0 @ r1<- 0 623 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 624 SET_VREG(r3, r2) @ fp[AA]<- exception obj 625 GET_INST_OPCODE(ip) @ extract opcode from rINST 626 str r1, [r0, #offThread_exception] @ dvmClearException bypass 627 GOTO_OPCODE(ip) @ jump to next instruction 628 629 630/* ------------------------------ */ 631 .balign 64 632.L_OP_RETURN_VOID: /* 0x0e */ 633/* File: armv5te/OP_RETURN_VOID.S */ 634 b common_returnFromMethod 635 636 637/* ------------------------------ */ 638 .balign 64 639.L_OP_RETURN: /* 0x0f */ 640/* File: armv5te/OP_RETURN.S */ 641 /* 642 * Return a 32-bit value. Copies the return value into the "glue" 643 * structure, then jumps to the return handler. 644 * 645 * for: return, return-object 646 */ 647 /* op vAA */ 648 mov r2, rINST, lsr #8 @ r2<- AA 649 GET_VREG(r0, r2) @ r0<- vAA 650 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 651 b common_returnFromMethod 652 653 654/* ------------------------------ */ 655 .balign 64 656.L_OP_RETURN_WIDE: /* 0x10 */ 657/* File: armv5te/OP_RETURN_WIDE.S */ 658 /* 659 * Return a 64-bit value. Copies the return value into the "glue" 660 * structure, then jumps to the return handler. 661 */ 662 /* return-wide vAA */ 663 mov r2, rINST, lsr #8 @ r2<- AA 664 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 665 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 666 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 667 stmia r3, {r0-r1} @ retval<- r0/r1 668 b common_returnFromMethod 669 670 671/* ------------------------------ */ 672 .balign 64 673.L_OP_RETURN_OBJECT: /* 0x11 */ 674/* File: armv5te/OP_RETURN_OBJECT.S */ 675/* File: armv5te/OP_RETURN.S */ 676 /* 677 * Return a 32-bit value. Copies the return value into the "glue" 678 * structure, then jumps to the return handler. 679 * 680 * for: return, return-object 681 */ 682 /* op vAA */ 683 mov r2, rINST, lsr #8 @ r2<- AA 684 GET_VREG(r0, r2) @ r0<- vAA 685 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 686 b common_returnFromMethod 687 688 689 690/* ------------------------------ */ 691 .balign 64 692.L_OP_CONST_4: /* 0x12 */ 693/* File: armv6t2/OP_CONST_4.S */ 694 /* const/4 vA, #+B */ 695 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 696 ubfx r0, rINST, #8, #4 @ r0<- A 697 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 698 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 699 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 700 SET_VREG(r1, r0) @ fp[A]<- r1 701 GOTO_OPCODE(ip) @ execute next instruction 702 703 704/* ------------------------------ */ 705 .balign 64 706.L_OP_CONST_16: /* 0x13 */ 707/* File: armv5te/OP_CONST_16.S */ 708 /* const/16 vAA, #+BBBB */ 709 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 710 mov r3, rINST, lsr #8 @ r3<- AA 711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 712 SET_VREG(r0, r3) @ vAA<- r0 713 GET_INST_OPCODE(ip) @ extract opcode from rINST 714 GOTO_OPCODE(ip) @ jump to next instruction 715 716 717/* ------------------------------ */ 718 .balign 64 719.L_OP_CONST: /* 0x14 */ 720/* File: armv5te/OP_CONST.S */ 721 /* const vAA, #+BBBBbbbb */ 722 mov r3, rINST, lsr #8 @ r3<- AA 723 FETCH(r0, 1) @ r0<- bbbb (low) 724 FETCH(r1, 2) @ r1<- BBBB (high) 725 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 726 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 727 GET_INST_OPCODE(ip) @ extract opcode from rINST 728 SET_VREG(r0, r3) @ vAA<- r0 729 GOTO_OPCODE(ip) @ jump to next instruction 730 731 732/* ------------------------------ */ 733 .balign 64 734.L_OP_CONST_HIGH16: /* 0x15 */ 735/* File: armv5te/OP_CONST_HIGH16.S */ 736 /* const/high16 vAA, #+BBBB0000 */ 737 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 738 mov r3, rINST, lsr #8 @ r3<- AA 739 mov r0, r0, lsl #16 @ r0<- BBBB0000 740 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 741 SET_VREG(r0, r3) @ vAA<- r0 742 GET_INST_OPCODE(ip) @ extract opcode from rINST 743 GOTO_OPCODE(ip) @ jump to next instruction 744 745 746/* ------------------------------ */ 747 .balign 64 748.L_OP_CONST_WIDE_16: /* 0x16 */ 749/* File: armv5te/OP_CONST_WIDE_16.S */ 750 /* const-wide/16 vAA, #+BBBB */ 751 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 752 mov r3, rINST, lsr #8 @ r3<- AA 753 mov r1, r0, asr #31 @ r1<- ssssssss 754 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 755 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 756 GET_INST_OPCODE(ip) @ extract opcode from rINST 757 stmia r3, {r0-r1} @ vAA<- r0/r1 758 GOTO_OPCODE(ip) @ jump to next instruction 759 760 761/* ------------------------------ */ 762 .balign 64 763.L_OP_CONST_WIDE_32: /* 0x17 */ 764/* File: armv5te/OP_CONST_WIDE_32.S */ 765 /* const-wide/32 vAA, #+BBBBbbbb */ 766 FETCH(r0, 1) @ r0<- 0000bbbb (low) 767 mov r3, rINST, lsr #8 @ r3<- AA 768 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 769 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 770 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 771 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 772 mov r1, r0, asr #31 @ r1<- ssssssss 773 GET_INST_OPCODE(ip) @ extract opcode from rINST 774 stmia r3, {r0-r1} @ vAA<- r0/r1 775 GOTO_OPCODE(ip) @ jump to next instruction 776 777 778/* ------------------------------ */ 779 .balign 64 780.L_OP_CONST_WIDE: /* 0x18 */ 781/* File: armv5te/OP_CONST_WIDE.S */ 782 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 783 FETCH(r0, 1) @ r0<- bbbb (low) 784 FETCH(r1, 2) @ r1<- BBBB (low middle) 785 FETCH(r2, 3) @ r2<- hhhh (high middle) 786 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 787 FETCH(r3, 4) @ r3<- HHHH (high) 788 mov r9, rINST, lsr #8 @ r9<- AA 789 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 790 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 791 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 792 GET_INST_OPCODE(ip) @ extract opcode from rINST 793 stmia r9, {r0-r1} @ vAA<- r0/r1 794 GOTO_OPCODE(ip) @ jump to next instruction 795 796 797/* ------------------------------ */ 798 .balign 64 799.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 800/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 801 /* const-wide/high16 vAA, #+BBBB000000000000 */ 802 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 803 mov r3, rINST, lsr #8 @ r3<- AA 804 mov r0, #0 @ r0<- 00000000 805 mov r1, r1, lsl #16 @ r1<- BBBB0000 806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 807 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 808 GET_INST_OPCODE(ip) @ extract opcode from rINST 809 stmia r3, {r0-r1} @ vAA<- r0/r1 810 GOTO_OPCODE(ip) @ jump to next instruction 811 812 813/* ------------------------------ */ 814 .balign 64 815.L_OP_CONST_STRING: /* 0x1a */ 816/* File: armv5te/OP_CONST_STRING.S */ 817 /* const/string vAA, String@BBBB */ 818 FETCH(r1, 1) @ r1<- BBBB 819 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 820 mov r9, rINST, lsr #8 @ r9<- AA 821 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 822 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 823 cmp r0, #0 @ not yet resolved? 824 beq .LOP_CONST_STRING_resolve 825 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 826 GET_INST_OPCODE(ip) @ extract opcode from rINST 827 SET_VREG(r0, r9) @ vAA<- r0 828 GOTO_OPCODE(ip) @ jump to next instruction 829 830/* ------------------------------ */ 831 .balign 64 832.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 833/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 834 /* const/string vAA, String@BBBBBBBB */ 835 FETCH(r0, 1) @ r0<- bbbb (low) 836 FETCH(r1, 2) @ r1<- BBBB (high) 837 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 838 mov r9, rINST, lsr #8 @ r9<- AA 839 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 840 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 841 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 842 cmp r0, #0 843 beq .LOP_CONST_STRING_JUMBO_resolve 844 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 845 GET_INST_OPCODE(ip) @ extract opcode from rINST 846 SET_VREG(r0, r9) @ vAA<- r0 847 GOTO_OPCODE(ip) @ jump to next instruction 848 849/* ------------------------------ */ 850 .balign 64 851.L_OP_CONST_CLASS: /* 0x1c */ 852/* File: armv5te/OP_CONST_CLASS.S */ 853 /* const/class vAA, Class@BBBB */ 854 FETCH(r1, 1) @ r1<- BBBB 855 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 856 mov r9, rINST, lsr #8 @ r9<- AA 857 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 858 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 859 cmp r0, #0 @ not yet resolved? 860 beq .LOP_CONST_CLASS_resolve 861 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 862 GET_INST_OPCODE(ip) @ extract opcode from rINST 863 SET_VREG(r0, r9) @ vAA<- r0 864 GOTO_OPCODE(ip) @ jump to next instruction 865 866/* ------------------------------ */ 867 .balign 64 868.L_OP_MONITOR_ENTER: /* 0x1d */ 869/* File: armv5te/OP_MONITOR_ENTER.S */ 870 /* 871 * Synchronize on an object. 872 */ 873 /* monitor-enter vAA */ 874 mov r2, rINST, lsr #8 @ r2<- AA 875 GET_VREG(r1, r2) @ r1<- vAA (object) 876 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 877 cmp r1, #0 @ null object? 878 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 879 beq common_errNullObject @ null object, throw an exception 880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 881 bl dvmLockObject @ call(self, obj) 882#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 883 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 884 ldr r1, [r0, #offThread_exception] @ check for exception 885 cmp r1, #0 886 bne common_exceptionThrown @ exception raised, bail out 887#endif 888 GET_INST_OPCODE(ip) @ extract opcode from rINST 889 GOTO_OPCODE(ip) @ jump to next instruction 890 891 892/* ------------------------------ */ 893 .balign 64 894.L_OP_MONITOR_EXIT: /* 0x1e */ 895/* File: armv5te/OP_MONITOR_EXIT.S */ 896 /* 897 * Unlock an object. 898 * 899 * Exceptions that occur when unlocking a monitor need to appear as 900 * if they happened at the following instruction. See the Dalvik 901 * instruction spec. 902 */ 903 /* monitor-exit vAA */ 904 mov r2, rINST, lsr #8 @ r2<- AA 905 EXPORT_PC() @ before fetch: export the PC 906 GET_VREG(r1, r2) @ r1<- vAA (object) 907 cmp r1, #0 @ null object? 908 beq 1f @ yes 909 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 910 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 911 cmp r0, #0 @ failed? 912 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 913 beq common_exceptionThrown @ yes, exception is pending 914 GET_INST_OPCODE(ip) @ extract opcode from rINST 915 GOTO_OPCODE(ip) @ jump to next instruction 9161: 917 FETCH_ADVANCE_INST(1) @ advance before throw 918 b common_errNullObject 919 920 921/* ------------------------------ */ 922 .balign 64 923.L_OP_CHECK_CAST: /* 0x1f */ 924/* File: armv5te/OP_CHECK_CAST.S */ 925 /* 926 * Check to see if a cast from one class to another is allowed. 927 */ 928 /* check-cast vAA, class@BBBB */ 929 mov r3, rINST, lsr #8 @ r3<- AA 930 FETCH(r2, 1) @ r2<- BBBB 931 GET_VREG(r9, r3) @ r9<- object 932 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 933 cmp r9, #0 @ is object null? 934 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 935 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 936 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 937 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 938 cmp r1, #0 @ have we resolved this before? 939 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 940.LOP_CHECK_CAST_resolved: 941 cmp r0, r1 @ same class (trivial success)? 942 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 943.LOP_CHECK_CAST_okay: 944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 945 GET_INST_OPCODE(ip) @ extract opcode from rINST 946 GOTO_OPCODE(ip) @ jump to next instruction 947 948/* ------------------------------ */ 949 .balign 64 950.L_OP_INSTANCE_OF: /* 0x20 */ 951/* File: armv5te/OP_INSTANCE_OF.S */ 952 /* 953 * Check to see if an object reference is an instance of a class. 954 * 955 * Most common situation is a non-null object, being compared against 956 * an already-resolved class. 957 */ 958 /* instance-of vA, vB, class@CCCC */ 959 mov r3, rINST, lsr #12 @ r3<- B 960 mov r9, rINST, lsr #8 @ r9<- A+ 961 GET_VREG(r0, r3) @ r0<- vB (object) 962 and r9, r9, #15 @ r9<- A 963 cmp r0, #0 @ is object null? 964 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 965 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 966 FETCH(r3, 1) @ r3<- CCCC 967 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 968 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 969 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 970 cmp r1, #0 @ have we resolved this before? 971 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 972.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 973 cmp r0, r1 @ same class (trivial success)? 974 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 975 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 976 977/* ------------------------------ */ 978 .balign 64 979.L_OP_ARRAY_LENGTH: /* 0x21 */ 980/* File: armv6t2/OP_ARRAY_LENGTH.S */ 981 /* 982 * Return the length of an array. 983 */ 984 mov r1, rINST, lsr #12 @ r1<- B 985 ubfx r2, rINST, #8, #4 @ r2<- A 986 GET_VREG(r0, r1) @ r0<- vB (object ref) 987 cmp r0, #0 @ is object null? 988 beq common_errNullObject @ yup, fail 989 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 990 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 991 GET_INST_OPCODE(ip) @ extract opcode from rINST 992 SET_VREG(r3, r2) @ vB<- length 993 GOTO_OPCODE(ip) @ jump to next instruction 994 995 996/* ------------------------------ */ 997 .balign 64 998.L_OP_NEW_INSTANCE: /* 0x22 */ 999/* File: armv5te/OP_NEW_INSTANCE.S */ 1000 /* 1001 * Create a new instance of a class. 1002 */ 1003 /* new-instance vAA, class@BBBB */ 1004 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1005 FETCH(r1, 1) @ r1<- BBBB 1006 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1007 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1008 EXPORT_PC() @ req'd for init, resolve, alloc 1009 cmp r0, #0 @ already resolved? 1010 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1011.LOP_NEW_INSTANCE_resolved: @ r0=class 1012 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1013 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1014 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1015.LOP_NEW_INSTANCE_initialized: @ r0=class 1016 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1017 bl dvmAllocObject @ r0<- new object 1018 b .LOP_NEW_INSTANCE_finish @ continue 1019 1020/* ------------------------------ */ 1021 .balign 64 1022.L_OP_NEW_ARRAY: /* 0x23 */ 1023/* File: armv5te/OP_NEW_ARRAY.S */ 1024 /* 1025 * Allocate an array of objects, specified with the array class 1026 * and a count. 1027 * 1028 * The verifier guarantees that this is an array class, so we don't 1029 * check for it here. 1030 */ 1031 /* new-array vA, vB, class@CCCC */ 1032 mov r0, rINST, lsr #12 @ r0<- B 1033 FETCH(r2, 1) @ r2<- CCCC 1034 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1035 GET_VREG(r1, r0) @ r1<- vB (array length) 1036 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1037 cmp r1, #0 @ check length 1038 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1039 bmi common_errNegativeArraySize @ negative length, bail 1040 cmp r0, #0 @ already resolved? 1041 EXPORT_PC() @ req'd for resolve, alloc 1042 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1043 b .LOP_NEW_ARRAY_resolve @ do resolve now 1044 1045/* ------------------------------ */ 1046 .balign 64 1047.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1048/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1049 /* 1050 * Create a new array with elements filled from registers. 1051 * 1052 * for: filled-new-array, filled-new-array/range 1053 */ 1054 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1055 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1056 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1057 FETCH(r1, 1) @ r1<- BBBB 1058 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1059 EXPORT_PC() @ need for resolve and alloc 1060 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1061 mov r10, rINST, lsr #8 @ r10<- AA or BA 1062 cmp r0, #0 @ already resolved? 1063 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10648: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1065 mov r2, #0 @ r2<- false 1066 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1067 bl dvmResolveClass @ r0<- call(clazz, ref) 1068 cmp r0, #0 @ got null? 1069 beq common_exceptionThrown @ yes, handle exception 1070 b .LOP_FILLED_NEW_ARRAY_continue 1071 1072/* ------------------------------ */ 1073 .balign 64 1074.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1075/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1076/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1077 /* 1078 * Create a new array with elements filled from registers. 1079 * 1080 * for: filled-new-array, filled-new-array/range 1081 */ 1082 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1083 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1084 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1085 FETCH(r1, 1) @ r1<- BBBB 1086 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1087 EXPORT_PC() @ need for resolve and alloc 1088 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1089 mov r10, rINST, lsr #8 @ r10<- AA or BA 1090 cmp r0, #0 @ already resolved? 1091 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10928: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1093 mov r2, #0 @ r2<- false 1094 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1095 bl dvmResolveClass @ r0<- call(clazz, ref) 1096 cmp r0, #0 @ got null? 1097 beq common_exceptionThrown @ yes, handle exception 1098 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1099 1100 1101/* ------------------------------ */ 1102 .balign 64 1103.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1104/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1105 /* fill-array-data vAA, +BBBBBBBB */ 1106 FETCH(r0, 1) @ r0<- bbbb (lo) 1107 FETCH(r1, 2) @ r1<- BBBB (hi) 1108 mov r3, rINST, lsr #8 @ r3<- AA 1109 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1110 GET_VREG(r0, r3) @ r0<- vAA (array object) 1111 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1112 EXPORT_PC(); 1113 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1114 cmp r0, #0 @ 0 means an exception is thrown 1115 beq common_exceptionThrown @ has exception 1116 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1117 GET_INST_OPCODE(ip) @ extract opcode from rINST 1118 GOTO_OPCODE(ip) @ jump to next instruction 1119 1120/* ------------------------------ */ 1121 .balign 64 1122.L_OP_THROW: /* 0x27 */ 1123/* File: armv5te/OP_THROW.S */ 1124 /* 1125 * Throw an exception object in the current thread. 1126 */ 1127 /* throw vAA */ 1128 mov r2, rINST, lsr #8 @ r2<- AA 1129 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1130 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1131 cmp r1, #0 @ null object? 1132 beq common_errNullObject @ yes, throw an NPE instead 1133 @ bypass dvmSetException, just store it 1134 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1135 b common_exceptionThrown 1136 1137 1138/* ------------------------------ */ 1139 .balign 64 1140.L_OP_GOTO: /* 0x28 */ 1141/* File: armv5te/OP_GOTO.S */ 1142 /* 1143 * Unconditional branch, 8-bit offset. 1144 * 1145 * The branch distance is a signed code-unit offset, which we need to 1146 * double to get a byte offset. 1147 */ 1148 /* goto +AA */ 1149 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1150 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1151 mov r9, r9, lsl #1 @ r9<- byte offset 1152 bmi common_backwardBranch @ backward branch, do periodic checks 1153#if defined(WITH_JIT) 1154 GET_JIT_PROF_TABLE(r0) 1155 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1156 cmp r0,#0 1157 bne common_updateProfile 1158 GET_INST_OPCODE(ip) @ extract opcode from rINST 1159 GOTO_OPCODE(ip) @ jump to next instruction 1160#else 1161 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1162 GET_INST_OPCODE(ip) @ extract opcode from rINST 1163 GOTO_OPCODE(ip) @ jump to next instruction 1164#endif 1165 1166/* ------------------------------ */ 1167 .balign 64 1168.L_OP_GOTO_16: /* 0x29 */ 1169/* File: armv5te/OP_GOTO_16.S */ 1170 /* 1171 * Unconditional branch, 16-bit offset. 1172 * 1173 * The branch distance is a signed code-unit offset, which we need to 1174 * double to get a byte offset. 1175 */ 1176 /* goto/16 +AAAA */ 1177 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1178 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1179 bmi common_backwardBranch @ backward branch, do periodic checks 1180#if defined(WITH_JIT) 1181 GET_JIT_PROF_TABLE(r0) 1182 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1183 cmp r0,#0 1184 bne common_updateProfile 1185 GET_INST_OPCODE(ip) @ extract opcode from rINST 1186 GOTO_OPCODE(ip) @ jump to next instruction 1187#else 1188 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1189 GET_INST_OPCODE(ip) @ extract opcode from rINST 1190 GOTO_OPCODE(ip) @ jump to next instruction 1191#endif 1192 1193 1194/* ------------------------------ */ 1195 .balign 64 1196.L_OP_GOTO_32: /* 0x2a */ 1197/* File: armv5te/OP_GOTO_32.S */ 1198 /* 1199 * Unconditional branch, 32-bit offset. 1200 * 1201 * The branch distance is a signed code-unit offset, which we need to 1202 * double to get a byte offset. 1203 * 1204 * Unlike most opcodes, this one is allowed to branch to itself, so 1205 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1206 * instruction doesn't affect the V flag, so we need to clear it 1207 * explicitly. 1208 */ 1209 /* goto/32 +AAAAAAAA */ 1210 FETCH(r0, 1) @ r0<- aaaa (lo) 1211 FETCH(r1, 2) @ r1<- AAAA (hi) 1212 cmp ip, ip @ (clear V flag during stall) 1213 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1214 mov r9, r0, asl #1 @ r9<- byte offset 1215 ble common_backwardBranch @ backward branch, do periodic checks 1216#if defined(WITH_JIT) 1217 GET_JIT_PROF_TABLE(r0) 1218 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1219 cmp r0,#0 1220 bne common_updateProfile 1221 GET_INST_OPCODE(ip) @ extract opcode from rINST 1222 GOTO_OPCODE(ip) @ jump to next instruction 1223#else 1224 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1225 GET_INST_OPCODE(ip) @ extract opcode from rINST 1226 GOTO_OPCODE(ip) @ jump to next instruction 1227#endif 1228 1229/* ------------------------------ */ 1230 .balign 64 1231.L_OP_PACKED_SWITCH: /* 0x2b */ 1232/* File: armv5te/OP_PACKED_SWITCH.S */ 1233 /* 1234 * Handle a packed-switch or sparse-switch instruction. In both cases 1235 * we decode it and hand it off to a helper function. 1236 * 1237 * We don't really expect backward branches in a switch statement, but 1238 * they're perfectly legal, so we check for them here. 1239 * 1240 * for: packed-switch, sparse-switch 1241 */ 1242 /* op vAA, +BBBB */ 1243 FETCH(r0, 1) @ r0<- bbbb (lo) 1244 FETCH(r1, 2) @ r1<- BBBB (hi) 1245 mov r3, rINST, lsr #8 @ r3<- AA 1246 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1247 GET_VREG(r1, r3) @ r1<- vAA 1248 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1249 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1250 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1251 bmi common_backwardBranch @ backward branch, do periodic checks 1252 beq common_backwardBranch @ (want to use BLE but V is unknown) 1253#if defined(WITH_JIT) 1254 GET_JIT_PROF_TABLE(r0) 1255 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1256 cmp r0,#0 1257 bne common_updateProfile 1258 GET_INST_OPCODE(ip) @ extract opcode from rINST 1259 GOTO_OPCODE(ip) @ jump to next instruction 1260#else 1261 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1262 GET_INST_OPCODE(ip) @ extract opcode from rINST 1263 GOTO_OPCODE(ip) @ jump to next instruction 1264#endif 1265 1266 1267/* ------------------------------ */ 1268 .balign 64 1269.L_OP_SPARSE_SWITCH: /* 0x2c */ 1270/* File: armv5te/OP_SPARSE_SWITCH.S */ 1271/* File: armv5te/OP_PACKED_SWITCH.S */ 1272 /* 1273 * Handle a packed-switch or sparse-switch instruction. In both cases 1274 * we decode it and hand it off to a helper function. 1275 * 1276 * We don't really expect backward branches in a switch statement, but 1277 * they're perfectly legal, so we check for them here. 1278 * 1279 * for: packed-switch, sparse-switch 1280 */ 1281 /* op vAA, +BBBB */ 1282 FETCH(r0, 1) @ r0<- bbbb (lo) 1283 FETCH(r1, 2) @ r1<- BBBB (hi) 1284 mov r3, rINST, lsr #8 @ r3<- AA 1285 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1286 GET_VREG(r1, r3) @ r1<- vAA 1287 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1288 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1289 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1290 bmi common_backwardBranch @ backward branch, do periodic checks 1291 beq common_backwardBranch @ (want to use BLE but V is unknown) 1292#if defined(WITH_JIT) 1293 GET_JIT_PROF_TABLE(r0) 1294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1295 cmp r0,#0 1296 bne common_updateProfile 1297 GET_INST_OPCODE(ip) @ extract opcode from rINST 1298 GOTO_OPCODE(ip) @ jump to next instruction 1299#else 1300 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1301 GET_INST_OPCODE(ip) @ extract opcode from rINST 1302 GOTO_OPCODE(ip) @ jump to next instruction 1303#endif 1304 1305 1306 1307/* ------------------------------ */ 1308 .balign 64 1309.L_OP_CMPL_FLOAT: /* 0x2d */ 1310/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1311 /* 1312 * Compare two floating-point values. Puts 0, 1, or -1 into the 1313 * destination register based on the results of the comparison. 1314 * 1315 * int compare(x, y) { 1316 * if (x == y) { 1317 * return 0; 1318 * } else if (x > y) { 1319 * return 1; 1320 * } else if (x < y) { 1321 * return -1; 1322 * } else { 1323 * return -1; 1324 * } 1325 * } 1326 */ 1327 /* op vAA, vBB, vCC */ 1328 FETCH(r0, 1) @ r0<- CCBB 1329 mov r9, rINST, lsr #8 @ r9<- AA 1330 and r2, r0, #255 @ r2<- BB 1331 mov r3, r0, lsr #8 @ r3<- CC 1332 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1333 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1334 flds s0, [r2] @ s0<- vBB 1335 flds s1, [r3] @ s1<- vCC 1336 fcmpes s0, s1 @ compare (vBB, vCC) 1337 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1338 mvn r0, #0 @ r0<- -1 (default) 1339 GET_INST_OPCODE(ip) @ extract opcode from rINST 1340 fmstat @ export status flags 1341 movgt r0, #1 @ (greater than) r1<- 1 1342 moveq r0, #0 @ (equal) r1<- 0 1343 b .LOP_CMPL_FLOAT_finish @ argh 1344 1345 1346/* ------------------------------ */ 1347 .balign 64 1348.L_OP_CMPG_FLOAT: /* 0x2e */ 1349/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1350 /* 1351 * Compare two floating-point values. Puts 0, 1, or -1 into the 1352 * destination register based on the results of the comparison. 1353 * 1354 * int compare(x, y) { 1355 * if (x == y) { 1356 * return 0; 1357 * } else if (x < y) { 1358 * return -1; 1359 * } else if (x > y) { 1360 * return 1; 1361 * } else { 1362 * return 1; 1363 * } 1364 * } 1365 */ 1366 /* op vAA, vBB, vCC */ 1367 FETCH(r0, 1) @ r0<- CCBB 1368 mov r9, rINST, lsr #8 @ r9<- AA 1369 and r2, r0, #255 @ r2<- BB 1370 mov r3, r0, lsr #8 @ r3<- CC 1371 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1372 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1373 flds s0, [r2] @ s0<- vBB 1374 flds s1, [r3] @ s1<- vCC 1375 fcmpes s0, s1 @ compare (vBB, vCC) 1376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1377 mov r0, #1 @ r0<- 1 (default) 1378 GET_INST_OPCODE(ip) @ extract opcode from rINST 1379 fmstat @ export status flags 1380 mvnmi r0, #0 @ (less than) r1<- -1 1381 moveq r0, #0 @ (equal) r1<- 0 1382 b .LOP_CMPG_FLOAT_finish @ argh 1383 1384 1385/* ------------------------------ */ 1386 .balign 64 1387.L_OP_CMPL_DOUBLE: /* 0x2f */ 1388/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1389 /* 1390 * Compare two floating-point values. Puts 0, 1, or -1 into the 1391 * destination register based on the results of the comparison. 1392 * 1393 * int compare(x, y) { 1394 * if (x == y) { 1395 * return 0; 1396 * } else if (x > y) { 1397 * return 1; 1398 * } else if (x < y) { 1399 * return -1; 1400 * } else { 1401 * return -1; 1402 * } 1403 * } 1404 */ 1405 /* op vAA, vBB, vCC */ 1406 FETCH(r0, 1) @ r0<- CCBB 1407 mov r9, rINST, lsr #8 @ r9<- AA 1408 and r2, r0, #255 @ r2<- BB 1409 mov r3, r0, lsr #8 @ r3<- CC 1410 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1411 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1412 fldd d0, [r2] @ d0<- vBB 1413 fldd d1, [r3] @ d1<- vCC 1414 fcmped d0, d1 @ compare (vBB, vCC) 1415 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1416 mvn r0, #0 @ r0<- -1 (default) 1417 GET_INST_OPCODE(ip) @ extract opcode from rINST 1418 fmstat @ export status flags 1419 movgt r0, #1 @ (greater than) r1<- 1 1420 moveq r0, #0 @ (equal) r1<- 0 1421 b .LOP_CMPL_DOUBLE_finish @ argh 1422 1423 1424/* ------------------------------ */ 1425 .balign 64 1426.L_OP_CMPG_DOUBLE: /* 0x30 */ 1427/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1428 /* 1429 * Compare two floating-point values. Puts 0, 1, or -1 into the 1430 * destination register based on the results of the comparison. 1431 * 1432 * int compare(x, y) { 1433 * if (x == y) { 1434 * return 0; 1435 * } else if (x < y) { 1436 * return -1; 1437 * } else if (x > y) { 1438 * return 1; 1439 * } else { 1440 * return 1; 1441 * } 1442 * } 1443 */ 1444 /* op vAA, vBB, vCC */ 1445 FETCH(r0, 1) @ r0<- CCBB 1446 mov r9, rINST, lsr #8 @ r9<- AA 1447 and r2, r0, #255 @ r2<- BB 1448 mov r3, r0, lsr #8 @ r3<- CC 1449 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1450 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1451 fldd d0, [r2] @ d0<- vBB 1452 fldd d1, [r3] @ d1<- vCC 1453 fcmped d0, d1 @ compare (vBB, vCC) 1454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1455 mov r0, #1 @ r0<- 1 (default) 1456 GET_INST_OPCODE(ip) @ extract opcode from rINST 1457 fmstat @ export status flags 1458 mvnmi r0, #0 @ (less than) r1<- -1 1459 moveq r0, #0 @ (equal) r1<- 0 1460 b .LOP_CMPG_DOUBLE_finish @ argh 1461 1462 1463/* ------------------------------ */ 1464 .balign 64 1465.L_OP_CMP_LONG: /* 0x31 */ 1466/* File: armv5te/OP_CMP_LONG.S */ 1467 /* 1468 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1469 * register based on the results of the comparison. 1470 * 1471 * We load the full values with LDM, but in practice many values could 1472 * be resolved by only looking at the high word. This could be made 1473 * faster or slower by splitting the LDM into a pair of LDRs. 1474 * 1475 * If we just wanted to set condition flags, we could do this: 1476 * subs ip, r0, r2 1477 * sbcs ip, r1, r3 1478 * subeqs ip, r0, r2 1479 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1480 * integer value, which we can do with 2 conditional mov/mvn instructions 1481 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1482 * us a constant 5-cycle path plus a branch at the end to the 1483 * instruction epilogue code. The multi-compare approach below needs 1484 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1485 * in the worst case (the 64-bit values are equal). 1486 */ 1487 /* cmp-long vAA, vBB, vCC */ 1488 FETCH(r0, 1) @ r0<- CCBB 1489 mov r9, rINST, lsr #8 @ r9<- AA 1490 and r2, r0, #255 @ r2<- BB 1491 mov r3, r0, lsr #8 @ r3<- CC 1492 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1493 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1494 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1495 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1496 cmp r1, r3 @ compare (vBB+1, vCC+1) 1497 blt .LOP_CMP_LONG_less @ signed compare on high part 1498 bgt .LOP_CMP_LONG_greater 1499 subs r1, r0, r2 @ r1<- r0 - r2 1500 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1501 bne .LOP_CMP_LONG_less 1502 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1503 1504/* ------------------------------ */ 1505 .balign 64 1506.L_OP_IF_EQ: /* 0x32 */ 1507/* File: armv6t2/OP_IF_EQ.S */ 1508/* File: armv6t2/bincmp.S */ 1509 /* 1510 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1511 * fragment that specifies the *reverse* comparison to perform, e.g. 1512 * for "if-le" you would use "gt". 1513 * 1514 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1515 */ 1516 /* if-cmp vA, vB, +CCCC */ 1517 mov r1, rINST, lsr #12 @ r1<- B 1518 ubfx r0, rINST, #8, #4 @ r0<- A 1519 GET_VREG(r3, r1) @ r3<- vB 1520 GET_VREG(r2, r0) @ r2<- vA 1521 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1522 cmp r2, r3 @ compare (vA, vB) 1523 bne 1f @ branch to 1 if comparison failed 1524 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1525 movs r9, r9, asl #1 @ convert to bytes, check sign 1526 bmi common_backwardBranch @ yes, do periodic checks 15271: 1528#if defined(WITH_JIT) 1529 GET_JIT_PROF_TABLE(r0) 1530 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1531 b common_testUpdateProfile 1532#else 1533 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1534 GET_INST_OPCODE(ip) @ extract opcode from rINST 1535 GOTO_OPCODE(ip) @ jump to next instruction 1536#endif 1537 1538 1539 1540/* ------------------------------ */ 1541 .balign 64 1542.L_OP_IF_NE: /* 0x33 */ 1543/* File: armv6t2/OP_IF_NE.S */ 1544/* File: armv6t2/bincmp.S */ 1545 /* 1546 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1547 * fragment that specifies the *reverse* comparison to perform, e.g. 1548 * for "if-le" you would use "gt". 1549 * 1550 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1551 */ 1552 /* if-cmp vA, vB, +CCCC */ 1553 mov r1, rINST, lsr #12 @ r1<- B 1554 ubfx r0, rINST, #8, #4 @ r0<- A 1555 GET_VREG(r3, r1) @ r3<- vB 1556 GET_VREG(r2, r0) @ r2<- vA 1557 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1558 cmp r2, r3 @ compare (vA, vB) 1559 beq 1f @ branch to 1 if comparison failed 1560 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1561 movs r9, r9, asl #1 @ convert to bytes, check sign 1562 bmi common_backwardBranch @ yes, do periodic checks 15631: 1564#if defined(WITH_JIT) 1565 GET_JIT_PROF_TABLE(r0) 1566 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 b common_testUpdateProfile 1568#else 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 GET_INST_OPCODE(ip) @ extract opcode from rINST 1571 GOTO_OPCODE(ip) @ jump to next instruction 1572#endif 1573 1574 1575 1576/* ------------------------------ */ 1577 .balign 64 1578.L_OP_IF_LT: /* 0x34 */ 1579/* File: armv6t2/OP_IF_LT.S */ 1580/* File: armv6t2/bincmp.S */ 1581 /* 1582 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1583 * fragment that specifies the *reverse* comparison to perform, e.g. 1584 * for "if-le" you would use "gt". 1585 * 1586 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1587 */ 1588 /* if-cmp vA, vB, +CCCC */ 1589 mov r1, rINST, lsr #12 @ r1<- B 1590 ubfx r0, rINST, #8, #4 @ r0<- A 1591 GET_VREG(r3, r1) @ r3<- vB 1592 GET_VREG(r2, r0) @ r2<- vA 1593 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1594 cmp r2, r3 @ compare (vA, vB) 1595 bge 1f @ branch to 1 if comparison failed 1596 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1597 movs r9, r9, asl #1 @ convert to bytes, check sign 1598 bmi common_backwardBranch @ yes, do periodic checks 15991: 1600#if defined(WITH_JIT) 1601 GET_JIT_PROF_TABLE(r0) 1602 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1603 b common_testUpdateProfile 1604#else 1605 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1606 GET_INST_OPCODE(ip) @ extract opcode from rINST 1607 GOTO_OPCODE(ip) @ jump to next instruction 1608#endif 1609 1610 1611 1612/* ------------------------------ */ 1613 .balign 64 1614.L_OP_IF_GE: /* 0x35 */ 1615/* File: armv6t2/OP_IF_GE.S */ 1616/* File: armv6t2/bincmp.S */ 1617 /* 1618 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1619 * fragment that specifies the *reverse* comparison to perform, e.g. 1620 * for "if-le" you would use "gt". 1621 * 1622 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1623 */ 1624 /* if-cmp vA, vB, +CCCC */ 1625 mov r1, rINST, lsr #12 @ r1<- B 1626 ubfx r0, rINST, #8, #4 @ r0<- A 1627 GET_VREG(r3, r1) @ r3<- vB 1628 GET_VREG(r2, r0) @ r2<- vA 1629 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1630 cmp r2, r3 @ compare (vA, vB) 1631 blt 1f @ branch to 1 if comparison failed 1632 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1633 movs r9, r9, asl #1 @ convert to bytes, check sign 1634 bmi common_backwardBranch @ yes, do periodic checks 16351: 1636#if defined(WITH_JIT) 1637 GET_JIT_PROF_TABLE(r0) 1638 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1639 b common_testUpdateProfile 1640#else 1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1642 GET_INST_OPCODE(ip) @ extract opcode from rINST 1643 GOTO_OPCODE(ip) @ jump to next instruction 1644#endif 1645 1646 1647 1648/* ------------------------------ */ 1649 .balign 64 1650.L_OP_IF_GT: /* 0x36 */ 1651/* File: armv6t2/OP_IF_GT.S */ 1652/* File: armv6t2/bincmp.S */ 1653 /* 1654 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1655 * fragment that specifies the *reverse* comparison to perform, e.g. 1656 * for "if-le" you would use "gt". 1657 * 1658 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1659 */ 1660 /* if-cmp vA, vB, +CCCC */ 1661 mov r1, rINST, lsr #12 @ r1<- B 1662 ubfx r0, rINST, #8, #4 @ r0<- A 1663 GET_VREG(r3, r1) @ r3<- vB 1664 GET_VREG(r2, r0) @ r2<- vA 1665 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1666 cmp r2, r3 @ compare (vA, vB) 1667 ble 1f @ branch to 1 if comparison failed 1668 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1669 movs r9, r9, asl #1 @ convert to bytes, check sign 1670 bmi common_backwardBranch @ yes, do periodic checks 16711: 1672#if defined(WITH_JIT) 1673 GET_JIT_PROF_TABLE(r0) 1674 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1675 b common_testUpdateProfile 1676#else 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 GET_INST_OPCODE(ip) @ extract opcode from rINST 1679 GOTO_OPCODE(ip) @ jump to next instruction 1680#endif 1681 1682 1683 1684/* ------------------------------ */ 1685 .balign 64 1686.L_OP_IF_LE: /* 0x37 */ 1687/* File: armv6t2/OP_IF_LE.S */ 1688/* File: armv6t2/bincmp.S */ 1689 /* 1690 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1691 * fragment that specifies the *reverse* comparison to perform, e.g. 1692 * for "if-le" you would use "gt". 1693 * 1694 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1695 */ 1696 /* if-cmp vA, vB, +CCCC */ 1697 mov r1, rINST, lsr #12 @ r1<- B 1698 ubfx r0, rINST, #8, #4 @ r0<- A 1699 GET_VREG(r3, r1) @ r3<- vB 1700 GET_VREG(r2, r0) @ r2<- vA 1701 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1702 cmp r2, r3 @ compare (vA, vB) 1703 bgt 1f @ branch to 1 if comparison failed 1704 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1705 movs r9, r9, asl #1 @ convert to bytes, check sign 1706 bmi common_backwardBranch @ yes, do periodic checks 17071: 1708#if defined(WITH_JIT) 1709 GET_JIT_PROF_TABLE(r0) 1710 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1711 b common_testUpdateProfile 1712#else 1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1714 GET_INST_OPCODE(ip) @ extract opcode from rINST 1715 GOTO_OPCODE(ip) @ jump to next instruction 1716#endif 1717 1718 1719 1720/* ------------------------------ */ 1721 .balign 64 1722.L_OP_IF_EQZ: /* 0x38 */ 1723/* File: armv5te/OP_IF_EQZ.S */ 1724/* File: armv5te/zcmp.S */ 1725 /* 1726 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1727 * fragment that specifies the *reverse* comparison to perform, e.g. 1728 * for "if-le" you would use "gt". 1729 * 1730 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1731 */ 1732 /* if-cmp vAA, +BBBB */ 1733 mov r0, rINST, lsr #8 @ r0<- AA 1734 GET_VREG(r2, r0) @ r2<- vAA 1735 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1736 cmp r2, #0 @ compare (vA, 0) 1737 bne 1f @ branch to 1 if comparison failed 1738 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1739 movs r9, r9, asl #1 @ convert to bytes, check sign 1740 bmi common_backwardBranch @ backward branch, do periodic checks 17411: 1742#if defined(WITH_JIT) 1743 GET_JIT_PROF_TABLE(r0) 1744 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1745 cmp r0,#0 1746 bne common_updateProfile 1747 GET_INST_OPCODE(ip) @ extract opcode from rINST 1748 GOTO_OPCODE(ip) @ jump to next instruction 1749#else 1750 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1751 GET_INST_OPCODE(ip) @ extract opcode from rINST 1752 GOTO_OPCODE(ip) @ jump to next instruction 1753#endif 1754 1755 1756 1757/* ------------------------------ */ 1758 .balign 64 1759.L_OP_IF_NEZ: /* 0x39 */ 1760/* File: armv5te/OP_IF_NEZ.S */ 1761/* File: armv5te/zcmp.S */ 1762 /* 1763 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1764 * fragment that specifies the *reverse* comparison to perform, e.g. 1765 * for "if-le" you would use "gt". 1766 * 1767 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1768 */ 1769 /* if-cmp vAA, +BBBB */ 1770 mov r0, rINST, lsr #8 @ r0<- AA 1771 GET_VREG(r2, r0) @ r2<- vAA 1772 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1773 cmp r2, #0 @ compare (vA, 0) 1774 beq 1f @ branch to 1 if comparison failed 1775 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1776 movs r9, r9, asl #1 @ convert to bytes, check sign 1777 bmi common_backwardBranch @ backward branch, do periodic checks 17781: 1779#if defined(WITH_JIT) 1780 GET_JIT_PROF_TABLE(r0) 1781 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1782 cmp r0,#0 1783 bne common_updateProfile 1784 GET_INST_OPCODE(ip) @ extract opcode from rINST 1785 GOTO_OPCODE(ip) @ jump to next instruction 1786#else 1787 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1788 GET_INST_OPCODE(ip) @ extract opcode from rINST 1789 GOTO_OPCODE(ip) @ jump to next instruction 1790#endif 1791 1792 1793 1794/* ------------------------------ */ 1795 .balign 64 1796.L_OP_IF_LTZ: /* 0x3a */ 1797/* File: armv5te/OP_IF_LTZ.S */ 1798/* File: armv5te/zcmp.S */ 1799 /* 1800 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1801 * fragment that specifies the *reverse* comparison to perform, e.g. 1802 * for "if-le" you would use "gt". 1803 * 1804 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1805 */ 1806 /* if-cmp vAA, +BBBB */ 1807 mov r0, rINST, lsr #8 @ r0<- AA 1808 GET_VREG(r2, r0) @ r2<- vAA 1809 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1810 cmp r2, #0 @ compare (vA, 0) 1811 bge 1f @ branch to 1 if comparison failed 1812 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1813 movs r9, r9, asl #1 @ convert to bytes, check sign 1814 bmi common_backwardBranch @ backward branch, do periodic checks 18151: 1816#if defined(WITH_JIT) 1817 GET_JIT_PROF_TABLE(r0) 1818 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1819 cmp r0,#0 1820 bne common_updateProfile 1821 GET_INST_OPCODE(ip) @ extract opcode from rINST 1822 GOTO_OPCODE(ip) @ jump to next instruction 1823#else 1824 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1825 GET_INST_OPCODE(ip) @ extract opcode from rINST 1826 GOTO_OPCODE(ip) @ jump to next instruction 1827#endif 1828 1829 1830 1831/* ------------------------------ */ 1832 .balign 64 1833.L_OP_IF_GEZ: /* 0x3b */ 1834/* File: armv5te/OP_IF_GEZ.S */ 1835/* File: armv5te/zcmp.S */ 1836 /* 1837 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1838 * fragment that specifies the *reverse* comparison to perform, e.g. 1839 * for "if-le" you would use "gt". 1840 * 1841 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1842 */ 1843 /* if-cmp vAA, +BBBB */ 1844 mov r0, rINST, lsr #8 @ r0<- AA 1845 GET_VREG(r2, r0) @ r2<- vAA 1846 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1847 cmp r2, #0 @ compare (vA, 0) 1848 blt 1f @ branch to 1 if comparison failed 1849 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1850 movs r9, r9, asl #1 @ convert to bytes, check sign 1851 bmi common_backwardBranch @ backward branch, do periodic checks 18521: 1853#if defined(WITH_JIT) 1854 GET_JIT_PROF_TABLE(r0) 1855 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1856 cmp r0,#0 1857 bne common_updateProfile 1858 GET_INST_OPCODE(ip) @ extract opcode from rINST 1859 GOTO_OPCODE(ip) @ jump to next instruction 1860#else 1861 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1862 GET_INST_OPCODE(ip) @ extract opcode from rINST 1863 GOTO_OPCODE(ip) @ jump to next instruction 1864#endif 1865 1866 1867 1868/* ------------------------------ */ 1869 .balign 64 1870.L_OP_IF_GTZ: /* 0x3c */ 1871/* File: armv5te/OP_IF_GTZ.S */ 1872/* File: armv5te/zcmp.S */ 1873 /* 1874 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1875 * fragment that specifies the *reverse* comparison to perform, e.g. 1876 * for "if-le" you would use "gt". 1877 * 1878 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1879 */ 1880 /* if-cmp vAA, +BBBB */ 1881 mov r0, rINST, lsr #8 @ r0<- AA 1882 GET_VREG(r2, r0) @ r2<- vAA 1883 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1884 cmp r2, #0 @ compare (vA, 0) 1885 ble 1f @ branch to 1 if comparison failed 1886 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1887 movs r9, r9, asl #1 @ convert to bytes, check sign 1888 bmi common_backwardBranch @ backward branch, do periodic checks 18891: 1890#if defined(WITH_JIT) 1891 GET_JIT_PROF_TABLE(r0) 1892 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1893 cmp r0,#0 1894 bne common_updateProfile 1895 GET_INST_OPCODE(ip) @ extract opcode from rINST 1896 GOTO_OPCODE(ip) @ jump to next instruction 1897#else 1898 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1899 GET_INST_OPCODE(ip) @ extract opcode from rINST 1900 GOTO_OPCODE(ip) @ jump to next instruction 1901#endif 1902 1903 1904 1905/* ------------------------------ */ 1906 .balign 64 1907.L_OP_IF_LEZ: /* 0x3d */ 1908/* File: armv5te/OP_IF_LEZ.S */ 1909/* File: armv5te/zcmp.S */ 1910 /* 1911 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1912 * fragment that specifies the *reverse* comparison to perform, e.g. 1913 * for "if-le" you would use "gt". 1914 * 1915 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1916 */ 1917 /* if-cmp vAA, +BBBB */ 1918 mov r0, rINST, lsr #8 @ r0<- AA 1919 GET_VREG(r2, r0) @ r2<- vAA 1920 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1921 cmp r2, #0 @ compare (vA, 0) 1922 bgt 1f @ branch to 1 if comparison failed 1923 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1924 movs r9, r9, asl #1 @ convert to bytes, check sign 1925 bmi common_backwardBranch @ backward branch, do periodic checks 19261: 1927#if defined(WITH_JIT) 1928 GET_JIT_PROF_TABLE(r0) 1929 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1930 cmp r0,#0 1931 bne common_updateProfile 1932 GET_INST_OPCODE(ip) @ extract opcode from rINST 1933 GOTO_OPCODE(ip) @ jump to next instruction 1934#else 1935 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1936 GET_INST_OPCODE(ip) @ extract opcode from rINST 1937 GOTO_OPCODE(ip) @ jump to next instruction 1938#endif 1939 1940 1941 1942/* ------------------------------ */ 1943 .balign 64 1944.L_OP_UNUSED_3E: /* 0x3e */ 1945/* File: armv5te/OP_UNUSED_3E.S */ 1946/* File: armv5te/unused.S */ 1947 bl common_abort 1948 1949 1950 1951/* ------------------------------ */ 1952 .balign 64 1953.L_OP_UNUSED_3F: /* 0x3f */ 1954/* File: armv5te/OP_UNUSED_3F.S */ 1955/* File: armv5te/unused.S */ 1956 bl common_abort 1957 1958 1959 1960/* ------------------------------ */ 1961 .balign 64 1962.L_OP_UNUSED_40: /* 0x40 */ 1963/* File: armv5te/OP_UNUSED_40.S */ 1964/* File: armv5te/unused.S */ 1965 bl common_abort 1966 1967 1968 1969/* ------------------------------ */ 1970 .balign 64 1971.L_OP_UNUSED_41: /* 0x41 */ 1972/* File: armv5te/OP_UNUSED_41.S */ 1973/* File: armv5te/unused.S */ 1974 bl common_abort 1975 1976 1977 1978/* ------------------------------ */ 1979 .balign 64 1980.L_OP_UNUSED_42: /* 0x42 */ 1981/* File: armv5te/OP_UNUSED_42.S */ 1982/* File: armv5te/unused.S */ 1983 bl common_abort 1984 1985 1986 1987/* ------------------------------ */ 1988 .balign 64 1989.L_OP_UNUSED_43: /* 0x43 */ 1990/* File: armv5te/OP_UNUSED_43.S */ 1991/* File: armv5te/unused.S */ 1992 bl common_abort 1993 1994 1995 1996/* ------------------------------ */ 1997 .balign 64 1998.L_OP_AGET: /* 0x44 */ 1999/* File: armv5te/OP_AGET.S */ 2000 /* 2001 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2002 * 2003 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2004 * instructions. We use a pair of FETCH_Bs instead. 2005 * 2006 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2007 */ 2008 /* op vAA, vBB, vCC */ 2009 FETCH_B(r2, 1, 0) @ r2<- BB 2010 mov r9, rINST, lsr #8 @ r9<- AA 2011 FETCH_B(r3, 1, 1) @ r3<- CC 2012 GET_VREG(r0, r2) @ r0<- vBB (array object) 2013 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2014 cmp r0, #0 @ null array object? 2015 beq common_errNullObject @ yes, bail 2016 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2017 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2018 cmp r1, r3 @ compare unsigned index, length 2019 bcs common_errArrayIndex @ index >= length, bail 2020 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2021 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2022 GET_INST_OPCODE(ip) @ extract opcode from rINST 2023 SET_VREG(r2, r9) @ vAA<- r2 2024 GOTO_OPCODE(ip) @ jump to next instruction 2025 2026 2027/* ------------------------------ */ 2028 .balign 64 2029.L_OP_AGET_WIDE: /* 0x45 */ 2030/* File: armv5te/OP_AGET_WIDE.S */ 2031 /* 2032 * Array get, 64 bits. vAA <- vBB[vCC]. 2033 * 2034 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2035 */ 2036 /* aget-wide vAA, vBB, vCC */ 2037 FETCH(r0, 1) @ r0<- CCBB 2038 mov r9, rINST, lsr #8 @ r9<- AA 2039 and r2, r0, #255 @ r2<- BB 2040 mov r3, r0, lsr #8 @ r3<- CC 2041 GET_VREG(r0, r2) @ r0<- vBB (array object) 2042 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2043 cmp r0, #0 @ null array object? 2044 beq common_errNullObject @ yes, bail 2045 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2046 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2047 cmp r1, r3 @ compare unsigned index, length 2048 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2049 b common_errArrayIndex @ index >= length, bail 2050 @ May want to swap the order of these two branches depending on how the 2051 @ branch prediction (if any) handles conditional forward branches vs. 2052 @ unconditional forward branches. 2053 2054/* ------------------------------ */ 2055 .balign 64 2056.L_OP_AGET_OBJECT: /* 0x46 */ 2057/* File: armv5te/OP_AGET_OBJECT.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 #2 @ 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 ldr 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/* ------------------------------ */ 2088 .balign 64 2089.L_OP_AGET_BOOLEAN: /* 0x47 */ 2090/* File: armv5te/OP_AGET_BOOLEAN.S */ 2091/* File: armv5te/OP_AGET.S */ 2092 /* 2093 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2094 * 2095 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2096 * instructions. We use a pair of FETCH_Bs instead. 2097 * 2098 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2099 */ 2100 /* op vAA, vBB, vCC */ 2101 FETCH_B(r2, 1, 0) @ r2<- BB 2102 mov r9, rINST, lsr #8 @ r9<- AA 2103 FETCH_B(r3, 1, 1) @ r3<- CC 2104 GET_VREG(r0, r2) @ r0<- vBB (array object) 2105 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2106 cmp r0, #0 @ null array object? 2107 beq common_errNullObject @ yes, bail 2108 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2109 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2110 cmp r1, r3 @ compare unsigned index, length 2111 bcs common_errArrayIndex @ index >= length, bail 2112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2113 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2114 GET_INST_OPCODE(ip) @ extract opcode from rINST 2115 SET_VREG(r2, r9) @ vAA<- r2 2116 GOTO_OPCODE(ip) @ jump to next instruction 2117 2118 2119 2120/* ------------------------------ */ 2121 .balign 64 2122.L_OP_AGET_BYTE: /* 0x48 */ 2123/* File: armv5te/OP_AGET_BYTE.S */ 2124/* File: armv5te/OP_AGET.S */ 2125 /* 2126 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2127 * 2128 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2129 * instructions. We use a pair of FETCH_Bs instead. 2130 * 2131 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2132 */ 2133 /* op vAA, vBB, vCC */ 2134 FETCH_B(r2, 1, 0) @ r2<- BB 2135 mov r9, rINST, lsr #8 @ r9<- AA 2136 FETCH_B(r3, 1, 1) @ r3<- CC 2137 GET_VREG(r0, r2) @ r0<- vBB (array object) 2138 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2139 cmp r0, #0 @ null array object? 2140 beq common_errNullObject @ yes, bail 2141 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2142 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2143 cmp r1, r3 @ compare unsigned index, length 2144 bcs common_errArrayIndex @ index >= length, bail 2145 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2146 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2147 GET_INST_OPCODE(ip) @ extract opcode from rINST 2148 SET_VREG(r2, r9) @ vAA<- r2 2149 GOTO_OPCODE(ip) @ jump to next instruction 2150 2151 2152 2153/* ------------------------------ */ 2154 .balign 64 2155.L_OP_AGET_CHAR: /* 0x49 */ 2156/* File: armv5te/OP_AGET_CHAR.S */ 2157/* File: armv5te/OP_AGET.S */ 2158 /* 2159 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2160 * 2161 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2162 * instructions. We use a pair of FETCH_Bs instead. 2163 * 2164 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2165 */ 2166 /* op vAA, vBB, vCC */ 2167 FETCH_B(r2, 1, 0) @ r2<- BB 2168 mov r9, rINST, lsr #8 @ r9<- AA 2169 FETCH_B(r3, 1, 1) @ r3<- CC 2170 GET_VREG(r0, r2) @ r0<- vBB (array object) 2171 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2172 cmp r0, #0 @ null array object? 2173 beq common_errNullObject @ yes, bail 2174 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2175 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2176 cmp r1, r3 @ compare unsigned index, length 2177 bcs common_errArrayIndex @ index >= length, bail 2178 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2179 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2180 GET_INST_OPCODE(ip) @ extract opcode from rINST 2181 SET_VREG(r2, r9) @ vAA<- r2 2182 GOTO_OPCODE(ip) @ jump to next instruction 2183 2184 2185 2186/* ------------------------------ */ 2187 .balign 64 2188.L_OP_AGET_SHORT: /* 0x4a */ 2189/* File: armv5te/OP_AGET_SHORT.S */ 2190/* File: armv5te/OP_AGET.S */ 2191 /* 2192 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2193 * 2194 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2195 * instructions. We use a pair of FETCH_Bs instead. 2196 * 2197 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2198 */ 2199 /* op vAA, vBB, vCC */ 2200 FETCH_B(r2, 1, 0) @ r2<- BB 2201 mov r9, rINST, lsr #8 @ r9<- AA 2202 FETCH_B(r3, 1, 1) @ r3<- CC 2203 GET_VREG(r0, r2) @ r0<- vBB (array object) 2204 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2205 cmp r0, #0 @ null array object? 2206 beq common_errNullObject @ yes, bail 2207 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2208 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2209 cmp r1, r3 @ compare unsigned index, length 2210 bcs common_errArrayIndex @ index >= length, bail 2211 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2212 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2213 GET_INST_OPCODE(ip) @ extract opcode from rINST 2214 SET_VREG(r2, r9) @ vAA<- r2 2215 GOTO_OPCODE(ip) @ jump to next instruction 2216 2217 2218 2219/* ------------------------------ */ 2220 .balign 64 2221.L_OP_APUT: /* 0x4b */ 2222/* File: armv5te/OP_APUT.S */ 2223 /* 2224 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2225 * 2226 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2227 * instructions. We use a pair of FETCH_Bs instead. 2228 * 2229 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2230 */ 2231 /* op vAA, vBB, vCC */ 2232 FETCH_B(r2, 1, 0) @ r2<- BB 2233 mov r9, rINST, lsr #8 @ r9<- AA 2234 FETCH_B(r3, 1, 1) @ r3<- CC 2235 GET_VREG(r0, r2) @ r0<- vBB (array object) 2236 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2237 cmp r0, #0 @ null array object? 2238 beq common_errNullObject @ yes, bail 2239 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2240 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2241 cmp r1, r3 @ compare unsigned index, length 2242 bcs common_errArrayIndex @ index >= length, bail 2243 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2244 GET_VREG(r2, r9) @ r2<- vAA 2245 GET_INST_OPCODE(ip) @ extract opcode from rINST 2246 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2247 GOTO_OPCODE(ip) @ jump to next instruction 2248 2249 2250/* ------------------------------ */ 2251 .balign 64 2252.L_OP_APUT_WIDE: /* 0x4c */ 2253/* File: armv5te/OP_APUT_WIDE.S */ 2254 /* 2255 * Array put, 64 bits. vBB[vCC] <- vAA. 2256 * 2257 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2258 */ 2259 /* aput-wide vAA, vBB, vCC */ 2260 FETCH(r0, 1) @ r0<- CCBB 2261 mov r9, rINST, lsr #8 @ r9<- AA 2262 and r2, r0, #255 @ r2<- BB 2263 mov r3, r0, lsr #8 @ r3<- CC 2264 GET_VREG(r0, r2) @ r0<- vBB (array object) 2265 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2266 cmp r0, #0 @ null array object? 2267 beq common_errNullObject @ yes, bail 2268 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2269 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2270 cmp r1, r3 @ compare unsigned index, length 2271 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2272 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2273 b common_errArrayIndex @ index >= length, bail 2274 @ May want to swap the order of these two branches depending on how the 2275 @ branch prediction (if any) handles conditional forward branches vs. 2276 @ unconditional forward branches. 2277 2278/* ------------------------------ */ 2279 .balign 64 2280.L_OP_APUT_OBJECT: /* 0x4d */ 2281/* File: armv5te/OP_APUT_OBJECT.S */ 2282 /* 2283 * Store an object into an array. vBB[vCC] <- vAA. 2284 * 2285 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2286 * instructions. We use a pair of FETCH_Bs instead. 2287 */ 2288 /* op vAA, vBB, vCC */ 2289 FETCH(r0, 1) @ r0<- CCBB 2290 mov r9, rINST, lsr #8 @ r9<- AA 2291 and r2, r0, #255 @ r2<- BB 2292 mov r3, r0, lsr #8 @ r3<- CC 2293 GET_VREG(r1, r2) @ r1<- vBB (array object) 2294 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2295 cmp r1, #0 @ null array object? 2296 GET_VREG(r9, r9) @ r9<- vAA 2297 beq common_errNullObject @ yes, bail 2298 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2299 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2300 cmp r0, r3 @ compare unsigned index, length 2301 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2302 b common_errArrayIndex @ index >= length, bail 2303 2304 2305/* ------------------------------ */ 2306 .balign 64 2307.L_OP_APUT_BOOLEAN: /* 0x4e */ 2308/* File: armv5te/OP_APUT_BOOLEAN.S */ 2309/* File: armv5te/OP_APUT.S */ 2310 /* 2311 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2312 * 2313 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2314 * instructions. We use a pair of FETCH_Bs instead. 2315 * 2316 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2317 */ 2318 /* op vAA, vBB, vCC */ 2319 FETCH_B(r2, 1, 0) @ r2<- BB 2320 mov r9, rINST, lsr #8 @ r9<- AA 2321 FETCH_B(r3, 1, 1) @ r3<- CC 2322 GET_VREG(r0, r2) @ r0<- vBB (array object) 2323 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2324 cmp r0, #0 @ null array object? 2325 beq common_errNullObject @ yes, bail 2326 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2327 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2328 cmp r1, r3 @ compare unsigned index, length 2329 bcs common_errArrayIndex @ index >= length, bail 2330 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2331 GET_VREG(r2, r9) @ r2<- vAA 2332 GET_INST_OPCODE(ip) @ extract opcode from rINST 2333 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2334 GOTO_OPCODE(ip) @ jump to next instruction 2335 2336 2337 2338/* ------------------------------ */ 2339 .balign 64 2340.L_OP_APUT_BYTE: /* 0x4f */ 2341/* File: armv5te/OP_APUT_BYTE.S */ 2342/* File: armv5te/OP_APUT.S */ 2343 /* 2344 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2345 * 2346 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2347 * instructions. We use a pair of FETCH_Bs instead. 2348 * 2349 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2350 */ 2351 /* op vAA, vBB, vCC */ 2352 FETCH_B(r2, 1, 0) @ r2<- BB 2353 mov r9, rINST, lsr #8 @ r9<- AA 2354 FETCH_B(r3, 1, 1) @ r3<- CC 2355 GET_VREG(r0, r2) @ r0<- vBB (array object) 2356 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2357 cmp r0, #0 @ null array object? 2358 beq common_errNullObject @ yes, bail 2359 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2360 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2361 cmp r1, r3 @ compare unsigned index, length 2362 bcs common_errArrayIndex @ index >= length, bail 2363 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2364 GET_VREG(r2, r9) @ r2<- vAA 2365 GET_INST_OPCODE(ip) @ extract opcode from rINST 2366 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2367 GOTO_OPCODE(ip) @ jump to next instruction 2368 2369 2370 2371/* ------------------------------ */ 2372 .balign 64 2373.L_OP_APUT_CHAR: /* 0x50 */ 2374/* File: armv5te/OP_APUT_CHAR.S */ 2375/* File: armv5te/OP_APUT.S */ 2376 /* 2377 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2378 * 2379 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2380 * instructions. We use a pair of FETCH_Bs instead. 2381 * 2382 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2383 */ 2384 /* op vAA, vBB, vCC */ 2385 FETCH_B(r2, 1, 0) @ r2<- BB 2386 mov r9, rINST, lsr #8 @ r9<- AA 2387 FETCH_B(r3, 1, 1) @ r3<- CC 2388 GET_VREG(r0, r2) @ r0<- vBB (array object) 2389 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2390 cmp r0, #0 @ null array object? 2391 beq common_errNullObject @ yes, bail 2392 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2393 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2394 cmp r1, r3 @ compare unsigned index, length 2395 bcs common_errArrayIndex @ index >= length, bail 2396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2397 GET_VREG(r2, r9) @ r2<- vAA 2398 GET_INST_OPCODE(ip) @ extract opcode from rINST 2399 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2400 GOTO_OPCODE(ip) @ jump to next instruction 2401 2402 2403 2404/* ------------------------------ */ 2405 .balign 64 2406.L_OP_APUT_SHORT: /* 0x51 */ 2407/* File: armv5te/OP_APUT_SHORT.S */ 2408/* File: armv5te/OP_APUT.S */ 2409 /* 2410 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2411 * 2412 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2413 * instructions. We use a pair of FETCH_Bs instead. 2414 * 2415 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2416 */ 2417 /* op vAA, vBB, vCC */ 2418 FETCH_B(r2, 1, 0) @ r2<- BB 2419 mov r9, rINST, lsr #8 @ r9<- AA 2420 FETCH_B(r3, 1, 1) @ r3<- CC 2421 GET_VREG(r0, r2) @ r0<- vBB (array object) 2422 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2423 cmp r0, #0 @ null array object? 2424 beq common_errNullObject @ yes, bail 2425 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2426 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2427 cmp r1, r3 @ compare unsigned index, length 2428 bcs common_errArrayIndex @ index >= length, bail 2429 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2430 GET_VREG(r2, r9) @ r2<- vAA 2431 GET_INST_OPCODE(ip) @ extract opcode from rINST 2432 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2433 GOTO_OPCODE(ip) @ jump to next instruction 2434 2435 2436 2437/* ------------------------------ */ 2438 .balign 64 2439.L_OP_IGET: /* 0x52 */ 2440/* File: armv6t2/OP_IGET.S */ 2441 /* 2442 * General 32-bit instance field get. 2443 * 2444 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2445 */ 2446 /* op vA, vB, field@CCCC */ 2447 mov r0, rINST, lsr #12 @ r0<- B 2448 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2449 FETCH(r1, 1) @ r1<- field ref CCCC 2450 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2451 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2452 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2453 cmp r0, #0 @ is resolved entry null? 2454 bne .LOP_IGET_finish @ no, already resolved 24558: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2456 EXPORT_PC() @ resolve() could throw 2457 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2458 bl dvmResolveInstField @ r0<- resolved InstField ptr 2459 cmp r0, #0 2460 bne .LOP_IGET_finish 2461 b common_exceptionThrown 2462 2463/* ------------------------------ */ 2464 .balign 64 2465.L_OP_IGET_WIDE: /* 0x53 */ 2466/* File: armv6t2/OP_IGET_WIDE.S */ 2467 /* 2468 * Wide 32-bit instance field get. 2469 */ 2470 /* iget-wide vA, vB, field@CCCC */ 2471 mov r0, rINST, lsr #12 @ r0<- B 2472 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2473 FETCH(r1, 1) @ r1<- field ref CCCC 2474 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2475 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2476 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2477 cmp r0, #0 @ is resolved entry null? 2478 bne .LOP_IGET_WIDE_finish @ no, already resolved 24798: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2480 EXPORT_PC() @ resolve() could throw 2481 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2482 bl dvmResolveInstField @ r0<- resolved InstField ptr 2483 cmp r0, #0 2484 bne .LOP_IGET_WIDE_finish 2485 b common_exceptionThrown 2486 2487/* ------------------------------ */ 2488 .balign 64 2489.L_OP_IGET_OBJECT: /* 0x54 */ 2490/* File: armv5te/OP_IGET_OBJECT.S */ 2491/* File: armv5te/OP_IGET.S */ 2492 /* 2493 * General 32-bit instance field get. 2494 * 2495 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2496 */ 2497 /* op vA, vB, field@CCCC */ 2498 mov r0, rINST, lsr #12 @ r0<- B 2499 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2500 FETCH(r1, 1) @ r1<- field ref CCCC 2501 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2502 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2503 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2504 cmp r0, #0 @ is resolved entry null? 2505 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25068: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2507 EXPORT_PC() @ resolve() could throw 2508 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2509 bl dvmResolveInstField @ r0<- resolved InstField ptr 2510 cmp r0, #0 2511 bne .LOP_IGET_OBJECT_finish 2512 b common_exceptionThrown 2513 2514 2515/* ------------------------------ */ 2516 .balign 64 2517.L_OP_IGET_BOOLEAN: /* 0x55 */ 2518/* File: armv5te/OP_IGET_BOOLEAN.S */ 2519@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2520/* File: armv5te/OP_IGET.S */ 2521 /* 2522 * General 32-bit instance field get. 2523 * 2524 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2525 */ 2526 /* op vA, vB, field@CCCC */ 2527 mov r0, rINST, lsr #12 @ r0<- B 2528 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2529 FETCH(r1, 1) @ r1<- field ref CCCC 2530 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2531 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2532 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2533 cmp r0, #0 @ is resolved entry null? 2534 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2536 EXPORT_PC() @ resolve() could throw 2537 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2538 bl dvmResolveInstField @ r0<- resolved InstField ptr 2539 cmp r0, #0 2540 bne .LOP_IGET_BOOLEAN_finish 2541 b common_exceptionThrown 2542 2543 2544/* ------------------------------ */ 2545 .balign 64 2546.L_OP_IGET_BYTE: /* 0x56 */ 2547/* File: armv5te/OP_IGET_BYTE.S */ 2548@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2549/* File: armv5te/OP_IGET.S */ 2550 /* 2551 * General 32-bit instance field get. 2552 * 2553 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2554 */ 2555 /* op vA, vB, field@CCCC */ 2556 mov r0, rINST, lsr #12 @ r0<- B 2557 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2558 FETCH(r1, 1) @ r1<- field ref CCCC 2559 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2560 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2561 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2562 cmp r0, #0 @ is resolved entry null? 2563 bne .LOP_IGET_BYTE_finish @ no, already resolved 25648: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2565 EXPORT_PC() @ resolve() could throw 2566 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2567 bl dvmResolveInstField @ r0<- resolved InstField ptr 2568 cmp r0, #0 2569 bne .LOP_IGET_BYTE_finish 2570 b common_exceptionThrown 2571 2572 2573/* ------------------------------ */ 2574 .balign 64 2575.L_OP_IGET_CHAR: /* 0x57 */ 2576/* File: armv5te/OP_IGET_CHAR.S */ 2577@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2578/* File: armv5te/OP_IGET.S */ 2579 /* 2580 * General 32-bit instance field get. 2581 * 2582 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2583 */ 2584 /* op vA, vB, field@CCCC */ 2585 mov r0, rINST, lsr #12 @ r0<- B 2586 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2587 FETCH(r1, 1) @ r1<- field ref CCCC 2588 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2589 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2590 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2591 cmp r0, #0 @ is resolved entry null? 2592 bne .LOP_IGET_CHAR_finish @ no, already resolved 25938: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2594 EXPORT_PC() @ resolve() could throw 2595 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2596 bl dvmResolveInstField @ r0<- resolved InstField ptr 2597 cmp r0, #0 2598 bne .LOP_IGET_CHAR_finish 2599 b common_exceptionThrown 2600 2601 2602/* ------------------------------ */ 2603 .balign 64 2604.L_OP_IGET_SHORT: /* 0x58 */ 2605/* File: armv5te/OP_IGET_SHORT.S */ 2606@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2607/* File: armv5te/OP_IGET.S */ 2608 /* 2609 * General 32-bit instance field get. 2610 * 2611 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2612 */ 2613 /* op vA, vB, field@CCCC */ 2614 mov r0, rINST, lsr #12 @ r0<- B 2615 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2616 FETCH(r1, 1) @ r1<- field ref CCCC 2617 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2618 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2619 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2620 cmp r0, #0 @ is resolved entry null? 2621 bne .LOP_IGET_SHORT_finish @ no, already resolved 26228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2623 EXPORT_PC() @ resolve() could throw 2624 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2625 bl dvmResolveInstField @ r0<- resolved InstField ptr 2626 cmp r0, #0 2627 bne .LOP_IGET_SHORT_finish 2628 b common_exceptionThrown 2629 2630 2631/* ------------------------------ */ 2632 .balign 64 2633.L_OP_IPUT: /* 0x59 */ 2634/* File: armv6t2/OP_IPUT.S */ 2635 /* 2636 * General 32-bit instance field put. 2637 * 2638 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2639 */ 2640 /* op vA, vB, field@CCCC */ 2641 mov r0, rINST, lsr #12 @ r0<- B 2642 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2643 FETCH(r1, 1) @ r1<- field ref CCCC 2644 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2645 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2646 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2647 cmp r0, #0 @ is resolved entry null? 2648 bne .LOP_IPUT_finish @ no, already resolved 26498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2650 EXPORT_PC() @ resolve() could throw 2651 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2652 bl dvmResolveInstField @ r0<- resolved InstField ptr 2653 cmp r0, #0 @ success? 2654 bne .LOP_IPUT_finish @ yes, finish up 2655 b common_exceptionThrown 2656 2657/* ------------------------------ */ 2658 .balign 64 2659.L_OP_IPUT_WIDE: /* 0x5a */ 2660/* File: armv6t2/OP_IPUT_WIDE.S */ 2661 /* iput-wide vA, vB, field@CCCC */ 2662 mov r0, rINST, lsr #12 @ r0<- B 2663 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2664 FETCH(r1, 1) @ r1<- field ref CCCC 2665 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2666 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2667 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2668 cmp r0, #0 @ is resolved entry null? 2669 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26708: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2671 EXPORT_PC() @ resolve() could throw 2672 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2673 bl dvmResolveInstField @ r0<- resolved InstField ptr 2674 cmp r0, #0 @ success? 2675 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2676 b common_exceptionThrown 2677 2678/* ------------------------------ */ 2679 .balign 64 2680.L_OP_IPUT_OBJECT: /* 0x5b */ 2681/* File: armv5te/OP_IPUT_OBJECT.S */ 2682/* File: armv5te/OP_IPUT.S */ 2683 /* 2684 * General 32-bit instance field put. 2685 * 2686 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2687 */ 2688 /* op vA, vB, field@CCCC */ 2689 mov r0, rINST, lsr #12 @ r0<- B 2690 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2691 FETCH(r1, 1) @ r1<- field ref CCCC 2692 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2693 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2694 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2695 cmp r0, #0 @ is resolved entry null? 2696 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26978: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2698 EXPORT_PC() @ resolve() could throw 2699 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2700 bl dvmResolveInstField @ r0<- resolved InstField ptr 2701 cmp r0, #0 @ success? 2702 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2703 b common_exceptionThrown 2704 2705 2706/* ------------------------------ */ 2707 .balign 64 2708.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2709/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2710@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2711/* File: armv5te/OP_IPUT.S */ 2712 /* 2713 * General 32-bit instance field put. 2714 * 2715 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2716 */ 2717 /* op vA, vB, field@CCCC */ 2718 mov r0, rINST, lsr #12 @ r0<- B 2719 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2720 FETCH(r1, 1) @ r1<- field ref CCCC 2721 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2722 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2723 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2724 cmp r0, #0 @ is resolved entry null? 2725 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27268: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2727 EXPORT_PC() @ resolve() could throw 2728 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2729 bl dvmResolveInstField @ r0<- resolved InstField ptr 2730 cmp r0, #0 @ success? 2731 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2732 b common_exceptionThrown 2733 2734 2735/* ------------------------------ */ 2736 .balign 64 2737.L_OP_IPUT_BYTE: /* 0x5d */ 2738/* File: armv5te/OP_IPUT_BYTE.S */ 2739@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2740/* File: armv5te/OP_IPUT.S */ 2741 /* 2742 * General 32-bit instance field put. 2743 * 2744 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2745 */ 2746 /* op vA, vB, field@CCCC */ 2747 mov r0, rINST, lsr #12 @ r0<- B 2748 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2749 FETCH(r1, 1) @ r1<- field ref CCCC 2750 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2751 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2752 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2753 cmp r0, #0 @ is resolved entry null? 2754 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27558: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2756 EXPORT_PC() @ resolve() could throw 2757 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2758 bl dvmResolveInstField @ r0<- resolved InstField ptr 2759 cmp r0, #0 @ success? 2760 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2761 b common_exceptionThrown 2762 2763 2764/* ------------------------------ */ 2765 .balign 64 2766.L_OP_IPUT_CHAR: /* 0x5e */ 2767/* File: armv5te/OP_IPUT_CHAR.S */ 2768@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2769/* File: armv5te/OP_IPUT.S */ 2770 /* 2771 * General 32-bit instance field put. 2772 * 2773 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2774 */ 2775 /* op vA, vB, field@CCCC */ 2776 mov r0, rINST, lsr #12 @ r0<- B 2777 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2778 FETCH(r1, 1) @ r1<- field ref CCCC 2779 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2780 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2781 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2782 cmp r0, #0 @ is resolved entry null? 2783 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27848: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2785 EXPORT_PC() @ resolve() could throw 2786 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2787 bl dvmResolveInstField @ r0<- resolved InstField ptr 2788 cmp r0, #0 @ success? 2789 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2790 b common_exceptionThrown 2791 2792 2793/* ------------------------------ */ 2794 .balign 64 2795.L_OP_IPUT_SHORT: /* 0x5f */ 2796/* File: armv5te/OP_IPUT_SHORT.S */ 2797@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2798/* File: armv5te/OP_IPUT.S */ 2799 /* 2800 * General 32-bit instance field put. 2801 * 2802 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2803 */ 2804 /* op vA, vB, field@CCCC */ 2805 mov r0, rINST, lsr #12 @ r0<- B 2806 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2807 FETCH(r1, 1) @ r1<- field ref CCCC 2808 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2809 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2810 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2811 cmp r0, #0 @ is resolved entry null? 2812 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2814 EXPORT_PC() @ resolve() could throw 2815 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2816 bl dvmResolveInstField @ r0<- resolved InstField ptr 2817 cmp r0, #0 @ success? 2818 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2819 b common_exceptionThrown 2820 2821 2822/* ------------------------------ */ 2823 .balign 64 2824.L_OP_SGET: /* 0x60 */ 2825/* File: armv5te/OP_SGET.S */ 2826 /* 2827 * General 32-bit SGET handler. 2828 * 2829 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2830 */ 2831 /* op vAA, field@BBBB */ 2832 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2833 FETCH(r1, 1) @ r1<- field ref BBBB 2834 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2835 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2836 cmp r0, #0 @ is resolved entry null? 2837 beq .LOP_SGET_resolve @ yes, do resolve 2838.LOP_SGET_finish: @ field ptr in r0 2839 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2840 mov r2, rINST, lsr #8 @ r2<- AA 2841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2842 SET_VREG(r1, r2) @ fp[AA]<- r1 2843 GET_INST_OPCODE(ip) @ extract opcode from rINST 2844 GOTO_OPCODE(ip) @ jump to next instruction 2845 2846/* ------------------------------ */ 2847 .balign 64 2848.L_OP_SGET_WIDE: /* 0x61 */ 2849/* File: armv5te/OP_SGET_WIDE.S */ 2850 /* 2851 * 64-bit SGET handler. 2852 */ 2853 /* sget-wide vAA, field@BBBB */ 2854 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2855 FETCH(r1, 1) @ r1<- field ref BBBB 2856 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2858 cmp r0, #0 @ is resolved entry null? 2859 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2860.LOP_SGET_WIDE_finish: 2861 mov r1, rINST, lsr #8 @ r1<- AA 2862 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2863 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2865 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2866 GET_INST_OPCODE(ip) @ extract opcode from rINST 2867 GOTO_OPCODE(ip) @ jump to next instruction 2868 2869/* ------------------------------ */ 2870 .balign 64 2871.L_OP_SGET_OBJECT: /* 0x62 */ 2872/* File: armv5te/OP_SGET_OBJECT.S */ 2873/* File: armv5te/OP_SGET.S */ 2874 /* 2875 * General 32-bit SGET handler. 2876 * 2877 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2878 */ 2879 /* op vAA, field@BBBB */ 2880 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2881 FETCH(r1, 1) @ r1<- field ref BBBB 2882 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2883 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2884 cmp r0, #0 @ is resolved entry null? 2885 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2886.LOP_SGET_OBJECT_finish: @ field ptr in r0 2887 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2888 mov r2, rINST, lsr #8 @ r2<- AA 2889 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2890 SET_VREG(r1, r2) @ fp[AA]<- r1 2891 GET_INST_OPCODE(ip) @ extract opcode from rINST 2892 GOTO_OPCODE(ip) @ jump to next instruction 2893 2894 2895/* ------------------------------ */ 2896 .balign 64 2897.L_OP_SGET_BOOLEAN: /* 0x63 */ 2898/* File: armv5te/OP_SGET_BOOLEAN.S */ 2899/* File: armv5te/OP_SGET.S */ 2900 /* 2901 * General 32-bit SGET handler. 2902 * 2903 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2904 */ 2905 /* op vAA, field@BBBB */ 2906 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2907 FETCH(r1, 1) @ r1<- field ref BBBB 2908 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2909 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2910 cmp r0, #0 @ is resolved entry null? 2911 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2912.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2913 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2914 mov r2, rINST, lsr #8 @ r2<- AA 2915 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2916 SET_VREG(r1, r2) @ fp[AA]<- r1 2917 GET_INST_OPCODE(ip) @ extract opcode from rINST 2918 GOTO_OPCODE(ip) @ jump to next instruction 2919 2920 2921/* ------------------------------ */ 2922 .balign 64 2923.L_OP_SGET_BYTE: /* 0x64 */ 2924/* File: armv5te/OP_SGET_BYTE.S */ 2925/* File: armv5te/OP_SGET.S */ 2926 /* 2927 * General 32-bit SGET handler. 2928 * 2929 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2930 */ 2931 /* op vAA, field@BBBB */ 2932 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2933 FETCH(r1, 1) @ r1<- field ref BBBB 2934 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2935 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2936 cmp r0, #0 @ is resolved entry null? 2937 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2938.LOP_SGET_BYTE_finish: @ field ptr in r0 2939 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2940 mov r2, rINST, lsr #8 @ r2<- AA 2941 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2942 SET_VREG(r1, r2) @ fp[AA]<- r1 2943 GET_INST_OPCODE(ip) @ extract opcode from rINST 2944 GOTO_OPCODE(ip) @ jump to next instruction 2945 2946 2947/* ------------------------------ */ 2948 .balign 64 2949.L_OP_SGET_CHAR: /* 0x65 */ 2950/* File: armv5te/OP_SGET_CHAR.S */ 2951/* File: armv5te/OP_SGET.S */ 2952 /* 2953 * General 32-bit SGET handler. 2954 * 2955 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2956 */ 2957 /* op vAA, field@BBBB */ 2958 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2959 FETCH(r1, 1) @ r1<- field ref BBBB 2960 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2961 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2962 cmp r0, #0 @ is resolved entry null? 2963 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2964.LOP_SGET_CHAR_finish: @ field ptr in r0 2965 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2966 mov r2, rINST, lsr #8 @ r2<- AA 2967 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2968 SET_VREG(r1, r2) @ fp[AA]<- r1 2969 GET_INST_OPCODE(ip) @ extract opcode from rINST 2970 GOTO_OPCODE(ip) @ jump to next instruction 2971 2972 2973/* ------------------------------ */ 2974 .balign 64 2975.L_OP_SGET_SHORT: /* 0x66 */ 2976/* File: armv5te/OP_SGET_SHORT.S */ 2977/* File: armv5te/OP_SGET.S */ 2978 /* 2979 * General 32-bit SGET handler. 2980 * 2981 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2982 */ 2983 /* op vAA, field@BBBB */ 2984 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2985 FETCH(r1, 1) @ r1<- field ref BBBB 2986 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2987 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2988 cmp r0, #0 @ is resolved entry null? 2989 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2990.LOP_SGET_SHORT_finish: @ field ptr in r0 2991 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2992 mov r2, rINST, lsr #8 @ r2<- AA 2993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2994 SET_VREG(r1, r2) @ fp[AA]<- r1 2995 GET_INST_OPCODE(ip) @ extract opcode from rINST 2996 GOTO_OPCODE(ip) @ jump to next instruction 2997 2998 2999/* ------------------------------ */ 3000 .balign 64 3001.L_OP_SPUT: /* 0x67 */ 3002/* File: armv5te/OP_SPUT.S */ 3003 /* 3004 * General 32-bit SPUT handler. 3005 * 3006 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3007 */ 3008 /* op vAA, field@BBBB */ 3009 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3010 FETCH(r1, 1) @ r1<- field ref BBBB 3011 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3012 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3013 cmp r0, #0 @ is resolved entry null? 3014 beq .LOP_SPUT_resolve @ yes, do resolve 3015.LOP_SPUT_finish: @ field ptr in r0 3016 mov r2, rINST, lsr #8 @ r2<- AA 3017 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3018 GET_VREG(r1, r2) @ r1<- fp[AA] 3019 GET_INST_OPCODE(ip) @ extract opcode from rINST 3020 str r1, [r0, #offStaticField_value] @ field<- vAA 3021 GOTO_OPCODE(ip) @ jump to next instruction 3022 3023/* ------------------------------ */ 3024 .balign 64 3025.L_OP_SPUT_WIDE: /* 0x68 */ 3026/* File: armv5te/OP_SPUT_WIDE.S */ 3027 /* 3028 * 64-bit SPUT handler. 3029 */ 3030 /* sput-wide vAA, field@BBBB */ 3031 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3032 FETCH(r1, 1) @ r1<- field ref BBBB 3033 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3034 mov r9, rINST, lsr #8 @ r9<- AA 3035 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3036 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3037 cmp r0, #0 @ is resolved entry null? 3038 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3039.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3041 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3042 GET_INST_OPCODE(ip) @ extract opcode from rINST 3043 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3044 GOTO_OPCODE(ip) @ jump to next instruction 3045 3046/* ------------------------------ */ 3047 .balign 64 3048.L_OP_SPUT_OBJECT: /* 0x69 */ 3049/* File: armv5te/OP_SPUT_OBJECT.S */ 3050/* File: armv5te/OP_SPUT.S */ 3051 /* 3052 * General 32-bit SPUT handler. 3053 * 3054 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3055 */ 3056 /* op vAA, field@BBBB */ 3057 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3058 FETCH(r1, 1) @ r1<- field ref BBBB 3059 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3060 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3061 cmp r0, #0 @ is resolved entry null? 3062 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3063.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3064 mov r2, rINST, lsr #8 @ r2<- AA 3065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3066 GET_VREG(r1, r2) @ r1<- fp[AA] 3067 GET_INST_OPCODE(ip) @ extract opcode from rINST 3068 str r1, [r0, #offStaticField_value] @ field<- vAA 3069 GOTO_OPCODE(ip) @ jump to next instruction 3070 3071 3072/* ------------------------------ */ 3073 .balign 64 3074.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3075/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3076/* File: armv5te/OP_SPUT.S */ 3077 /* 3078 * General 32-bit SPUT handler. 3079 * 3080 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3081 */ 3082 /* op vAA, field@BBBB */ 3083 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3084 FETCH(r1, 1) @ r1<- field ref BBBB 3085 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3086 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3087 cmp r0, #0 @ is resolved entry null? 3088 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3089.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3090 mov r2, rINST, lsr #8 @ r2<- AA 3091 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3092 GET_VREG(r1, r2) @ r1<- fp[AA] 3093 GET_INST_OPCODE(ip) @ extract opcode from rINST 3094 str r1, [r0, #offStaticField_value] @ field<- vAA 3095 GOTO_OPCODE(ip) @ jump to next instruction 3096 3097 3098/* ------------------------------ */ 3099 .balign 64 3100.L_OP_SPUT_BYTE: /* 0x6b */ 3101/* File: armv5te/OP_SPUT_BYTE.S */ 3102/* File: armv5te/OP_SPUT.S */ 3103 /* 3104 * General 32-bit SPUT handler. 3105 * 3106 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3107 */ 3108 /* op vAA, field@BBBB */ 3109 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3110 FETCH(r1, 1) @ r1<- field ref BBBB 3111 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3112 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3113 cmp r0, #0 @ is resolved entry null? 3114 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3115.LOP_SPUT_BYTE_finish: @ field ptr in r0 3116 mov r2, rINST, lsr #8 @ r2<- AA 3117 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3118 GET_VREG(r1, r2) @ r1<- fp[AA] 3119 GET_INST_OPCODE(ip) @ extract opcode from rINST 3120 str r1, [r0, #offStaticField_value] @ field<- vAA 3121 GOTO_OPCODE(ip) @ jump to next instruction 3122 3123 3124/* ------------------------------ */ 3125 .balign 64 3126.L_OP_SPUT_CHAR: /* 0x6c */ 3127/* File: armv5te/OP_SPUT_CHAR.S */ 3128/* File: armv5te/OP_SPUT.S */ 3129 /* 3130 * General 32-bit SPUT handler. 3131 * 3132 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3133 */ 3134 /* op vAA, field@BBBB */ 3135 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3136 FETCH(r1, 1) @ r1<- field ref BBBB 3137 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3138 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3139 cmp r0, #0 @ is resolved entry null? 3140 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3141.LOP_SPUT_CHAR_finish: @ field ptr in r0 3142 mov r2, rINST, lsr #8 @ r2<- AA 3143 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3144 GET_VREG(r1, r2) @ r1<- fp[AA] 3145 GET_INST_OPCODE(ip) @ extract opcode from rINST 3146 str r1, [r0, #offStaticField_value] @ field<- vAA 3147 GOTO_OPCODE(ip) @ jump to next instruction 3148 3149 3150/* ------------------------------ */ 3151 .balign 64 3152.L_OP_SPUT_SHORT: /* 0x6d */ 3153/* File: armv5te/OP_SPUT_SHORT.S */ 3154/* File: armv5te/OP_SPUT.S */ 3155 /* 3156 * General 32-bit SPUT handler. 3157 * 3158 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3159 */ 3160 /* op vAA, field@BBBB */ 3161 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3162 FETCH(r1, 1) @ r1<- field ref BBBB 3163 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3164 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3165 cmp r0, #0 @ is resolved entry null? 3166 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3167.LOP_SPUT_SHORT_finish: @ field ptr in r0 3168 mov r2, rINST, lsr #8 @ r2<- AA 3169 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3170 GET_VREG(r1, r2) @ r1<- fp[AA] 3171 GET_INST_OPCODE(ip) @ extract opcode from rINST 3172 str r1, [r0, #offStaticField_value] @ field<- vAA 3173 GOTO_OPCODE(ip) @ jump to next instruction 3174 3175 3176/* ------------------------------ */ 3177 .balign 64 3178.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3179/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3180 /* 3181 * Handle a virtual method call. 3182 * 3183 * for: invoke-virtual, invoke-virtual/range 3184 */ 3185 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3186 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3187 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3188 FETCH(r1, 1) @ r1<- BBBB 3189 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3190 FETCH(r10, 2) @ r10<- GFED or CCCC 3191 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3192 .if (!0) 3193 and r10, r10, #15 @ r10<- D (or stays CCCC) 3194 .endif 3195 cmp r0, #0 @ already resolved? 3196 EXPORT_PC() @ must export for invoke 3197 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3198 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3199 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3200 mov r2, #METHOD_VIRTUAL @ resolver method type 3201 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3202 cmp r0, #0 @ got null? 3203 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3204 b common_exceptionThrown @ yes, handle exception 3205 3206/* ------------------------------ */ 3207 .balign 64 3208.L_OP_INVOKE_SUPER: /* 0x6f */ 3209/* File: armv5te/OP_INVOKE_SUPER.S */ 3210 /* 3211 * Handle a "super" method call. 3212 * 3213 * for: invoke-super, invoke-super/range 3214 */ 3215 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3216 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3217 FETCH(r10, 2) @ r10<- GFED or CCCC 3218 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3219 .if (!0) 3220 and r10, r10, #15 @ r10<- D (or stays CCCC) 3221 .endif 3222 FETCH(r1, 1) @ r1<- BBBB 3223 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3224 GET_VREG(r2, r10) @ r2<- "this" ptr 3225 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3226 cmp r2, #0 @ null "this"? 3227 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3228 beq common_errNullObject @ null "this", throw exception 3229 cmp r0, #0 @ already resolved? 3230 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3231 EXPORT_PC() @ must export for invoke 3232 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3233 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3234 3235/* ------------------------------ */ 3236 .balign 64 3237.L_OP_INVOKE_DIRECT: /* 0x70 */ 3238/* File: armv5te/OP_INVOKE_DIRECT.S */ 3239 /* 3240 * Handle a direct method call. 3241 * 3242 * (We could defer the "is 'this' pointer null" test to the common 3243 * method invocation code, and use a flag to indicate that static 3244 * calls don't count. If we do this as part of copying the arguments 3245 * out we could avoiding loading the first arg twice.) 3246 * 3247 * for: invoke-direct, invoke-direct/range 3248 */ 3249 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3250 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3251 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3252 FETCH(r1, 1) @ r1<- BBBB 3253 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3254 FETCH(r10, 2) @ r10<- GFED or CCCC 3255 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3256 .if (!0) 3257 and r10, r10, #15 @ r10<- D (or stays CCCC) 3258 .endif 3259 cmp r0, #0 @ already resolved? 3260 EXPORT_PC() @ must export for invoke 3261 GET_VREG(r2, r10) @ r2<- "this" ptr 3262 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3263.LOP_INVOKE_DIRECT_finish: 3264 cmp r2, #0 @ null "this" ref? 3265 bne common_invokeMethodNoRange @ no, continue on 3266 b common_errNullObject @ yes, throw exception 3267 3268/* ------------------------------ */ 3269 .balign 64 3270.L_OP_INVOKE_STATIC: /* 0x71 */ 3271/* File: armv5te/OP_INVOKE_STATIC.S */ 3272 /* 3273 * Handle a static method call. 3274 * 3275 * for: invoke-static, invoke-static/range 3276 */ 3277 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3278 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3279 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3280 FETCH(r1, 1) @ r1<- BBBB 3281 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3282 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3283 cmp r0, #0 @ already resolved? 3284 EXPORT_PC() @ must export for invoke 3285 bne common_invokeMethodNoRange @ yes, continue on 32860: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3287 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3288 mov r2, #METHOD_STATIC @ resolver method type 3289 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3290 cmp r0, #0 @ got null? 3291 bne common_invokeMethodNoRange @ no, continue 3292 b common_exceptionThrown @ yes, handle exception 3293 3294 3295/* ------------------------------ */ 3296 .balign 64 3297.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3298/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3299 /* 3300 * Handle an interface method call. 3301 * 3302 * for: invoke-interface, invoke-interface/range 3303 */ 3304 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3305 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3306 FETCH(r2, 2) @ r2<- FEDC or CCCC 3307 FETCH(r1, 1) @ r1<- BBBB 3308 .if (!0) 3309 and r2, r2, #15 @ r2<- C (or stays CCCC) 3310 .endif 3311 EXPORT_PC() @ must export for invoke 3312 GET_VREG(r0, r2) @ r0<- first arg ("this") 3313 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3314 cmp r0, #0 @ null obj? 3315 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3316 beq common_errNullObject @ yes, fail 3317 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3318 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3319 cmp r0, #0 @ failed? 3320 beq common_exceptionThrown @ yes, handle exception 3321 b common_invokeMethodNoRange @ jump to common handler 3322 3323 3324/* ------------------------------ */ 3325 .balign 64 3326.L_OP_UNUSED_73: /* 0x73 */ 3327/* File: armv5te/OP_UNUSED_73.S */ 3328/* File: armv5te/unused.S */ 3329 bl common_abort 3330 3331 3332 3333/* ------------------------------ */ 3334 .balign 64 3335.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3336/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3337/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3338 /* 3339 * Handle a virtual method call. 3340 * 3341 * for: invoke-virtual, invoke-virtual/range 3342 */ 3343 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3344 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3345 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3346 FETCH(r1, 1) @ r1<- BBBB 3347 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3348 FETCH(r10, 2) @ r10<- GFED or CCCC 3349 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3350 .if (!1) 3351 and r10, r10, #15 @ r10<- D (or stays CCCC) 3352 .endif 3353 cmp r0, #0 @ already resolved? 3354 EXPORT_PC() @ must export for invoke 3355 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3356 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3357 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3358 mov r2, #METHOD_VIRTUAL @ resolver method type 3359 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3360 cmp r0, #0 @ got null? 3361 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3362 b common_exceptionThrown @ yes, handle exception 3363 3364 3365/* ------------------------------ */ 3366 .balign 64 3367.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3368/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3369/* File: armv5te/OP_INVOKE_SUPER.S */ 3370 /* 3371 * Handle a "super" method call. 3372 * 3373 * for: invoke-super, invoke-super/range 3374 */ 3375 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3376 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3377 FETCH(r10, 2) @ r10<- GFED or CCCC 3378 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3379 .if (!1) 3380 and r10, r10, #15 @ r10<- D (or stays CCCC) 3381 .endif 3382 FETCH(r1, 1) @ r1<- BBBB 3383 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3384 GET_VREG(r2, r10) @ r2<- "this" ptr 3385 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3386 cmp r2, #0 @ null "this"? 3387 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3388 beq common_errNullObject @ null "this", throw exception 3389 cmp r0, #0 @ already resolved? 3390 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3391 EXPORT_PC() @ must export for invoke 3392 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3393 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3394 3395 3396/* ------------------------------ */ 3397 .balign 64 3398.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3399/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3400/* File: armv5te/OP_INVOKE_DIRECT.S */ 3401 /* 3402 * Handle a direct method call. 3403 * 3404 * (We could defer the "is 'this' pointer null" test to the common 3405 * method invocation code, and use a flag to indicate that static 3406 * calls don't count. If we do this as part of copying the arguments 3407 * out we could avoiding loading the first arg twice.) 3408 * 3409 * for: invoke-direct, invoke-direct/range 3410 */ 3411 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3412 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3413 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3414 FETCH(r1, 1) @ r1<- BBBB 3415 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3416 FETCH(r10, 2) @ r10<- GFED or CCCC 3417 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3418 .if (!1) 3419 and r10, r10, #15 @ r10<- D (or stays CCCC) 3420 .endif 3421 cmp r0, #0 @ already resolved? 3422 EXPORT_PC() @ must export for invoke 3423 GET_VREG(r2, r10) @ r2<- "this" ptr 3424 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3425.LOP_INVOKE_DIRECT_RANGE_finish: 3426 cmp r2, #0 @ null "this" ref? 3427 bne common_invokeMethodRange @ no, continue on 3428 b common_errNullObject @ yes, throw exception 3429 3430 3431/* ------------------------------ */ 3432 .balign 64 3433.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3434/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3435/* File: armv5te/OP_INVOKE_STATIC.S */ 3436 /* 3437 * Handle a static method call. 3438 * 3439 * for: invoke-static, invoke-static/range 3440 */ 3441 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3442 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3443 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3444 FETCH(r1, 1) @ r1<- BBBB 3445 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3446 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3447 cmp r0, #0 @ already resolved? 3448 EXPORT_PC() @ must export for invoke 3449 bne common_invokeMethodRange @ yes, continue on 34500: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3451 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3452 mov r2, #METHOD_STATIC @ resolver method type 3453 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3454 cmp r0, #0 @ got null? 3455 bne common_invokeMethodRange @ no, continue 3456 b common_exceptionThrown @ yes, handle exception 3457 3458 3459 3460/* ------------------------------ */ 3461 .balign 64 3462.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3463/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3464/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3465 /* 3466 * Handle an interface method call. 3467 * 3468 * for: invoke-interface, invoke-interface/range 3469 */ 3470 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3471 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3472 FETCH(r2, 2) @ r2<- FEDC or CCCC 3473 FETCH(r1, 1) @ r1<- BBBB 3474 .if (!1) 3475 and r2, r2, #15 @ r2<- C (or stays CCCC) 3476 .endif 3477 EXPORT_PC() @ must export for invoke 3478 GET_VREG(r0, r2) @ r0<- first arg ("this") 3479 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3480 cmp r0, #0 @ null obj? 3481 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3482 beq common_errNullObject @ yes, fail 3483 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3484 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3485 cmp r0, #0 @ failed? 3486 beq common_exceptionThrown @ yes, handle exception 3487 b common_invokeMethodRange @ jump to common handler 3488 3489 3490 3491/* ------------------------------ */ 3492 .balign 64 3493.L_OP_UNUSED_79: /* 0x79 */ 3494/* File: armv5te/OP_UNUSED_79.S */ 3495/* File: armv5te/unused.S */ 3496 bl common_abort 3497 3498 3499 3500/* ------------------------------ */ 3501 .balign 64 3502.L_OP_UNUSED_7A: /* 0x7a */ 3503/* File: armv5te/OP_UNUSED_7A.S */ 3504/* File: armv5te/unused.S */ 3505 bl common_abort 3506 3507 3508 3509/* ------------------------------ */ 3510 .balign 64 3511.L_OP_NEG_INT: /* 0x7b */ 3512/* File: armv6t2/OP_NEG_INT.S */ 3513/* File: armv6t2/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 ubfx r9, rINST, #8, #4 @ r9<- A 3525 GET_VREG(r0, r3) @ r0<- vB 3526 @ optional op; may set condition codes 3527 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3528 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3529 GET_INST_OPCODE(ip) @ extract opcode from rINST 3530 SET_VREG(r0, r9) @ vAA<- r0 3531 GOTO_OPCODE(ip) @ jump to next instruction 3532 /* 8-9 instructions */ 3533 3534 3535/* ------------------------------ */ 3536 .balign 64 3537.L_OP_NOT_INT: /* 0x7c */ 3538/* File: armv6t2/OP_NOT_INT.S */ 3539/* File: armv6t2/unop.S */ 3540 /* 3541 * Generic 32-bit unary operation. Provide an "instr" line that 3542 * specifies an instruction that performs "result = op r0". 3543 * This could be an ARM instruction or a function call. 3544 * 3545 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3546 * int-to-byte, int-to-char, int-to-short 3547 */ 3548 /* unop vA, vB */ 3549 mov r3, rINST, lsr #12 @ r3<- B 3550 ubfx r9, rINST, #8, #4 @ r9<- A 3551 GET_VREG(r0, r3) @ r0<- vB 3552 @ optional op; may set condition codes 3553 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3554 mvn r0, r0 @ r0<- op, r0-r3 changed 3555 GET_INST_OPCODE(ip) @ extract opcode from rINST 3556 SET_VREG(r0, r9) @ vAA<- r0 3557 GOTO_OPCODE(ip) @ jump to next instruction 3558 /* 8-9 instructions */ 3559 3560 3561/* ------------------------------ */ 3562 .balign 64 3563.L_OP_NEG_LONG: /* 0x7d */ 3564/* File: armv6t2/OP_NEG_LONG.S */ 3565/* File: armv6t2/unopWide.S */ 3566 /* 3567 * Generic 64-bit unary operation. Provide an "instr" line that 3568 * specifies an instruction that performs "result = op r0/r1". 3569 * This could be an ARM instruction or a function call. 3570 * 3571 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3572 */ 3573 /* unop vA, vB */ 3574 mov r3, rINST, lsr #12 @ r3<- B 3575 ubfx r9, rINST, #8, #4 @ r9<- A 3576 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3577 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3578 ldmia r3, {r0-r1} @ r0/r1<- vAA 3579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3580 rsbs r0, r0, #0 @ optional op; may set condition codes 3581 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3582 GET_INST_OPCODE(ip) @ extract opcode from rINST 3583 stmia r9, {r0-r1} @ vAA<- r0/r1 3584 GOTO_OPCODE(ip) @ jump to next instruction 3585 /* 10-11 instructions */ 3586 3587 3588 3589/* ------------------------------ */ 3590 .balign 64 3591.L_OP_NOT_LONG: /* 0x7e */ 3592/* File: armv6t2/OP_NOT_LONG.S */ 3593/* File: armv6t2/unopWide.S */ 3594 /* 3595 * Generic 64-bit unary operation. Provide an "instr" line that 3596 * specifies an instruction that performs "result = op r0/r1". 3597 * This could be an ARM instruction or a function call. 3598 * 3599 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3600 */ 3601 /* unop vA, vB */ 3602 mov r3, rINST, lsr #12 @ r3<- B 3603 ubfx r9, rINST, #8, #4 @ r9<- A 3604 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3605 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3606 ldmia r3, {r0-r1} @ r0/r1<- vAA 3607 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3608 mvn r0, r0 @ optional op; may set condition codes 3609 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3610 GET_INST_OPCODE(ip) @ extract opcode from rINST 3611 stmia r9, {r0-r1} @ vAA<- r0/r1 3612 GOTO_OPCODE(ip) @ jump to next instruction 3613 /* 10-11 instructions */ 3614 3615 3616 3617/* ------------------------------ */ 3618 .balign 64 3619.L_OP_NEG_FLOAT: /* 0x7f */ 3620/* File: armv6t2/OP_NEG_FLOAT.S */ 3621/* File: armv6t2/unop.S */ 3622 /* 3623 * Generic 32-bit unary operation. Provide an "instr" line that 3624 * specifies an instruction that performs "result = op r0". 3625 * This could be an ARM instruction or a function call. 3626 * 3627 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3628 * int-to-byte, int-to-char, int-to-short 3629 */ 3630 /* unop vA, vB */ 3631 mov r3, rINST, lsr #12 @ r3<- B 3632 ubfx r9, rINST, #8, #4 @ r9<- A 3633 GET_VREG(r0, r3) @ r0<- vB 3634 @ optional op; may set condition codes 3635 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3636 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3637 GET_INST_OPCODE(ip) @ extract opcode from rINST 3638 SET_VREG(r0, r9) @ vAA<- r0 3639 GOTO_OPCODE(ip) @ jump to next instruction 3640 /* 8-9 instructions */ 3641 3642 3643/* ------------------------------ */ 3644 .balign 64 3645.L_OP_NEG_DOUBLE: /* 0x80 */ 3646/* File: armv6t2/OP_NEG_DOUBLE.S */ 3647/* File: armv6t2/unopWide.S */ 3648 /* 3649 * Generic 64-bit unary operation. Provide an "instr" line that 3650 * specifies an instruction that performs "result = op r0/r1". 3651 * This could be an ARM instruction or a function call. 3652 * 3653 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3654 */ 3655 /* unop vA, vB */ 3656 mov r3, rINST, lsr #12 @ r3<- B 3657 ubfx r9, rINST, #8, #4 @ r9<- A 3658 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3659 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3660 ldmia r3, {r0-r1} @ r0/r1<- vAA 3661 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3662 @ optional op; may set condition codes 3663 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3664 GET_INST_OPCODE(ip) @ extract opcode from rINST 3665 stmia r9, {r0-r1} @ vAA<- r0/r1 3666 GOTO_OPCODE(ip) @ jump to next instruction 3667 /* 10-11 instructions */ 3668 3669 3670 3671/* ------------------------------ */ 3672 .balign 64 3673.L_OP_INT_TO_LONG: /* 0x81 */ 3674/* File: armv6t2/OP_INT_TO_LONG.S */ 3675/* File: armv6t2/unopWider.S */ 3676 /* 3677 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3678 * that specifies an instruction that performs "result = op r0", where 3679 * "result" is a 64-bit quantity in r0/r1. 3680 * 3681 * For: int-to-long, int-to-double, float-to-long, float-to-double 3682 */ 3683 /* unop vA, vB */ 3684 mov r3, rINST, lsr #12 @ r3<- B 3685 ubfx r9, rINST, #8, #4 @ r9<- A 3686 GET_VREG(r0, r3) @ r0<- vB 3687 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3688 @ optional op; may set condition codes 3689 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3690 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3691 GET_INST_OPCODE(ip) @ extract opcode from rINST 3692 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3693 GOTO_OPCODE(ip) @ jump to next instruction 3694 /* 9-10 instructions */ 3695 3696 3697/* ------------------------------ */ 3698 .balign 64 3699.L_OP_INT_TO_FLOAT: /* 0x82 */ 3700/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3701/* File: arm-vfp/funop.S */ 3702 /* 3703 * Generic 32-bit unary floating-point operation. Provide an "instr" 3704 * line that specifies an instruction that performs "s1 = op s0". 3705 * 3706 * for: int-to-float, float-to-int 3707 */ 3708 /* unop vA, vB */ 3709 mov r3, rINST, lsr #12 @ r3<- B 3710 mov r9, rINST, lsr #8 @ r9<- A+ 3711 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3712 flds s0, [r3] @ s0<- vB 3713 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3714 and r9, r9, #15 @ r9<- A 3715 fsitos s1, s0 @ s1<- op 3716 GET_INST_OPCODE(ip) @ extract opcode from rINST 3717 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3718 fsts s1, [r9] @ vA<- s1 3719 GOTO_OPCODE(ip) @ jump to next instruction 3720 3721 3722/* ------------------------------ */ 3723 .balign 64 3724.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3725/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3726/* File: arm-vfp/funopWider.S */ 3727 /* 3728 * Generic 32bit-to-64bit floating point unary operation. Provide an 3729 * "instr" line that specifies an instruction that performs "d0 = op s0". 3730 * 3731 * For: int-to-double, float-to-double 3732 */ 3733 /* unop vA, vB */ 3734 mov r3, rINST, lsr #12 @ r3<- B 3735 mov r9, rINST, lsr #8 @ r9<- A+ 3736 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3737 flds s0, [r3] @ s0<- vB 3738 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3739 and r9, r9, #15 @ r9<- A 3740 fsitod d0, s0 @ d0<- op 3741 GET_INST_OPCODE(ip) @ extract opcode from rINST 3742 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3743 fstd d0, [r9] @ vA<- d0 3744 GOTO_OPCODE(ip) @ jump to next instruction 3745 3746 3747/* ------------------------------ */ 3748 .balign 64 3749.L_OP_LONG_TO_INT: /* 0x84 */ 3750/* File: armv5te/OP_LONG_TO_INT.S */ 3751/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3752/* File: armv5te/OP_MOVE.S */ 3753 /* for move, move-object, long-to-int */ 3754 /* op vA, vB */ 3755 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3756 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3757 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3758 GET_VREG(r2, r1) @ r2<- fp[B] 3759 and r0, r0, #15 3760 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3761 SET_VREG(r2, r0) @ fp[A]<- r2 3762 GOTO_OPCODE(ip) @ execute next instruction 3763 3764 3765 3766/* ------------------------------ */ 3767 .balign 64 3768.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3769/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3770/* File: armv6t2/unopNarrower.S */ 3771 /* 3772 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3773 * that specifies an instruction that performs "result = op r0/r1", where 3774 * "result" is a 32-bit quantity in r0. 3775 * 3776 * For: long-to-float, double-to-int, double-to-float 3777 * 3778 * (This would work for long-to-int, but that instruction is actually 3779 * an exact match for OP_MOVE.) 3780 */ 3781 /* unop vA, vB */ 3782 mov r3, rINST, lsr #12 @ r3<- B 3783 ubfx r9, rINST, #8, #4 @ r9<- A 3784 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3785 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3786 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3787 @ optional op; may set condition codes 3788 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3789 GET_INST_OPCODE(ip) @ extract opcode from rINST 3790 SET_VREG(r0, r9) @ vA<- r0 3791 GOTO_OPCODE(ip) @ jump to next instruction 3792 /* 9-10 instructions */ 3793 3794 3795/* ------------------------------ */ 3796 .balign 64 3797.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3798/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3799/* File: armv6t2/unopWide.S */ 3800 /* 3801 * Generic 64-bit unary operation. Provide an "instr" line that 3802 * specifies an instruction that performs "result = op r0/r1". 3803 * This could be an ARM instruction or a function call. 3804 * 3805 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3806 */ 3807 /* unop vA, vB */ 3808 mov r3, rINST, lsr #12 @ r3<- B 3809 ubfx r9, rINST, #8, #4 @ r9<- A 3810 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3811 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3812 ldmia r3, {r0-r1} @ r0/r1<- vAA 3813 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3814 @ optional op; may set condition codes 3815 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3816 GET_INST_OPCODE(ip) @ extract opcode from rINST 3817 stmia r9, {r0-r1} @ vAA<- r0/r1 3818 GOTO_OPCODE(ip) @ jump to next instruction 3819 /* 10-11 instructions */ 3820 3821 3822 3823/* ------------------------------ */ 3824 .balign 64 3825.L_OP_FLOAT_TO_INT: /* 0x87 */ 3826/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3827/* File: arm-vfp/funop.S */ 3828 /* 3829 * Generic 32-bit unary floating-point operation. Provide an "instr" 3830 * line that specifies an instruction that performs "s1 = op s0". 3831 * 3832 * for: int-to-float, float-to-int 3833 */ 3834 /* unop vA, vB */ 3835 mov r3, rINST, lsr #12 @ r3<- B 3836 mov r9, rINST, lsr #8 @ r9<- A+ 3837 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3838 flds s0, [r3] @ s0<- vB 3839 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3840 and r9, r9, #15 @ r9<- A 3841 ftosizs s1, s0 @ s1<- op 3842 GET_INST_OPCODE(ip) @ extract opcode from rINST 3843 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3844 fsts s1, [r9] @ vA<- s1 3845 GOTO_OPCODE(ip) @ jump to next instruction 3846 3847 3848/* ------------------------------ */ 3849 .balign 64 3850.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3851/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3852@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3853/* File: armv6t2/unopWider.S */ 3854 /* 3855 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3856 * that specifies an instruction that performs "result = op r0", where 3857 * "result" is a 64-bit quantity in r0/r1. 3858 * 3859 * For: int-to-long, int-to-double, float-to-long, float-to-double 3860 */ 3861 /* unop vA, vB */ 3862 mov r3, rINST, lsr #12 @ r3<- B 3863 ubfx r9, rINST, #8, #4 @ r9<- A 3864 GET_VREG(r0, r3) @ r0<- vB 3865 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3866 @ optional op; may set condition codes 3867 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3868 bl f2l_doconv @ r0<- op, r0-r3 changed 3869 GET_INST_OPCODE(ip) @ extract opcode from rINST 3870 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3871 GOTO_OPCODE(ip) @ jump to next instruction 3872 /* 9-10 instructions */ 3873 3874 3875 3876/* ------------------------------ */ 3877 .balign 64 3878.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3879/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3880/* File: arm-vfp/funopWider.S */ 3881 /* 3882 * Generic 32bit-to-64bit floating point unary operation. Provide an 3883 * "instr" line that specifies an instruction that performs "d0 = op s0". 3884 * 3885 * For: int-to-double, float-to-double 3886 */ 3887 /* unop vA, vB */ 3888 mov r3, rINST, lsr #12 @ r3<- B 3889 mov r9, rINST, lsr #8 @ r9<- A+ 3890 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3891 flds s0, [r3] @ s0<- vB 3892 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3893 and r9, r9, #15 @ r9<- A 3894 fcvtds d0, s0 @ d0<- op 3895 GET_INST_OPCODE(ip) @ extract opcode from rINST 3896 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3897 fstd d0, [r9] @ vA<- d0 3898 GOTO_OPCODE(ip) @ jump to next instruction 3899 3900 3901/* ------------------------------ */ 3902 .balign 64 3903.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3904/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3905/* File: arm-vfp/funopNarrower.S */ 3906 /* 3907 * Generic 64bit-to-32bit unary floating point operation. Provide an 3908 * "instr" line that specifies an instruction that performs "s0 = op d0". 3909 * 3910 * For: double-to-int, double-to-float 3911 */ 3912 /* unop vA, vB */ 3913 mov r3, rINST, lsr #12 @ r3<- B 3914 mov r9, rINST, lsr #8 @ r9<- A+ 3915 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3916 fldd d0, [r3] @ d0<- vB 3917 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3918 and r9, r9, #15 @ r9<- A 3919 ftosizd s0, d0 @ s0<- op 3920 GET_INST_OPCODE(ip) @ extract opcode from rINST 3921 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3922 fsts s0, [r9] @ vA<- s0 3923 GOTO_OPCODE(ip) @ jump to next instruction 3924 3925 3926/* ------------------------------ */ 3927 .balign 64 3928.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3929/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3930@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3931/* File: armv6t2/unopWide.S */ 3932 /* 3933 * Generic 64-bit unary operation. Provide an "instr" line that 3934 * specifies an instruction that performs "result = op r0/r1". 3935 * This could be an ARM instruction or a function call. 3936 * 3937 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3938 */ 3939 /* unop vA, vB */ 3940 mov r3, rINST, lsr #12 @ r3<- B 3941 ubfx r9, rINST, #8, #4 @ r9<- A 3942 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3943 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3944 ldmia r3, {r0-r1} @ r0/r1<- vAA 3945 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3946 @ optional op; may set condition codes 3947 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3948 GET_INST_OPCODE(ip) @ extract opcode from rINST 3949 stmia r9, {r0-r1} @ vAA<- r0/r1 3950 GOTO_OPCODE(ip) @ jump to next instruction 3951 /* 10-11 instructions */ 3952 3953 3954 3955 3956/* ------------------------------ */ 3957 .balign 64 3958.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3959/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3960/* File: arm-vfp/funopNarrower.S */ 3961 /* 3962 * Generic 64bit-to-32bit unary floating point operation. Provide an 3963 * "instr" line that specifies an instruction that performs "s0 = op d0". 3964 * 3965 * For: double-to-int, double-to-float 3966 */ 3967 /* unop vA, vB */ 3968 mov r3, rINST, lsr #12 @ r3<- B 3969 mov r9, rINST, lsr #8 @ r9<- A+ 3970 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3971 fldd d0, [r3] @ d0<- vB 3972 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3973 and r9, r9, #15 @ r9<- A 3974 fcvtsd s0, d0 @ s0<- op 3975 GET_INST_OPCODE(ip) @ extract opcode from rINST 3976 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3977 fsts s0, [r9] @ vA<- s0 3978 GOTO_OPCODE(ip) @ jump to next instruction 3979 3980 3981/* ------------------------------ */ 3982 .balign 64 3983.L_OP_INT_TO_BYTE: /* 0x8d */ 3984/* File: armv6t2/OP_INT_TO_BYTE.S */ 3985/* File: armv6t2/unop.S */ 3986 /* 3987 * Generic 32-bit unary operation. Provide an "instr" line that 3988 * specifies an instruction that performs "result = op r0". 3989 * This could be an ARM instruction or a function call. 3990 * 3991 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3992 * int-to-byte, int-to-char, int-to-short 3993 */ 3994 /* unop vA, vB */ 3995 mov r3, rINST, lsr #12 @ r3<- B 3996 ubfx r9, rINST, #8, #4 @ r9<- A 3997 GET_VREG(r0, r3) @ r0<- vB 3998 @ optional op; may set condition codes 3999 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4000 sxtb r0, r0 @ r0<- op, r0-r3 changed 4001 GET_INST_OPCODE(ip) @ extract opcode from rINST 4002 SET_VREG(r0, r9) @ vAA<- r0 4003 GOTO_OPCODE(ip) @ jump to next instruction 4004 /* 8-9 instructions */ 4005 4006 4007/* ------------------------------ */ 4008 .balign 64 4009.L_OP_INT_TO_CHAR: /* 0x8e */ 4010/* File: armv6t2/OP_INT_TO_CHAR.S */ 4011/* File: armv6t2/unop.S */ 4012 /* 4013 * Generic 32-bit unary operation. Provide an "instr" line that 4014 * specifies an instruction that performs "result = op r0". 4015 * This could be an ARM instruction or a function call. 4016 * 4017 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4018 * int-to-byte, int-to-char, int-to-short 4019 */ 4020 /* unop vA, vB */ 4021 mov r3, rINST, lsr #12 @ r3<- B 4022 ubfx r9, rINST, #8, #4 @ r9<- A 4023 GET_VREG(r0, r3) @ r0<- vB 4024 @ optional op; may set condition codes 4025 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4026 uxth r0, r0 @ r0<- op, r0-r3 changed 4027 GET_INST_OPCODE(ip) @ extract opcode from rINST 4028 SET_VREG(r0, r9) @ vAA<- r0 4029 GOTO_OPCODE(ip) @ jump to next instruction 4030 /* 8-9 instructions */ 4031 4032 4033/* ------------------------------ */ 4034 .balign 64 4035.L_OP_INT_TO_SHORT: /* 0x8f */ 4036/* File: armv6t2/OP_INT_TO_SHORT.S */ 4037/* File: armv6t2/unop.S */ 4038 /* 4039 * Generic 32-bit unary operation. Provide an "instr" line that 4040 * specifies an instruction that performs "result = op r0". 4041 * This could be an ARM instruction or a function call. 4042 * 4043 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4044 * int-to-byte, int-to-char, int-to-short 4045 */ 4046 /* unop vA, vB */ 4047 mov r3, rINST, lsr #12 @ r3<- B 4048 ubfx r9, rINST, #8, #4 @ r9<- A 4049 GET_VREG(r0, r3) @ r0<- vB 4050 @ optional op; may set condition codes 4051 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4052 sxth r0, r0 @ r0<- op, r0-r3 changed 4053 GET_INST_OPCODE(ip) @ extract opcode from rINST 4054 SET_VREG(r0, r9) @ vAA<- r0 4055 GOTO_OPCODE(ip) @ jump to next instruction 4056 /* 8-9 instructions */ 4057 4058 4059/* ------------------------------ */ 4060 .balign 64 4061.L_OP_ADD_INT: /* 0x90 */ 4062/* File: armv5te/OP_ADD_INT.S */ 4063/* File: armv5te/binop.S */ 4064 /* 4065 * Generic 32-bit binary operation. Provide an "instr" line that 4066 * specifies an instruction that performs "result = r0 op r1". 4067 * This could be an ARM instruction or a function call. (If the result 4068 * comes back in a register other than r0, you can override "result".) 4069 * 4070 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4071 * vCC (r1). Useful for integer division and modulus. Note that we 4072 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4073 * handles it correctly. 4074 * 4075 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4076 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4077 * mul-float, div-float, rem-float 4078 */ 4079 /* binop vAA, vBB, vCC */ 4080 FETCH(r0, 1) @ r0<- CCBB 4081 mov r9, rINST, lsr #8 @ r9<- AA 4082 mov r3, r0, lsr #8 @ r3<- CC 4083 and r2, r0, #255 @ r2<- BB 4084 GET_VREG(r1, r3) @ r1<- vCC 4085 GET_VREG(r0, r2) @ r0<- vBB 4086 .if 0 4087 cmp r1, #0 @ is second operand zero? 4088 beq common_errDivideByZero 4089 .endif 4090 4091 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4092 @ optional op; may set condition codes 4093 add r0, r0, r1 @ r0<- op, r0-r3 changed 4094 GET_INST_OPCODE(ip) @ extract opcode from rINST 4095 SET_VREG(r0, r9) @ vAA<- r0 4096 GOTO_OPCODE(ip) @ jump to next instruction 4097 /* 11-14 instructions */ 4098 4099 4100 4101/* ------------------------------ */ 4102 .balign 64 4103.L_OP_SUB_INT: /* 0x91 */ 4104/* File: armv5te/OP_SUB_INT.S */ 4105/* File: armv5te/binop.S */ 4106 /* 4107 * Generic 32-bit binary operation. Provide an "instr" line that 4108 * specifies an instruction that performs "result = r0 op r1". 4109 * This could be an ARM instruction or a function call. (If the result 4110 * comes back in a register other than r0, you can override "result".) 4111 * 4112 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4113 * vCC (r1). Useful for integer division and modulus. Note that we 4114 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4115 * handles it correctly. 4116 * 4117 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4118 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4119 * mul-float, div-float, rem-float 4120 */ 4121 /* binop vAA, vBB, vCC */ 4122 FETCH(r0, 1) @ r0<- CCBB 4123 mov r9, rINST, lsr #8 @ r9<- AA 4124 mov r3, r0, lsr #8 @ r3<- CC 4125 and r2, r0, #255 @ r2<- BB 4126 GET_VREG(r1, r3) @ r1<- vCC 4127 GET_VREG(r0, r2) @ r0<- vBB 4128 .if 0 4129 cmp r1, #0 @ is second operand zero? 4130 beq common_errDivideByZero 4131 .endif 4132 4133 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4134 @ optional op; may set condition codes 4135 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4136 GET_INST_OPCODE(ip) @ extract opcode from rINST 4137 SET_VREG(r0, r9) @ vAA<- r0 4138 GOTO_OPCODE(ip) @ jump to next instruction 4139 /* 11-14 instructions */ 4140 4141 4142 4143/* ------------------------------ */ 4144 .balign 64 4145.L_OP_MUL_INT: /* 0x92 */ 4146/* File: armv5te/OP_MUL_INT.S */ 4147/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4148/* File: armv5te/binop.S */ 4149 /* 4150 * Generic 32-bit binary operation. Provide an "instr" line that 4151 * specifies an instruction that performs "result = r0 op r1". 4152 * This could be an ARM instruction or a function call. (If the result 4153 * comes back in a register other than r0, you can override "result".) 4154 * 4155 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4156 * vCC (r1). Useful for integer division and modulus. Note that we 4157 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4158 * handles it correctly. 4159 * 4160 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4161 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4162 * mul-float, div-float, rem-float 4163 */ 4164 /* binop vAA, vBB, vCC */ 4165 FETCH(r0, 1) @ r0<- CCBB 4166 mov r9, rINST, lsr #8 @ r9<- AA 4167 mov r3, r0, lsr #8 @ r3<- CC 4168 and r2, r0, #255 @ r2<- BB 4169 GET_VREG(r1, r3) @ r1<- vCC 4170 GET_VREG(r0, r2) @ r0<- vBB 4171 .if 0 4172 cmp r1, #0 @ is second operand zero? 4173 beq common_errDivideByZero 4174 .endif 4175 4176 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4177 @ optional op; may set condition codes 4178 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4179 GET_INST_OPCODE(ip) @ extract opcode from rINST 4180 SET_VREG(r0, r9) @ vAA<- r0 4181 GOTO_OPCODE(ip) @ jump to next instruction 4182 /* 11-14 instructions */ 4183 4184 4185 4186/* ------------------------------ */ 4187 .balign 64 4188.L_OP_DIV_INT: /* 0x93 */ 4189/* File: armv5te/OP_DIV_INT.S */ 4190/* File: armv5te/binop.S */ 4191 /* 4192 * Generic 32-bit binary operation. Provide an "instr" line that 4193 * specifies an instruction that performs "result = r0 op r1". 4194 * This could be an ARM instruction or a function call. (If the result 4195 * comes back in a register other than r0, you can override "result".) 4196 * 4197 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4198 * vCC (r1). Useful for integer division and modulus. Note that we 4199 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4200 * handles it correctly. 4201 * 4202 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4203 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4204 * mul-float, div-float, rem-float 4205 */ 4206 /* binop vAA, vBB, vCC */ 4207 FETCH(r0, 1) @ r0<- CCBB 4208 mov r9, rINST, lsr #8 @ r9<- AA 4209 mov r3, r0, lsr #8 @ r3<- CC 4210 and r2, r0, #255 @ r2<- BB 4211 GET_VREG(r1, r3) @ r1<- vCC 4212 GET_VREG(r0, r2) @ r0<- vBB 4213 .if 1 4214 cmp r1, #0 @ is second operand zero? 4215 beq common_errDivideByZero 4216 .endif 4217 4218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4219 @ optional op; may set condition codes 4220 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4221 GET_INST_OPCODE(ip) @ extract opcode from rINST 4222 SET_VREG(r0, r9) @ vAA<- r0 4223 GOTO_OPCODE(ip) @ jump to next instruction 4224 /* 11-14 instructions */ 4225 4226 4227 4228/* ------------------------------ */ 4229 .balign 64 4230.L_OP_REM_INT: /* 0x94 */ 4231/* File: armv5te/OP_REM_INT.S */ 4232/* idivmod returns quotient in r0 and remainder in r1 */ 4233/* File: armv5te/binop.S */ 4234 /* 4235 * Generic 32-bit binary operation. Provide an "instr" line that 4236 * specifies an instruction that performs "result = r0 op r1". 4237 * This could be an ARM instruction or a function call. (If the result 4238 * comes back in a register other than r0, you can override "result".) 4239 * 4240 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4241 * vCC (r1). Useful for integer division and modulus. Note that we 4242 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4243 * handles it correctly. 4244 * 4245 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4246 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4247 * mul-float, div-float, rem-float 4248 */ 4249 /* binop vAA, vBB, vCC */ 4250 FETCH(r0, 1) @ r0<- CCBB 4251 mov r9, rINST, lsr #8 @ r9<- AA 4252 mov r3, r0, lsr #8 @ r3<- CC 4253 and r2, r0, #255 @ r2<- BB 4254 GET_VREG(r1, r3) @ r1<- vCC 4255 GET_VREG(r0, r2) @ r0<- vBB 4256 .if 1 4257 cmp r1, #0 @ is second operand zero? 4258 beq common_errDivideByZero 4259 .endif 4260 4261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4262 @ optional op; may set condition codes 4263 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4264 GET_INST_OPCODE(ip) @ extract opcode from rINST 4265 SET_VREG(r1, r9) @ vAA<- r1 4266 GOTO_OPCODE(ip) @ jump to next instruction 4267 /* 11-14 instructions */ 4268 4269 4270 4271/* ------------------------------ */ 4272 .balign 64 4273.L_OP_AND_INT: /* 0x95 */ 4274/* File: armv5te/OP_AND_INT.S */ 4275/* File: armv5te/binop.S */ 4276 /* 4277 * Generic 32-bit binary operation. Provide an "instr" line that 4278 * specifies an instruction that performs "result = r0 op r1". 4279 * This could be an ARM instruction or a function call. (If the result 4280 * comes back in a register other than r0, you can override "result".) 4281 * 4282 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4283 * vCC (r1). Useful for integer division and modulus. Note that we 4284 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4285 * handles it correctly. 4286 * 4287 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4288 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4289 * mul-float, div-float, rem-float 4290 */ 4291 /* binop vAA, vBB, vCC */ 4292 FETCH(r0, 1) @ r0<- CCBB 4293 mov r9, rINST, lsr #8 @ r9<- AA 4294 mov r3, r0, lsr #8 @ r3<- CC 4295 and r2, r0, #255 @ r2<- BB 4296 GET_VREG(r1, r3) @ r1<- vCC 4297 GET_VREG(r0, r2) @ r0<- vBB 4298 .if 0 4299 cmp r1, #0 @ is second operand zero? 4300 beq common_errDivideByZero 4301 .endif 4302 4303 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4304 @ optional op; may set condition codes 4305 and r0, r0, r1 @ r0<- op, r0-r3 changed 4306 GET_INST_OPCODE(ip) @ extract opcode from rINST 4307 SET_VREG(r0, r9) @ vAA<- r0 4308 GOTO_OPCODE(ip) @ jump to next instruction 4309 /* 11-14 instructions */ 4310 4311 4312 4313/* ------------------------------ */ 4314 .balign 64 4315.L_OP_OR_INT: /* 0x96 */ 4316/* File: armv5te/OP_OR_INT.S */ 4317/* File: armv5te/binop.S */ 4318 /* 4319 * Generic 32-bit binary operation. Provide an "instr" line that 4320 * specifies an instruction that performs "result = r0 op r1". 4321 * This could be an ARM instruction or a function call. (If the result 4322 * comes back in a register other than r0, you can override "result".) 4323 * 4324 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4325 * vCC (r1). Useful for integer division and modulus. Note that we 4326 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4327 * handles it correctly. 4328 * 4329 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4330 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4331 * mul-float, div-float, rem-float 4332 */ 4333 /* binop vAA, vBB, vCC */ 4334 FETCH(r0, 1) @ r0<- CCBB 4335 mov r9, rINST, lsr #8 @ r9<- AA 4336 mov r3, r0, lsr #8 @ r3<- CC 4337 and r2, r0, #255 @ r2<- BB 4338 GET_VREG(r1, r3) @ r1<- vCC 4339 GET_VREG(r0, r2) @ r0<- vBB 4340 .if 0 4341 cmp r1, #0 @ is second operand zero? 4342 beq common_errDivideByZero 4343 .endif 4344 4345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4346 @ optional op; may set condition codes 4347 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4348 GET_INST_OPCODE(ip) @ extract opcode from rINST 4349 SET_VREG(r0, r9) @ vAA<- r0 4350 GOTO_OPCODE(ip) @ jump to next instruction 4351 /* 11-14 instructions */ 4352 4353 4354 4355/* ------------------------------ */ 4356 .balign 64 4357.L_OP_XOR_INT: /* 0x97 */ 4358/* File: armv5te/OP_XOR_INT.S */ 4359/* File: armv5te/binop.S */ 4360 /* 4361 * Generic 32-bit binary operation. Provide an "instr" line that 4362 * specifies an instruction that performs "result = r0 op r1". 4363 * This could be an ARM instruction or a function call. (If the result 4364 * comes back in a register other than r0, you can override "result".) 4365 * 4366 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4367 * vCC (r1). Useful for integer division and modulus. Note that we 4368 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4369 * handles it correctly. 4370 * 4371 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4372 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4373 * mul-float, div-float, rem-float 4374 */ 4375 /* binop vAA, vBB, vCC */ 4376 FETCH(r0, 1) @ r0<- CCBB 4377 mov r9, rINST, lsr #8 @ r9<- AA 4378 mov r3, r0, lsr #8 @ r3<- CC 4379 and r2, r0, #255 @ r2<- BB 4380 GET_VREG(r1, r3) @ r1<- vCC 4381 GET_VREG(r0, r2) @ r0<- vBB 4382 .if 0 4383 cmp r1, #0 @ is second operand zero? 4384 beq common_errDivideByZero 4385 .endif 4386 4387 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4388 @ optional op; may set condition codes 4389 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4390 GET_INST_OPCODE(ip) @ extract opcode from rINST 4391 SET_VREG(r0, r9) @ vAA<- r0 4392 GOTO_OPCODE(ip) @ jump to next instruction 4393 /* 11-14 instructions */ 4394 4395 4396 4397/* ------------------------------ */ 4398 .balign 64 4399.L_OP_SHL_INT: /* 0x98 */ 4400/* File: armv5te/OP_SHL_INT.S */ 4401/* File: armv5te/binop.S */ 4402 /* 4403 * Generic 32-bit binary operation. Provide an "instr" line that 4404 * specifies an instruction that performs "result = r0 op r1". 4405 * This could be an ARM instruction or a function call. (If the result 4406 * comes back in a register other than r0, you can override "result".) 4407 * 4408 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4409 * vCC (r1). Useful for integer division and modulus. Note that we 4410 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4411 * handles it correctly. 4412 * 4413 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4414 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4415 * mul-float, div-float, rem-float 4416 */ 4417 /* binop vAA, vBB, vCC */ 4418 FETCH(r0, 1) @ r0<- CCBB 4419 mov r9, rINST, lsr #8 @ r9<- AA 4420 mov r3, r0, lsr #8 @ r3<- CC 4421 and r2, r0, #255 @ r2<- BB 4422 GET_VREG(r1, r3) @ r1<- vCC 4423 GET_VREG(r0, r2) @ r0<- vBB 4424 .if 0 4425 cmp r1, #0 @ is second operand zero? 4426 beq common_errDivideByZero 4427 .endif 4428 4429 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4430 and r1, r1, #31 @ optional op; may set condition codes 4431 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4432 GET_INST_OPCODE(ip) @ extract opcode from rINST 4433 SET_VREG(r0, r9) @ vAA<- r0 4434 GOTO_OPCODE(ip) @ jump to next instruction 4435 /* 11-14 instructions */ 4436 4437 4438 4439/* ------------------------------ */ 4440 .balign 64 4441.L_OP_SHR_INT: /* 0x99 */ 4442/* File: armv5te/OP_SHR_INT.S */ 4443/* File: armv5te/binop.S */ 4444 /* 4445 * Generic 32-bit binary operation. Provide an "instr" line that 4446 * specifies an instruction that performs "result = r0 op r1". 4447 * This could be an ARM instruction or a function call. (If the result 4448 * comes back in a register other than r0, you can override "result".) 4449 * 4450 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4451 * vCC (r1). Useful for integer division and modulus. Note that we 4452 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4453 * handles it correctly. 4454 * 4455 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4456 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4457 * mul-float, div-float, rem-float 4458 */ 4459 /* binop vAA, vBB, vCC */ 4460 FETCH(r0, 1) @ r0<- CCBB 4461 mov r9, rINST, lsr #8 @ r9<- AA 4462 mov r3, r0, lsr #8 @ r3<- CC 4463 and r2, r0, #255 @ r2<- BB 4464 GET_VREG(r1, r3) @ r1<- vCC 4465 GET_VREG(r0, r2) @ r0<- vBB 4466 .if 0 4467 cmp r1, #0 @ is second operand zero? 4468 beq common_errDivideByZero 4469 .endif 4470 4471 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4472 and r1, r1, #31 @ optional op; may set condition codes 4473 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4474 GET_INST_OPCODE(ip) @ extract opcode from rINST 4475 SET_VREG(r0, r9) @ vAA<- r0 4476 GOTO_OPCODE(ip) @ jump to next instruction 4477 /* 11-14 instructions */ 4478 4479 4480 4481/* ------------------------------ */ 4482 .balign 64 4483.L_OP_USHR_INT: /* 0x9a */ 4484/* File: armv5te/OP_USHR_INT.S */ 4485/* File: armv5te/binop.S */ 4486 /* 4487 * Generic 32-bit binary operation. Provide an "instr" line that 4488 * specifies an instruction that performs "result = r0 op r1". 4489 * This could be an ARM instruction or a function call. (If the result 4490 * comes back in a register other than r0, you can override "result".) 4491 * 4492 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4493 * vCC (r1). Useful for integer division and modulus. Note that we 4494 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4495 * handles it correctly. 4496 * 4497 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4498 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4499 * mul-float, div-float, rem-float 4500 */ 4501 /* binop vAA, vBB, vCC */ 4502 FETCH(r0, 1) @ r0<- CCBB 4503 mov r9, rINST, lsr #8 @ r9<- AA 4504 mov r3, r0, lsr #8 @ r3<- CC 4505 and r2, r0, #255 @ r2<- BB 4506 GET_VREG(r1, r3) @ r1<- vCC 4507 GET_VREG(r0, r2) @ r0<- vBB 4508 .if 0 4509 cmp r1, #0 @ is second operand zero? 4510 beq common_errDivideByZero 4511 .endif 4512 4513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4514 and r1, r1, #31 @ optional op; may set condition codes 4515 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4516 GET_INST_OPCODE(ip) @ extract opcode from rINST 4517 SET_VREG(r0, r9) @ vAA<- r0 4518 GOTO_OPCODE(ip) @ jump to next instruction 4519 /* 11-14 instructions */ 4520 4521 4522 4523/* ------------------------------ */ 4524 .balign 64 4525.L_OP_ADD_LONG: /* 0x9b */ 4526/* File: armv5te/OP_ADD_LONG.S */ 4527/* File: armv5te/binopWide.S */ 4528 /* 4529 * Generic 64-bit binary operation. Provide an "instr" line that 4530 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4531 * This could be an ARM instruction or a function call. (If the result 4532 * comes back in a register other than r0, you can override "result".) 4533 * 4534 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4535 * vCC (r1). Useful for integer division and modulus. 4536 * 4537 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4538 * xor-long, add-double, sub-double, mul-double, div-double, 4539 * rem-double 4540 * 4541 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4542 */ 4543 /* binop vAA, vBB, vCC */ 4544 FETCH(r0, 1) @ r0<- CCBB 4545 mov r9, rINST, lsr #8 @ r9<- AA 4546 and r2, r0, #255 @ r2<- BB 4547 mov r3, r0, lsr #8 @ r3<- CC 4548 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4549 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4550 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4551 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4552 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4553 .if 0 4554 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4555 beq common_errDivideByZero 4556 .endif 4557 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4558 4559 adds r0, r0, r2 @ optional op; may set condition codes 4560 adc r1, r1, r3 @ result<- op, r0-r3 changed 4561 GET_INST_OPCODE(ip) @ extract opcode from rINST 4562 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4563 GOTO_OPCODE(ip) @ jump to next instruction 4564 /* 14-17 instructions */ 4565 4566 4567 4568/* ------------------------------ */ 4569 .balign 64 4570.L_OP_SUB_LONG: /* 0x9c */ 4571/* File: armv5te/OP_SUB_LONG.S */ 4572/* File: armv5te/binopWide.S */ 4573 /* 4574 * Generic 64-bit binary operation. Provide an "instr" line that 4575 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4576 * This could be an ARM instruction or a function call. (If the result 4577 * comes back in a register other than r0, you can override "result".) 4578 * 4579 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4580 * vCC (r1). Useful for integer division and modulus. 4581 * 4582 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4583 * xor-long, add-double, sub-double, mul-double, div-double, 4584 * rem-double 4585 * 4586 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4587 */ 4588 /* binop vAA, vBB, vCC */ 4589 FETCH(r0, 1) @ r0<- CCBB 4590 mov r9, rINST, lsr #8 @ r9<- AA 4591 and r2, r0, #255 @ r2<- BB 4592 mov r3, r0, lsr #8 @ r3<- CC 4593 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4594 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4595 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4596 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4597 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4598 .if 0 4599 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4600 beq common_errDivideByZero 4601 .endif 4602 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4603 4604 subs r0, r0, r2 @ optional op; may set condition codes 4605 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4606 GET_INST_OPCODE(ip) @ extract opcode from rINST 4607 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4608 GOTO_OPCODE(ip) @ jump to next instruction 4609 /* 14-17 instructions */ 4610 4611 4612 4613/* ------------------------------ */ 4614 .balign 64 4615.L_OP_MUL_LONG: /* 0x9d */ 4616/* File: armv5te/OP_MUL_LONG.S */ 4617 /* 4618 * Signed 64-bit integer multiply. 4619 * 4620 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4621 * WX 4622 * x YZ 4623 * -------- 4624 * ZW ZX 4625 * YW YX 4626 * 4627 * The low word of the result holds ZX, the high word holds 4628 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4629 * it doesn't fit in the low 64 bits. 4630 * 4631 * Unlike most ARM math operations, multiply instructions have 4632 * restrictions on using the same register more than once (Rd and Rm 4633 * cannot be the same). 4634 */ 4635 /* mul-long vAA, vBB, vCC */ 4636 FETCH(r0, 1) @ r0<- CCBB 4637 and r2, r0, #255 @ r2<- BB 4638 mov r3, r0, lsr #8 @ r3<- CC 4639 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4640 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4641 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4642 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4643 mul ip, r2, r1 @ ip<- ZxW 4644 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4645 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4646 mov r0, rINST, lsr #8 @ r0<- AA 4647 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4648 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4649 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4650 b .LOP_MUL_LONG_finish 4651 4652/* ------------------------------ */ 4653 .balign 64 4654.L_OP_DIV_LONG: /* 0x9e */ 4655/* File: armv5te/OP_DIV_LONG.S */ 4656/* File: armv5te/binopWide.S */ 4657 /* 4658 * Generic 64-bit binary operation. Provide an "instr" line that 4659 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4660 * This could be an ARM instruction or a function call. (If the result 4661 * comes back in a register other than r0, you can override "result".) 4662 * 4663 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4664 * vCC (r1). Useful for integer division and modulus. 4665 * 4666 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4667 * xor-long, add-double, sub-double, mul-double, div-double, 4668 * rem-double 4669 * 4670 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4671 */ 4672 /* binop vAA, vBB, vCC */ 4673 FETCH(r0, 1) @ r0<- CCBB 4674 mov r9, rINST, lsr #8 @ r9<- AA 4675 and r2, r0, #255 @ r2<- BB 4676 mov r3, r0, lsr #8 @ r3<- CC 4677 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4678 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4679 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4680 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4681 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4682 .if 1 4683 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4684 beq common_errDivideByZero 4685 .endif 4686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4687 4688 @ optional op; may set condition codes 4689 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4690 GET_INST_OPCODE(ip) @ extract opcode from rINST 4691 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4692 GOTO_OPCODE(ip) @ jump to next instruction 4693 /* 14-17 instructions */ 4694 4695 4696 4697/* ------------------------------ */ 4698 .balign 64 4699.L_OP_REM_LONG: /* 0x9f */ 4700/* File: armv5te/OP_REM_LONG.S */ 4701/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4702/* File: armv5te/binopWide.S */ 4703 /* 4704 * Generic 64-bit binary operation. Provide an "instr" line that 4705 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4706 * This could be an ARM instruction or a function call. (If the result 4707 * comes back in a register other than r0, you can override "result".) 4708 * 4709 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4710 * vCC (r1). Useful for integer division and modulus. 4711 * 4712 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4713 * xor-long, add-double, sub-double, mul-double, div-double, 4714 * rem-double 4715 * 4716 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4717 */ 4718 /* binop vAA, vBB, vCC */ 4719 FETCH(r0, 1) @ r0<- CCBB 4720 mov r9, rINST, lsr #8 @ r9<- AA 4721 and r2, r0, #255 @ r2<- BB 4722 mov r3, r0, lsr #8 @ r3<- CC 4723 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4724 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4725 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4726 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4727 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4728 .if 1 4729 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4730 beq common_errDivideByZero 4731 .endif 4732 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4733 4734 @ optional op; may set condition codes 4735 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4736 GET_INST_OPCODE(ip) @ extract opcode from rINST 4737 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4738 GOTO_OPCODE(ip) @ jump to next instruction 4739 /* 14-17 instructions */ 4740 4741 4742 4743/* ------------------------------ */ 4744 .balign 64 4745.L_OP_AND_LONG: /* 0xa0 */ 4746/* File: armv5te/OP_AND_LONG.S */ 4747/* File: armv5te/binopWide.S */ 4748 /* 4749 * Generic 64-bit binary operation. Provide an "instr" line that 4750 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4751 * This could be an ARM instruction or a function call. (If the result 4752 * comes back in a register other than r0, you can override "result".) 4753 * 4754 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4755 * vCC (r1). Useful for integer division and modulus. 4756 * 4757 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4758 * xor-long, add-double, sub-double, mul-double, div-double, 4759 * rem-double 4760 * 4761 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4762 */ 4763 /* binop vAA, vBB, vCC */ 4764 FETCH(r0, 1) @ r0<- CCBB 4765 mov r9, rINST, lsr #8 @ r9<- AA 4766 and r2, r0, #255 @ r2<- BB 4767 mov r3, r0, lsr #8 @ r3<- CC 4768 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4769 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4770 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4771 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4772 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4773 .if 0 4774 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4775 beq common_errDivideByZero 4776 .endif 4777 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4778 4779 and r0, r0, r2 @ optional op; may set condition codes 4780 and r1, r1, r3 @ result<- op, r0-r3 changed 4781 GET_INST_OPCODE(ip) @ extract opcode from rINST 4782 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4783 GOTO_OPCODE(ip) @ jump to next instruction 4784 /* 14-17 instructions */ 4785 4786 4787 4788/* ------------------------------ */ 4789 .balign 64 4790.L_OP_OR_LONG: /* 0xa1 */ 4791/* File: armv5te/OP_OR_LONG.S */ 4792/* File: armv5te/binopWide.S */ 4793 /* 4794 * Generic 64-bit binary operation. Provide an "instr" line that 4795 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4796 * This could be an ARM instruction or a function call. (If the result 4797 * comes back in a register other than r0, you can override "result".) 4798 * 4799 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4800 * vCC (r1). Useful for integer division and modulus. 4801 * 4802 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4803 * xor-long, add-double, sub-double, mul-double, div-double, 4804 * rem-double 4805 * 4806 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4807 */ 4808 /* binop vAA, vBB, vCC */ 4809 FETCH(r0, 1) @ r0<- CCBB 4810 mov r9, rINST, lsr #8 @ r9<- AA 4811 and r2, r0, #255 @ r2<- BB 4812 mov r3, r0, lsr #8 @ r3<- CC 4813 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4814 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4815 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4816 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4817 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4818 .if 0 4819 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4820 beq common_errDivideByZero 4821 .endif 4822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4823 4824 orr r0, r0, r2 @ optional op; may set condition codes 4825 orr r1, r1, r3 @ result<- op, r0-r3 changed 4826 GET_INST_OPCODE(ip) @ extract opcode from rINST 4827 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4828 GOTO_OPCODE(ip) @ jump to next instruction 4829 /* 14-17 instructions */ 4830 4831 4832 4833/* ------------------------------ */ 4834 .balign 64 4835.L_OP_XOR_LONG: /* 0xa2 */ 4836/* File: armv5te/OP_XOR_LONG.S */ 4837/* File: armv5te/binopWide.S */ 4838 /* 4839 * Generic 64-bit binary operation. Provide an "instr" line that 4840 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4841 * This could be an ARM instruction or a function call. (If the result 4842 * comes back in a register other than r0, you can override "result".) 4843 * 4844 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4845 * vCC (r1). Useful for integer division and modulus. 4846 * 4847 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4848 * xor-long, add-double, sub-double, mul-double, div-double, 4849 * rem-double 4850 * 4851 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4852 */ 4853 /* binop vAA, vBB, vCC */ 4854 FETCH(r0, 1) @ r0<- CCBB 4855 mov r9, rINST, lsr #8 @ r9<- AA 4856 and r2, r0, #255 @ r2<- BB 4857 mov r3, r0, lsr #8 @ r3<- CC 4858 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4859 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4860 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4861 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4862 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4863 .if 0 4864 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4865 beq common_errDivideByZero 4866 .endif 4867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4868 4869 eor r0, r0, r2 @ optional op; may set condition codes 4870 eor r1, r1, r3 @ result<- op, r0-r3 changed 4871 GET_INST_OPCODE(ip) @ extract opcode from rINST 4872 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4873 GOTO_OPCODE(ip) @ jump to next instruction 4874 /* 14-17 instructions */ 4875 4876 4877 4878/* ------------------------------ */ 4879 .balign 64 4880.L_OP_SHL_LONG: /* 0xa3 */ 4881/* File: armv5te/OP_SHL_LONG.S */ 4882 /* 4883 * Long integer shift. This is different from the generic 32/64-bit 4884 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4885 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4886 * 6 bits of the shift distance. 4887 */ 4888 /* shl-long vAA, vBB, vCC */ 4889 FETCH(r0, 1) @ r0<- CCBB 4890 mov r9, rINST, lsr #8 @ r9<- AA 4891 and r3, r0, #255 @ r3<- BB 4892 mov r0, r0, lsr #8 @ r0<- CC 4893 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4894 GET_VREG(r2, r0) @ r2<- vCC 4895 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4896 and r2, r2, #63 @ r2<- r2 & 0x3f 4897 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4898 4899 mov r1, r1, asl r2 @ r1<- r1 << r2 4900 rsb r3, r2, #32 @ r3<- 32 - r2 4901 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4902 subs ip, r2, #32 @ ip<- r2 - 32 4903 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4904 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4905 b .LOP_SHL_LONG_finish 4906 4907/* ------------------------------ */ 4908 .balign 64 4909.L_OP_SHR_LONG: /* 0xa4 */ 4910/* File: armv5te/OP_SHR_LONG.S */ 4911 /* 4912 * Long integer shift. This is different from the generic 32/64-bit 4913 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4914 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4915 * 6 bits of the shift distance. 4916 */ 4917 /* shr-long vAA, vBB, vCC */ 4918 FETCH(r0, 1) @ r0<- CCBB 4919 mov r9, rINST, lsr #8 @ r9<- AA 4920 and r3, r0, #255 @ r3<- BB 4921 mov r0, r0, lsr #8 @ r0<- CC 4922 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4923 GET_VREG(r2, r0) @ r2<- vCC 4924 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4925 and r2, r2, #63 @ r0<- r0 & 0x3f 4926 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4927 4928 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4929 rsb r3, r2, #32 @ r3<- 32 - r2 4930 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4931 subs ip, r2, #32 @ ip<- r2 - 32 4932 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4933 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4934 b .LOP_SHR_LONG_finish 4935 4936/* ------------------------------ */ 4937 .balign 64 4938.L_OP_USHR_LONG: /* 0xa5 */ 4939/* File: armv5te/OP_USHR_LONG.S */ 4940 /* 4941 * Long integer shift. This is different from the generic 32/64-bit 4942 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4943 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4944 * 6 bits of the shift distance. 4945 */ 4946 /* ushr-long vAA, vBB, vCC */ 4947 FETCH(r0, 1) @ r0<- CCBB 4948 mov r9, rINST, lsr #8 @ r9<- AA 4949 and r3, r0, #255 @ r3<- BB 4950 mov r0, r0, lsr #8 @ r0<- CC 4951 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4952 GET_VREG(r2, r0) @ r2<- vCC 4953 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4954 and r2, r2, #63 @ r0<- r0 & 0x3f 4955 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4956 4957 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4958 rsb r3, r2, #32 @ r3<- 32 - r2 4959 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4960 subs ip, r2, #32 @ ip<- r2 - 32 4961 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4962 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4963 b .LOP_USHR_LONG_finish 4964 4965/* ------------------------------ */ 4966 .balign 64 4967.L_OP_ADD_FLOAT: /* 0xa6 */ 4968/* File: arm-vfp/OP_ADD_FLOAT.S */ 4969/* File: arm-vfp/fbinop.S */ 4970 /* 4971 * Generic 32-bit floating-point operation. Provide an "instr" line that 4972 * specifies an instruction that performs "s2 = s0 op s1". Because we 4973 * use the "softfp" ABI, this must be an instruction, not a function call. 4974 * 4975 * For: add-float, sub-float, mul-float, div-float 4976 */ 4977 /* floatop vAA, vBB, vCC */ 4978 FETCH(r0, 1) @ r0<- CCBB 4979 mov r9, rINST, lsr #8 @ r9<- AA 4980 mov r3, r0, lsr #8 @ r3<- CC 4981 and r2, r0, #255 @ r2<- BB 4982 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4983 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4984 flds s1, [r3] @ s1<- vCC 4985 flds s0, [r2] @ s0<- vBB 4986 4987 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4988 fadds s2, s0, s1 @ s2<- op 4989 GET_INST_OPCODE(ip) @ extract opcode from rINST 4990 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4991 fsts s2, [r9] @ vAA<- s2 4992 GOTO_OPCODE(ip) @ jump to next instruction 4993 4994 4995/* ------------------------------ */ 4996 .balign 64 4997.L_OP_SUB_FLOAT: /* 0xa7 */ 4998/* File: arm-vfp/OP_SUB_FLOAT.S */ 4999/* File: arm-vfp/fbinop.S */ 5000 /* 5001 * Generic 32-bit floating-point operation. Provide an "instr" line that 5002 * specifies an instruction that performs "s2 = s0 op s1". Because we 5003 * use the "softfp" ABI, this must be an instruction, not a function call. 5004 * 5005 * For: add-float, sub-float, mul-float, div-float 5006 */ 5007 /* floatop vAA, vBB, vCC */ 5008 FETCH(r0, 1) @ r0<- CCBB 5009 mov r9, rINST, lsr #8 @ r9<- AA 5010 mov r3, r0, lsr #8 @ r3<- CC 5011 and r2, r0, #255 @ r2<- BB 5012 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5013 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5014 flds s1, [r3] @ s1<- vCC 5015 flds s0, [r2] @ s0<- vBB 5016 5017 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5018 fsubs s2, s0, s1 @ s2<- op 5019 GET_INST_OPCODE(ip) @ extract opcode from rINST 5020 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5021 fsts s2, [r9] @ vAA<- s2 5022 GOTO_OPCODE(ip) @ jump to next instruction 5023 5024 5025/* ------------------------------ */ 5026 .balign 64 5027.L_OP_MUL_FLOAT: /* 0xa8 */ 5028/* File: arm-vfp/OP_MUL_FLOAT.S */ 5029/* File: arm-vfp/fbinop.S */ 5030 /* 5031 * Generic 32-bit floating-point operation. Provide an "instr" line that 5032 * specifies an instruction that performs "s2 = s0 op s1". Because we 5033 * use the "softfp" ABI, this must be an instruction, not a function call. 5034 * 5035 * For: add-float, sub-float, mul-float, div-float 5036 */ 5037 /* floatop vAA, vBB, vCC */ 5038 FETCH(r0, 1) @ r0<- CCBB 5039 mov r9, rINST, lsr #8 @ r9<- AA 5040 mov r3, r0, lsr #8 @ r3<- CC 5041 and r2, r0, #255 @ r2<- BB 5042 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5043 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5044 flds s1, [r3] @ s1<- vCC 5045 flds s0, [r2] @ s0<- vBB 5046 5047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5048 fmuls s2, s0, s1 @ s2<- op 5049 GET_INST_OPCODE(ip) @ extract opcode from rINST 5050 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5051 fsts s2, [r9] @ vAA<- s2 5052 GOTO_OPCODE(ip) @ jump to next instruction 5053 5054 5055/* ------------------------------ */ 5056 .balign 64 5057.L_OP_DIV_FLOAT: /* 0xa9 */ 5058/* File: arm-vfp/OP_DIV_FLOAT.S */ 5059/* File: arm-vfp/fbinop.S */ 5060 /* 5061 * Generic 32-bit floating-point operation. Provide an "instr" line that 5062 * specifies an instruction that performs "s2 = s0 op s1". Because we 5063 * use the "softfp" ABI, this must be an instruction, not a function call. 5064 * 5065 * For: add-float, sub-float, mul-float, div-float 5066 */ 5067 /* floatop vAA, vBB, vCC */ 5068 FETCH(r0, 1) @ r0<- CCBB 5069 mov r9, rINST, lsr #8 @ r9<- AA 5070 mov r3, r0, lsr #8 @ r3<- CC 5071 and r2, r0, #255 @ r2<- BB 5072 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5073 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5074 flds s1, [r3] @ s1<- vCC 5075 flds s0, [r2] @ s0<- vBB 5076 5077 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5078 fdivs s2, s0, s1 @ s2<- op 5079 GET_INST_OPCODE(ip) @ extract opcode from rINST 5080 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5081 fsts s2, [r9] @ vAA<- s2 5082 GOTO_OPCODE(ip) @ jump to next instruction 5083 5084 5085/* ------------------------------ */ 5086 .balign 64 5087.L_OP_REM_FLOAT: /* 0xaa */ 5088/* File: armv5te/OP_REM_FLOAT.S */ 5089/* EABI doesn't define a float remainder function, but libm does */ 5090/* File: armv5te/binop.S */ 5091 /* 5092 * Generic 32-bit binary operation. Provide an "instr" line that 5093 * specifies an instruction that performs "result = r0 op r1". 5094 * This could be an ARM instruction or a function call. (If the result 5095 * comes back in a register other than r0, you can override "result".) 5096 * 5097 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5098 * vCC (r1). Useful for integer division and modulus. Note that we 5099 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5100 * handles it correctly. 5101 * 5102 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5103 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5104 * mul-float, div-float, rem-float 5105 */ 5106 /* binop vAA, vBB, vCC */ 5107 FETCH(r0, 1) @ r0<- CCBB 5108 mov r9, rINST, lsr #8 @ r9<- AA 5109 mov r3, r0, lsr #8 @ r3<- CC 5110 and r2, r0, #255 @ r2<- BB 5111 GET_VREG(r1, r3) @ r1<- vCC 5112 GET_VREG(r0, r2) @ r0<- vBB 5113 .if 0 5114 cmp r1, #0 @ is second operand zero? 5115 beq common_errDivideByZero 5116 .endif 5117 5118 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5119 @ optional op; may set condition codes 5120 bl fmodf @ r0<- op, r0-r3 changed 5121 GET_INST_OPCODE(ip) @ extract opcode from rINST 5122 SET_VREG(r0, r9) @ vAA<- r0 5123 GOTO_OPCODE(ip) @ jump to next instruction 5124 /* 11-14 instructions */ 5125 5126 5127 5128/* ------------------------------ */ 5129 .balign 64 5130.L_OP_ADD_DOUBLE: /* 0xab */ 5131/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5132/* File: arm-vfp/fbinopWide.S */ 5133 /* 5134 * Generic 64-bit double-precision floating point binary operation. 5135 * Provide an "instr" line that specifies an instruction that performs 5136 * "d2 = d0 op d1". 5137 * 5138 * for: add-double, sub-double, mul-double, div-double 5139 */ 5140 /* doubleop vAA, vBB, vCC */ 5141 FETCH(r0, 1) @ r0<- CCBB 5142 mov r9, rINST, lsr #8 @ r9<- AA 5143 mov r3, r0, lsr #8 @ r3<- CC 5144 and r2, r0, #255 @ r2<- BB 5145 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5146 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5147 fldd d1, [r3] @ d1<- vCC 5148 fldd d0, [r2] @ d0<- vBB 5149 5150 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5151 faddd d2, d0, d1 @ s2<- op 5152 GET_INST_OPCODE(ip) @ extract opcode from rINST 5153 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5154 fstd d2, [r9] @ vAA<- d2 5155 GOTO_OPCODE(ip) @ jump to next instruction 5156 5157 5158/* ------------------------------ */ 5159 .balign 64 5160.L_OP_SUB_DOUBLE: /* 0xac */ 5161/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5162/* File: arm-vfp/fbinopWide.S */ 5163 /* 5164 * Generic 64-bit double-precision floating point binary operation. 5165 * Provide an "instr" line that specifies an instruction that performs 5166 * "d2 = d0 op d1". 5167 * 5168 * for: add-double, sub-double, mul-double, div-double 5169 */ 5170 /* doubleop vAA, vBB, vCC */ 5171 FETCH(r0, 1) @ r0<- CCBB 5172 mov r9, rINST, lsr #8 @ r9<- AA 5173 mov r3, r0, lsr #8 @ r3<- CC 5174 and r2, r0, #255 @ r2<- BB 5175 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5176 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5177 fldd d1, [r3] @ d1<- vCC 5178 fldd d0, [r2] @ d0<- vBB 5179 5180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5181 fsubd d2, d0, d1 @ s2<- op 5182 GET_INST_OPCODE(ip) @ extract opcode from rINST 5183 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5184 fstd d2, [r9] @ vAA<- d2 5185 GOTO_OPCODE(ip) @ jump to next instruction 5186 5187 5188/* ------------------------------ */ 5189 .balign 64 5190.L_OP_MUL_DOUBLE: /* 0xad */ 5191/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5192/* File: arm-vfp/fbinopWide.S */ 5193 /* 5194 * Generic 64-bit double-precision floating point binary operation. 5195 * Provide an "instr" line that specifies an instruction that performs 5196 * "d2 = d0 op d1". 5197 * 5198 * for: add-double, sub-double, mul-double, div-double 5199 */ 5200 /* doubleop vAA, vBB, vCC */ 5201 FETCH(r0, 1) @ r0<- CCBB 5202 mov r9, rINST, lsr #8 @ r9<- AA 5203 mov r3, r0, lsr #8 @ r3<- CC 5204 and r2, r0, #255 @ r2<- BB 5205 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5206 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5207 fldd d1, [r3] @ d1<- vCC 5208 fldd d0, [r2] @ d0<- vBB 5209 5210 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5211 fmuld d2, d0, d1 @ s2<- op 5212 GET_INST_OPCODE(ip) @ extract opcode from rINST 5213 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5214 fstd d2, [r9] @ vAA<- d2 5215 GOTO_OPCODE(ip) @ jump to next instruction 5216 5217 5218/* ------------------------------ */ 5219 .balign 64 5220.L_OP_DIV_DOUBLE: /* 0xae */ 5221/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5222/* File: arm-vfp/fbinopWide.S */ 5223 /* 5224 * Generic 64-bit double-precision floating point binary operation. 5225 * Provide an "instr" line that specifies an instruction that performs 5226 * "d2 = d0 op d1". 5227 * 5228 * for: add-double, sub-double, mul-double, div-double 5229 */ 5230 /* doubleop vAA, vBB, vCC */ 5231 FETCH(r0, 1) @ r0<- CCBB 5232 mov r9, rINST, lsr #8 @ r9<- AA 5233 mov r3, r0, lsr #8 @ r3<- CC 5234 and r2, r0, #255 @ r2<- BB 5235 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5236 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5237 fldd d1, [r3] @ d1<- vCC 5238 fldd d0, [r2] @ d0<- vBB 5239 5240 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5241 fdivd d2, d0, d1 @ s2<- op 5242 GET_INST_OPCODE(ip) @ extract opcode from rINST 5243 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5244 fstd d2, [r9] @ vAA<- d2 5245 GOTO_OPCODE(ip) @ jump to next instruction 5246 5247 5248/* ------------------------------ */ 5249 .balign 64 5250.L_OP_REM_DOUBLE: /* 0xaf */ 5251/* File: armv5te/OP_REM_DOUBLE.S */ 5252/* EABI doesn't define a double remainder function, but libm does */ 5253/* File: armv5te/binopWide.S */ 5254 /* 5255 * Generic 64-bit binary operation. Provide an "instr" line that 5256 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5257 * This could be an ARM instruction or a function call. (If the result 5258 * comes back in a register other than r0, you can override "result".) 5259 * 5260 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5261 * vCC (r1). Useful for integer division and modulus. 5262 * 5263 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5264 * xor-long, add-double, sub-double, mul-double, div-double, 5265 * rem-double 5266 * 5267 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5268 */ 5269 /* binop vAA, vBB, vCC */ 5270 FETCH(r0, 1) @ r0<- CCBB 5271 mov r9, rINST, lsr #8 @ r9<- AA 5272 and r2, r0, #255 @ r2<- BB 5273 mov r3, r0, lsr #8 @ r3<- CC 5274 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5275 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5276 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5277 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5278 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5279 .if 0 5280 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5281 beq common_errDivideByZero 5282 .endif 5283 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5284 5285 @ optional op; may set condition codes 5286 bl fmod @ result<- op, r0-r3 changed 5287 GET_INST_OPCODE(ip) @ extract opcode from rINST 5288 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5289 GOTO_OPCODE(ip) @ jump to next instruction 5290 /* 14-17 instructions */ 5291 5292 5293 5294/* ------------------------------ */ 5295 .balign 64 5296.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5297/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5298/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5315 ubfx r9, rINST, #8, #4 @ r9<- A 5316 GET_VREG(r1, r3) @ r1<- vB 5317 GET_VREG(r0, r9) @ r0<- vA 5318 .if 0 5319 cmp r1, #0 @ is second operand zero? 5320 beq common_errDivideByZero 5321 .endif 5322 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5323 5324 @ optional op; may set condition codes 5325 add r0, r0, r1 @ r0<- op, r0-r3 changed 5326 GET_INST_OPCODE(ip) @ extract opcode from rINST 5327 SET_VREG(r0, r9) @ vAA<- r0 5328 GOTO_OPCODE(ip) @ jump to next instruction 5329 /* 10-13 instructions */ 5330 5331 5332 5333/* ------------------------------ */ 5334 .balign 64 5335.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5336/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5337/* File: armv6t2/binop2addr.S */ 5338 /* 5339 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5340 * that specifies an instruction that performs "result = r0 op r1". 5341 * This could be an ARM instruction or a function call. (If the result 5342 * comes back in a register other than r0, you can override "result".) 5343 * 5344 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5345 * vCC (r1). Useful for integer division and modulus. 5346 * 5347 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5348 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5349 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5350 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5351 */ 5352 /* binop/2addr vA, vB */ 5353 mov r3, rINST, lsr #12 @ r3<- B 5354 ubfx r9, rINST, #8, #4 @ r9<- A 5355 GET_VREG(r1, r3) @ r1<- vB 5356 GET_VREG(r0, r9) @ r0<- vA 5357 .if 0 5358 cmp r1, #0 @ is second operand zero? 5359 beq common_errDivideByZero 5360 .endif 5361 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5362 5363 @ optional op; may set condition codes 5364 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5365 GET_INST_OPCODE(ip) @ extract opcode from rINST 5366 SET_VREG(r0, r9) @ vAA<- r0 5367 GOTO_OPCODE(ip) @ jump to next instruction 5368 /* 10-13 instructions */ 5369 5370 5371 5372/* ------------------------------ */ 5373 .balign 64 5374.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5375/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5376/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5377/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5394 ubfx r9, rINST, #8, #4 @ r9<- A 5395 GET_VREG(r1, r3) @ r1<- vB 5396 GET_VREG(r0, r9) @ r0<- vA 5397 .if 0 5398 cmp r1, #0 @ is second operand zero? 5399 beq common_errDivideByZero 5400 .endif 5401 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5402 5403 @ optional op; may set condition codes 5404 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5405 GET_INST_OPCODE(ip) @ extract opcode from rINST 5406 SET_VREG(r0, r9) @ vAA<- r0 5407 GOTO_OPCODE(ip) @ jump to next instruction 5408 /* 10-13 instructions */ 5409 5410 5411 5412/* ------------------------------ */ 5413 .balign 64 5414.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5415/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5416/* File: armv6t2/binop2addr.S */ 5417 /* 5418 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5419 * that specifies an instruction that performs "result = r0 op r1". 5420 * This could be an ARM instruction or a function call. (If the result 5421 * comes back in a register other than r0, you can override "result".) 5422 * 5423 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5424 * vCC (r1). Useful for integer division and modulus. 5425 * 5426 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5427 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5428 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5429 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5430 */ 5431 /* binop/2addr vA, vB */ 5432 mov r3, rINST, lsr #12 @ r3<- B 5433 ubfx r9, rINST, #8, #4 @ r9<- A 5434 GET_VREG(r1, r3) @ r1<- vB 5435 GET_VREG(r0, r9) @ r0<- vA 5436 .if 1 5437 cmp r1, #0 @ is second operand zero? 5438 beq common_errDivideByZero 5439 .endif 5440 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5441 5442 @ optional op; may set condition codes 5443 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5444 GET_INST_OPCODE(ip) @ extract opcode from rINST 5445 SET_VREG(r0, r9) @ vAA<- r0 5446 GOTO_OPCODE(ip) @ jump to next instruction 5447 /* 10-13 instructions */ 5448 5449 5450 5451/* ------------------------------ */ 5452 .balign 64 5453.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5454/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5455/* idivmod returns quotient in r0 and remainder in r1 */ 5456/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5473 ubfx r9, rINST, #8, #4 @ r9<- A 5474 GET_VREG(r1, r3) @ r1<- vB 5475 GET_VREG(r0, r9) @ r0<- vA 5476 .if 1 5477 cmp r1, #0 @ is second operand zero? 5478 beq common_errDivideByZero 5479 .endif 5480 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5481 5482 @ optional op; may set condition codes 5483 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5484 GET_INST_OPCODE(ip) @ extract opcode from rINST 5485 SET_VREG(r1, r9) @ vAA<- r1 5486 GOTO_OPCODE(ip) @ jump to next instruction 5487 /* 10-13 instructions */ 5488 5489 5490 5491/* ------------------------------ */ 5492 .balign 64 5493.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5494/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5495/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5512 ubfx r9, rINST, #8, #4 @ r9<- A 5513 GET_VREG(r1, r3) @ r1<- vB 5514 GET_VREG(r0, r9) @ r0<- vA 5515 .if 0 5516 cmp r1, #0 @ is second operand zero? 5517 beq common_errDivideByZero 5518 .endif 5519 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5520 5521 @ optional op; may set condition codes 5522 and r0, r0, r1 @ r0<- op, r0-r3 changed 5523 GET_INST_OPCODE(ip) @ extract opcode from rINST 5524 SET_VREG(r0, r9) @ vAA<- r0 5525 GOTO_OPCODE(ip) @ jump to next instruction 5526 /* 10-13 instructions */ 5527 5528 5529 5530/* ------------------------------ */ 5531 .balign 64 5532.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5533/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5534/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5551 ubfx r9, rINST, #8, #4 @ r9<- A 5552 GET_VREG(r1, r3) @ r1<- vB 5553 GET_VREG(r0, r9) @ r0<- vA 5554 .if 0 5555 cmp r1, #0 @ is second operand zero? 5556 beq common_errDivideByZero 5557 .endif 5558 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5559 5560 @ optional op; may set condition codes 5561 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5562 GET_INST_OPCODE(ip) @ extract opcode from rINST 5563 SET_VREG(r0, r9) @ vAA<- r0 5564 GOTO_OPCODE(ip) @ jump to next instruction 5565 /* 10-13 instructions */ 5566 5567 5568 5569/* ------------------------------ */ 5570 .balign 64 5571.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5572/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5573/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5590 ubfx r9, rINST, #8, #4 @ r9<- A 5591 GET_VREG(r1, r3) @ r1<- vB 5592 GET_VREG(r0, r9) @ r0<- vA 5593 .if 0 5594 cmp r1, #0 @ is second operand zero? 5595 beq common_errDivideByZero 5596 .endif 5597 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5598 5599 @ optional op; may set condition codes 5600 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5601 GET_INST_OPCODE(ip) @ extract opcode from rINST 5602 SET_VREG(r0, r9) @ vAA<- r0 5603 GOTO_OPCODE(ip) @ jump to next instruction 5604 /* 10-13 instructions */ 5605 5606 5607 5608/* ------------------------------ */ 5609 .balign 64 5610.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5611/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5612/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5629 ubfx r9, rINST, #8, #4 @ r9<- A 5630 GET_VREG(r1, r3) @ r1<- vB 5631 GET_VREG(r0, r9) @ r0<- vA 5632 .if 0 5633 cmp r1, #0 @ is second operand zero? 5634 beq common_errDivideByZero 5635 .endif 5636 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5637 5638 and r1, r1, #31 @ optional op; may set condition codes 5639 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5640 GET_INST_OPCODE(ip) @ extract opcode from rINST 5641 SET_VREG(r0, r9) @ vAA<- r0 5642 GOTO_OPCODE(ip) @ jump to next instruction 5643 /* 10-13 instructions */ 5644 5645 5646 5647/* ------------------------------ */ 5648 .balign 64 5649.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5650/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5651/* File: armv6t2/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 r3, rINST, lsr #12 @ r3<- B 5668 ubfx r9, rINST, #8, #4 @ r9<- A 5669 GET_VREG(r1, r3) @ r1<- vB 5670 GET_VREG(r0, r9) @ r0<- vA 5671 .if 0 5672 cmp r1, #0 @ is second operand zero? 5673 beq common_errDivideByZero 5674 .endif 5675 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5676 5677 and r1, r1, #31 @ optional op; may set condition codes 5678 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5679 GET_INST_OPCODE(ip) @ extract opcode from rINST 5680 SET_VREG(r0, r9) @ vAA<- r0 5681 GOTO_OPCODE(ip) @ jump to next instruction 5682 /* 10-13 instructions */ 5683 5684 5685 5686/* ------------------------------ */ 5687 .balign 64 5688.L_OP_USHR_INT_2ADDR: /* 0xba */ 5689/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5690/* File: armv6t2/binop2addr.S */ 5691 /* 5692 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5693 * that specifies an instruction that performs "result = r0 op r1". 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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5701 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5702 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5703 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5704 */ 5705 /* binop/2addr vA, vB */ 5706 mov r3, rINST, lsr #12 @ r3<- B 5707 ubfx r9, rINST, #8, #4 @ r9<- A 5708 GET_VREG(r1, r3) @ r1<- vB 5709 GET_VREG(r0, r9) @ r0<- vA 5710 .if 0 5711 cmp r1, #0 @ is second operand zero? 5712 beq common_errDivideByZero 5713 .endif 5714 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5715 5716 and r1, r1, #31 @ optional op; may set condition codes 5717 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5718 GET_INST_OPCODE(ip) @ extract opcode from rINST 5719 SET_VREG(r0, r9) @ vAA<- r0 5720 GOTO_OPCODE(ip) @ jump to next instruction 5721 /* 10-13 instructions */ 5722 5723 5724 5725/* ------------------------------ */ 5726 .balign 64 5727.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5728/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5729/* File: armv6t2/binopWide2addr.S */ 5730 /* 5731 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5732 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5733 * This could be an ARM instruction or a function call. (If the result 5734 * comes back in a register other than r0, you can override "result".) 5735 * 5736 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5737 * vCC (r1). Useful for integer division and modulus. 5738 * 5739 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5740 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5741 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5742 * rem-double/2addr 5743 */ 5744 /* binop/2addr vA, vB */ 5745 mov r1, rINST, lsr #12 @ r1<- B 5746 ubfx r9, rINST, #8, #4 @ r9<- A 5747 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5748 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5749 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5750 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5751 .if 0 5752 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5753 beq common_errDivideByZero 5754 .endif 5755 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5756 5757 adds r0, r0, r2 @ optional op; may set condition codes 5758 adc r1, r1, r3 @ result<- op, r0-r3 changed 5759 GET_INST_OPCODE(ip) @ extract opcode from rINST 5760 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5761 GOTO_OPCODE(ip) @ jump to next instruction 5762 /* 12-15 instructions */ 5763 5764 5765 5766/* ------------------------------ */ 5767 .balign 64 5768.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5769/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5770/* File: armv6t2/binopWide2addr.S */ 5771 /* 5772 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5773 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5774 * This could be an ARM instruction or a function call. (If the result 5775 * comes back in a register other than r0, you can override "result".) 5776 * 5777 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5778 * vCC (r1). Useful for integer division and modulus. 5779 * 5780 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5781 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5782 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5783 * rem-double/2addr 5784 */ 5785 /* binop/2addr vA, vB */ 5786 mov r1, rINST, lsr #12 @ r1<- B 5787 ubfx r9, rINST, #8, #4 @ r9<- A 5788 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5789 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5790 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5791 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5792 .if 0 5793 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5794 beq common_errDivideByZero 5795 .endif 5796 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5797 5798 subs r0, r0, r2 @ optional op; may set condition codes 5799 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5800 GET_INST_OPCODE(ip) @ extract opcode from rINST 5801 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5802 GOTO_OPCODE(ip) @ jump to next instruction 5803 /* 12-15 instructions */ 5804 5805 5806 5807/* ------------------------------ */ 5808 .balign 64 5809.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5810/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5811 /* 5812 * Signed 64-bit integer multiply, "/2addr" version. 5813 * 5814 * See OP_MUL_LONG for an explanation. 5815 * 5816 * We get a little tight on registers, so to avoid looking up &fp[A] 5817 * again we stuff it into rINST. 5818 */ 5819 /* mul-long/2addr vA, vB */ 5820 mov r1, rINST, lsr #12 @ r1<- B 5821 ubfx r9, rINST, #8, #4 @ r9<- A 5822 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5823 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5824 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5825 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5826 mul ip, r2, r1 @ ip<- ZxW 5827 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5828 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5829 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5830 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5831 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5832 GET_INST_OPCODE(ip) @ extract opcode from rINST 5833 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5834 GOTO_OPCODE(ip) @ jump to next instruction 5835 5836 5837/* ------------------------------ */ 5838 .balign 64 5839.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5840/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5841/* File: armv6t2/binopWide2addr.S */ 5842 /* 5843 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5844 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5845 * This could be an ARM instruction or a function call. (If the result 5846 * comes back in a register other than r0, you can override "result".) 5847 * 5848 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5849 * vCC (r1). Useful for integer division and modulus. 5850 * 5851 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5852 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5853 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5854 * rem-double/2addr 5855 */ 5856 /* binop/2addr vA, vB */ 5857 mov r1, rINST, lsr #12 @ r1<- B 5858 ubfx r9, rINST, #8, #4 @ r9<- A 5859 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5860 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5861 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5862 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5863 .if 1 5864 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5865 beq common_errDivideByZero 5866 .endif 5867 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5868 5869 @ optional op; may set condition codes 5870 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5871 GET_INST_OPCODE(ip) @ extract opcode from rINST 5872 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5873 GOTO_OPCODE(ip) @ jump to next instruction 5874 /* 12-15 instructions */ 5875 5876 5877 5878/* ------------------------------ */ 5879 .balign 64 5880.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5881/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5882/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5883/* File: armv6t2/binopWide2addr.S */ 5884 /* 5885 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5886 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5887 * This could be an ARM instruction or a function call. (If the result 5888 * comes back in a register other than r0, you can override "result".) 5889 * 5890 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5891 * vCC (r1). Useful for integer division and modulus. 5892 * 5893 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5894 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5895 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5896 * rem-double/2addr 5897 */ 5898 /* binop/2addr vA, vB */ 5899 mov r1, rINST, lsr #12 @ r1<- B 5900 ubfx r9, rINST, #8, #4 @ r9<- A 5901 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5902 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5903 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5904 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5905 .if 1 5906 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5907 beq common_errDivideByZero 5908 .endif 5909 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5910 5911 @ optional op; may set condition codes 5912 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5913 GET_INST_OPCODE(ip) @ extract opcode from rINST 5914 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5915 GOTO_OPCODE(ip) @ jump to next instruction 5916 /* 12-15 instructions */ 5917 5918 5919 5920/* ------------------------------ */ 5921 .balign 64 5922.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5923/* File: armv6t2/OP_AND_LONG_2ADDR.S */ 5924/* File: armv6t2/binopWide2addr.S */ 5925 /* 5926 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5927 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5928 * This could be an ARM instruction or a function call. (If the result 5929 * comes back in a register other than r0, you can override "result".) 5930 * 5931 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5932 * vCC (r1). Useful for integer division and modulus. 5933 * 5934 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5935 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5936 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5937 * rem-double/2addr 5938 */ 5939 /* binop/2addr vA, vB */ 5940 mov r1, rINST, lsr #12 @ r1<- B 5941 ubfx r9, rINST, #8, #4 @ r9<- A 5942 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5943 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5944 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5945 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5946 .if 0 5947 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5948 beq common_errDivideByZero 5949 .endif 5950 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5951 5952 and r0, r0, r2 @ optional op; may set condition codes 5953 and r1, r1, r3 @ result<- op, r0-r3 changed 5954 GET_INST_OPCODE(ip) @ extract opcode from rINST 5955 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5956 GOTO_OPCODE(ip) @ jump to next instruction 5957 /* 12-15 instructions */ 5958 5959 5960 5961/* ------------------------------ */ 5962 .balign 64 5963.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5964/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5965/* File: armv6t2/binopWide2addr.S */ 5966 /* 5967 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5968 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5969 * This could be an ARM instruction or a function call. (If the result 5970 * comes back in a register other than r0, you can override "result".) 5971 * 5972 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5973 * vCC (r1). Useful for integer division and modulus. 5974 * 5975 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5976 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5977 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5978 * rem-double/2addr 5979 */ 5980 /* binop/2addr vA, vB */ 5981 mov r1, rINST, lsr #12 @ r1<- B 5982 ubfx r9, rINST, #8, #4 @ r9<- A 5983 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5984 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5985 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5986 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5987 .if 0 5988 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5989 beq common_errDivideByZero 5990 .endif 5991 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5992 5993 orr r0, r0, r2 @ optional op; may set condition codes 5994 orr r1, r1, r3 @ result<- op, r0-r3 changed 5995 GET_INST_OPCODE(ip) @ extract opcode from rINST 5996 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5997 GOTO_OPCODE(ip) @ jump to next instruction 5998 /* 12-15 instructions */ 5999 6000 6001 6002/* ------------------------------ */ 6003 .balign 64 6004.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6005/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 6006/* File: armv6t2/binopWide2addr.S */ 6007 /* 6008 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6009 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6010 * This could be an ARM instruction or a function call. (If the result 6011 * comes back in a register other than r0, you can override "result".) 6012 * 6013 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6014 * vCC (r1). Useful for integer division and modulus. 6015 * 6016 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6017 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6018 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6019 * rem-double/2addr 6020 */ 6021 /* binop/2addr vA, vB */ 6022 mov r1, rINST, lsr #12 @ r1<- B 6023 ubfx r9, rINST, #8, #4 @ r9<- A 6024 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6025 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6026 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6027 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6028 .if 0 6029 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6030 beq common_errDivideByZero 6031 .endif 6032 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6033 6034 eor r0, r0, r2 @ optional op; may set condition codes 6035 eor r1, r1, r3 @ result<- op, r0-r3 changed 6036 GET_INST_OPCODE(ip) @ extract opcode from rINST 6037 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6038 GOTO_OPCODE(ip) @ jump to next instruction 6039 /* 12-15 instructions */ 6040 6041 6042 6043/* ------------------------------ */ 6044 .balign 64 6045.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6046/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 6047 /* 6048 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6049 * 32-bit shift distance. 6050 */ 6051 /* shl-long/2addr vA, vB */ 6052 mov r3, rINST, lsr #12 @ r3<- B 6053 ubfx r9, rINST, #8, #4 @ r9<- A 6054 GET_VREG(r2, r3) @ r2<- vB 6055 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6056 and r2, r2, #63 @ r2<- r2 & 0x3f 6057 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6058 6059 mov r1, r1, asl r2 @ r1<- r1 << r2 6060 rsb r3, r2, #32 @ r3<- 32 - r2 6061 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6062 subs ip, r2, #32 @ ip<- r2 - 32 6063 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6064 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6065 mov r0, r0, asl r2 @ r0<- r0 << r2 6066 b .LOP_SHL_LONG_2ADDR_finish 6067 6068/* ------------------------------ */ 6069 .balign 64 6070.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6071/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 6072 /* 6073 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6074 * 32-bit shift distance. 6075 */ 6076 /* shr-long/2addr vA, vB */ 6077 mov r3, rINST, lsr #12 @ r3<- B 6078 ubfx r9, rINST, #8, #4 @ r9<- A 6079 GET_VREG(r2, r3) @ r2<- vB 6080 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6081 and r2, r2, #63 @ r2<- r2 & 0x3f 6082 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6083 6084 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6085 rsb r3, r2, #32 @ r3<- 32 - r2 6086 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6087 subs ip, r2, #32 @ ip<- r2 - 32 6088 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6089 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6090 mov r1, r1, asr r2 @ r1<- r1 >> r2 6091 b .LOP_SHR_LONG_2ADDR_finish 6092 6093/* ------------------------------ */ 6094 .balign 64 6095.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6096/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6097 /* 6098 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6099 * 32-bit shift distance. 6100 */ 6101 /* ushr-long/2addr vA, vB */ 6102 mov r3, rINST, lsr #12 @ r3<- B 6103 ubfx r9, rINST, #8, #4 @ r9<- A 6104 GET_VREG(r2, r3) @ r2<- vB 6105 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6106 and r2, r2, #63 @ r2<- r2 & 0x3f 6107 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6108 6109 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6110 rsb r3, r2, #32 @ r3<- 32 - r2 6111 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6112 subs ip, r2, #32 @ ip<- r2 - 32 6113 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6114 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6115 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6116 b .LOP_USHR_LONG_2ADDR_finish 6117 6118/* ------------------------------ */ 6119 .balign 64 6120.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6121/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6122/* File: arm-vfp/fbinop2addr.S */ 6123 /* 6124 * Generic 32-bit floating point "/2addr" binary operation. Provide 6125 * an "instr" line that specifies an instruction that performs 6126 * "s2 = s0 op s1". 6127 * 6128 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6129 */ 6130 /* binop/2addr vA, vB */ 6131 mov r3, rINST, lsr #12 @ r3<- B 6132 mov r9, rINST, lsr #8 @ r9<- A+ 6133 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6134 and r9, r9, #15 @ r9<- A 6135 flds s1, [r3] @ s1<- vB 6136 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6137 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6138 flds s0, [r9] @ s0<- vA 6139 6140 fadds s2, s0, s1 @ s2<- op 6141 GET_INST_OPCODE(ip) @ extract opcode from rINST 6142 fsts s2, [r9] @ vAA<- s2 6143 GOTO_OPCODE(ip) @ jump to next instruction 6144 6145 6146/* ------------------------------ */ 6147 .balign 64 6148.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6149/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6150/* File: arm-vfp/fbinop2addr.S */ 6151 /* 6152 * Generic 32-bit floating point "/2addr" binary operation. Provide 6153 * an "instr" line that specifies an instruction that performs 6154 * "s2 = s0 op s1". 6155 * 6156 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6157 */ 6158 /* binop/2addr vA, vB */ 6159 mov r3, rINST, lsr #12 @ r3<- B 6160 mov r9, rINST, lsr #8 @ r9<- A+ 6161 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6162 and r9, r9, #15 @ r9<- A 6163 flds s1, [r3] @ s1<- vB 6164 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6165 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6166 flds s0, [r9] @ s0<- vA 6167 6168 fsubs s2, s0, s1 @ s2<- op 6169 GET_INST_OPCODE(ip) @ extract opcode from rINST 6170 fsts s2, [r9] @ vAA<- s2 6171 GOTO_OPCODE(ip) @ jump to next instruction 6172 6173 6174/* ------------------------------ */ 6175 .balign 64 6176.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6177/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6178/* File: arm-vfp/fbinop2addr.S */ 6179 /* 6180 * Generic 32-bit floating point "/2addr" binary operation. Provide 6181 * an "instr" line that specifies an instruction that performs 6182 * "s2 = s0 op s1". 6183 * 6184 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6185 */ 6186 /* binop/2addr vA, vB */ 6187 mov r3, rINST, lsr #12 @ r3<- B 6188 mov r9, rINST, lsr #8 @ r9<- A+ 6189 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6190 and r9, r9, #15 @ r9<- A 6191 flds s1, [r3] @ s1<- vB 6192 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6193 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6194 flds s0, [r9] @ s0<- vA 6195 6196 fmuls s2, s0, s1 @ s2<- op 6197 GET_INST_OPCODE(ip) @ extract opcode from rINST 6198 fsts s2, [r9] @ vAA<- s2 6199 GOTO_OPCODE(ip) @ jump to next instruction 6200 6201 6202/* ------------------------------ */ 6203 .balign 64 6204.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6205/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6206/* File: arm-vfp/fbinop2addr.S */ 6207 /* 6208 * Generic 32-bit floating point "/2addr" binary operation. Provide 6209 * an "instr" line that specifies an instruction that performs 6210 * "s2 = s0 op s1". 6211 * 6212 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6213 */ 6214 /* binop/2addr vA, vB */ 6215 mov r3, rINST, lsr #12 @ r3<- B 6216 mov r9, rINST, lsr #8 @ r9<- A+ 6217 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6218 and r9, r9, #15 @ r9<- A 6219 flds s1, [r3] @ s1<- vB 6220 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6221 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6222 flds s0, [r9] @ s0<- vA 6223 6224 fdivs s2, s0, s1 @ s2<- op 6225 GET_INST_OPCODE(ip) @ extract opcode from rINST 6226 fsts s2, [r9] @ vAA<- s2 6227 GOTO_OPCODE(ip) @ jump to next instruction 6228 6229 6230/* ------------------------------ */ 6231 .balign 64 6232.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6233/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6234/* EABI doesn't define a float remainder function, but libm does */ 6235/* File: armv6t2/binop2addr.S */ 6236 /* 6237 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6238 * that specifies an instruction that performs "result = r0 op r1". 6239 * This could be an ARM instruction or a function call. (If the result 6240 * comes back in a register other than r0, you can override "result".) 6241 * 6242 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6243 * vCC (r1). Useful for integer division and modulus. 6244 * 6245 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6246 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6247 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6248 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6249 */ 6250 /* binop/2addr vA, vB */ 6251 mov r3, rINST, lsr #12 @ r3<- B 6252 ubfx r9, rINST, #8, #4 @ r9<- A 6253 GET_VREG(r1, r3) @ r1<- vB 6254 GET_VREG(r0, r9) @ r0<- vA 6255 .if 0 6256 cmp r1, #0 @ is second operand zero? 6257 beq common_errDivideByZero 6258 .endif 6259 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6260 6261 @ optional op; may set condition codes 6262 bl fmodf @ r0<- op, r0-r3 changed 6263 GET_INST_OPCODE(ip) @ extract opcode from rINST 6264 SET_VREG(r0, r9) @ vAA<- r0 6265 GOTO_OPCODE(ip) @ jump to next instruction 6266 /* 10-13 instructions */ 6267 6268 6269 6270/* ------------------------------ */ 6271 .balign 64 6272.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6273/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6274/* File: arm-vfp/fbinopWide2addr.S */ 6275 /* 6276 * Generic 64-bit floating point "/2addr" binary operation. Provide 6277 * an "instr" line that specifies an instruction that performs 6278 * "d2 = d0 op d1". 6279 * 6280 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6281 * div-double/2addr 6282 */ 6283 /* binop/2addr vA, vB */ 6284 mov r3, rINST, lsr #12 @ r3<- B 6285 mov r9, rINST, lsr #8 @ r9<- A+ 6286 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6287 and r9, r9, #15 @ r9<- A 6288 fldd d1, [r3] @ d1<- vB 6289 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6290 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6291 fldd d0, [r9] @ d0<- vA 6292 6293 faddd d2, d0, d1 @ d2<- op 6294 GET_INST_OPCODE(ip) @ extract opcode from rINST 6295 fstd d2, [r9] @ vAA<- d2 6296 GOTO_OPCODE(ip) @ jump to next instruction 6297 6298 6299/* ------------------------------ */ 6300 .balign 64 6301.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6302/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6303/* File: arm-vfp/fbinopWide2addr.S */ 6304 /* 6305 * Generic 64-bit floating point "/2addr" binary operation. Provide 6306 * an "instr" line that specifies an instruction that performs 6307 * "d2 = d0 op d1". 6308 * 6309 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6310 * div-double/2addr 6311 */ 6312 /* binop/2addr vA, vB */ 6313 mov r3, rINST, lsr #12 @ r3<- B 6314 mov r9, rINST, lsr #8 @ r9<- A+ 6315 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6316 and r9, r9, #15 @ r9<- A 6317 fldd d1, [r3] @ d1<- vB 6318 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6319 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6320 fldd d0, [r9] @ d0<- vA 6321 6322 fsubd d2, d0, d1 @ d2<- op 6323 GET_INST_OPCODE(ip) @ extract opcode from rINST 6324 fstd d2, [r9] @ vAA<- d2 6325 GOTO_OPCODE(ip) @ jump to next instruction 6326 6327 6328/* ------------------------------ */ 6329 .balign 64 6330.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6331/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6332/* File: arm-vfp/fbinopWide2addr.S */ 6333 /* 6334 * Generic 64-bit floating point "/2addr" binary operation. Provide 6335 * an "instr" line that specifies an instruction that performs 6336 * "d2 = d0 op d1". 6337 * 6338 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6339 * div-double/2addr 6340 */ 6341 /* binop/2addr vA, vB */ 6342 mov r3, rINST, lsr #12 @ r3<- B 6343 mov r9, rINST, lsr #8 @ r9<- A+ 6344 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6345 and r9, r9, #15 @ r9<- A 6346 fldd d1, [r3] @ d1<- vB 6347 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6348 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6349 fldd d0, [r9] @ d0<- vA 6350 6351 fmuld d2, d0, d1 @ d2<- op 6352 GET_INST_OPCODE(ip) @ extract opcode from rINST 6353 fstd d2, [r9] @ vAA<- d2 6354 GOTO_OPCODE(ip) @ jump to next instruction 6355 6356 6357/* ------------------------------ */ 6358 .balign 64 6359.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6360/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6361/* File: arm-vfp/fbinopWide2addr.S */ 6362 /* 6363 * Generic 64-bit floating point "/2addr" binary operation. Provide 6364 * an "instr" line that specifies an instruction that performs 6365 * "d2 = d0 op d1". 6366 * 6367 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6368 * div-double/2addr 6369 */ 6370 /* binop/2addr vA, vB */ 6371 mov r3, rINST, lsr #12 @ r3<- B 6372 mov r9, rINST, lsr #8 @ r9<- A+ 6373 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6374 and r9, r9, #15 @ r9<- A 6375 fldd d1, [r3] @ d1<- vB 6376 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6377 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6378 fldd d0, [r9] @ d0<- vA 6379 6380 fdivd d2, d0, d1 @ d2<- op 6381 GET_INST_OPCODE(ip) @ extract opcode from rINST 6382 fstd d2, [r9] @ vAA<- d2 6383 GOTO_OPCODE(ip) @ jump to next instruction 6384 6385 6386/* ------------------------------ */ 6387 .balign 64 6388.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6389/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6390/* EABI doesn't define a double remainder function, but libm does */ 6391/* File: armv6t2/binopWide2addr.S */ 6392 /* 6393 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6394 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6395 * This could be an ARM instruction or a function call. (If the result 6396 * comes back in a register other than r0, you can override "result".) 6397 * 6398 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6399 * vCC (r1). Useful for integer division and modulus. 6400 * 6401 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6402 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6403 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6404 * rem-double/2addr 6405 */ 6406 /* binop/2addr vA, vB */ 6407 mov r1, rINST, lsr #12 @ r1<- B 6408 ubfx r9, rINST, #8, #4 @ r9<- A 6409 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6410 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6411 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6412 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6413 .if 0 6414 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6415 beq common_errDivideByZero 6416 .endif 6417 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6418 6419 @ optional op; may set condition codes 6420 bl fmod @ result<- op, r0-r3 changed 6421 GET_INST_OPCODE(ip) @ extract opcode from rINST 6422 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6423 GOTO_OPCODE(ip) @ jump to next instruction 6424 /* 12-15 instructions */ 6425 6426 6427 6428/* ------------------------------ */ 6429 .balign 64 6430.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6431/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6432/* File: armv6t2/binopLit16.S */ 6433 /* 6434 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6435 * that specifies an instruction that performs "result = r0 op r1". 6436 * This could be an ARM instruction or a function call. (If the result 6437 * comes back in a register other than r0, you can override "result".) 6438 * 6439 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6440 * vCC (r1). Useful for integer division and modulus. 6441 * 6442 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6443 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6444 */ 6445 /* binop/lit16 vA, vB, #+CCCC */ 6446 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6447 mov r2, rINST, lsr #12 @ r2<- B 6448 ubfx r9, rINST, #8, #4 @ r9<- A 6449 GET_VREG(r0, r2) @ r0<- vB 6450 .if 0 6451 cmp r1, #0 @ is second operand zero? 6452 beq common_errDivideByZero 6453 .endif 6454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6455 6456 add r0, r0, r1 @ r0<- op, r0-r3 changed 6457 GET_INST_OPCODE(ip) @ extract opcode from rINST 6458 SET_VREG(r0, r9) @ vAA<- r0 6459 GOTO_OPCODE(ip) @ jump to next instruction 6460 /* 10-13 instructions */ 6461 6462 6463 6464/* ------------------------------ */ 6465 .balign 64 6466.L_OP_RSUB_INT: /* 0xd1 */ 6467/* File: armv6t2/OP_RSUB_INT.S */ 6468/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6469/* File: armv6t2/binopLit16.S */ 6470 /* 6471 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6472 * that specifies an instruction that performs "result = r0 op r1". 6473 * This could be an ARM instruction or a function call. (If the result 6474 * comes back in a register other than r0, you can override "result".) 6475 * 6476 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6477 * vCC (r1). Useful for integer division and modulus. 6478 * 6479 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6480 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6481 */ 6482 /* binop/lit16 vA, vB, #+CCCC */ 6483 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6484 mov r2, rINST, lsr #12 @ r2<- B 6485 ubfx r9, rINST, #8, #4 @ r9<- A 6486 GET_VREG(r0, r2) @ r0<- vB 6487 .if 0 6488 cmp r1, #0 @ is second operand zero? 6489 beq common_errDivideByZero 6490 .endif 6491 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6492 6493 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6494 GET_INST_OPCODE(ip) @ extract opcode from rINST 6495 SET_VREG(r0, r9) @ vAA<- r0 6496 GOTO_OPCODE(ip) @ jump to next instruction 6497 /* 10-13 instructions */ 6498 6499 6500 6501/* ------------------------------ */ 6502 .balign 64 6503.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6504/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6505/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6506/* File: armv6t2/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 ubfx r9, rINST, #8, #4 @ r9<- A 6523 GET_VREG(r0, r2) @ r0<- vB 6524 .if 0 6525 cmp r1, #0 @ is second operand zero? 6526 beq common_errDivideByZero 6527 .endif 6528 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6529 6530 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6531 GET_INST_OPCODE(ip) @ extract opcode from rINST 6532 SET_VREG(r0, r9) @ vAA<- r0 6533 GOTO_OPCODE(ip) @ jump to next instruction 6534 /* 10-13 instructions */ 6535 6536 6537 6538/* ------------------------------ */ 6539 .balign 64 6540.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6541/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6542/* File: armv6t2/binopLit16.S */ 6543 /* 6544 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6545 * that specifies an instruction that performs "result = r0 op r1". 6546 * This could be an ARM instruction or a function call. (If the result 6547 * comes back in a register other than r0, you can override "result".) 6548 * 6549 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6550 * vCC (r1). Useful for integer division and modulus. 6551 * 6552 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6553 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6554 */ 6555 /* binop/lit16 vA, vB, #+CCCC */ 6556 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6557 mov r2, rINST, lsr #12 @ r2<- B 6558 ubfx r9, rINST, #8, #4 @ r9<- A 6559 GET_VREG(r0, r2) @ r0<- vB 6560 .if 1 6561 cmp r1, #0 @ is second operand zero? 6562 beq common_errDivideByZero 6563 .endif 6564 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6565 6566 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6567 GET_INST_OPCODE(ip) @ extract opcode from rINST 6568 SET_VREG(r0, r9) @ vAA<- r0 6569 GOTO_OPCODE(ip) @ jump to next instruction 6570 /* 10-13 instructions */ 6571 6572 6573 6574/* ------------------------------ */ 6575 .balign 64 6576.L_OP_REM_INT_LIT16: /* 0xd4 */ 6577/* File: armv6t2/OP_REM_INT_LIT16.S */ 6578/* idivmod returns quotient in r0 and remainder in r1 */ 6579/* File: armv6t2/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 ubfx r9, rINST, #8, #4 @ r9<- A 6596 GET_VREG(r0, r2) @ r0<- vB 6597 .if 1 6598 cmp r1, #0 @ is second operand zero? 6599 beq common_errDivideByZero 6600 .endif 6601 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6602 6603 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6604 GET_INST_OPCODE(ip) @ extract opcode from rINST 6605 SET_VREG(r1, r9) @ vAA<- r1 6606 GOTO_OPCODE(ip) @ jump to next instruction 6607 /* 10-13 instructions */ 6608 6609 6610 6611/* ------------------------------ */ 6612 .balign 64 6613.L_OP_AND_INT_LIT16: /* 0xd5 */ 6614/* File: armv6t2/OP_AND_INT_LIT16.S */ 6615/* File: armv6t2/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 ubfx r9, rINST, #8, #4 @ r9<- A 6632 GET_VREG(r0, r2) @ r0<- vB 6633 .if 0 6634 cmp r1, #0 @ is second operand zero? 6635 beq common_errDivideByZero 6636 .endif 6637 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6638 6639 and r0, r0, r1 @ r0<- op, r0-r3 changed 6640 GET_INST_OPCODE(ip) @ extract opcode from rINST 6641 SET_VREG(r0, r9) @ vAA<- r0 6642 GOTO_OPCODE(ip) @ jump to next instruction 6643 /* 10-13 instructions */ 6644 6645 6646 6647/* ------------------------------ */ 6648 .balign 64 6649.L_OP_OR_INT_LIT16: /* 0xd6 */ 6650/* File: armv6t2/OP_OR_INT_LIT16.S */ 6651/* File: armv6t2/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 ubfx r9, rINST, #8, #4 @ r9<- A 6668 GET_VREG(r0, r2) @ r0<- vB 6669 .if 0 6670 cmp r1, #0 @ is second operand zero? 6671 beq common_errDivideByZero 6672 .endif 6673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6674 6675 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6676 GET_INST_OPCODE(ip) @ extract opcode from rINST 6677 SET_VREG(r0, r9) @ vAA<- r0 6678 GOTO_OPCODE(ip) @ jump to next instruction 6679 /* 10-13 instructions */ 6680 6681 6682 6683/* ------------------------------ */ 6684 .balign 64 6685.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6686/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6687/* File: armv6t2/binopLit16.S */ 6688 /* 6689 * Generic 32-bit "lit16" 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/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6698 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6699 */ 6700 /* binop/lit16 vA, vB, #+CCCC */ 6701 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6702 mov r2, rINST, lsr #12 @ r2<- B 6703 ubfx r9, rINST, #8, #4 @ r9<- A 6704 GET_VREG(r0, r2) @ r0<- vB 6705 .if 0 6706 cmp r1, #0 @ is second operand zero? 6707 beq common_errDivideByZero 6708 .endif 6709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6710 6711 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6712 GET_INST_OPCODE(ip) @ extract opcode from rINST 6713 SET_VREG(r0, r9) @ vAA<- r0 6714 GOTO_OPCODE(ip) @ jump to next instruction 6715 /* 10-13 instructions */ 6716 6717 6718 6719/* ------------------------------ */ 6720 .balign 64 6721.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6722/* File: armv5te/OP_ADD_INT_LIT8.S */ 6723/* File: armv5te/binopLit8.S */ 6724 /* 6725 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6726 * that specifies an instruction that performs "result = r0 op r1". 6727 * This could be an ARM instruction or a function call. (If the result 6728 * comes back in a register other than r0, you can override "result".) 6729 * 6730 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6731 * vCC (r1). Useful for integer division and modulus. 6732 * 6733 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6734 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6735 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6736 */ 6737 /* binop/lit8 vAA, vBB, #+CC */ 6738 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6739 mov r9, rINST, lsr #8 @ r9<- AA 6740 and r2, r3, #255 @ r2<- BB 6741 GET_VREG(r0, r2) @ r0<- vBB 6742 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6743 .if 0 6744 @cmp r1, #0 @ is second operand zero? 6745 beq common_errDivideByZero 6746 .endif 6747 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6748 6749 @ optional op; may set condition codes 6750 add r0, r0, r1 @ r0<- op, r0-r3 changed 6751 GET_INST_OPCODE(ip) @ extract opcode from rINST 6752 SET_VREG(r0, r9) @ vAA<- r0 6753 GOTO_OPCODE(ip) @ jump to next instruction 6754 /* 10-12 instructions */ 6755 6756 6757 6758/* ------------------------------ */ 6759 .balign 64 6760.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6761/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6762/* File: armv5te/binopLit8.S */ 6763 /* 6764 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6765 * that specifies an instruction that performs "result = r0 op r1". 6766 * This could be an ARM instruction or a function call. (If the result 6767 * comes back in a register other than r0, you can override "result".) 6768 * 6769 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6770 * vCC (r1). Useful for integer division and modulus. 6771 * 6772 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6773 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6774 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6775 */ 6776 /* binop/lit8 vAA, vBB, #+CC */ 6777 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6778 mov r9, rINST, lsr #8 @ r9<- AA 6779 and r2, r3, #255 @ r2<- BB 6780 GET_VREG(r0, r2) @ r0<- vBB 6781 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6782 .if 0 6783 @cmp r1, #0 @ is second operand zero? 6784 beq common_errDivideByZero 6785 .endif 6786 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6787 6788 @ optional op; may set condition codes 6789 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6790 GET_INST_OPCODE(ip) @ extract opcode from rINST 6791 SET_VREG(r0, r9) @ vAA<- r0 6792 GOTO_OPCODE(ip) @ jump to next instruction 6793 /* 10-12 instructions */ 6794 6795 6796 6797/* ------------------------------ */ 6798 .balign 64 6799.L_OP_MUL_INT_LIT8: /* 0xda */ 6800/* File: armv5te/OP_MUL_INT_LIT8.S */ 6801/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 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 0 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 mul r0, r1, r0 @ 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/* ------------------------------ */ 6838 .balign 64 6839.L_OP_DIV_INT_LIT8: /* 0xdb */ 6840/* File: armv5te/OP_DIV_INT_LIT8.S */ 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_idiv @ r0<- op, r0-r3 changed 6869 GET_INST_OPCODE(ip) @ extract opcode from rINST 6870 SET_VREG(r0, r9) @ vAA<- r0 6871 GOTO_OPCODE(ip) @ jump to next instruction 6872 /* 10-12 instructions */ 6873 6874 6875 6876/* ------------------------------ */ 6877 .balign 64 6878.L_OP_REM_INT_LIT8: /* 0xdc */ 6879/* File: armv5te/OP_REM_INT_LIT8.S */ 6880/* idivmod returns quotient in r0 and remainder in r1 */ 6881/* File: armv5te/binopLit8.S */ 6882 /* 6883 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6884 * that specifies an instruction that performs "result = r0 op r1". 6885 * This could be an ARM instruction or a function call. (If the result 6886 * comes back in a register other than r0, you can override "result".) 6887 * 6888 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6889 * vCC (r1). Useful for integer division and modulus. 6890 * 6891 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6892 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6893 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6894 */ 6895 /* binop/lit8 vAA, vBB, #+CC */ 6896 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6897 mov r9, rINST, lsr #8 @ r9<- AA 6898 and r2, r3, #255 @ r2<- BB 6899 GET_VREG(r0, r2) @ r0<- vBB 6900 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6901 .if 1 6902 @cmp r1, #0 @ is second operand zero? 6903 beq common_errDivideByZero 6904 .endif 6905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6906 6907 @ optional op; may set condition codes 6908 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6909 GET_INST_OPCODE(ip) @ extract opcode from rINST 6910 SET_VREG(r1, r9) @ vAA<- r1 6911 GOTO_OPCODE(ip) @ jump to next instruction 6912 /* 10-12 instructions */ 6913 6914 6915 6916/* ------------------------------ */ 6917 .balign 64 6918.L_OP_AND_INT_LIT8: /* 0xdd */ 6919/* File: armv5te/OP_AND_INT_LIT8.S */ 6920/* File: armv5te/binopLit8.S */ 6921 /* 6922 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6923 * that specifies an instruction that performs "result = r0 op r1". 6924 * This could be an ARM instruction or a function call. (If the result 6925 * comes back in a register other than r0, you can override "result".) 6926 * 6927 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6928 * vCC (r1). Useful for integer division and modulus. 6929 * 6930 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6931 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6932 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6933 */ 6934 /* binop/lit8 vAA, vBB, #+CC */ 6935 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6936 mov r9, rINST, lsr #8 @ r9<- AA 6937 and r2, r3, #255 @ r2<- BB 6938 GET_VREG(r0, r2) @ r0<- vBB 6939 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6940 .if 0 6941 @cmp r1, #0 @ is second operand zero? 6942 beq common_errDivideByZero 6943 .endif 6944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6945 6946 @ optional op; may set condition codes 6947 and r0, r0, r1 @ r0<- op, r0-r3 changed 6948 GET_INST_OPCODE(ip) @ extract opcode from rINST 6949 SET_VREG(r0, r9) @ vAA<- r0 6950 GOTO_OPCODE(ip) @ jump to next instruction 6951 /* 10-12 instructions */ 6952 6953 6954 6955/* ------------------------------ */ 6956 .balign 64 6957.L_OP_OR_INT_LIT8: /* 0xde */ 6958/* File: armv5te/OP_OR_INT_LIT8.S */ 6959/* File: armv5te/binopLit8.S */ 6960 /* 6961 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6962 * that specifies an instruction that performs "result = r0 op r1". 6963 * This could be an ARM instruction or a function call. (If the result 6964 * comes back in a register other than r0, you can override "result".) 6965 * 6966 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6967 * vCC (r1). Useful for integer division and modulus. 6968 * 6969 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6970 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6971 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6972 */ 6973 /* binop/lit8 vAA, vBB, #+CC */ 6974 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6975 mov r9, rINST, lsr #8 @ r9<- AA 6976 and r2, r3, #255 @ r2<- BB 6977 GET_VREG(r0, r2) @ r0<- vBB 6978 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6979 .if 0 6980 @cmp r1, #0 @ is second operand zero? 6981 beq common_errDivideByZero 6982 .endif 6983 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6984 6985 @ optional op; may set condition codes 6986 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6987 GET_INST_OPCODE(ip) @ extract opcode from rINST 6988 SET_VREG(r0, r9) @ vAA<- r0 6989 GOTO_OPCODE(ip) @ jump to next instruction 6990 /* 10-12 instructions */ 6991 6992 6993 6994/* ------------------------------ */ 6995 .balign 64 6996.L_OP_XOR_INT_LIT8: /* 0xdf */ 6997/* File: armv5te/OP_XOR_INT_LIT8.S */ 6998/* File: armv5te/binopLit8.S */ 6999 /* 7000 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7001 * that specifies an instruction that performs "result = r0 op r1". 7002 * This could be an ARM instruction or a function call. (If the result 7003 * comes back in a register other than r0, you can override "result".) 7004 * 7005 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7006 * vCC (r1). Useful for integer division and modulus. 7007 * 7008 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7009 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7010 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7011 */ 7012 /* binop/lit8 vAA, vBB, #+CC */ 7013 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7014 mov r9, rINST, lsr #8 @ r9<- AA 7015 and r2, r3, #255 @ r2<- BB 7016 GET_VREG(r0, r2) @ r0<- vBB 7017 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7018 .if 0 7019 @cmp r1, #0 @ is second operand zero? 7020 beq common_errDivideByZero 7021 .endif 7022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7023 7024 @ optional op; may set condition codes 7025 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7026 GET_INST_OPCODE(ip) @ extract opcode from rINST 7027 SET_VREG(r0, r9) @ vAA<- r0 7028 GOTO_OPCODE(ip) @ jump to next instruction 7029 /* 10-12 instructions */ 7030 7031 7032 7033/* ------------------------------ */ 7034 .balign 64 7035.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7036/* File: armv5te/OP_SHL_INT_LIT8.S */ 7037/* File: armv5te/binopLit8.S */ 7038 /* 7039 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7040 * that specifies an instruction that performs "result = r0 op r1". 7041 * This could be an ARM instruction or a function call. (If the result 7042 * comes back in a register other than r0, you can override "result".) 7043 * 7044 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7045 * vCC (r1). Useful for integer division and modulus. 7046 * 7047 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7048 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7049 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7050 */ 7051 /* binop/lit8 vAA, vBB, #+CC */ 7052 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7053 mov r9, rINST, lsr #8 @ r9<- AA 7054 and r2, r3, #255 @ r2<- BB 7055 GET_VREG(r0, r2) @ r0<- vBB 7056 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7057 .if 0 7058 @cmp r1, #0 @ is second operand zero? 7059 beq common_errDivideByZero 7060 .endif 7061 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7062 7063 and r1, r1, #31 @ optional op; may set condition codes 7064 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7065 GET_INST_OPCODE(ip) @ extract opcode from rINST 7066 SET_VREG(r0, r9) @ vAA<- r0 7067 GOTO_OPCODE(ip) @ jump to next instruction 7068 /* 10-12 instructions */ 7069 7070 7071 7072/* ------------------------------ */ 7073 .balign 64 7074.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7075/* File: armv5te/OP_SHR_INT_LIT8.S */ 7076/* File: armv5te/binopLit8.S */ 7077 /* 7078 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7079 * that specifies an instruction that performs "result = r0 op r1". 7080 * This could be an ARM instruction or a function call. (If the result 7081 * comes back in a register other than r0, you can override "result".) 7082 * 7083 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7084 * vCC (r1). Useful for integer division and modulus. 7085 * 7086 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7087 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7088 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7089 */ 7090 /* binop/lit8 vAA, vBB, #+CC */ 7091 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7092 mov r9, rINST, lsr #8 @ r9<- AA 7093 and r2, r3, #255 @ r2<- BB 7094 GET_VREG(r0, r2) @ r0<- vBB 7095 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7096 .if 0 7097 @cmp r1, #0 @ is second operand zero? 7098 beq common_errDivideByZero 7099 .endif 7100 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7101 7102 and r1, r1, #31 @ optional op; may set condition codes 7103 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7104 GET_INST_OPCODE(ip) @ extract opcode from rINST 7105 SET_VREG(r0, r9) @ vAA<- r0 7106 GOTO_OPCODE(ip) @ jump to next instruction 7107 /* 10-12 instructions */ 7108 7109 7110 7111/* ------------------------------ */ 7112 .balign 64 7113.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7114/* File: armv5te/OP_USHR_INT_LIT8.S */ 7115/* File: armv5te/binopLit8.S */ 7116 /* 7117 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7118 * that specifies an instruction that performs "result = r0 op r1". 7119 * This could be an ARM instruction or a function call. (If the result 7120 * comes back in a register other than r0, you can override "result".) 7121 * 7122 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7123 * vCC (r1). Useful for integer division and modulus. 7124 * 7125 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7126 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7127 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7128 */ 7129 /* binop/lit8 vAA, vBB, #+CC */ 7130 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7131 mov r9, rINST, lsr #8 @ r9<- AA 7132 and r2, r3, #255 @ r2<- BB 7133 GET_VREG(r0, r2) @ r0<- vBB 7134 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7135 .if 0 7136 @cmp r1, #0 @ is second operand zero? 7137 beq common_errDivideByZero 7138 .endif 7139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7140 7141 and r1, r1, #31 @ optional op; may set condition codes 7142 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7143 GET_INST_OPCODE(ip) @ extract opcode from rINST 7144 SET_VREG(r0, r9) @ vAA<- r0 7145 GOTO_OPCODE(ip) @ jump to next instruction 7146 /* 10-12 instructions */ 7147 7148 7149 7150/* ------------------------------ */ 7151 .balign 64 7152.L_OP_UNUSED_E3: /* 0xe3 */ 7153/* File: armv5te/OP_UNUSED_E3.S */ 7154/* File: armv5te/unused.S */ 7155 bl common_abort 7156 7157 7158 7159/* ------------------------------ */ 7160 .balign 64 7161.L_OP_UNUSED_E4: /* 0xe4 */ 7162/* File: armv5te/OP_UNUSED_E4.S */ 7163/* File: armv5te/unused.S */ 7164 bl common_abort 7165 7166 7167 7168/* ------------------------------ */ 7169 .balign 64 7170.L_OP_UNUSED_E5: /* 0xe5 */ 7171/* File: armv5te/OP_UNUSED_E5.S */ 7172/* File: armv5te/unused.S */ 7173 bl common_abort 7174 7175 7176 7177/* ------------------------------ */ 7178 .balign 64 7179.L_OP_UNUSED_E6: /* 0xe6 */ 7180/* File: armv5te/OP_UNUSED_E6.S */ 7181/* File: armv5te/unused.S */ 7182 bl common_abort 7183 7184 7185 7186/* ------------------------------ */ 7187 .balign 64 7188.L_OP_UNUSED_E7: /* 0xe7 */ 7189/* File: armv5te/OP_UNUSED_E7.S */ 7190/* File: armv5te/unused.S */ 7191 bl common_abort 7192 7193 7194 7195/* ------------------------------ */ 7196 .balign 64 7197.L_OP_UNUSED_E8: /* 0xe8 */ 7198/* File: armv5te/OP_UNUSED_E8.S */ 7199/* File: armv5te/unused.S */ 7200 bl common_abort 7201 7202 7203 7204/* ------------------------------ */ 7205 .balign 64 7206.L_OP_UNUSED_E9: /* 0xe9 */ 7207/* File: armv5te/OP_UNUSED_E9.S */ 7208/* File: armv5te/unused.S */ 7209 bl common_abort 7210 7211 7212 7213/* ------------------------------ */ 7214 .balign 64 7215.L_OP_UNUSED_EA: /* 0xea */ 7216/* File: armv5te/OP_UNUSED_EA.S */ 7217/* File: armv5te/unused.S */ 7218 bl common_abort 7219 7220 7221 7222/* ------------------------------ */ 7223 .balign 64 7224.L_OP_UNUSED_EB: /* 0xeb */ 7225/* File: armv5te/OP_UNUSED_EB.S */ 7226/* File: armv5te/unused.S */ 7227 bl common_abort 7228 7229 7230 7231/* ------------------------------ */ 7232 .balign 64 7233.L_OP_BREAKPOINT: /* 0xec */ 7234/* File: armv5te/OP_BREAKPOINT.S */ 7235/* File: armv5te/unused.S */ 7236 bl common_abort 7237 7238 7239 7240/* ------------------------------ */ 7241 .balign 64 7242.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7243/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7244 /* 7245 * Handle a throw-verification-error instruction. This throws an 7246 * exception for an error discovered during verification. The 7247 * exception is indicated by AA, with some detail provided by BBBB. 7248 */ 7249 /* op AA, ref@BBBB */ 7250 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7251 FETCH(r2, 1) @ r2<- BBBB 7252 EXPORT_PC() @ export the PC 7253 mov r1, rINST, lsr #8 @ r1<- AA 7254 bl dvmThrowVerificationError @ always throws 7255 b common_exceptionThrown @ handle exception 7256 7257 7258/* ------------------------------ */ 7259 .balign 64 7260.L_OP_EXECUTE_INLINE: /* 0xee */ 7261/* File: armv5te/OP_EXECUTE_INLINE.S */ 7262 /* 7263 * Execute a "native inline" instruction. 7264 * 7265 * We need to call an InlineOp4Func: 7266 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7267 * 7268 * The first four args are in r0-r3, pointer to return value storage 7269 * is on the stack. The function's return value is a flag that tells 7270 * us if an exception was thrown. 7271 */ 7272 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7273 FETCH(r10, 1) @ r10<- BBBB 7274 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7275 EXPORT_PC() @ can throw 7276 sub sp, sp, #8 @ make room for arg, +64 bit align 7277 mov r0, rINST, lsr #12 @ r0<- B 7278 str r1, [sp] @ push &glue->retval 7279 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7280 add sp, sp, #8 @ pop stack 7281 cmp r0, #0 @ test boolean result of inline 7282 beq common_exceptionThrown @ returned false, handle exception 7283 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7284 GET_INST_OPCODE(ip) @ extract opcode from rINST 7285 GOTO_OPCODE(ip) @ jump to next instruction 7286 7287/* ------------------------------ */ 7288 .balign 64 7289.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7290/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7291 /* 7292 * Execute a "native inline" instruction, using "/range" semantics. 7293 * Same idea as execute-inline, but we get the args differently. 7294 * 7295 * We need to call an InlineOp4Func: 7296 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7297 * 7298 * The first four args are in r0-r3, pointer to return value storage 7299 * is on the stack. The function's return value is a flag that tells 7300 * us if an exception was thrown. 7301 */ 7302 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7303 FETCH(r10, 1) @ r10<- BBBB 7304 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7305 EXPORT_PC() @ can throw 7306 sub sp, sp, #8 @ make room for arg, +64 bit align 7307 mov r0, rINST, lsr #8 @ r0<- AA 7308 str r1, [sp] @ push &glue->retval 7309 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7310 add sp, sp, #8 @ pop stack 7311 cmp r0, #0 @ test boolean result of inline 7312 beq common_exceptionThrown @ returned false, handle exception 7313 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7314 GET_INST_OPCODE(ip) @ extract opcode from rINST 7315 GOTO_OPCODE(ip) @ jump to next instruction 7316 7317/* ------------------------------ */ 7318 .balign 64 7319.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7320/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7321 /* 7322 * invoke-direct-empty is a no-op in a "standard" interpreter. 7323 */ 7324 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7325 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7326 GOTO_OPCODE(ip) @ execute it 7327 7328/* ------------------------------ */ 7329 .balign 64 7330.L_OP_UNUSED_F1: /* 0xf1 */ 7331/* File: armv5te/OP_UNUSED_F1.S */ 7332/* File: armv5te/unused.S */ 7333 bl common_abort 7334 7335 7336 7337/* ------------------------------ */ 7338 .balign 64 7339.L_OP_IGET_QUICK: /* 0xf2 */ 7340/* File: armv6t2/OP_IGET_QUICK.S */ 7341 /* For: iget-quick, iget-object-quick */ 7342 /* op vA, vB, offset@CCCC */ 7343 mov r2, rINST, lsr #12 @ r2<- B 7344 FETCH(r1, 1) @ r1<- field byte offset 7345 GET_VREG(r3, r2) @ r3<- object we're operating on 7346 ubfx r2, rINST, #8, #4 @ r2<- A 7347 cmp r3, #0 @ check object for null 7348 beq common_errNullObject @ object was null 7349 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7350 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7351 GET_INST_OPCODE(ip) @ extract opcode from rINST 7352 SET_VREG(r0, r2) @ fp[A]<- r0 7353 GOTO_OPCODE(ip) @ jump to next instruction 7354 7355 7356/* ------------------------------ */ 7357 .balign 64 7358.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7359/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7360 /* iget-wide-quick vA, vB, offset@CCCC */ 7361 mov r2, rINST, lsr #12 @ r2<- B 7362 FETCH(r1, 1) @ r1<- field byte offset 7363 GET_VREG(r3, r2) @ r3<- object we're operating on 7364 ubfx r2, rINST, #8, #4 @ r2<- A 7365 cmp r3, #0 @ check object for null 7366 beq common_errNullObject @ object was null 7367 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7369 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7370 GET_INST_OPCODE(ip) @ extract opcode from rINST 7371 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7372 GOTO_OPCODE(ip) @ jump to next instruction 7373 7374 7375/* ------------------------------ */ 7376 .balign 64 7377.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7378/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7379/* File: armv5te/OP_IGET_QUICK.S */ 7380 /* For: iget-quick, iget-object-quick */ 7381 /* op vA, vB, offset@CCCC */ 7382 mov r2, rINST, lsr #12 @ r2<- B 7383 GET_VREG(r3, r2) @ r3<- object we're operating on 7384 FETCH(r1, 1) @ r1<- field byte offset 7385 cmp r3, #0 @ check object for null 7386 mov r2, rINST, lsr #8 @ r2<- A(+) 7387 beq common_errNullObject @ object was null 7388 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7389 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7390 and r2, r2, #15 7391 GET_INST_OPCODE(ip) @ extract opcode from rINST 7392 SET_VREG(r0, r2) @ fp[A]<- r0 7393 GOTO_OPCODE(ip) @ jump to next instruction 7394 7395 7396 7397/* ------------------------------ */ 7398 .balign 64 7399.L_OP_IPUT_QUICK: /* 0xf5 */ 7400/* File: armv6t2/OP_IPUT_QUICK.S */ 7401 /* For: iput-quick, iput-object-quick */ 7402 /* op vA, vB, offset@CCCC */ 7403 mov r2, rINST, lsr #12 @ r2<- B 7404 FETCH(r1, 1) @ r1<- field byte offset 7405 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7406 ubfx r2, rINST, #8, #4 @ r2<- A 7407 cmp r3, #0 @ check object for null 7408 beq common_errNullObject @ object was null 7409 GET_VREG(r0, r2) @ r0<- fp[A] 7410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7411 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7412 GET_INST_OPCODE(ip) @ extract opcode from rINST 7413 GOTO_OPCODE(ip) @ jump to next instruction 7414 7415 7416/* ------------------------------ */ 7417 .balign 64 7418.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7419/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7420 /* iput-wide-quick vA, vB, offset@CCCC */ 7421 mov r1, rINST, lsr #12 @ r1<- B 7422 ubfx r0, rINST, #8, #4 @ r0<- A 7423 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7424 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7425 cmp r2, #0 @ check object for null 7426 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7427 beq common_errNullObject @ object was null 7428 FETCH(r3, 1) @ r3<- field byte offset 7429 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7430 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7431 GET_INST_OPCODE(ip) @ extract opcode from rINST 7432 GOTO_OPCODE(ip) @ jump to next instruction 7433 7434 7435/* ------------------------------ */ 7436 .balign 64 7437.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7438/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7439/* File: armv5te/OP_IPUT_QUICK.S */ 7440 /* For: iput-quick, iput-object-quick */ 7441 /* op vA, vB, offset@CCCC */ 7442 mov r2, rINST, lsr #12 @ r2<- B 7443 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7444 FETCH(r1, 1) @ r1<- field byte offset 7445 cmp r3, #0 @ check object for null 7446 mov r2, rINST, lsr #8 @ r2<- A(+) 7447 beq common_errNullObject @ object was null 7448 and r2, r2, #15 7449 GET_VREG(r0, r2) @ r0<- fp[A] 7450 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7451 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7452 GET_INST_OPCODE(ip) @ extract opcode from rINST 7453 GOTO_OPCODE(ip) @ jump to next instruction 7454 7455 7456 7457/* ------------------------------ */ 7458 .balign 64 7459.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7460/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7461 /* 7462 * Handle an optimized virtual method call. 7463 * 7464 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7465 */ 7466 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7467 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7468 FETCH(r3, 2) @ r3<- FEDC or CCCC 7469 FETCH(r1, 1) @ r1<- BBBB 7470 .if (!0) 7471 and r3, r3, #15 @ r3<- C (or stays CCCC) 7472 .endif 7473 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7474 cmp r2, #0 @ is "this" null? 7475 beq common_errNullObject @ null "this", throw exception 7476 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7477 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7478 EXPORT_PC() @ invoke must export 7479 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7480 bl common_invokeMethodNoRange @ continue on 7481 7482/* ------------------------------ */ 7483 .balign 64 7484.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7485/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7486/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7487 /* 7488 * Handle an optimized virtual method call. 7489 * 7490 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7491 */ 7492 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7493 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7494 FETCH(r3, 2) @ r3<- FEDC or CCCC 7495 FETCH(r1, 1) @ r1<- BBBB 7496 .if (!1) 7497 and r3, r3, #15 @ r3<- C (or stays CCCC) 7498 .endif 7499 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7500 cmp r2, #0 @ is "this" null? 7501 beq common_errNullObject @ null "this", throw exception 7502 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7503 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7504 EXPORT_PC() @ invoke must export 7505 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7506 bl common_invokeMethodRange @ continue on 7507 7508 7509/* ------------------------------ */ 7510 .balign 64 7511.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7512/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7513 /* 7514 * Handle an optimized "super" method call. 7515 * 7516 * for: [opt] invoke-super-quick, invoke-super-quick/range 7517 */ 7518 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7519 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7520 FETCH(r10, 2) @ r10<- GFED or CCCC 7521 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7522 .if (!0) 7523 and r10, r10, #15 @ r10<- D (or stays CCCC) 7524 .endif 7525 FETCH(r1, 1) @ r1<- BBBB 7526 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7527 EXPORT_PC() @ must export for invoke 7528 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7529 GET_VREG(r3, r10) @ r3<- "this" 7530 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7531 cmp r3, #0 @ null "this" ref? 7532 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7533 beq common_errNullObject @ "this" is null, throw exception 7534 bl common_invokeMethodNoRange @ continue on 7535 7536 7537/* ------------------------------ */ 7538 .balign 64 7539.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7540/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7541/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7542 /* 7543 * Handle an optimized "super" method call. 7544 * 7545 * for: [opt] invoke-super-quick, invoke-super-quick/range 7546 */ 7547 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7548 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7549 FETCH(r10, 2) @ r10<- GFED or CCCC 7550 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7551 .if (!1) 7552 and r10, r10, #15 @ r10<- D (or stays CCCC) 7553 .endif 7554 FETCH(r1, 1) @ r1<- BBBB 7555 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7556 EXPORT_PC() @ must export for invoke 7557 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7558 GET_VREG(r3, r10) @ r3<- "this" 7559 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7560 cmp r3, #0 @ null "this" ref? 7561 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7562 beq common_errNullObject @ "this" is null, throw exception 7563 bl common_invokeMethodRange @ continue on 7564 7565 7566 7567/* ------------------------------ */ 7568 .balign 64 7569.L_OP_UNUSED_FC: /* 0xfc */ 7570/* File: armv5te/OP_UNUSED_FC.S */ 7571/* File: armv5te/unused.S */ 7572 bl common_abort 7573 7574 7575 7576/* ------------------------------ */ 7577 .balign 64 7578.L_OP_UNUSED_FD: /* 0xfd */ 7579/* File: armv5te/OP_UNUSED_FD.S */ 7580/* File: armv5te/unused.S */ 7581 bl common_abort 7582 7583 7584 7585/* ------------------------------ */ 7586 .balign 64 7587.L_OP_UNUSED_FE: /* 0xfe */ 7588/* File: armv5te/OP_UNUSED_FE.S */ 7589/* File: armv5te/unused.S */ 7590 bl common_abort 7591 7592 7593 7594/* ------------------------------ */ 7595 .balign 64 7596.L_OP_UNUSED_FF: /* 0xff */ 7597/* File: armv5te/OP_UNUSED_FF.S */ 7598/* File: armv5te/unused.S */ 7599 bl common_abort 7600 7601 7602 7603 7604 .balign 64 7605 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7606 .global dvmAsmInstructionEnd 7607dvmAsmInstructionEnd: 7608 7609/* 7610 * =========================================================================== 7611 * Sister implementations 7612 * =========================================================================== 7613 */ 7614 .global dvmAsmSisterStart 7615 .type dvmAsmSisterStart, %function 7616 .text 7617 .balign 4 7618dvmAsmSisterStart: 7619 7620/* continuation for OP_CONST_STRING */ 7621 7622 /* 7623 * Continuation if the String has not yet been resolved. 7624 * r1: BBBB (String ref) 7625 * r9: target register 7626 */ 7627.LOP_CONST_STRING_resolve: 7628 EXPORT_PC() 7629 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7630 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7631 bl dvmResolveString @ r0<- String reference 7632 cmp r0, #0 @ failed? 7633 beq common_exceptionThrown @ yup, handle the exception 7634 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7635 GET_INST_OPCODE(ip) @ extract opcode from rINST 7636 SET_VREG(r0, r9) @ vAA<- r0 7637 GOTO_OPCODE(ip) @ jump to next instruction 7638 7639 7640/* continuation for OP_CONST_STRING_JUMBO */ 7641 7642 /* 7643 * Continuation if the String has not yet been resolved. 7644 * r1: BBBBBBBB (String ref) 7645 * r9: target register 7646 */ 7647.LOP_CONST_STRING_JUMBO_resolve: 7648 EXPORT_PC() 7649 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7650 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7651 bl dvmResolveString @ r0<- String reference 7652 cmp r0, #0 @ failed? 7653 beq common_exceptionThrown @ yup, handle the exception 7654 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7655 GET_INST_OPCODE(ip) @ extract opcode from rINST 7656 SET_VREG(r0, r9) @ vAA<- r0 7657 GOTO_OPCODE(ip) @ jump to next instruction 7658 7659 7660/* continuation for OP_CONST_CLASS */ 7661 7662 /* 7663 * Continuation if the Class has not yet been resolved. 7664 * r1: BBBB (Class ref) 7665 * r9: target register 7666 */ 7667.LOP_CONST_CLASS_resolve: 7668 EXPORT_PC() 7669 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7670 mov r2, #1 @ r2<- true 7671 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7672 bl dvmResolveClass @ r0<- Class reference 7673 cmp r0, #0 @ failed? 7674 beq common_exceptionThrown @ yup, handle the exception 7675 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7676 GET_INST_OPCODE(ip) @ extract opcode from rINST 7677 SET_VREG(r0, r9) @ vAA<- r0 7678 GOTO_OPCODE(ip) @ jump to next instruction 7679 7680 7681/* continuation for OP_CHECK_CAST */ 7682 7683 /* 7684 * Trivial test failed, need to perform full check. This is common. 7685 * r0 holds obj->clazz 7686 * r1 holds class resolved from BBBB 7687 * r9 holds object 7688 */ 7689.LOP_CHECK_CAST_fullcheck: 7690 bl dvmInstanceofNonTrivial @ r0<- boolean result 7691 cmp r0, #0 @ failed? 7692 bne .LOP_CHECK_CAST_okay @ no, success 7693 7694 @ A cast has failed. We need to throw a ClassCastException with the 7695 @ class of the object that failed to be cast. 7696 EXPORT_PC() @ about to throw 7697 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7698 ldr r0, .LstrClassCastExceptionPtr 7699 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7700 bl dvmThrowExceptionWithClassMessage 7701 b common_exceptionThrown 7702 7703 /* 7704 * Resolution required. This is the least-likely path. 7705 * 7706 * r2 holds BBBB 7707 * r9 holds object 7708 */ 7709.LOP_CHECK_CAST_resolve: 7710 EXPORT_PC() @ resolve() could throw 7711 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7712 mov r1, r2 @ r1<- BBBB 7713 mov r2, #0 @ r2<- false 7714 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7715 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7716 cmp r0, #0 @ got null? 7717 beq common_exceptionThrown @ yes, handle exception 7718 mov r1, r0 @ r1<- class resolved from BBB 7719 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7720 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7721 7722.LstrClassCastExceptionPtr: 7723 .word .LstrClassCastException 7724 7725 7726/* continuation for OP_INSTANCE_OF */ 7727 7728 /* 7729 * Trivial test failed, need to perform full check. This is common. 7730 * r0 holds obj->clazz 7731 * r1 holds class resolved from BBBB 7732 * r9 holds A 7733 */ 7734.LOP_INSTANCE_OF_fullcheck: 7735 bl dvmInstanceofNonTrivial @ r0<- boolean result 7736 @ fall through to OP_INSTANCE_OF_store 7737 7738 /* 7739 * r0 holds boolean result 7740 * r9 holds A 7741 */ 7742.LOP_INSTANCE_OF_store: 7743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7744 SET_VREG(r0, r9) @ vA<- r0 7745 GET_INST_OPCODE(ip) @ extract opcode from rINST 7746 GOTO_OPCODE(ip) @ jump to next instruction 7747 7748 /* 7749 * Trivial test succeeded, save and bail. 7750 * r9 holds A 7751 */ 7752.LOP_INSTANCE_OF_trivial: 7753 mov r0, #1 @ indicate success 7754 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7755 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7756 SET_VREG(r0, r9) @ vA<- r0 7757 GET_INST_OPCODE(ip) @ extract opcode from rINST 7758 GOTO_OPCODE(ip) @ jump to next instruction 7759 7760 /* 7761 * Resolution required. This is the least-likely path. 7762 * 7763 * r3 holds BBBB 7764 * r9 holds A 7765 */ 7766.LOP_INSTANCE_OF_resolve: 7767 EXPORT_PC() @ resolve() could throw 7768 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7769 mov r1, r3 @ r1<- BBBB 7770 mov r2, #1 @ r2<- true 7771 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7772 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7773 cmp r0, #0 @ got null? 7774 beq common_exceptionThrown @ yes, handle exception 7775 mov r1, r0 @ r1<- class resolved from BBB 7776 mov r3, rINST, lsr #12 @ r3<- B 7777 GET_VREG(r0, r3) @ r0<- vB (object) 7778 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7779 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7780 7781 7782/* continuation for OP_NEW_INSTANCE */ 7783 7784 .balign 32 @ minimize cache lines 7785.LOP_NEW_INSTANCE_finish: @ r0=new object 7786 mov r3, rINST, lsr #8 @ r3<- AA 7787 cmp r0, #0 @ failed? 7788 beq common_exceptionThrown @ yes, handle the exception 7789 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7790 GET_INST_OPCODE(ip) @ extract opcode from rINST 7791 SET_VREG(r0, r3) @ vAA<- r0 7792 GOTO_OPCODE(ip) @ jump to next instruction 7793 7794 /* 7795 * Class initialization required. 7796 * 7797 * r0 holds class object 7798 */ 7799.LOP_NEW_INSTANCE_needinit: 7800 mov r9, r0 @ save r0 7801 bl dvmInitClass @ initialize class 7802 cmp r0, #0 @ check boolean result 7803 mov r0, r9 @ restore r0 7804 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7805 b common_exceptionThrown @ failed, deal with init exception 7806 7807 /* 7808 * Resolution required. This is the least-likely path. 7809 * 7810 * r1 holds BBBB 7811 */ 7812.LOP_NEW_INSTANCE_resolve: 7813 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7814 mov r2, #0 @ r2<- false 7815 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7816 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7817 cmp r0, #0 @ got null? 7818 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7819 b common_exceptionThrown @ yes, handle exception 7820 7821.LstrInstantiationErrorPtr: 7822 .word .LstrInstantiationError 7823 7824 7825/* continuation for OP_NEW_ARRAY */ 7826 7827 7828 /* 7829 * Resolve class. (This is an uncommon case.) 7830 * 7831 * r1 holds array length 7832 * r2 holds class ref CCCC 7833 */ 7834.LOP_NEW_ARRAY_resolve: 7835 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7836 mov r9, r1 @ r9<- length (save) 7837 mov r1, r2 @ r1<- CCCC 7838 mov r2, #0 @ r2<- false 7839 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7840 bl dvmResolveClass @ r0<- call(clazz, ref) 7841 cmp r0, #0 @ got null? 7842 mov r1, r9 @ r1<- length (restore) 7843 beq common_exceptionThrown @ yes, handle exception 7844 @ fall through to OP_NEW_ARRAY_finish 7845 7846 /* 7847 * Finish allocation. 7848 * 7849 * r0 holds class 7850 * r1 holds array length 7851 */ 7852.LOP_NEW_ARRAY_finish: 7853 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7854 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7855 cmp r0, #0 @ failed? 7856 mov r2, rINST, lsr #8 @ r2<- A+ 7857 beq common_exceptionThrown @ yes, handle the exception 7858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7859 and r2, r2, #15 @ r2<- A 7860 GET_INST_OPCODE(ip) @ extract opcode from rINST 7861 SET_VREG(r0, r2) @ vA<- r0 7862 GOTO_OPCODE(ip) @ jump to next instruction 7863 7864 7865/* continuation for OP_FILLED_NEW_ARRAY */ 7866 7867 /* 7868 * On entry: 7869 * r0 holds array class 7870 * r10 holds AA or BA 7871 */ 7872.LOP_FILLED_NEW_ARRAY_continue: 7873 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7874 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7875 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7876 .if 0 7877 mov r1, r10 @ r1<- AA (length) 7878 .else 7879 mov r1, r10, lsr #4 @ r1<- B (length) 7880 .endif 7881 cmp r3, #'I' @ array of ints? 7882 cmpne r3, #'L' @ array of objects? 7883 cmpne r3, #'[' @ array of arrays? 7884 mov r9, r1 @ save length in r9 7885 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7886 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7887 cmp r0, #0 @ null return? 7888 beq common_exceptionThrown @ alloc failed, handle exception 7889 7890 FETCH(r1, 2) @ r1<- FEDC or CCCC 7891 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7892 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7893 subs r9, r9, #1 @ length--, check for neg 7894 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7895 bmi 2f @ was zero, bail 7896 7897 @ copy values from registers into the array 7898 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7899 .if 0 7900 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79011: ldr r3, [r2], #4 @ r3<- *r2++ 7902 subs r9, r9, #1 @ count-- 7903 str r3, [r0], #4 @ *contents++ = vX 7904 bpl 1b 7905 @ continue at 2 7906 .else 7907 cmp r9, #4 @ length was initially 5? 7908 and r2, r10, #15 @ r2<- A 7909 bne 1f @ <= 4 args, branch 7910 GET_VREG(r3, r2) @ r3<- vA 7911 sub r9, r9, #1 @ count-- 7912 str r3, [r0, #16] @ contents[4] = vA 79131: and r2, r1, #15 @ r2<- F/E/D/C 7914 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7915 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7916 subs r9, r9, #1 @ count-- 7917 str r3, [r0], #4 @ *contents++ = vX 7918 bpl 1b 7919 @ continue at 2 7920 .endif 7921 79222: 7923 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7924 GOTO_OPCODE(ip) @ execute it 7925 7926 /* 7927 * Throw an exception indicating that we have not implemented this 7928 * mode of filled-new-array. 7929 */ 7930.LOP_FILLED_NEW_ARRAY_notimpl: 7931 ldr r0, .L_strInternalError 7932 ldr r1, .L_strFilledNewArrayNotImpl 7933 bl dvmThrowException 7934 b common_exceptionThrown 7935 7936 .if (!0) @ define in one or the other, not both 7937.L_strFilledNewArrayNotImpl: 7938 .word .LstrFilledNewArrayNotImpl 7939.L_strInternalError: 7940 .word .LstrInternalError 7941 .endif 7942 7943 7944/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7945 7946 /* 7947 * On entry: 7948 * r0 holds array class 7949 * r10 holds AA or BA 7950 */ 7951.LOP_FILLED_NEW_ARRAY_RANGE_continue: 7952 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7953 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7954 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7955 .if 1 7956 mov r1, r10 @ r1<- AA (length) 7957 .else 7958 mov r1, r10, lsr #4 @ r1<- B (length) 7959 .endif 7960 cmp r3, #'I' @ array of ints? 7961 cmpne r3, #'L' @ array of objects? 7962 cmpne r3, #'[' @ array of arrays? 7963 mov r9, r1 @ save length in r9 7964 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 7965 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7966 cmp r0, #0 @ null return? 7967 beq common_exceptionThrown @ alloc failed, handle exception 7968 7969 FETCH(r1, 2) @ r1<- FEDC or CCCC 7970 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7971 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7972 subs r9, r9, #1 @ length--, check for neg 7973 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7974 bmi 2f @ was zero, bail 7975 7976 @ copy values from registers into the array 7977 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7978 .if 1 7979 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79801: ldr r3, [r2], #4 @ r3<- *r2++ 7981 subs r9, r9, #1 @ count-- 7982 str r3, [r0], #4 @ *contents++ = vX 7983 bpl 1b 7984 @ continue at 2 7985 .else 7986 cmp r9, #4 @ length was initially 5? 7987 and r2, r10, #15 @ r2<- A 7988 bne 1f @ <= 4 args, branch 7989 GET_VREG(r3, r2) @ r3<- vA 7990 sub r9, r9, #1 @ count-- 7991 str r3, [r0, #16] @ contents[4] = vA 79921: and r2, r1, #15 @ r2<- F/E/D/C 7993 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7994 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7995 subs r9, r9, #1 @ count-- 7996 str r3, [r0], #4 @ *contents++ = vX 7997 bpl 1b 7998 @ continue at 2 7999 .endif 8000 80012: 8002 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8003 GOTO_OPCODE(ip) @ execute it 8004 8005 /* 8006 * Throw an exception indicating that we have not implemented this 8007 * mode of filled-new-array. 8008 */ 8009.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8010 ldr r0, .L_strInternalError 8011 ldr r1, .L_strFilledNewArrayNotImpl 8012 bl dvmThrowException 8013 b common_exceptionThrown 8014 8015 .if (!1) @ define in one or the other, not both 8016.L_strFilledNewArrayNotImpl: 8017 .word .LstrFilledNewArrayNotImpl 8018.L_strInternalError: 8019 .word .LstrInternalError 8020 .endif 8021 8022 8023/* continuation for OP_CMPL_FLOAT */ 8024.LOP_CMPL_FLOAT_finish: 8025 SET_VREG(r0, r9) @ vAA<- r0 8026 GOTO_OPCODE(ip) @ jump to next instruction 8027 8028 8029/* continuation for OP_CMPG_FLOAT */ 8030.LOP_CMPG_FLOAT_finish: 8031 SET_VREG(r0, r9) @ vAA<- r0 8032 GOTO_OPCODE(ip) @ jump to next instruction 8033 8034 8035/* continuation for OP_CMPL_DOUBLE */ 8036.LOP_CMPL_DOUBLE_finish: 8037 SET_VREG(r0, r9) @ vAA<- r0 8038 GOTO_OPCODE(ip) @ jump to next instruction 8039 8040 8041/* continuation for OP_CMPG_DOUBLE */ 8042.LOP_CMPG_DOUBLE_finish: 8043 SET_VREG(r0, r9) @ vAA<- r0 8044 GOTO_OPCODE(ip) @ jump to next instruction 8045 8046 8047/* continuation for OP_CMP_LONG */ 8048 8049.LOP_CMP_LONG_less: 8050 mvn r1, #0 @ r1<- -1 8051 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8052 @ instead, we just replicate the tail end. 8053 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8054 SET_VREG(r1, r9) @ vAA<- r1 8055 GET_INST_OPCODE(ip) @ extract opcode from rINST 8056 GOTO_OPCODE(ip) @ jump to next instruction 8057 8058.LOP_CMP_LONG_greater: 8059 mov r1, #1 @ r1<- 1 8060 @ fall through to _finish 8061 8062.LOP_CMP_LONG_finish: 8063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8064 SET_VREG(r1, r9) @ vAA<- r1 8065 GET_INST_OPCODE(ip) @ extract opcode from rINST 8066 GOTO_OPCODE(ip) @ jump to next instruction 8067 8068 8069/* continuation for OP_AGET_WIDE */ 8070 8071.LOP_AGET_WIDE_finish: 8072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8073 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8074 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8075 GET_INST_OPCODE(ip) @ extract opcode from rINST 8076 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8077 GOTO_OPCODE(ip) @ jump to next instruction 8078 8079 8080/* continuation for OP_APUT_WIDE */ 8081 8082.LOP_APUT_WIDE_finish: 8083 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8084 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8085 GET_INST_OPCODE(ip) @ extract opcode from rINST 8086 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8087 GOTO_OPCODE(ip) @ jump to next instruction 8088 8089 8090/* continuation for OP_APUT_OBJECT */ 8091 /* 8092 * On entry: 8093 * r1 = vBB (arrayObj) 8094 * r9 = vAA (obj) 8095 * r10 = offset into array (vBB + vCC * width) 8096 */ 8097.LOP_APUT_OBJECT_finish: 8098 cmp r9, #0 @ storing null reference? 8099 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8100 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8101 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8102 bl dvmCanPutArrayElement @ test object type vs. array type 8103 cmp r0, #0 @ okay? 8104 beq common_errArrayStore @ no 8105.LOP_APUT_OBJECT_skip_check: 8106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8107 GET_INST_OPCODE(ip) @ extract opcode from rINST 8108 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8109 GOTO_OPCODE(ip) @ jump to next instruction 8110 8111 8112/* continuation for OP_IGET */ 8113 8114 /* 8115 * Currently: 8116 * r0 holds resolved field 8117 * r9 holds object 8118 */ 8119.LOP_IGET_finish: 8120 @bl common_squeak0 8121 cmp r9, #0 @ check object for null 8122 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8123 beq common_errNullObject @ object was null 8124 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8125 ubfx r2, rINST, #8, #4 @ r2<- A 8126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8127 GET_INST_OPCODE(ip) @ extract opcode from rINST 8128 SET_VREG(r0, r2) @ fp[A]<- r0 8129 GOTO_OPCODE(ip) @ jump to next instruction 8130 8131 8132/* continuation for OP_IGET_WIDE */ 8133 8134 /* 8135 * Currently: 8136 * r0 holds resolved field 8137 * r9 holds object 8138 */ 8139.LOP_IGET_WIDE_finish: 8140 cmp r9, #0 @ check object for null 8141 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8142 beq common_errNullObject @ object was null 8143 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8144 ubfx r2, rINST, #8, #4 @ r2<- A 8145 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8146 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8147 GET_INST_OPCODE(ip) @ extract opcode from rINST 8148 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8149 GOTO_OPCODE(ip) @ jump to next instruction 8150 8151 8152/* continuation for OP_IGET_OBJECT */ 8153 8154 /* 8155 * Currently: 8156 * r0 holds resolved field 8157 * r9 holds object 8158 */ 8159.LOP_IGET_OBJECT_finish: 8160 @bl common_squeak0 8161 cmp r9, #0 @ check object for null 8162 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8163 beq common_errNullObject @ object was null 8164 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8165 mov r2, rINST, lsr #8 @ r2<- A+ 8166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8167 and r2, r2, #15 @ r2<- A 8168 GET_INST_OPCODE(ip) @ extract opcode from rINST 8169 SET_VREG(r0, r2) @ fp[A]<- r0 8170 GOTO_OPCODE(ip) @ jump to next instruction 8171 8172 8173/* continuation for OP_IGET_BOOLEAN */ 8174 8175 /* 8176 * Currently: 8177 * r0 holds resolved field 8178 * r9 holds object 8179 */ 8180.LOP_IGET_BOOLEAN_finish: 8181 @bl common_squeak1 8182 cmp r9, #0 @ check object for null 8183 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8184 beq common_errNullObject @ object was null 8185 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8186 mov r2, rINST, lsr #8 @ r2<- A+ 8187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8188 and r2, r2, #15 @ r2<- A 8189 GET_INST_OPCODE(ip) @ extract opcode from rINST 8190 SET_VREG(r0, r2) @ fp[A]<- r0 8191 GOTO_OPCODE(ip) @ jump to next instruction 8192 8193 8194/* continuation for OP_IGET_BYTE */ 8195 8196 /* 8197 * Currently: 8198 * r0 holds resolved field 8199 * r9 holds object 8200 */ 8201.LOP_IGET_BYTE_finish: 8202 @bl common_squeak2 8203 cmp r9, #0 @ check object for null 8204 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8205 beq common_errNullObject @ object was null 8206 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8207 mov r2, rINST, lsr #8 @ r2<- A+ 8208 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8209 and r2, r2, #15 @ r2<- A 8210 GET_INST_OPCODE(ip) @ extract opcode from rINST 8211 SET_VREG(r0, r2) @ fp[A]<- r0 8212 GOTO_OPCODE(ip) @ jump to next instruction 8213 8214 8215/* continuation for OP_IGET_CHAR */ 8216 8217 /* 8218 * Currently: 8219 * r0 holds resolved field 8220 * r9 holds object 8221 */ 8222.LOP_IGET_CHAR_finish: 8223 @bl common_squeak3 8224 cmp r9, #0 @ check object for null 8225 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8226 beq common_errNullObject @ object was null 8227 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8228 mov r2, rINST, lsr #8 @ r2<- A+ 8229 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8230 and r2, r2, #15 @ r2<- A 8231 GET_INST_OPCODE(ip) @ extract opcode from rINST 8232 SET_VREG(r0, r2) @ fp[A]<- r0 8233 GOTO_OPCODE(ip) @ jump to next instruction 8234 8235 8236/* continuation for OP_IGET_SHORT */ 8237 8238 /* 8239 * Currently: 8240 * r0 holds resolved field 8241 * r9 holds object 8242 */ 8243.LOP_IGET_SHORT_finish: 8244 @bl common_squeak4 8245 cmp r9, #0 @ check object for null 8246 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8247 beq common_errNullObject @ object was null 8248 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8249 mov r2, rINST, lsr #8 @ r2<- A+ 8250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8251 and r2, r2, #15 @ r2<- A 8252 GET_INST_OPCODE(ip) @ extract opcode from rINST 8253 SET_VREG(r0, r2) @ fp[A]<- r0 8254 GOTO_OPCODE(ip) @ jump to next instruction 8255 8256 8257/* continuation for OP_IPUT */ 8258 8259 /* 8260 * Currently: 8261 * r0 holds resolved field 8262 * r9 holds object 8263 */ 8264.LOP_IPUT_finish: 8265 @bl common_squeak0 8266 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8267 ubfx r1, rINST, #8, #4 @ r1<- A 8268 cmp r9, #0 @ check object for null 8269 GET_VREG(r0, r1) @ r0<- fp[A] 8270 beq common_errNullObject @ object was null 8271 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8272 GET_INST_OPCODE(ip) @ extract opcode from rINST 8273 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8274 GOTO_OPCODE(ip) @ jump to next instruction 8275 8276 8277/* continuation for OP_IPUT_WIDE */ 8278 8279 /* 8280 * Currently: 8281 * r0 holds resolved field 8282 * r9 holds object 8283 */ 8284.LOP_IPUT_WIDE_finish: 8285 ubfx r2, rINST, #8, #4 @ r2<- A 8286 cmp r9, #0 @ check object for null 8287 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8288 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8289 beq common_errNullObject @ object was null 8290 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8291 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8292 GET_INST_OPCODE(ip) @ extract opcode from rINST 8293 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8294 GOTO_OPCODE(ip) @ jump to next instruction 8295 8296 8297/* continuation for OP_IPUT_OBJECT */ 8298 8299 /* 8300 * Currently: 8301 * r0 holds resolved field 8302 * r9 holds object 8303 */ 8304.LOP_IPUT_OBJECT_finish: 8305 @bl common_squeak0 8306 mov r1, rINST, lsr #8 @ r1<- A+ 8307 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8308 and r1, r1, #15 @ r1<- A 8309 cmp r9, #0 @ check object for null 8310 GET_VREG(r0, r1) @ r0<- fp[A] 8311 beq common_errNullObject @ object was null 8312 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8313 GET_INST_OPCODE(ip) @ extract opcode from rINST 8314 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8315 GOTO_OPCODE(ip) @ jump to next instruction 8316 8317 8318/* continuation for OP_IPUT_BOOLEAN */ 8319 8320 /* 8321 * Currently: 8322 * r0 holds resolved field 8323 * r9 holds object 8324 */ 8325.LOP_IPUT_BOOLEAN_finish: 8326 @bl common_squeak1 8327 mov r1, rINST, lsr #8 @ r1<- A+ 8328 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8329 and r1, r1, #15 @ r1<- A 8330 cmp r9, #0 @ check object for null 8331 GET_VREG(r0, r1) @ r0<- fp[A] 8332 beq common_errNullObject @ object was null 8333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8334 GET_INST_OPCODE(ip) @ extract opcode from rINST 8335 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8336 GOTO_OPCODE(ip) @ jump to next instruction 8337 8338 8339/* continuation for OP_IPUT_BYTE */ 8340 8341 /* 8342 * Currently: 8343 * r0 holds resolved field 8344 * r9 holds object 8345 */ 8346.LOP_IPUT_BYTE_finish: 8347 @bl common_squeak2 8348 mov r1, rINST, lsr #8 @ r1<- A+ 8349 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8350 and r1, r1, #15 @ r1<- A 8351 cmp r9, #0 @ check object for null 8352 GET_VREG(r0, r1) @ r0<- fp[A] 8353 beq common_errNullObject @ object was null 8354 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8355 GET_INST_OPCODE(ip) @ extract opcode from rINST 8356 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8357 GOTO_OPCODE(ip) @ jump to next instruction 8358 8359 8360/* continuation for OP_IPUT_CHAR */ 8361 8362 /* 8363 * Currently: 8364 * r0 holds resolved field 8365 * r9 holds object 8366 */ 8367.LOP_IPUT_CHAR_finish: 8368 @bl common_squeak3 8369 mov r1, rINST, lsr #8 @ r1<- A+ 8370 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8371 and r1, r1, #15 @ r1<- A 8372 cmp r9, #0 @ check object for null 8373 GET_VREG(r0, r1) @ r0<- fp[A] 8374 beq common_errNullObject @ object was null 8375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8376 GET_INST_OPCODE(ip) @ extract opcode from rINST 8377 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8378 GOTO_OPCODE(ip) @ jump to next instruction 8379 8380 8381/* continuation for OP_IPUT_SHORT */ 8382 8383 /* 8384 * Currently: 8385 * r0 holds resolved field 8386 * r9 holds object 8387 */ 8388.LOP_IPUT_SHORT_finish: 8389 @bl common_squeak4 8390 mov r1, rINST, lsr #8 @ r1<- A+ 8391 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8392 and r1, r1, #15 @ r1<- A 8393 cmp r9, #0 @ check object for null 8394 GET_VREG(r0, r1) @ r0<- fp[A] 8395 beq common_errNullObject @ object was null 8396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8397 GET_INST_OPCODE(ip) @ extract opcode from rINST 8398 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8399 GOTO_OPCODE(ip) @ jump to next instruction 8400 8401 8402/* continuation for OP_SGET */ 8403 8404 /* 8405 * Continuation if the field has not yet been resolved. 8406 * r1: BBBB field ref 8407 */ 8408.LOP_SGET_resolve: 8409 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8410 EXPORT_PC() @ resolve() could throw, so export now 8411 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8412 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8413 cmp r0, #0 @ success? 8414 bne .LOP_SGET_finish @ yes, finish 8415 b common_exceptionThrown @ no, handle exception 8416 8417 8418/* continuation for OP_SGET_WIDE */ 8419 8420 /* 8421 * Continuation if the field has not yet been resolved. 8422 * r1: BBBB field ref 8423 */ 8424.LOP_SGET_WIDE_resolve: 8425 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8426 EXPORT_PC() @ resolve() could throw, so export now 8427 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8428 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8429 cmp r0, #0 @ success? 8430 bne .LOP_SGET_WIDE_finish @ yes, finish 8431 b common_exceptionThrown @ no, handle exception 8432 8433 8434/* continuation for OP_SGET_OBJECT */ 8435 8436 /* 8437 * Continuation if the field has not yet been resolved. 8438 * r1: BBBB field ref 8439 */ 8440.LOP_SGET_OBJECT_resolve: 8441 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8442 EXPORT_PC() @ resolve() could throw, so export now 8443 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8444 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8445 cmp r0, #0 @ success? 8446 bne .LOP_SGET_OBJECT_finish @ yes, finish 8447 b common_exceptionThrown @ no, handle exception 8448 8449 8450/* continuation for OP_SGET_BOOLEAN */ 8451 8452 /* 8453 * Continuation if the field has not yet been resolved. 8454 * r1: BBBB field ref 8455 */ 8456.LOP_SGET_BOOLEAN_resolve: 8457 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8458 EXPORT_PC() @ resolve() could throw, so export now 8459 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8460 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8461 cmp r0, #0 @ success? 8462 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8463 b common_exceptionThrown @ no, handle exception 8464 8465 8466/* continuation for OP_SGET_BYTE */ 8467 8468 /* 8469 * Continuation if the field has not yet been resolved. 8470 * r1: BBBB field ref 8471 */ 8472.LOP_SGET_BYTE_resolve: 8473 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8474 EXPORT_PC() @ resolve() could throw, so export now 8475 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8476 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8477 cmp r0, #0 @ success? 8478 bne .LOP_SGET_BYTE_finish @ yes, finish 8479 b common_exceptionThrown @ no, handle exception 8480 8481 8482/* continuation for OP_SGET_CHAR */ 8483 8484 /* 8485 * Continuation if the field has not yet been resolved. 8486 * r1: BBBB field ref 8487 */ 8488.LOP_SGET_CHAR_resolve: 8489 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8490 EXPORT_PC() @ resolve() could throw, so export now 8491 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8492 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8493 cmp r0, #0 @ success? 8494 bne .LOP_SGET_CHAR_finish @ yes, finish 8495 b common_exceptionThrown @ no, handle exception 8496 8497 8498/* continuation for OP_SGET_SHORT */ 8499 8500 /* 8501 * Continuation if the field has not yet been resolved. 8502 * r1: BBBB field ref 8503 */ 8504.LOP_SGET_SHORT_resolve: 8505 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8506 EXPORT_PC() @ resolve() could throw, so export now 8507 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8508 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8509 cmp r0, #0 @ success? 8510 bne .LOP_SGET_SHORT_finish @ yes, finish 8511 b common_exceptionThrown @ no, handle exception 8512 8513 8514/* continuation for OP_SPUT */ 8515 8516 /* 8517 * Continuation if the field has not yet been resolved. 8518 * r1: BBBB field ref 8519 */ 8520.LOP_SPUT_resolve: 8521 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8522 EXPORT_PC() @ resolve() could throw, so export now 8523 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8524 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8525 cmp r0, #0 @ success? 8526 bne .LOP_SPUT_finish @ yes, finish 8527 b common_exceptionThrown @ no, handle exception 8528 8529 8530/* continuation for OP_SPUT_WIDE */ 8531 8532 /* 8533 * Continuation if the field has not yet been resolved. 8534 * r1: BBBB field ref 8535 * r9: &fp[AA] 8536 */ 8537.LOP_SPUT_WIDE_resolve: 8538 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8539 EXPORT_PC() @ resolve() could throw, so export now 8540 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8541 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8542 cmp r0, #0 @ success? 8543 bne .LOP_SPUT_WIDE_finish @ yes, finish 8544 b common_exceptionThrown @ no, handle exception 8545 8546 8547/* continuation for OP_SPUT_OBJECT */ 8548 8549 /* 8550 * Continuation if the field has not yet been resolved. 8551 * r1: BBBB field ref 8552 */ 8553.LOP_SPUT_OBJECT_resolve: 8554 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8555 EXPORT_PC() @ resolve() could throw, so export now 8556 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8557 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8558 cmp r0, #0 @ success? 8559 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8560 b common_exceptionThrown @ no, handle exception 8561 8562 8563/* continuation for OP_SPUT_BOOLEAN */ 8564 8565 /* 8566 * Continuation if the field has not yet been resolved. 8567 * r1: BBBB field ref 8568 */ 8569.LOP_SPUT_BOOLEAN_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_SPUT_BOOLEAN_finish @ yes, finish 8576 b common_exceptionThrown @ no, handle exception 8577 8578 8579/* continuation for OP_SPUT_BYTE */ 8580 8581 /* 8582 * Continuation if the field has not yet been resolved. 8583 * r1: BBBB field ref 8584 */ 8585.LOP_SPUT_BYTE_resolve: 8586 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8587 EXPORT_PC() @ resolve() could throw, so export now 8588 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8589 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8590 cmp r0, #0 @ success? 8591 bne .LOP_SPUT_BYTE_finish @ yes, finish 8592 b common_exceptionThrown @ no, handle exception 8593 8594 8595/* continuation for OP_SPUT_CHAR */ 8596 8597 /* 8598 * Continuation if the field has not yet been resolved. 8599 * r1: BBBB field ref 8600 */ 8601.LOP_SPUT_CHAR_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_SPUT_CHAR_finish @ yes, finish 8608 b common_exceptionThrown @ no, handle exception 8609 8610 8611/* continuation for OP_SPUT_SHORT */ 8612 8613 /* 8614 * Continuation if the field has not yet been resolved. 8615 * r1: BBBB field ref 8616 */ 8617.LOP_SPUT_SHORT_resolve: 8618 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8619 EXPORT_PC() @ resolve() could throw, so export now 8620 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8621 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8622 cmp r0, #0 @ success? 8623 bne .LOP_SPUT_SHORT_finish @ yes, finish 8624 b common_exceptionThrown @ no, handle exception 8625 8626 8627/* continuation for OP_INVOKE_VIRTUAL */ 8628 8629 /* 8630 * At this point: 8631 * r0 = resolved base method 8632 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8633 */ 8634.LOP_INVOKE_VIRTUAL_continue: 8635 GET_VREG(r1, r10) @ r1<- "this" ptr 8636 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8637 cmp r1, #0 @ is "this" null? 8638 beq common_errNullObject @ null "this", throw exception 8639 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8640 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8641 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8642 bl common_invokeMethodNoRange @ continue on 8643 8644 8645/* continuation for OP_INVOKE_SUPER */ 8646 8647 /* 8648 * At this point: 8649 * r0 = resolved base method 8650 * r9 = method->clazz 8651 */ 8652.LOP_INVOKE_SUPER_continue: 8653 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8654 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8655 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8656 EXPORT_PC() @ must export for invoke 8657 cmp r2, r3 @ compare (methodIndex, vtableCount) 8658 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8659 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8660 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8661 bl common_invokeMethodNoRange @ continue on 8662 8663.LOP_INVOKE_SUPER_resolve: 8664 mov r0, r9 @ r0<- method->clazz 8665 mov r2, #METHOD_VIRTUAL @ resolver method type 8666 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8667 cmp r0, #0 @ got null? 8668 bne .LOP_INVOKE_SUPER_continue @ no, continue 8669 b common_exceptionThrown @ yes, handle exception 8670 8671 /* 8672 * Throw a NoSuchMethodError with the method name as the message. 8673 * r0 = resolved base method 8674 */ 8675.LOP_INVOKE_SUPER_nsm: 8676 ldr r1, [r0, #offMethod_name] @ r1<- method name 8677 b common_errNoSuchMethod 8678 8679 8680/* continuation for OP_INVOKE_DIRECT */ 8681 8682 /* 8683 * On entry: 8684 * r1 = reference (BBBB or CCCC) 8685 * r10 = "this" register 8686 */ 8687.LOP_INVOKE_DIRECT_resolve: 8688 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8689 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8690 mov r2, #METHOD_DIRECT @ resolver method type 8691 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8692 cmp r0, #0 @ got null? 8693 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8694 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8695 b common_exceptionThrown @ yes, handle exception 8696 8697 8698/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8699 8700 /* 8701 * At this point: 8702 * r0 = resolved base method 8703 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8704 */ 8705.LOP_INVOKE_VIRTUAL_RANGE_continue: 8706 GET_VREG(r1, r10) @ r1<- "this" ptr 8707 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8708 cmp r1, #0 @ is "this" null? 8709 beq common_errNullObject @ null "this", throw exception 8710 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8711 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8712 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8713 bl common_invokeMethodRange @ continue on 8714 8715 8716/* continuation for OP_INVOKE_SUPER_RANGE */ 8717 8718 /* 8719 * At this point: 8720 * r0 = resolved base method 8721 * r9 = method->clazz 8722 */ 8723.LOP_INVOKE_SUPER_RANGE_continue: 8724 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8725 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8726 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8727 EXPORT_PC() @ must export for invoke 8728 cmp r2, r3 @ compare (methodIndex, vtableCount) 8729 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8730 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8731 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8732 bl common_invokeMethodRange @ continue on 8733 8734.LOP_INVOKE_SUPER_RANGE_resolve: 8735 mov r0, r9 @ r0<- method->clazz 8736 mov r2, #METHOD_VIRTUAL @ resolver method type 8737 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8738 cmp r0, #0 @ got null? 8739 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8740 b common_exceptionThrown @ yes, handle exception 8741 8742 /* 8743 * Throw a NoSuchMethodError with the method name as the message. 8744 * r0 = resolved base method 8745 */ 8746.LOP_INVOKE_SUPER_RANGE_nsm: 8747 ldr r1, [r0, #offMethod_name] @ r1<- method name 8748 b common_errNoSuchMethod 8749 8750 8751/* continuation for OP_INVOKE_DIRECT_RANGE */ 8752 8753 /* 8754 * On entry: 8755 * r1 = reference (BBBB or CCCC) 8756 * r10 = "this" register 8757 */ 8758.LOP_INVOKE_DIRECT_RANGE_resolve: 8759 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8760 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8761 mov r2, #METHOD_DIRECT @ resolver method type 8762 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8763 cmp r0, #0 @ got null? 8764 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8765 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8766 b common_exceptionThrown @ yes, handle exception 8767 8768 8769/* continuation for OP_FLOAT_TO_LONG */ 8770/* 8771 * Convert the float in r0 to a long in r0/r1. 8772 * 8773 * We have to clip values to long min/max per the specification. The 8774 * expected common case is a "reasonable" value that converts directly 8775 * to modest integer. The EABI convert function isn't doing this for us. 8776 */ 8777f2l_doconv: 8778 stmfd sp!, {r4, lr} 8779 mov r1, #0x5f000000 @ (float)maxlong 8780 mov r4, r0 8781 bl __aeabi_fcmpge @ is arg >= maxlong? 8782 cmp r0, #0 @ nonzero == yes 8783 mvnne r0, #0 @ return maxlong (7fffffff) 8784 mvnne r1, #0x80000000 8785 ldmnefd sp!, {r4, pc} 8786 8787 mov r0, r4 @ recover arg 8788 mov r1, #0xdf000000 @ (float)minlong 8789 bl __aeabi_fcmple @ is arg <= minlong? 8790 cmp r0, #0 @ nonzero == yes 8791 movne r0, #0 @ return minlong (80000000) 8792 movne r1, #0x80000000 8793 ldmnefd sp!, {r4, pc} 8794 8795 mov r0, r4 @ recover arg 8796 mov r1, r4 8797 bl __aeabi_fcmpeq @ is arg == self? 8798 cmp r0, #0 @ zero == no 8799 moveq r1, #0 @ return zero for NaN 8800 ldmeqfd sp!, {r4, pc} 8801 8802 mov r0, r4 @ recover arg 8803 bl __aeabi_f2lz @ convert float to long 8804 ldmfd sp!, {r4, pc} 8805 8806 8807/* continuation for OP_DOUBLE_TO_LONG */ 8808/* 8809 * Convert the double in r0/r1 to a long in r0/r1. 8810 * 8811 * We have to clip values to long min/max per the specification. The 8812 * expected common case is a "reasonable" value that converts directly 8813 * to modest integer. The EABI convert function isn't doing this for us. 8814 */ 8815d2l_doconv: 8816 stmfd sp!, {r4, r5, lr} @ save regs 8817 mov r3, #0x43000000 @ maxlong, as a double (high word) 8818 add r3, #0x00e00000 @ 0x43e00000 8819 mov r2, #0 @ maxlong, as a double (low word) 8820 sub sp, sp, #4 @ align for EABI 8821 mov r4, r0 @ save a copy of r0 8822 mov r5, r1 @ and r1 8823 bl __aeabi_dcmpge @ is arg >= maxlong? 8824 cmp r0, #0 @ nonzero == yes 8825 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8826 mvnne r1, #0x80000000 8827 bne 1f 8828 8829 mov r0, r4 @ recover arg 8830 mov r1, r5 8831 mov r3, #0xc3000000 @ minlong, as a double (high word) 8832 add r3, #0x00e00000 @ 0xc3e00000 8833 mov r2, #0 @ minlong, as a double (low word) 8834 bl __aeabi_dcmple @ is arg <= minlong? 8835 cmp r0, #0 @ nonzero == yes 8836 movne r0, #0 @ return minlong (8000000000000000) 8837 movne r1, #0x80000000 8838 bne 1f 8839 8840 mov r0, r4 @ recover arg 8841 mov r1, r5 8842 mov r2, r4 @ compare against self 8843 mov r3, r5 8844 bl __aeabi_dcmpeq @ is arg == self? 8845 cmp r0, #0 @ zero == no 8846 moveq r1, #0 @ return zero for NaN 8847 beq 1f 8848 8849 mov r0, r4 @ recover arg 8850 mov r1, r5 8851 bl __aeabi_d2lz @ convert double to long 8852 88531: 8854 add sp, sp, #4 8855 ldmfd sp!, {r4, r5, pc} 8856 8857 8858/* continuation for OP_MUL_LONG */ 8859 8860.LOP_MUL_LONG_finish: 8861 GET_INST_OPCODE(ip) @ extract opcode from rINST 8862 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8863 GOTO_OPCODE(ip) @ jump to next instruction 8864 8865 8866/* continuation for OP_SHL_LONG */ 8867 8868.LOP_SHL_LONG_finish: 8869 mov r0, r0, asl r2 @ r0<- r0 << r2 8870 GET_INST_OPCODE(ip) @ extract opcode from rINST 8871 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8872 GOTO_OPCODE(ip) @ jump to next instruction 8873 8874 8875/* continuation for OP_SHR_LONG */ 8876 8877.LOP_SHR_LONG_finish: 8878 mov r1, r1, asr r2 @ r1<- r1 >> r2 8879 GET_INST_OPCODE(ip) @ extract opcode from rINST 8880 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8881 GOTO_OPCODE(ip) @ jump to next instruction 8882 8883 8884/* continuation for OP_USHR_LONG */ 8885 8886.LOP_USHR_LONG_finish: 8887 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8888 GET_INST_OPCODE(ip) @ extract opcode from rINST 8889 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8890 GOTO_OPCODE(ip) @ jump to next instruction 8891 8892 8893/* continuation for OP_SHL_LONG_2ADDR */ 8894 8895.LOP_SHL_LONG_2ADDR_finish: 8896 GET_INST_OPCODE(ip) @ extract opcode from rINST 8897 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8898 GOTO_OPCODE(ip) @ jump to next instruction 8899 8900 8901/* continuation for OP_SHR_LONG_2ADDR */ 8902 8903.LOP_SHR_LONG_2ADDR_finish: 8904 GET_INST_OPCODE(ip) @ extract opcode from rINST 8905 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8906 GOTO_OPCODE(ip) @ jump to next instruction 8907 8908 8909/* continuation for OP_USHR_LONG_2ADDR */ 8910 8911.LOP_USHR_LONG_2ADDR_finish: 8912 GET_INST_OPCODE(ip) @ extract opcode from rINST 8913 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8914 GOTO_OPCODE(ip) @ jump to next instruction 8915 8916 8917/* continuation for OP_EXECUTE_INLINE */ 8918 8919 /* 8920 * Extract args, call function. 8921 * r0 = #of args (0-4) 8922 * r10 = call index 8923 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8924 * 8925 * Other ideas: 8926 * - Use a jump table from the main piece to jump directly into the 8927 * AND/LDR pairs. Costs a data load, saves a branch. 8928 * - Have five separate pieces that do the loading, so we can work the 8929 * interleave a little better. Increases code size. 8930 */ 8931.LOP_EXECUTE_INLINE_continue: 8932 rsb r0, r0, #4 @ r0<- 4-r0 8933 FETCH(r9, 2) @ r9<- FEDC 8934 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8935 bl common_abort @ (skipped due to ARM prefetch) 89364: and ip, r9, #0xf000 @ isolate F 8937 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89383: and ip, r9, #0x0f00 @ isolate E 8939 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 89402: and ip, r9, #0x00f0 @ isolate D 8941 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 89421: and ip, r9, #0x000f @ isolate C 8943 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 89440: 8945 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 8946 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 8947 @ (not reached) 8948 8949.LOP_EXECUTE_INLINE_table: 8950 .word gDvmInlineOpsTable 8951 8952 8953/* continuation for OP_EXECUTE_INLINE_RANGE */ 8954 8955 /* 8956 * Extract args, call function. 8957 * r0 = #of args (0-4) 8958 * r10 = call index 8959 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8960 */ 8961.LOP_EXECUTE_INLINE_RANGE_continue: 8962 rsb r0, r0, #4 @ r0<- 4-r0 8963 FETCH(r9, 2) @ r9<- CCCC 8964 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8965 bl common_abort @ (skipped due to ARM prefetch) 89664: add ip, r9, #3 @ base+3 8967 GET_VREG(r3, ip) @ r3<- vBase[3] 89683: add ip, r9, #2 @ base+2 8969 GET_VREG(r2, ip) @ r2<- vBase[2] 89702: add ip, r9, #1 @ base+1 8971 GET_VREG(r1, ip) @ r1<- vBase[1] 89721: add ip, r9, #0 @ (nop) 8973 GET_VREG(r0, ip) @ r0<- vBase[0] 89740: 8975 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 8976 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 8977 @ (not reached) 8978 8979.LOP_EXECUTE_INLINE_RANGE_table: 8980 .word gDvmInlineOpsTable 8981 8982 8983 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8984 .global dvmAsmSisterEnd 8985dvmAsmSisterEnd: 8986 8987/* File: armv5te/footer.S */ 8988 8989/* 8990 * =========================================================================== 8991 * Common subroutines and data 8992 * =========================================================================== 8993 */ 8994 8995 8996 8997 .text 8998 .align 2 8999 9000#if defined(WITH_JIT) 9001#if defined(WITH_SELF_VERIFICATION) 9002 .global dvmJitToInterpPunt 9003dvmJitToInterpPunt: 9004 mov r2,#kSVSPunt @ r2<- interpreter entry point 9005 b dvmJitSelfVerificationEnd @ doesn't return 9006 9007 .global dvmJitToInterpSingleStep 9008dvmJitToInterpSingleStep: 9009 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9010 b dvmJitSelfVerificationEnd @ doesn't return 9011 9012 .global dvmJitToInterpTraceSelectNoChain 9013dvmJitToInterpTraceSelectNoChain: 9014 mov r0,rPC @ pass our target PC 9015 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point 9016 b dvmJitSelfVerificationEnd @ doesn't return 9017 9018 .global dvmJitToInterpTraceSelect 9019dvmJitToInterpTraceSelect: 9020 ldr r0,[lr, #-1] @ pass our target PC 9021 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9022 b dvmJitSelfVerificationEnd @ doesn't return 9023 9024 .global dvmJitToInterpBackwardBranch 9025dvmJitToInterpBackwardBranch: 9026 ldr r0,[lr, #-1] @ pass our target PC 9027 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9028 b dvmJitSelfVerificationEnd @ doesn't return 9029 9030 .global dvmJitToInterpNormal 9031dvmJitToInterpNormal: 9032 ldr r0,[lr, #-1] @ pass our target PC 9033 mov r2,#kSVSNormal @ r2<- interpreter entry point 9034 b dvmJitSelfVerificationEnd @ doesn't return 9035 9036 .global dvmJitToInterpNoChain 9037dvmJitToInterpNoChain: 9038 mov r0,rPC @ pass our target PC 9039 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9040 b dvmJitSelfVerificationEnd @ doesn't return 9041#else 9042/* 9043 * Return from the translation cache to the interpreter when the compiler is 9044 * having issues translating/executing a Dalvik instruction. We have to skip 9045 * the code cache lookup otherwise it is possible to indefinitely bouce 9046 * between the interpreter and the code cache if the instruction that fails 9047 * to be compiled happens to be at a trace start. 9048 */ 9049 .global dvmJitToInterpPunt 9050dvmJitToInterpPunt: 9051 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9052 mov rPC, r0 9053#ifdef JIT_STATS 9054 mov r0,lr 9055 bl dvmBumpPunt; 9056#endif 9057 EXPORT_PC() 9058 mov r0, #0 9059 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9060 adrl rIBASE, dvmAsmInstructionStart 9061 FETCH_INST() 9062 GET_INST_OPCODE(ip) 9063 GOTO_OPCODE(ip) 9064 9065/* 9066 * Return to the interpreter to handle a single instruction. 9067 * On entry: 9068 * r0 <= PC 9069 * r1 <= PC of resume instruction 9070 * lr <= resume point in translation 9071 */ 9072 .global dvmJitToInterpSingleStep 9073dvmJitToInterpSingleStep: 9074 str lr,[rGLUE,#offGlue_jitResume] 9075 str r1,[rGLUE,#offGlue_jitResumePC] 9076 mov r1,#kInterpEntryInstr 9077 @ enum is 4 byte in aapcs-EABI 9078 str r1, [rGLUE, #offGlue_entryPoint] 9079 mov rPC,r0 9080 EXPORT_PC() 9081 9082 adrl rIBASE, dvmAsmInstructionStart 9083 mov r2,#kJitSingleStep @ Ask for single step and then revert 9084 str r2,[rGLUE,#offGlue_jitState] 9085 mov r1,#1 @ set changeInterp to bail to debug interp 9086 b common_gotoBail 9087 9088/* 9089 * Return from the translation cache and immediately request 9090 * a translation for the exit target. Commonly used for callees. 9091 */ 9092 .global dvmJitToInterpTraceSelectNoChain 9093dvmJitToInterpTraceSelectNoChain: 9094#ifdef JIT_STATS 9095 bl dvmBumpNoChain 9096#endif 9097 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9098 mov r0,rPC 9099 bl dvmJitGetCodeAddr @ Is there a translation? 9100 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9101 mov r1, rPC @ arg1 of translation may need this 9102 mov lr, #0 @ in case target is HANDLER_INTERPRET 9103 cmp r0,#0 9104 bxne r0 @ continue native execution if so 9105 b 2f 9106 9107/* 9108 * Return from the translation cache and immediately request 9109 * a translation for the exit target. Commonly used following 9110 * invokes. 9111 */ 9112 .global dvmJitToInterpTraceSelect 9113dvmJitToInterpTraceSelect: 9114 ldr rPC,[lr, #-1] @ get our target PC 9115 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9116 add rINST,lr,#-5 @ save start of chain branch 9117 mov r0,rPC 9118 bl dvmJitGetCodeAddr @ Is there a translation? 9119 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9120 cmp r0,#0 9121 beq 2f 9122 mov r1,rINST 9123 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9124 mov r1, rPC @ arg1 of translation may need this 9125 mov lr, #0 @ in case target is HANDLER_INTERPRET 9126 cmp r0,#0 @ successful chain? 9127 bxne r0 @ continue native execution 9128 b toInterpreter @ didn't chain - resume with interpreter 9129 9130/* No translation, so request one if profiling isn't disabled*/ 91312: 9132 adrl rIBASE, dvmAsmInstructionStart 9133 GET_JIT_PROF_TABLE(r0) 9134 FETCH_INST() 9135 cmp r0, #0 9136 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9137 bne common_selectTrace 9138 GET_INST_OPCODE(ip) 9139 GOTO_OPCODE(ip) 9140 9141/* 9142 * Return from the translation cache to the interpreter. 9143 * The return was done with a BLX from thumb mode, and 9144 * the following 32-bit word contains the target rPC value. 9145 * Note that lr (r14) will have its low-order bit set to denote 9146 * its thumb-mode origin. 9147 * 9148 * We'll need to stash our lr origin away, recover the new 9149 * target and then check to see if there is a translation available 9150 * for our new target. If so, we do a translation chain and 9151 * go back to native execution. Otherwise, it's back to the 9152 * interpreter (after treating this entry as a potential 9153 * trace start). 9154 */ 9155 .global dvmJitToInterpNormal 9156dvmJitToInterpNormal: 9157 ldr rPC,[lr, #-1] @ get our target PC 9158 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9159 add rINST,lr,#-5 @ save start of chain branch 9160#ifdef JIT_STATS 9161 bl dvmBumpNormal 9162#endif 9163 mov r0,rPC 9164 bl dvmJitGetCodeAddr @ Is there a translation? 9165 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9166 cmp r0,#0 9167 beq toInterpreter @ go if not, otherwise do chain 9168 mov r1,rINST 9169 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9170 mov r1, rPC @ arg1 of translation may need this 9171 mov lr, #0 @ in case target is HANDLER_INTERPRET 9172 cmp r0,#0 @ successful chain? 9173 bxne r0 @ continue native execution 9174 b toInterpreter @ didn't chain - resume with interpreter 9175 9176/* 9177 * Return from the translation cache to the interpreter to do method invocation. 9178 * Check if translation exists for the callee, but don't chain to it. 9179 */ 9180 .global dvmJitToInterpNoChain 9181dvmJitToInterpNoChain: 9182#ifdef JIT_STATS 9183 bl dvmBumpNoChain 9184#endif 9185 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9186 mov r0,rPC 9187 bl dvmJitGetCodeAddr @ Is there a translation? 9188 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9189 mov r1, rPC @ arg1 of translation may need this 9190 mov lr, #0 @ in case target is HANDLER_INTERPRET 9191 cmp r0,#0 9192 bxne r0 @ continue native execution if so 9193#endif 9194 9195/* 9196 * No translation, restore interpreter regs and start interpreting. 9197 * rGLUE & rFP were preserved in the translated code, and rPC has 9198 * already been restored by the time we get here. We'll need to set 9199 * up rIBASE & rINST, and load the address of the JitTable into r0. 9200 */ 9201toInterpreter: 9202 EXPORT_PC() 9203 adrl rIBASE, dvmAsmInstructionStart 9204 FETCH_INST() 9205 GET_JIT_PROF_TABLE(r0) 9206 @ NOTE: intended fallthrough 9207/* 9208 * Common code to update potential trace start counter, and initiate 9209 * a trace-build if appropriate. On entry, rPC should point to the 9210 * next instruction to execute, and rINST should be already loaded with 9211 * the next opcode word, and r0 holds a pointer to the jit profile 9212 * table (pJitProfTable). 9213 */ 9214common_testUpdateProfile: 9215 cmp r0,#0 9216 GET_INST_OPCODE(ip) 9217 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9218 9219common_updateProfile: 9220 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9221 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9222 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9223 GET_INST_OPCODE(ip) 9224 subs r1,r1,#1 @ decrement counter 9225 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9226 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9227 9228/* 9229 * Here, we switch to the debug interpreter to request 9230 * trace selection. First, though, check to see if there 9231 * is already a native translation in place (and, if so, 9232 * jump to it now). 9233 */ 9234 GET_JIT_THRESHOLD(r1) 9235 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9236 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9237 EXPORT_PC() 9238 mov r0,rPC 9239 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9240 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9241 mov r1, rPC @ arg1 of translation may need this 9242 mov lr, #0 @ in case target is HANDLER_INTERPRET 9243 cmp r0,#0 9244#if !defined(WITH_SELF_VERIFICATION) 9245 bxne r0 @ jump to the translation 9246 mov r2,#kJitTSelectRequest @ ask for trace selection 9247 @ fall-through to common_selectTrace 9248#else 9249 moveq r2,#kJitTSelectRequest @ ask for trace selection 9250 beq common_selectTrace 9251 /* 9252 * At this point, we have a target translation. However, if 9253 * that translation is actually the interpret-only pseudo-translation 9254 * we want to treat it the same as no translation. 9255 */ 9256 mov r10, r0 @ save target 9257 bl dvmCompilerGetInterpretTemplate 9258 cmp r0, r10 @ special case? 9259 bne dvmJitSelfVerificationStart @ set up self verification 9260 GET_INST_OPCODE(ip) 9261 GOTO_OPCODE(ip) 9262 /* no return */ 9263#endif 9264 9265/* 9266 * On entry: 9267 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9268 */ 9269common_selectTrace: 9270 str r2,[rGLUE,#offGlue_jitState] 9271 mov r2,#kInterpEntryInstr @ normal entry reason 9272 str r2,[rGLUE,#offGlue_entryPoint] 9273 mov r1,#1 @ set changeInterp 9274 b common_gotoBail 9275 9276#if defined(WITH_SELF_VERIFICATION) 9277/* 9278 * Save PC and registers to shadow memory for self verification mode 9279 * before jumping to native translation. 9280 * On entry, r10 contains the address of the target translation. 9281 */ 9282dvmJitSelfVerificationStart: 9283 mov r0,rPC @ r0<- program counter 9284 mov r1,rFP @ r1<- frame pointer 9285 mov r2,rGLUE @ r2<- InterpState pointer 9286 mov r3,r10 @ r3<- target translation 9287 bl dvmSelfVerificationSaveState @ save registers to shadow space 9288 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9289 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9290 bx r10 @ jump to the translation 9291 9292/* 9293 * Restore PC, registers, and interpState to original values 9294 * before jumping back to the interpreter. 9295 */ 9296dvmJitSelfVerificationEnd: 9297 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9298 mov r1, #0 9299 str r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9300 mov r1,rFP @ pass ending fp 9301 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9302 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9303 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9304 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9305 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9306 cmp r1,#0 @ check for punt condition 9307 beq 1f 9308 mov r2,#kJitSelfVerification @ ask for self verification 9309 str r2,[rGLUE,#offGlue_jitState] 9310 mov r2,#kInterpEntryInstr @ normal entry reason 9311 str r2,[rGLUE,#offGlue_entryPoint] 9312 mov r1,#1 @ set changeInterp 9313 b common_gotoBail 9314 93151: @ exit to interpreter without check 9316 EXPORT_PC() 9317 adrl rIBASE, dvmAsmInstructionStart 9318 FETCH_INST() 9319 GET_INST_OPCODE(ip) 9320 GOTO_OPCODE(ip) 9321#endif 9322 9323#endif 9324 9325/* 9326 * Common code when a backward branch is taken. 9327 * 9328 * On entry: 9329 * r9 is PC adjustment *in bytes* 9330 */ 9331common_backwardBranch: 9332 mov r0, #kInterpEntryInstr 9333 bl common_periodicChecks 9334#if defined(WITH_JIT) 9335 GET_JIT_PROF_TABLE(r0) 9336 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9337 cmp r0,#0 9338 bne common_updateProfile 9339 GET_INST_OPCODE(ip) 9340 GOTO_OPCODE(ip) 9341#else 9342 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9343 GET_INST_OPCODE(ip) @ extract opcode from rINST 9344 GOTO_OPCODE(ip) @ jump to next instruction 9345#endif 9346 9347 9348/* 9349 * Need to see if the thread needs to be suspended or debugger/profiler 9350 * activity has begun. 9351 * 9352 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9353 * have to do the second ldr. 9354 * 9355 * TODO: reduce this so we're just checking a single location. 9356 * 9357 * On entry: 9358 * r0 is reentry type, e.g. kInterpEntryInstr 9359 * r9 is trampoline PC adjustment *in bytes* 9360 */ 9361common_periodicChecks: 9362 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9363 9364 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9365 str r0, [rGLUE, #offGlue_entryPoint] 9366 9367#if defined(WITH_DEBUGGER) 9368 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9369#endif 9370#if defined(WITH_PROFILER) 9371 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9372#endif 9373 9374 ldr r3, [r3] @ r3<- suspendCount (int) 9375 9376#if defined(WITH_DEBUGGER) 9377 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9378#endif 9379#if defined (WITH_PROFILER) 9380 ldr r2, [r2] @ r2<- activeProfilers (int) 9381#endif 9382 9383 cmp r3, #0 @ suspend pending? 9384 bne 2f @ yes, do full suspension check 9385 9386#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9387# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9388 orrs r1, r1, r2 @ r1<- r1 | r2 9389 cmp r1, #0 @ debugger attached or profiler started? 9390# elif defined(WITH_DEBUGGER) 9391 cmp r1, #0 @ debugger attached? 9392# elif defined(WITH_PROFILER) 9393 cmp r2, #0 @ profiler started? 9394# endif 9395 bne 3f @ debugger/profiler, switch interp 9396#endif 9397 9398 bx lr @ nothing to do, return 9399 94002: @ check suspend 9401#if defined(WITH_JIT) 9402 /* 9403 * Refresh the Jit's cached copy of profile table pointer. This pointer 9404 * doubles as the Jit's on/off switch. 9405 */ 9406 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable 9407 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9408 ldr r3, [r3] @ r10 <- pJitProfTable 9409 EXPORT_PC() @ need for precise GC 9410 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9411#else 9412 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9413 EXPORT_PC() @ need for precise GC 9414#endif 9415 b dvmCheckSuspendPending @ suspend if necessary, then return 9416 94173: @ debugger/profiler enabled, bail out 9418 add rPC, rPC, r9 @ update rPC 9419 mov r1, #1 @ "want switch" = true 9420 b common_gotoBail 9421 9422 9423/* 9424 * The equivalent of "goto bail", this calls through the "bail handler". 9425 * 9426 * State registers will be saved to the "glue" area before bailing. 9427 * 9428 * On entry: 9429 * r1 is "bool changeInterp", indicating if we want to switch to the 9430 * other interpreter or just bail all the way out 9431 */ 9432common_gotoBail: 9433 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9434 mov r0, rGLUE @ r0<- glue ptr 9435 b dvmMterpStdBail @ call(glue, changeInterp) 9436 9437 @add r1, r1, #1 @ using (boolean+1) 9438 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9439 @bl _longjmp @ does not return 9440 @bl common_abort 9441 9442 9443/* 9444 * Common code for method invocation with range. 9445 * 9446 * On entry: 9447 * r0 is "Method* methodToCall", the method we're trying to call 9448 */ 9449common_invokeMethodRange: 9450.LinvokeNewRange: 9451 @ prepare to copy args to "outs" area of current frame 9452 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9453 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9454 beq .LinvokeArgsDone @ if no args, skip the rest 9455 FETCH(r1, 2) @ r1<- CCCC 9456 9457 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9458 @ (very few methods have > 10 args; could unroll for common cases) 9459 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9460 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9461 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94621: ldr r1, [r3], #4 @ val = *fp++ 9463 subs r2, r2, #1 @ count-- 9464 str r1, [r10], #4 @ *outs++ = val 9465 bne 1b @ ...while count != 0 9466 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9467 b .LinvokeArgsDone 9468 9469/* 9470 * Common code for method invocation without range. 9471 * 9472 * On entry: 9473 * r0 is "Method* methodToCall", the method we're trying to call 9474 */ 9475common_invokeMethodNoRange: 9476.LinvokeNewNoRange: 9477 @ prepare to copy args to "outs" area of current frame 9478 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9479 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9480 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9481 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9482 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9483 beq .LinvokeArgsDone 9484 9485 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9486.LinvokeNonRange: 9487 rsb r2, r2, #5 @ r2<- 5-r2 9488 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9489 bl common_abort @ (skipped due to ARM prefetch) 94905: and ip, rINST, #0x0f00 @ isolate A 9491 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9492 mov r0, r0 @ nop 9493 str r2, [r10, #-4]! @ *--outs = vA 94944: and ip, r1, #0xf000 @ isolate G 9495 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9496 mov r0, r0 @ nop 9497 str r2, [r10, #-4]! @ *--outs = vG 94983: and ip, r1, #0x0f00 @ isolate F 9499 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9500 mov r0, r0 @ nop 9501 str r2, [r10, #-4]! @ *--outs = vF 95022: and ip, r1, #0x00f0 @ isolate E 9503 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9504 mov r0, r0 @ nop 9505 str r2, [r10, #-4]! @ *--outs = vE 95061: and ip, r1, #0x000f @ isolate D 9507 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9508 mov r0, r0 @ nop 9509 str r2, [r10, #-4]! @ *--outs = vD 95100: @ fall through to .LinvokeArgsDone 9511 9512.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9513 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9514 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9515 @ find space for the new stack frame, check for overflow 9516 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9517 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9518 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9519@ bl common_dumpRegs 9520 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9521 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9522 cmp r3, r9 @ bottom < interpStackEnd? 9523 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9524 blt .LstackOverflow @ yes, this frame will overflow stack 9525 9526 @ set up newSaveArea 9527#ifdef EASY_GDB 9528 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9529 str ip, [r10, #offStackSaveArea_prevSave] 9530#endif 9531 str rFP, [r10, #offStackSaveArea_prevFrame] 9532 str rPC, [r10, #offStackSaveArea_savedPc] 9533#if defined(WITH_JIT) 9534 mov r9, #0 9535 str r9, [r10, #offStackSaveArea_returnAddr] 9536#endif 9537 str r0, [r10, #offStackSaveArea_method] 9538 tst r3, #ACC_NATIVE 9539 bne .LinvokeNative 9540 9541 /* 9542 stmfd sp!, {r0-r3} 9543 bl common_printNewline 9544 mov r0, rFP 9545 mov r1, #0 9546 bl dvmDumpFp 9547 ldmfd sp!, {r0-r3} 9548 stmfd sp!, {r0-r3} 9549 mov r0, r1 9550 mov r1, r10 9551 bl dvmDumpFp 9552 bl common_printNewline 9553 ldmfd sp!, {r0-r3} 9554 */ 9555 9556 ldrh r9, [r2] @ r9 <- load INST from new PC 9557 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9558 mov rPC, r2 @ publish new rPC 9559 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9560 9561 @ Update "glue" values for the new method 9562 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9563 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9564 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9565#if defined(WITH_JIT) 9566 GET_JIT_PROF_TABLE(r0) 9567 mov rFP, r1 @ fp = newFp 9568 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9569 mov rINST, r9 @ publish new rINST 9570 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9571 cmp r0,#0 9572 bne common_updateProfile 9573 GOTO_OPCODE(ip) @ jump to next instruction 9574#else 9575 mov rFP, r1 @ fp = newFp 9576 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9577 mov rINST, r9 @ publish new rINST 9578 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9579 GOTO_OPCODE(ip) @ jump to next instruction 9580#endif 9581 9582.LinvokeNative: 9583 @ Prep for the native call 9584 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9585 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9586 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9587 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9588 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9589 mov r9, r3 @ r9<- glue->self (preserve) 9590 9591 mov r2, r0 @ r2<- methodToCall 9592 mov r0, r1 @ r0<- newFp (points to args) 9593 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9594 9595#ifdef ASSIST_DEBUGGER 9596 /* insert fake function header to help gdb find the stack frame */ 9597 b .Lskip 9598 .type dalvik_mterp, %function 9599dalvik_mterp: 9600 .fnstart 9601 MTERP_ENTRY1 9602 MTERP_ENTRY2 9603.Lskip: 9604#endif 9605 9606 @mov lr, pc @ set return addr 9607 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9608 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9609 9610#if defined(WITH_JIT) 9611 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9612#endif 9613 9614 @ native return; r9=self, r10=newSaveArea 9615 @ equivalent to dvmPopJniLocals 9616 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9617 ldr r1, [r9, #offThread_exception] @ check for exception 9618#if defined(WITH_JIT) 9619 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9620#endif 9621 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9622 cmp r1, #0 @ null? 9623 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9624#if defined(WITH_JIT) 9625 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9626#endif 9627 bne common_exceptionThrown @ no, handle exception 9628 9629 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9630 GET_INST_OPCODE(ip) @ extract opcode from rINST 9631 GOTO_OPCODE(ip) @ jump to next instruction 9632 9633.LstackOverflow: @ r0=methodToCall 9634 mov r1, r0 @ r1<- methodToCall 9635 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9636 bl dvmHandleStackOverflow 9637 b common_exceptionThrown 9638#ifdef ASSIST_DEBUGGER 9639 .fnend 9640#endif 9641 9642 9643 /* 9644 * Common code for method invocation, calling through "glue code". 9645 * 9646 * TODO: now that we have range and non-range invoke handlers, this 9647 * needs to be split into two. Maybe just create entry points 9648 * that set r9 and jump here? 9649 * 9650 * On entry: 9651 * r0 is "Method* methodToCall", the method we're trying to call 9652 * r9 is "bool methodCallRange", indicating if this is a /range variant 9653 */ 9654 .if 0 9655.LinvokeOld: 9656 sub sp, sp, #8 @ space for args + pad 9657 FETCH(ip, 2) @ ip<- FEDC or CCCC 9658 mov r2, r0 @ A2<- methodToCall 9659 mov r0, rGLUE @ A0<- glue 9660 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9661 mov r1, r9 @ A1<- methodCallRange 9662 mov r3, rINST, lsr #8 @ A3<- AA 9663 str ip, [sp, #0] @ A4<- ip 9664 bl dvmMterp_invokeMethod @ call the C invokeMethod 9665 add sp, sp, #8 @ remove arg area 9666 b common_resumeAfterGlueCall @ continue to next instruction 9667 .endif 9668 9669 9670 9671/* 9672 * Common code for handling a return instruction. 9673 * 9674 * This does not return. 9675 */ 9676common_returnFromMethod: 9677.LreturnNew: 9678 mov r0, #kInterpEntryReturn 9679 mov r9, #0 9680 bl common_periodicChecks 9681 9682 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9683 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9684 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9685 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9686 @ r2<- method we're returning to 9687 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9688 cmp r2, #0 @ is this a break frame? 9689 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9690 mov r1, #0 @ "want switch" = false 9691 beq common_gotoBail @ break frame, bail out completely 9692 9693 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9694 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9695 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9696 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9697#if defined(WITH_JIT) 9698 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 9699 GET_JIT_PROF_TABLE(r0) 9700 mov rPC, r9 @ publish new rPC 9701 str r1, [rGLUE, #offGlue_methodClassDex] 9702 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 9703 cmp r10, #0 @ caller is compiled code 9704 blxne r10 9705 GET_INST_OPCODE(ip) @ extract opcode from rINST 9706 cmp r0,#0 9707 bne common_updateProfile 9708 GOTO_OPCODE(ip) @ jump to next instruction 9709#else 9710 GET_INST_OPCODE(ip) @ extract opcode from rINST 9711 mov rPC, r9 @ publish new rPC 9712 str r1, [rGLUE, #offGlue_methodClassDex] 9713 GOTO_OPCODE(ip) @ jump to next instruction 9714#endif 9715 9716 /* 9717 * Return handling, calls through "glue code". 9718 */ 9719 .if 0 9720.LreturnOld: 9721 SAVE_PC_FP_TO_GLUE() @ export state 9722 mov r0, rGLUE @ arg to function 9723 bl dvmMterp_returnFromMethod 9724 b common_resumeAfterGlueCall 9725 .endif 9726 9727 9728/* 9729 * Somebody has thrown an exception. Handle it. 9730 * 9731 * If the exception processing code returns to us (instead of falling 9732 * out of the interpreter), continue with whatever the next instruction 9733 * now happens to be. 9734 * 9735 * This does not return. 9736 */ 9737 .global dvmMterpCommonExceptionThrown 9738dvmMterpCommonExceptionThrown: 9739common_exceptionThrown: 9740.LexceptionNew: 9741 mov r0, #kInterpEntryThrow 9742 mov r9, #0 9743 bl common_periodicChecks 9744 9745 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9746 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9747 mov r1, r10 @ r1<- self 9748 mov r0, r9 @ r0<- exception 9749 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9750 mov r3, #0 @ r3<- NULL 9751 str r3, [r10, #offThread_exception] @ self->exception = NULL 9752 9753 /* set up args and a local for "&fp" */ 9754 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9755 str rFP, [sp, #-4]! @ *--sp = fp 9756 mov ip, sp @ ip<- &fp 9757 mov r3, #0 @ r3<- false 9758 str ip, [sp, #-4]! @ *--sp = &fp 9759 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9760 mov r0, r10 @ r0<- self 9761 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9762 mov r2, r9 @ r2<- exception 9763 sub r1, rPC, r1 @ r1<- pc - method->insns 9764 mov r1, r1, asr #1 @ r1<- offset in code units 9765 9766 /* call, r0 gets catchRelPc (a code-unit offset) */ 9767 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9768 9769 /* fix earlier stack overflow if necessary; may trash rFP */ 9770 ldrb r1, [r10, #offThread_stackOverflowed] 9771 cmp r1, #0 @ did we overflow earlier? 9772 beq 1f @ no, skip ahead 9773 mov rFP, r0 @ save relPc result in rFP 9774 mov r0, r10 @ r0<- self 9775 mov r1, r9 @ r1<- exception 9776 bl dvmCleanupStackOverflow @ call(self) 9777 mov r0, rFP @ restore result 97781: 9779 9780 /* update frame pointer and check result from dvmFindCatchBlock */ 9781 ldr rFP, [sp, #4] @ retrieve the updated rFP 9782 cmp r0, #0 @ is catchRelPc < 0? 9783 add sp, sp, #8 @ restore stack 9784 bmi .LnotCaughtLocally 9785 9786 /* adjust locals to match self->curFrame and updated PC */ 9787 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9788 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9789 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9790 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9791 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9792 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9793 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9794 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9795 9796 /* release the tracked alloc on the exception */ 9797 mov r0, r9 @ r0<- exception 9798 mov r1, r10 @ r1<- self 9799 bl dvmReleaseTrackedAlloc @ release the exception 9800 9801 /* restore the exception if the handler wants it */ 9802 FETCH_INST() @ load rINST from rPC 9803 GET_INST_OPCODE(ip) @ extract opcode from rINST 9804 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9805 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9806 GOTO_OPCODE(ip) @ jump to next instruction 9807 9808.LnotCaughtLocally: @ r9=exception, r10=self 9809 /* fix stack overflow if necessary */ 9810 ldrb r1, [r10, #offThread_stackOverflowed] 9811 cmp r1, #0 @ did we overflow earlier? 9812 movne r0, r10 @ if yes: r0<- self 9813 movne r1, r9 @ if yes: r1<- exception 9814 blne dvmCleanupStackOverflow @ if yes: call(self) 9815 9816 @ may want to show "not caught locally" debug messages here 9817#if DVM_SHOW_EXCEPTION >= 2 9818 /* call __android_log_print(prio, tag, format, ...) */ 9819 /* "Exception %s from %s:%d not caught locally" */ 9820 @ dvmLineNumFromPC(method, pc - method->insns) 9821 ldr r0, [rGLUE, #offGlue_method] 9822 ldr r1, [r0, #offMethod_insns] 9823 sub r1, rPC, r1 9824 asr r1, r1, #1 9825 bl dvmLineNumFromPC 9826 str r0, [sp, #-4]! 9827 @ dvmGetMethodSourceFile(method) 9828 ldr r0, [rGLUE, #offGlue_method] 9829 bl dvmGetMethodSourceFile 9830 str r0, [sp, #-4]! 9831 @ exception->clazz->descriptor 9832 ldr r3, [r9, #offObject_clazz] 9833 ldr r3, [r3, #offClassObject_descriptor] 9834 @ 9835 ldr r2, strExceptionNotCaughtLocally 9836 ldr r1, strLogTag 9837 mov r0, #3 @ LOG_DEBUG 9838 bl __android_log_print 9839#endif 9840 str r9, [r10, #offThread_exception] @ restore exception 9841 mov r0, r9 @ r0<- exception 9842 mov r1, r10 @ r1<- self 9843 bl dvmReleaseTrackedAlloc @ release the exception 9844 mov r1, #0 @ "want switch" = false 9845 b common_gotoBail @ bail out 9846 9847 9848 /* 9849 * Exception handling, calls through "glue code". 9850 */ 9851 .if 0 9852.LexceptionOld: 9853 SAVE_PC_FP_TO_GLUE() @ export state 9854 mov r0, rGLUE @ arg to function 9855 bl dvmMterp_exceptionThrown 9856 b common_resumeAfterGlueCall 9857 .endif 9858 9859 9860/* 9861 * After returning from a "glued" function, pull out the updated 9862 * values and start executing at the next instruction. 9863 */ 9864common_resumeAfterGlueCall: 9865 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9866 FETCH_INST() @ load rINST from rPC 9867 GET_INST_OPCODE(ip) @ extract opcode from rINST 9868 GOTO_OPCODE(ip) @ jump to next instruction 9869 9870/* 9871 * Invalid array index. 9872 */ 9873common_errArrayIndex: 9874 EXPORT_PC() 9875 ldr r0, strArrayIndexException 9876 mov r1, #0 9877 bl dvmThrowException 9878 b common_exceptionThrown 9879 9880/* 9881 * Invalid array value. 9882 */ 9883common_errArrayStore: 9884 EXPORT_PC() 9885 ldr r0, strArrayStoreException 9886 mov r1, #0 9887 bl dvmThrowException 9888 b common_exceptionThrown 9889 9890/* 9891 * Integer divide or mod by zero. 9892 */ 9893common_errDivideByZero: 9894 EXPORT_PC() 9895 ldr r0, strArithmeticException 9896 ldr r1, strDivideByZero 9897 bl dvmThrowException 9898 b common_exceptionThrown 9899 9900/* 9901 * Attempt to allocate an array with a negative size. 9902 */ 9903common_errNegativeArraySize: 9904 EXPORT_PC() 9905 ldr r0, strNegativeArraySizeException 9906 mov r1, #0 9907 bl dvmThrowException 9908 b common_exceptionThrown 9909 9910/* 9911 * Invocation of a non-existent method. 9912 */ 9913common_errNoSuchMethod: 9914 EXPORT_PC() 9915 ldr r0, strNoSuchMethodError 9916 mov r1, #0 9917 bl dvmThrowException 9918 b common_exceptionThrown 9919 9920/* 9921 * We encountered a null object when we weren't expecting one. We 9922 * export the PC, throw a NullPointerException, and goto the exception 9923 * processing code. 9924 */ 9925common_errNullObject: 9926 EXPORT_PC() 9927 ldr r0, strNullPointerException 9928 mov r1, #0 9929 bl dvmThrowException 9930 b common_exceptionThrown 9931 9932/* 9933 * For debugging, cause an immediate fault. The source address will 9934 * be in lr (use a bl instruction to jump here). 9935 */ 9936common_abort: 9937 ldr pc, .LdeadFood 9938.LdeadFood: 9939 .word 0xdeadf00d 9940 9941/* 9942 * Spit out a "we were here", preserving all registers. (The attempt 9943 * to save ip won't work, but we need to save an even number of 9944 * registers for EABI 64-bit stack alignment.) 9945 */ 9946 .macro SQUEAK num 9947common_squeak\num: 9948 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9949 ldr r0, strSqueak 9950 mov r1, #\num 9951 bl printf 9952 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9953 bx lr 9954 .endm 9955 9956 SQUEAK 0 9957 SQUEAK 1 9958 SQUEAK 2 9959 SQUEAK 3 9960 SQUEAK 4 9961 SQUEAK 5 9962 9963/* 9964 * Spit out the number in r0, preserving registers. 9965 */ 9966common_printNum: 9967 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9968 mov r1, r0 9969 ldr r0, strSqueak 9970 bl printf 9971 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9972 bx lr 9973 9974/* 9975 * Print a newline, preserving registers. 9976 */ 9977common_printNewline: 9978 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9979 ldr r0, strNewline 9980 bl printf 9981 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9982 bx lr 9983 9984 /* 9985 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9986 */ 9987common_printHex: 9988 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9989 mov r1, r0 9990 ldr r0, strPrintHex 9991 bl printf 9992 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9993 bx lr 9994 9995/* 9996 * Print the 64-bit quantity in r0-r1, preserving registers. 9997 */ 9998common_printLong: 9999 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10000 mov r3, r1 10001 mov r2, r0 10002 ldr r0, strPrintLong 10003 bl printf 10004 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10005 bx lr 10006 10007/* 10008 * Print full method info. Pass the Method* in r0. Preserves regs. 10009 */ 10010common_printMethod: 10011 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10012 bl dvmMterpPrintMethod 10013 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10014 bx lr 10015 10016/* 10017 * Call a C helper function that dumps regs and possibly some 10018 * additional info. Requires the C function to be compiled in. 10019 */ 10020 .if 0 10021common_dumpRegs: 10022 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10023 bl dvmMterpDumpArmRegs 10024 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10025 bx lr 10026 .endif 10027 10028#if 0 10029/* 10030 * Experiment on VFP mode. 10031 * 10032 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10033 * 10034 * Updates the bits specified by "mask", setting them to the values in "val". 10035 */ 10036setFPSCR: 10037 and r0, r0, r1 @ make sure no stray bits are set 10038 fmrx r2, fpscr @ get VFP reg 10039 mvn r1, r1 @ bit-invert mask 10040 and r2, r2, r1 @ clear masked bits 10041 orr r2, r2, r0 @ set specified bits 10042 fmxr fpscr, r2 @ set VFP reg 10043 mov r0, r2 @ return new value 10044 bx lr 10045 10046 .align 2 10047 .global dvmConfigureFP 10048 .type dvmConfigureFP, %function 10049dvmConfigureFP: 10050 stmfd sp!, {ip, lr} 10051 /* 0x03000000 sets DN/FZ */ 10052 /* 0x00009f00 clears the six exception enable flags */ 10053 bl common_squeak0 10054 mov r0, #0x03000000 @ r0<- 0x03000000 10055 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10056 bl setFPSCR 10057 ldmfd sp!, {ip, pc} 10058#endif 10059 10060 10061/* 10062 * String references, must be close to the code that uses them. 10063 */ 10064 .align 2 10065strArithmeticException: 10066 .word .LstrArithmeticException 10067strArrayIndexException: 10068 .word .LstrArrayIndexException 10069strArrayStoreException: 10070 .word .LstrArrayStoreException 10071strDivideByZero: 10072 .word .LstrDivideByZero 10073strNegativeArraySizeException: 10074 .word .LstrNegativeArraySizeException 10075strNoSuchMethodError: 10076 .word .LstrNoSuchMethodError 10077strNullPointerException: 10078 .word .LstrNullPointerException 10079 10080strLogTag: 10081 .word .LstrLogTag 10082strExceptionNotCaughtLocally: 10083 .word .LstrExceptionNotCaughtLocally 10084 10085strNewline: 10086 .word .LstrNewline 10087strSqueak: 10088 .word .LstrSqueak 10089strPrintHex: 10090 .word .LstrPrintHex 10091strPrintLong: 10092 .word .LstrPrintLong 10093 10094/* 10095 * Zero-terminated ASCII string data. 10096 * 10097 * On ARM we have two choices: do like gcc does, and LDR from a .word 10098 * with the address, or use an ADR pseudo-op to get the address 10099 * directly. ADR saves 4 bytes and an indirection, but it's using a 10100 * PC-relative addressing mode and hence has a limited range, which 10101 * makes it not work well with mergeable string sections. 10102 */ 10103 .section .rodata.str1.4,"aMS",%progbits,1 10104 10105.LstrBadEntryPoint: 10106 .asciz "Bad entry point %d\n" 10107.LstrArithmeticException: 10108 .asciz "Ljava/lang/ArithmeticException;" 10109.LstrArrayIndexException: 10110 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10111.LstrArrayStoreException: 10112 .asciz "Ljava/lang/ArrayStoreException;" 10113.LstrClassCastException: 10114 .asciz "Ljava/lang/ClassCastException;" 10115.LstrDivideByZero: 10116 .asciz "divide by zero" 10117.LstrFilledNewArrayNotImpl: 10118 .asciz "filled-new-array only implemented for objects and 'int'" 10119.LstrInternalError: 10120 .asciz "Ljava/lang/InternalError;" 10121.LstrInstantiationError: 10122 .asciz "Ljava/lang/InstantiationError;" 10123.LstrNegativeArraySizeException: 10124 .asciz "Ljava/lang/NegativeArraySizeException;" 10125.LstrNoSuchMethodError: 10126 .asciz "Ljava/lang/NoSuchMethodError;" 10127.LstrNullPointerException: 10128 .asciz "Ljava/lang/NullPointerException;" 10129 10130.LstrLogTag: 10131 .asciz "mterp" 10132.LstrExceptionNotCaughtLocally: 10133 .asciz "Exception %s from %s:%d not caught locally\n" 10134 10135.LstrNewline: 10136 .asciz "\n" 10137.LstrSqueak: 10138 .asciz "<%d>" 10139.LstrPrintHex: 10140 .asciz "<0x%x>" 10141.LstrPrintLong: 10142 .asciz "<%lld>" 10143 10144 10145