1/* 2 * This file was generated automatically by gen-mterp.py for 'armv4t'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* 25 * ARMv5 definitions and declarations. 26 */ 27 28/* 29ARM EABI general notes: 30 31r0-r3 hold first 4 args to a method; they are not preserved across method calls 32r4-r8 are available for general use 33r9 is given special treatment in some situations, but not for us 34r10 (sl) seems to be generally available 35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 36r12 (ip) is scratch -- not preserved across method calls 37r13 (sp) should be managed carefully in case a signal arrives 38r14 (lr) must be preserved 39r15 (pc) can be tinkered with directly 40 41r0 holds returns of <= 4 bytes 42r0-r1 hold returns of 8 bytes, low word in r0 43 44Callee must save/restore r4+ (except r12) if it modifies them. If VFP 45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 46s0-s15 (d0-d7, q0-a3) do not need to be. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59Mterp and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r4 rPC interpreted program counter, used for fetching instructions 65 r5 rFP interpreted frame pointer, used for accessing locals and args 66 r6 rGLUE MterpGlue pointer 67 r7 rINST first 16-bit code unit of current instruction 68 r8 rIBASE interpreted instruction base pointer, used for computed goto 69 70Macros are provided for common operations. Each macro MUST emit only 71one instruction to make instruction-counting easier. They MUST NOT alter 72unspecified registers or condition codes. 73*/ 74 75/* single-purpose registers, given names for clarity */ 76#define rPC r4 77#define rFP r5 78#define rGLUE r6 79#define rINST r7 80#define rIBASE r8 81 82/* save/restore the PC and/or FP from the glue struct */ 83#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 84#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 85#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 86#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 87#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 88#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 89 90/* 91 * "export" the PC to the stack frame, f/b/o future exception objects. Must 92 * be done *before* something calls dvmThrowException. 93 * 94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 96 * 97 * It's okay to do this more than once. 98 */ 99#define EXPORT_PC() \ 100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 101 102/* 103 * Given a frame pointer, find the stack save area. 104 * 105 * In C this is "((StackSaveArea*)(_fp) -1)". 106 */ 107#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 108 sub _reg, _fpreg, #sizeofStackSaveArea 109 110/* 111 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 112 */ 113#define FETCH_INST() ldrh rINST, [rPC] 114 115/* 116 * Fetch the next instruction from the specified offset. Advances rPC 117 * to point to the next instruction. "_count" is in 16-bit code units. 118 * 119 * Because of the limited size of immediate constants on ARM, this is only 120 * suitable for small forward movements (i.e. don't try to implement "goto" 121 * with this). 122 * 123 * This must come AFTER anything that can throw an exception, or the 124 * exception catch may miss. (This also implies that it must come after 125 * EXPORT_PC().) 126 */ 127#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 128 129/* 130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 131 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 132 */ 133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 134 ldrh _dreg, [_sreg, #(_count*2)]! 135 136/* 137 * Fetch the next instruction from an offset specified by _reg. Updates 138 * rPC to point to the next instruction. "_reg" must specify the distance 139 * in bytes, *not* 16-bit code units, and may be a signed value. 140 * 141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 142 * bits that hold the shift distance are used for the half/byte/sign flags. 143 * In some cases we can pre-double _reg for free, so we require a byte offset 144 * here. 145 */ 146#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 147 148/* 149 * Fetch a half-word code unit from an offset past the current PC. The 150 * "_count" value is in 16-bit code units. Does not advance rPC. 151 * 152 * The "_S" variant works the same but treats the value as signed. 153 */ 154#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 155#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 156 157/* 158 * Fetch one byte from an offset past the current PC. Pass in the same 159 * "_count" as you would for FETCH, and an additional 0/1 indicating which 160 * byte of the halfword you want (lo/hi). 161 */ 162#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 163 164/* 165 * Put the instruction's opcode field into the specified register. 166 */ 167#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 168 169/* 170 * Put the prefetched instruction's opcode field into the specified register. 171 */ 172#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 173 174/* 175 * Begin executing the opcode in _reg. Because this only jumps within the 176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 177 */ 178#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 180#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 181 182/* 183 * Get/set the 32-bit value from a Dalvik register. 184 */ 185#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 186#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 187 188#if defined(WITH_JIT) 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205#if defined(WITH_JIT) 206#include "../common/jit-config.h" 207#endif 208 209/* File: armv5te/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 218 * one-way branch. 219 * 220 * May modify IP. Does not modify LR. 221 */ 222.macro LDR_PC source 223 ldr pc, \source 224.endm 225 226/* 227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 228 * Jump to subroutine. 229 * 230 * May modify IP and LR. 231 */ 232.macro LDR_PC_LR source 233 mov lr, pc 234 ldr pc, \source 235.endm 236 237/* 238 * Macro for "LDMFD SP!, {...regs...,PC}". 239 * 240 * May modify IP and LR. 241 */ 242.macro LDMFD_PC regs 243 ldmfd sp!, {\regs,pc} 244.endm 245 246/* 247 * Macro for data memory barrier; not meaningful pre-ARMv6K. 248 */ 249.macro SMP_DMB 250.endm 251 252/* File: armv5te/entry.S */ 253/* 254 * Copyright (C) 2008 The Android Open Source Project 255 * 256 * Licensed under the Apache License, Version 2.0 (the "License"); 257 * you may not use this file except in compliance with the License. 258 * You may obtain a copy of the License at 259 * 260 * http://www.apache.org/licenses/LICENSE-2.0 261 * 262 * Unless required by applicable law or agreed to in writing, software 263 * distributed under the License is distributed on an "AS IS" BASIS, 264 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 265 * See the License for the specific language governing permissions and 266 * limitations under the License. 267 */ 268/* 269 * Interpreter entry point. 270 */ 271 272/* 273 * We don't have formal stack frames, so gdb scans upward in the code 274 * to find the start of the function (a label with the %function type), 275 * and then looks at the next few instructions to figure out what 276 * got pushed onto the stack. From this it figures out how to restore 277 * the registers, including PC, for the previous stack frame. If gdb 278 * sees a non-function label, it stops scanning, so either we need to 279 * have nothing but assembler-local labels between the entry point and 280 * the break, or we need to fake it out. 281 * 282 * When this is defined, we add some stuff to make gdb less confused. 283 */ 284#define ASSIST_DEBUGGER 1 285 286 .text 287 .align 2 288 .global dvmMterpStdRun 289 .type dvmMterpStdRun, %function 290 291/* 292 * On entry: 293 * r0 MterpGlue* glue 294 * 295 * This function returns a boolean "changeInterp" value. The return comes 296 * via a call to dvmMterpStdBail(). 297 */ 298dvmMterpStdRun: 299#define MTERP_ENTRY1 \ 300 .save {r4-r10,fp,lr}; \ 301 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 302#define MTERP_ENTRY2 \ 303 .pad #4; \ 304 sub sp, sp, #4 @ align 64 305 306 .fnstart 307 MTERP_ENTRY1 308 MTERP_ENTRY2 309 310 /* save stack pointer, add magic word for debuggerd */ 311 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 312 313 /* set up "named" registers, figure out entry point */ 314 mov rGLUE, r0 @ set rGLUE 315 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 316 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 317 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 318 cmp r1, #kInterpEntryInstr @ usual case? 319 bne .Lnot_instr @ no, handle it 320 321#if defined(WITH_JIT) 322.LentryInstr: 323 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 324 /* Entry is always a possible trace start */ 325 GET_JIT_PROF_TABLE(r0) 326 FETCH_INST() 327 mov r1, #0 @ prepare the value for the new state 328 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 329 cmp r0,#0 @ is profiling disabled? 330#if !defined(WITH_SELF_VERIFICATION) 331 bne common_updateProfile @ profiling is enabled 332#else 333 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 334 beq 1f @ profiling is disabled 335 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 336 cmp r3, #kSVSTraceSelect @ hot trace following? 337 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 338 beq common_selectTrace @ go build the trace 339 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 340 beq 1f @ intrepret the next instruction 341 b common_updateProfile @ collect profiles 342#endif 3431: 344 GET_INST_OPCODE(ip) 345 GOTO_OPCODE(ip) 346#else 347 /* start executing the instruction at rPC */ 348 FETCH_INST() @ load rINST from rPC 349 GET_INST_OPCODE(ip) @ extract opcode from rINST 350 GOTO_OPCODE(ip) @ jump to next instruction 351#endif 352 353.Lnot_instr: 354 cmp r1, #kInterpEntryReturn @ were we returning from a method? 355 beq common_returnFromMethod 356 357.Lnot_return: 358 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 359 beq common_exceptionThrown 360 361#if defined(WITH_JIT) 362.Lnot_throw: 363 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 364 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 365 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 366 bne .Lbad_arg 367 cmp rPC,r2 368 bne .LentryInstr @ must have branched, don't resume 369#if defined(WITH_SELF_VERIFICATION) 370 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 371 b jitSVShadowRunStart @ re-enter the translation after the 372 @ single-stepped instruction 373 @noreturn 374#endif 375 mov r1, #kInterpEntryInstr 376 str r1, [rGLUE, #offGlue_entryPoint] 377 bx r10 @ re-enter the translation 378#endif 379 380.Lbad_arg: 381 ldr r0, strBadEntryPoint 382 @ r1 holds value of entryPoint 383 bl printf 384 bl dvmAbort 385 .fnend 386 387 388 .global dvmMterpStdBail 389 .type dvmMterpStdBail, %function 390 391/* 392 * Restore the stack pointer and PC from the save point established on entry. 393 * This is essentially the same as a longjmp, but should be cheaper. The 394 * last instruction causes us to return to whoever called dvmMterpStdRun. 395 * 396 * We pushed some registers on the stack in dvmMterpStdRun, then saved 397 * SP and LR. Here we restore SP, restore the registers, and then restore 398 * LR to PC. 399 * 400 * On entry: 401 * r0 MterpGlue* glue 402 * r1 bool changeInterp 403 */ 404dvmMterpStdBail: 405 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 406 mov r0, r1 @ return the changeInterp value 407 add sp, sp, #4 @ un-align 64 408 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 409 410 411/* 412 * String references. 413 */ 414strBadEntryPoint: 415 .word .LstrBadEntryPoint 416 417 418 .global dvmAsmInstructionStart 419 .type dvmAsmInstructionStart, %function 420dvmAsmInstructionStart = .L_OP_NOP 421 .text 422 423/* ------------------------------ */ 424 .balign 64 425.L_OP_NOP: /* 0x00 */ 426/* File: armv5te/OP_NOP.S */ 427 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 428 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 429 GOTO_OPCODE(ip) @ execute it 430 431#ifdef ASSIST_DEBUGGER 432 /* insert fake function header to help gdb find the stack frame */ 433 .type dalvik_inst, %function 434dalvik_inst: 435 .fnstart 436 MTERP_ENTRY1 437 MTERP_ENTRY2 438 .fnend 439#endif 440 441/* ------------------------------ */ 442 .balign 64 443.L_OP_MOVE: /* 0x01 */ 444/* File: armv5te/OP_MOVE.S */ 445 /* for move, move-object, long-to-int */ 446 /* op vA, vB */ 447 mov r1, rINST, lsr #12 @ r1<- B from 15:12 448 mov r0, rINST, lsr #8 @ r0<- A from 11:8 449 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 450 GET_VREG(r2, r1) @ r2<- fp[B] 451 and r0, r0, #15 452 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 453 SET_VREG(r2, r0) @ fp[A]<- r2 454 GOTO_OPCODE(ip) @ execute next instruction 455 456/* ------------------------------ */ 457 .balign 64 458.L_OP_MOVE_FROM16: /* 0x02 */ 459/* File: armv5te/OP_MOVE_FROM16.S */ 460 /* for: move/from16, move-object/from16 */ 461 /* op vAA, vBBBB */ 462 FETCH(r1, 1) @ r1<- BBBB 463 mov r0, rINST, lsr #8 @ r0<- AA 464 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 465 GET_VREG(r2, r1) @ r2<- fp[BBBB] 466 GET_INST_OPCODE(ip) @ extract opcode from rINST 467 SET_VREG(r2, r0) @ fp[AA]<- r2 468 GOTO_OPCODE(ip) @ jump to next instruction 469 470/* ------------------------------ */ 471 .balign 64 472.L_OP_MOVE_16: /* 0x03 */ 473/* File: armv5te/OP_MOVE_16.S */ 474 /* for: move/16, move-object/16 */ 475 /* op vAAAA, vBBBB */ 476 FETCH(r1, 2) @ r1<- BBBB 477 FETCH(r0, 1) @ r0<- AAAA 478 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 479 GET_VREG(r2, r1) @ r2<- fp[BBBB] 480 GET_INST_OPCODE(ip) @ extract opcode from rINST 481 SET_VREG(r2, r0) @ fp[AAAA]<- r2 482 GOTO_OPCODE(ip) @ jump to next instruction 483 484/* ------------------------------ */ 485 .balign 64 486.L_OP_MOVE_WIDE: /* 0x04 */ 487/* File: armv5te/OP_MOVE_WIDE.S */ 488 /* move-wide vA, vB */ 489 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 490 mov r2, rINST, lsr #8 @ r2<- A(+) 491 mov r3, rINST, lsr #12 @ r3<- B 492 and r2, r2, #15 493 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 494 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 495 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 496 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 497 GET_INST_OPCODE(ip) @ extract opcode from rINST 498 stmia r2, {r0-r1} @ fp[A]<- r0/r1 499 GOTO_OPCODE(ip) @ jump to next instruction 500 501/* ------------------------------ */ 502 .balign 64 503.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 504/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 505 /* move-wide/from16 vAA, vBBBB */ 506 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 507 FETCH(r3, 1) @ r3<- BBBB 508 mov r2, rINST, lsr #8 @ r2<- AA 509 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 510 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 511 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 513 GET_INST_OPCODE(ip) @ extract opcode from rINST 514 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 515 GOTO_OPCODE(ip) @ jump to next instruction 516 517/* ------------------------------ */ 518 .balign 64 519.L_OP_MOVE_WIDE_16: /* 0x06 */ 520/* File: armv5te/OP_MOVE_WIDE_16.S */ 521 /* move-wide/16 vAAAA, vBBBB */ 522 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 523 FETCH(r3, 2) @ r3<- BBBB 524 FETCH(r2, 1) @ r2<- AAAA 525 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 526 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 527 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 528 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 529 GET_INST_OPCODE(ip) @ extract opcode from rINST 530 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 531 GOTO_OPCODE(ip) @ jump to next instruction 532 533/* ------------------------------ */ 534 .balign 64 535.L_OP_MOVE_OBJECT: /* 0x07 */ 536/* File: armv5te/OP_MOVE_OBJECT.S */ 537/* File: armv5te/OP_MOVE.S */ 538 /* for move, move-object, long-to-int */ 539 /* op vA, vB */ 540 mov r1, rINST, lsr #12 @ r1<- B from 15:12 541 mov r0, rINST, lsr #8 @ r0<- A from 11:8 542 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 543 GET_VREG(r2, r1) @ r2<- fp[B] 544 and r0, r0, #15 545 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 546 SET_VREG(r2, r0) @ fp[A]<- r2 547 GOTO_OPCODE(ip) @ execute next instruction 548 549 550/* ------------------------------ */ 551 .balign 64 552.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 553/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 554/* File: armv5te/OP_MOVE_FROM16.S */ 555 /* for: move/from16, move-object/from16 */ 556 /* op vAA, vBBBB */ 557 FETCH(r1, 1) @ r1<- BBBB 558 mov r0, rINST, lsr #8 @ r0<- AA 559 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 560 GET_VREG(r2, r1) @ r2<- fp[BBBB] 561 GET_INST_OPCODE(ip) @ extract opcode from rINST 562 SET_VREG(r2, r0) @ fp[AA]<- r2 563 GOTO_OPCODE(ip) @ jump to next instruction 564 565 566/* ------------------------------ */ 567 .balign 64 568.L_OP_MOVE_OBJECT_16: /* 0x09 */ 569/* File: armv5te/OP_MOVE_OBJECT_16.S */ 570/* File: armv5te/OP_MOVE_16.S */ 571 /* for: move/16, move-object/16 */ 572 /* op vAAAA, vBBBB */ 573 FETCH(r1, 2) @ r1<- BBBB 574 FETCH(r0, 1) @ r0<- AAAA 575 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 576 GET_VREG(r2, r1) @ r2<- fp[BBBB] 577 GET_INST_OPCODE(ip) @ extract opcode from rINST 578 SET_VREG(r2, r0) @ fp[AAAA]<- r2 579 GOTO_OPCODE(ip) @ jump to next instruction 580 581 582/* ------------------------------ */ 583 .balign 64 584.L_OP_MOVE_RESULT: /* 0x0a */ 585/* File: armv5te/OP_MOVE_RESULT.S */ 586 /* for: move-result, move-result-object */ 587 /* op vAA */ 588 mov r2, rINST, lsr #8 @ r2<- AA 589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 590 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 591 GET_INST_OPCODE(ip) @ extract opcode from rINST 592 SET_VREG(r0, r2) @ fp[AA]<- r0 593 GOTO_OPCODE(ip) @ jump to next instruction 594 595/* ------------------------------ */ 596 .balign 64 597.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 598/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 599 /* move-result-wide vAA */ 600 mov r2, rINST, lsr #8 @ r2<- AA 601 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 602 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 603 ldmia r3, {r0-r1} @ r0/r1<- retval.j 604 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 605 GET_INST_OPCODE(ip) @ extract opcode from rINST 606 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 607 GOTO_OPCODE(ip) @ jump to next instruction 608 609/* ------------------------------ */ 610 .balign 64 611.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 612/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 613/* File: armv5te/OP_MOVE_RESULT.S */ 614 /* for: move-result, move-result-object */ 615 /* op vAA */ 616 mov r2, rINST, lsr #8 @ r2<- AA 617 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 618 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 619 GET_INST_OPCODE(ip) @ extract opcode from rINST 620 SET_VREG(r0, r2) @ fp[AA]<- r0 621 GOTO_OPCODE(ip) @ jump to next instruction 622 623 624/* ------------------------------ */ 625 .balign 64 626.L_OP_MOVE_EXCEPTION: /* 0x0d */ 627/* File: armv5te/OP_MOVE_EXCEPTION.S */ 628 /* move-exception vAA */ 629 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 630 mov r2, rINST, lsr #8 @ r2<- AA 631 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 632 mov r1, #0 @ r1<- 0 633 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 634 SET_VREG(r3, r2) @ fp[AA]<- exception obj 635 GET_INST_OPCODE(ip) @ extract opcode from rINST 636 str r1, [r0, #offThread_exception] @ dvmClearException bypass 637 GOTO_OPCODE(ip) @ jump to next instruction 638 639/* ------------------------------ */ 640 .balign 64 641.L_OP_RETURN_VOID: /* 0x0e */ 642/* File: armv5te/OP_RETURN_VOID.S */ 643 b common_returnFromMethod 644 645/* ------------------------------ */ 646 .balign 64 647.L_OP_RETURN: /* 0x0f */ 648/* File: armv5te/OP_RETURN.S */ 649 /* 650 * Return a 32-bit value. Copies the return value into the "glue" 651 * structure, then jumps to the return handler. 652 * 653 * for: return, return-object 654 */ 655 /* op vAA */ 656 mov r2, rINST, lsr #8 @ r2<- AA 657 GET_VREG(r0, r2) @ r0<- vAA 658 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 659 b common_returnFromMethod 660 661/* ------------------------------ */ 662 .balign 64 663.L_OP_RETURN_WIDE: /* 0x10 */ 664/* File: armv5te/OP_RETURN_WIDE.S */ 665 /* 666 * Return a 64-bit value. Copies the return value into the "glue" 667 * structure, then jumps to the return handler. 668 */ 669 /* return-wide vAA */ 670 mov r2, rINST, lsr #8 @ r2<- AA 671 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 672 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 673 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 674 stmia r3, {r0-r1} @ retval<- r0/r1 675 b common_returnFromMethod 676 677/* ------------------------------ */ 678 .balign 64 679.L_OP_RETURN_OBJECT: /* 0x11 */ 680/* File: armv5te/OP_RETURN_OBJECT.S */ 681/* File: armv5te/OP_RETURN.S */ 682 /* 683 * Return a 32-bit value. Copies the return value into the "glue" 684 * structure, then jumps to the return handler. 685 * 686 * for: return, return-object 687 */ 688 /* op vAA */ 689 mov r2, rINST, lsr #8 @ r2<- AA 690 GET_VREG(r0, r2) @ r0<- vAA 691 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 692 b common_returnFromMethod 693 694 695/* ------------------------------ */ 696 .balign 64 697.L_OP_CONST_4: /* 0x12 */ 698/* File: armv5te/OP_CONST_4.S */ 699 /* const/4 vA, #+B */ 700 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 701 mov r0, rINST, lsr #8 @ r0<- A+ 702 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 703 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 704 and r0, r0, #15 705 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 706 SET_VREG(r1, r0) @ fp[A]<- r1 707 GOTO_OPCODE(ip) @ execute next instruction 708 709/* ------------------------------ */ 710 .balign 64 711.L_OP_CONST_16: /* 0x13 */ 712/* File: armv5te/OP_CONST_16.S */ 713 /* const/16 vAA, #+BBBB */ 714 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 715 mov r3, rINST, lsr #8 @ r3<- AA 716 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 717 SET_VREG(r0, r3) @ vAA<- r0 718 GET_INST_OPCODE(ip) @ extract opcode from rINST 719 GOTO_OPCODE(ip) @ jump to next instruction 720 721/* ------------------------------ */ 722 .balign 64 723.L_OP_CONST: /* 0x14 */ 724/* File: armv5te/OP_CONST.S */ 725 /* const vAA, #+BBBBbbbb */ 726 mov r3, rINST, lsr #8 @ r3<- AA 727 FETCH(r0, 1) @ r0<- bbbb (low) 728 FETCH(r1, 2) @ r1<- BBBB (high) 729 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 730 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 731 GET_INST_OPCODE(ip) @ extract opcode from rINST 732 SET_VREG(r0, r3) @ vAA<- r0 733 GOTO_OPCODE(ip) @ jump to next instruction 734 735/* ------------------------------ */ 736 .balign 64 737.L_OP_CONST_HIGH16: /* 0x15 */ 738/* File: armv5te/OP_CONST_HIGH16.S */ 739 /* const/high16 vAA, #+BBBB0000 */ 740 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 741 mov r3, rINST, lsr #8 @ r3<- AA 742 mov r0, r0, lsl #16 @ r0<- BBBB0000 743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 744 SET_VREG(r0, r3) @ vAA<- r0 745 GET_INST_OPCODE(ip) @ extract opcode from rINST 746 GOTO_OPCODE(ip) @ jump to next instruction 747 748/* ------------------------------ */ 749 .balign 64 750.L_OP_CONST_WIDE_16: /* 0x16 */ 751/* File: armv5te/OP_CONST_WIDE_16.S */ 752 /* const-wide/16 vAA, #+BBBB */ 753 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 754 mov r3, rINST, lsr #8 @ r3<- AA 755 mov r1, r0, asr #31 @ r1<- ssssssss 756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 757 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 758 GET_INST_OPCODE(ip) @ extract opcode from rINST 759 stmia r3, {r0-r1} @ vAA<- r0/r1 760 GOTO_OPCODE(ip) @ jump to next instruction 761 762/* ------------------------------ */ 763 .balign 64 764.L_OP_CONST_WIDE_32: /* 0x17 */ 765/* File: armv5te/OP_CONST_WIDE_32.S */ 766 /* const-wide/32 vAA, #+BBBBbbbb */ 767 FETCH(r0, 1) @ r0<- 0000bbbb (low) 768 mov r3, rINST, lsr #8 @ r3<- AA 769 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 770 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 771 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 772 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 773 mov r1, r0, asr #31 @ r1<- ssssssss 774 GET_INST_OPCODE(ip) @ extract opcode from rINST 775 stmia r3, {r0-r1} @ vAA<- r0/r1 776 GOTO_OPCODE(ip) @ jump to next instruction 777 778/* ------------------------------ */ 779 .balign 64 780.L_OP_CONST_WIDE: /* 0x18 */ 781/* File: armv5te/OP_CONST_WIDE.S */ 782 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 783 FETCH(r0, 1) @ r0<- bbbb (low) 784 FETCH(r1, 2) @ r1<- BBBB (low middle) 785 FETCH(r2, 3) @ r2<- hhhh (high middle) 786 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 787 FETCH(r3, 4) @ r3<- HHHH (high) 788 mov r9, rINST, lsr #8 @ r9<- AA 789 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 790 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 791 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 792 GET_INST_OPCODE(ip) @ extract opcode from rINST 793 stmia r9, {r0-r1} @ vAA<- r0/r1 794 GOTO_OPCODE(ip) @ jump to next instruction 795 796/* ------------------------------ */ 797 .balign 64 798.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 799/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 800 /* const-wide/high16 vAA, #+BBBB000000000000 */ 801 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 802 mov r3, rINST, lsr #8 @ r3<- AA 803 mov r0, #0 @ r0<- 00000000 804 mov r1, r1, lsl #16 @ r1<- BBBB0000 805 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 806 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 807 GET_INST_OPCODE(ip) @ extract opcode from rINST 808 stmia r3, {r0-r1} @ vAA<- r0/r1 809 GOTO_OPCODE(ip) @ jump to next instruction 810 811/* ------------------------------ */ 812 .balign 64 813.L_OP_CONST_STRING: /* 0x1a */ 814/* File: armv5te/OP_CONST_STRING.S */ 815 /* const/string vAA, String@BBBB */ 816 FETCH(r1, 1) @ r1<- BBBB 817 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 818 mov r9, rINST, lsr #8 @ r9<- AA 819 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 820 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 821 cmp r0, #0 @ not yet resolved? 822 beq .LOP_CONST_STRING_resolve 823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 824 GET_INST_OPCODE(ip) @ extract opcode from rINST 825 SET_VREG(r0, r9) @ vAA<- r0 826 GOTO_OPCODE(ip) @ jump to next instruction 827 828/* ------------------------------ */ 829 .balign 64 830.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 831/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 832 /* const/string vAA, String@BBBBBBBB */ 833 FETCH(r0, 1) @ r0<- bbbb (low) 834 FETCH(r1, 2) @ r1<- BBBB (high) 835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 836 mov r9, rINST, lsr #8 @ r9<- AA 837 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 838 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 839 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 840 cmp r0, #0 841 beq .LOP_CONST_STRING_JUMBO_resolve 842 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 843 GET_INST_OPCODE(ip) @ extract opcode from rINST 844 SET_VREG(r0, r9) @ vAA<- r0 845 GOTO_OPCODE(ip) @ jump to next instruction 846 847/* ------------------------------ */ 848 .balign 64 849.L_OP_CONST_CLASS: /* 0x1c */ 850/* File: armv5te/OP_CONST_CLASS.S */ 851 /* const/class vAA, Class@BBBB */ 852 FETCH(r1, 1) @ r1<- BBBB 853 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 854 mov r9, rINST, lsr #8 @ r9<- AA 855 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 856 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 857 cmp r0, #0 @ not yet resolved? 858 beq .LOP_CONST_CLASS_resolve 859 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 860 GET_INST_OPCODE(ip) @ extract opcode from rINST 861 SET_VREG(r0, r9) @ vAA<- r0 862 GOTO_OPCODE(ip) @ jump to next instruction 863 864/* ------------------------------ */ 865 .balign 64 866.L_OP_MONITOR_ENTER: /* 0x1d */ 867/* File: armv5te/OP_MONITOR_ENTER.S */ 868 /* 869 * Synchronize on an object. 870 */ 871 /* monitor-enter vAA */ 872 mov r2, rINST, lsr #8 @ r2<- AA 873 GET_VREG(r1, r2) @ r1<- vAA (object) 874 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 875 cmp r1, #0 @ null object? 876 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 877 beq common_errNullObject @ null object, throw an exception 878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 879 bl dvmLockObject @ call(self, obj) 880#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 881 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 882 ldr r1, [r0, #offThread_exception] @ check for exception 883 cmp r1, #0 884 bne common_exceptionThrown @ exception raised, bail out 885#endif 886 GET_INST_OPCODE(ip) @ extract opcode from rINST 887 GOTO_OPCODE(ip) @ jump to next instruction 888 889/* ------------------------------ */ 890 .balign 64 891.L_OP_MONITOR_EXIT: /* 0x1e */ 892/* File: armv5te/OP_MONITOR_EXIT.S */ 893 /* 894 * Unlock an object. 895 * 896 * Exceptions that occur when unlocking a monitor need to appear as 897 * if they happened at the following instruction. See the Dalvik 898 * instruction spec. 899 */ 900 /* monitor-exit vAA */ 901 mov r2, rINST, lsr #8 @ r2<- AA 902 EXPORT_PC() @ before fetch: export the PC 903 GET_VREG(r1, r2) @ r1<- vAA (object) 904 cmp r1, #0 @ null object? 905 beq 1f @ yes 906 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 907 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 908 cmp r0, #0 @ failed? 909 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 910 beq common_exceptionThrown @ yes, exception is pending 911 GET_INST_OPCODE(ip) @ extract opcode from rINST 912 GOTO_OPCODE(ip) @ jump to next instruction 9131: 914 FETCH_ADVANCE_INST(1) @ advance before throw 915 b common_errNullObject 916 917/* ------------------------------ */ 918 .balign 64 919.L_OP_CHECK_CAST: /* 0x1f */ 920/* File: armv5te/OP_CHECK_CAST.S */ 921 /* 922 * Check to see if a cast from one class to another is allowed. 923 */ 924 /* check-cast vAA, class@BBBB */ 925 mov r3, rINST, lsr #8 @ r3<- AA 926 FETCH(r2, 1) @ r2<- BBBB 927 GET_VREG(r9, r3) @ r9<- object 928 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 929 cmp r9, #0 @ is object null? 930 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 931 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 932 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 933 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 934 cmp r1, #0 @ have we resolved this before? 935 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 936.LOP_CHECK_CAST_resolved: 937 cmp r0, r1 @ same class (trivial success)? 938 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 939.LOP_CHECK_CAST_okay: 940 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 941 GET_INST_OPCODE(ip) @ extract opcode from rINST 942 GOTO_OPCODE(ip) @ jump to next instruction 943 944/* ------------------------------ */ 945 .balign 64 946.L_OP_INSTANCE_OF: /* 0x20 */ 947/* File: armv5te/OP_INSTANCE_OF.S */ 948 /* 949 * Check to see if an object reference is an instance of a class. 950 * 951 * Most common situation is a non-null object, being compared against 952 * an already-resolved class. 953 */ 954 /* instance-of vA, vB, class@CCCC */ 955 mov r3, rINST, lsr #12 @ r3<- B 956 mov r9, rINST, lsr #8 @ r9<- A+ 957 GET_VREG(r0, r3) @ r0<- vB (object) 958 and r9, r9, #15 @ r9<- A 959 cmp r0, #0 @ is object null? 960 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 961 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 962 FETCH(r3, 1) @ r3<- CCCC 963 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 964 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 965 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 966 cmp r1, #0 @ have we resolved this before? 967 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 968.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 969 cmp r0, r1 @ same class (trivial success)? 970 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 971 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 972 973/* ------------------------------ */ 974 .balign 64 975.L_OP_ARRAY_LENGTH: /* 0x21 */ 976/* File: armv5te/OP_ARRAY_LENGTH.S */ 977 /* 978 * Return the length of an array. 979 */ 980 mov r1, rINST, lsr #12 @ r1<- B 981 mov r2, rINST, lsr #8 @ r2<- A+ 982 GET_VREG(r0, r1) @ r0<- vB (object ref) 983 and r2, r2, #15 @ r2<- A 984 cmp r0, #0 @ is object null? 985 beq common_errNullObject @ yup, fail 986 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 987 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 988 GET_INST_OPCODE(ip) @ extract opcode from rINST 989 SET_VREG(r3, r2) @ vB<- length 990 GOTO_OPCODE(ip) @ jump to next instruction 991 992/* ------------------------------ */ 993 .balign 64 994.L_OP_NEW_INSTANCE: /* 0x22 */ 995/* File: armv5te/OP_NEW_INSTANCE.S */ 996 /* 997 * Create a new instance of a class. 998 */ 999 /* new-instance vAA, class@BBBB */ 1000 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1001 FETCH(r1, 1) @ r1<- BBBB 1002 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1003 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1004 EXPORT_PC() @ req'd for init, resolve, alloc 1005 cmp r0, #0 @ already resolved? 1006 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1007.LOP_NEW_INSTANCE_resolved: @ r0=class 1008 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1009 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1010 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1011.LOP_NEW_INSTANCE_initialized: @ r0=class 1012 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1013 bl dvmAllocObject @ r0<- new object 1014 b .LOP_NEW_INSTANCE_finish @ continue 1015 1016/* ------------------------------ */ 1017 .balign 64 1018.L_OP_NEW_ARRAY: /* 0x23 */ 1019/* File: armv5te/OP_NEW_ARRAY.S */ 1020 /* 1021 * Allocate an array of objects, specified with the array class 1022 * and a count. 1023 * 1024 * The verifier guarantees that this is an array class, so we don't 1025 * check for it here. 1026 */ 1027 /* new-array vA, vB, class@CCCC */ 1028 mov r0, rINST, lsr #12 @ r0<- B 1029 FETCH(r2, 1) @ r2<- CCCC 1030 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1031 GET_VREG(r1, r0) @ r1<- vB (array length) 1032 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1033 cmp r1, #0 @ check length 1034 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1035 bmi common_errNegativeArraySize @ negative length, bail 1036 cmp r0, #0 @ already resolved? 1037 EXPORT_PC() @ req'd for resolve, alloc 1038 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1039 b .LOP_NEW_ARRAY_resolve @ do resolve now 1040 1041/* ------------------------------ */ 1042 .balign 64 1043.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1044/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1045 /* 1046 * Create a new array with elements filled from registers. 1047 * 1048 * for: filled-new-array, filled-new-array/range 1049 */ 1050 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1051 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1052 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1053 FETCH(r1, 1) @ r1<- BBBB 1054 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1055 EXPORT_PC() @ need for resolve and alloc 1056 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1057 mov r10, rINST, lsr #8 @ r10<- AA or BA 1058 cmp r0, #0 @ already resolved? 1059 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10608: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1061 mov r2, #0 @ r2<- false 1062 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1063 bl dvmResolveClass @ r0<- call(clazz, ref) 1064 cmp r0, #0 @ got null? 1065 beq common_exceptionThrown @ yes, handle exception 1066 b .LOP_FILLED_NEW_ARRAY_continue 1067 1068/* ------------------------------ */ 1069 .balign 64 1070.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1071/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1072/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1073 /* 1074 * Create a new array with elements filled from registers. 1075 * 1076 * for: filled-new-array, filled-new-array/range 1077 */ 1078 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1079 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1080 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1081 FETCH(r1, 1) @ r1<- BBBB 1082 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1083 EXPORT_PC() @ need for resolve and alloc 1084 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1085 mov r10, rINST, lsr #8 @ r10<- AA or BA 1086 cmp r0, #0 @ already resolved? 1087 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10888: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1089 mov r2, #0 @ r2<- false 1090 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1091 bl dvmResolveClass @ r0<- call(clazz, ref) 1092 cmp r0, #0 @ got null? 1093 beq common_exceptionThrown @ yes, handle exception 1094 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1095 1096 1097/* ------------------------------ */ 1098 .balign 64 1099.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1100/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1101 /* fill-array-data vAA, +BBBBBBBB */ 1102 FETCH(r0, 1) @ r0<- bbbb (lo) 1103 FETCH(r1, 2) @ r1<- BBBB (hi) 1104 mov r3, rINST, lsr #8 @ r3<- AA 1105 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1106 GET_VREG(r0, r3) @ r0<- vAA (array object) 1107 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1108 EXPORT_PC(); 1109 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1110 cmp r0, #0 @ 0 means an exception is thrown 1111 beq common_exceptionThrown @ has exception 1112 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1113 GET_INST_OPCODE(ip) @ extract opcode from rINST 1114 GOTO_OPCODE(ip) @ jump to next instruction 1115 1116/* ------------------------------ */ 1117 .balign 64 1118.L_OP_THROW: /* 0x27 */ 1119/* File: armv5te/OP_THROW.S */ 1120 /* 1121 * Throw an exception object in the current thread. 1122 */ 1123 /* throw vAA */ 1124 mov r2, rINST, lsr #8 @ r2<- AA 1125 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1126 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1127 EXPORT_PC() @ exception handler can throw 1128 cmp r1, #0 @ null object? 1129 beq common_errNullObject @ yes, throw an NPE instead 1130 @ bypass dvmSetException, just store it 1131 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1132 b common_exceptionThrown 1133 1134/* ------------------------------ */ 1135 .balign 64 1136.L_OP_GOTO: /* 0x28 */ 1137/* File: armv5te/OP_GOTO.S */ 1138 /* 1139 * Unconditional branch, 8-bit offset. 1140 * 1141 * The branch distance is a signed code-unit offset, which we need to 1142 * double to get a byte offset. 1143 */ 1144 /* goto +AA */ 1145 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1146 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1147 mov r9, r9, lsl #1 @ r9<- byte offset 1148 bmi common_backwardBranch @ backward branch, do periodic checks 1149#if defined(WITH_JIT) 1150 GET_JIT_PROF_TABLE(r0) 1151 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1152 cmp r0,#0 1153 bne common_updateProfile 1154 GET_INST_OPCODE(ip) @ extract opcode from rINST 1155 GOTO_OPCODE(ip) @ jump to next instruction 1156#else 1157 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1158 GET_INST_OPCODE(ip) @ extract opcode from rINST 1159 GOTO_OPCODE(ip) @ jump to next instruction 1160#endif 1161 1162/* ------------------------------ */ 1163 .balign 64 1164.L_OP_GOTO_16: /* 0x29 */ 1165/* File: armv5te/OP_GOTO_16.S */ 1166 /* 1167 * Unconditional branch, 16-bit offset. 1168 * 1169 * The branch distance is a signed code-unit offset, which we need to 1170 * double to get a byte offset. 1171 */ 1172 /* goto/16 +AAAA */ 1173 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1174 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1175 bmi common_backwardBranch @ backward branch, do periodic checks 1176#if defined(WITH_JIT) 1177 GET_JIT_PROF_TABLE(r0) 1178 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1179 cmp r0,#0 1180 bne common_updateProfile 1181 GET_INST_OPCODE(ip) @ extract opcode from rINST 1182 GOTO_OPCODE(ip) @ jump to next instruction 1183#else 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 GET_INST_OPCODE(ip) @ extract opcode from rINST 1186 GOTO_OPCODE(ip) @ jump to next instruction 1187#endif 1188 1189/* ------------------------------ */ 1190 .balign 64 1191.L_OP_GOTO_32: /* 0x2a */ 1192/* File: armv5te/OP_GOTO_32.S */ 1193 /* 1194 * Unconditional branch, 32-bit offset. 1195 * 1196 * The branch distance is a signed code-unit offset, which we need to 1197 * double to get a byte offset. 1198 * 1199 * Unlike most opcodes, this one is allowed to branch to itself, so 1200 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1201 * instruction doesn't affect the V flag, so we need to clear it 1202 * explicitly. 1203 */ 1204 /* goto/32 +AAAAAAAA */ 1205 FETCH(r0, 1) @ r0<- aaaa (lo) 1206 FETCH(r1, 2) @ r1<- AAAA (hi) 1207 cmp ip, ip @ (clear V flag during stall) 1208 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1209 mov r9, r0, asl #1 @ r9<- byte offset 1210 ble common_backwardBranch @ backward branch, do periodic checks 1211#if defined(WITH_JIT) 1212 GET_JIT_PROF_TABLE(r0) 1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1214 cmp r0,#0 1215 bne common_updateProfile 1216 GET_INST_OPCODE(ip) @ extract opcode from rINST 1217 GOTO_OPCODE(ip) @ jump to next instruction 1218#else 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 GET_INST_OPCODE(ip) @ extract opcode from rINST 1221 GOTO_OPCODE(ip) @ jump to next instruction 1222#endif 1223 1224/* ------------------------------ */ 1225 .balign 64 1226.L_OP_PACKED_SWITCH: /* 0x2b */ 1227/* File: armv5te/OP_PACKED_SWITCH.S */ 1228 /* 1229 * Handle a packed-switch or sparse-switch instruction. In both cases 1230 * we decode it and hand it off to a helper function. 1231 * 1232 * We don't really expect backward branches in a switch statement, but 1233 * they're perfectly legal, so we check for them here. 1234 * 1235 * for: packed-switch, sparse-switch 1236 */ 1237 /* op vAA, +BBBB */ 1238 FETCH(r0, 1) @ r0<- bbbb (lo) 1239 FETCH(r1, 2) @ r1<- BBBB (hi) 1240 mov r3, rINST, lsr #8 @ r3<- AA 1241 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1242 GET_VREG(r1, r3) @ r1<- vAA 1243 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1244 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1245 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1246 bmi common_backwardBranch @ backward branch, do periodic checks 1247 beq common_backwardBranch @ (want to use BLE but V is unknown) 1248#if defined(WITH_JIT) 1249 GET_JIT_PROF_TABLE(r0) 1250 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1251 cmp r0,#0 1252 bne common_updateProfile 1253 GET_INST_OPCODE(ip) @ extract opcode from rINST 1254 GOTO_OPCODE(ip) @ jump to next instruction 1255#else 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 GOTO_OPCODE(ip) @ jump to next instruction 1259#endif 1260 1261/* ------------------------------ */ 1262 .balign 64 1263.L_OP_SPARSE_SWITCH: /* 0x2c */ 1264/* File: armv5te/OP_SPARSE_SWITCH.S */ 1265/* File: armv5te/OP_PACKED_SWITCH.S */ 1266 /* 1267 * Handle a packed-switch or sparse-switch instruction. In both cases 1268 * we decode it and hand it off to a helper function. 1269 * 1270 * We don't really expect backward branches in a switch statement, but 1271 * they're perfectly legal, so we check for them here. 1272 * 1273 * for: packed-switch, sparse-switch 1274 */ 1275 /* op vAA, +BBBB */ 1276 FETCH(r0, 1) @ r0<- bbbb (lo) 1277 FETCH(r1, 2) @ r1<- BBBB (hi) 1278 mov r3, rINST, lsr #8 @ r3<- AA 1279 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1280 GET_VREG(r1, r3) @ r1<- vAA 1281 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1282 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1283 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1284 bmi common_backwardBranch @ backward branch, do periodic checks 1285 beq common_backwardBranch @ (want to use BLE but V is unknown) 1286#if defined(WITH_JIT) 1287 GET_JIT_PROF_TABLE(r0) 1288 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1289 cmp r0,#0 1290 bne common_updateProfile 1291 GET_INST_OPCODE(ip) @ extract opcode from rINST 1292 GOTO_OPCODE(ip) @ jump to next instruction 1293#else 1294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1295 GET_INST_OPCODE(ip) @ extract opcode from rINST 1296 GOTO_OPCODE(ip) @ jump to next instruction 1297#endif 1298 1299 1300/* ------------------------------ */ 1301 .balign 64 1302.L_OP_CMPL_FLOAT: /* 0x2d */ 1303/* File: armv5te/OP_CMPL_FLOAT.S */ 1304 /* 1305 * Compare two floating-point values. Puts 0, 1, or -1 into the 1306 * destination register based on the results of the comparison. 1307 * 1308 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1309 * on what value we'd like to return when one of the operands is NaN. 1310 * 1311 * The operation we're implementing is: 1312 * if (x == y) 1313 * return 0; 1314 * else if (x < y) 1315 * return -1; 1316 * else if (x > y) 1317 * return 1; 1318 * else 1319 * return {-1,1}; // one or both operands was NaN 1320 * 1321 * The straightforward implementation requires 3 calls to functions 1322 * that return a result in r0. We can do it with two calls if our 1323 * EABI library supports __aeabi_cfcmple (only one if we want to check 1324 * for NaN directly): 1325 * check x <= y 1326 * if <, return -1 1327 * if ==, return 0 1328 * check y <= x 1329 * if <, return 1 1330 * return {-1,1} 1331 * 1332 * for: cmpl-float, cmpg-float 1333 */ 1334 /* op vAA, vBB, vCC */ 1335 FETCH(r0, 1) @ r0<- CCBB 1336 and r2, r0, #255 @ r2<- BB 1337 mov r3, r0, lsr #8 @ r3<- CC 1338 GET_VREG(r9, r2) @ r9<- vBB 1339 GET_VREG(r10, r3) @ r10<- vCC 1340 mov r0, r9 @ copy to arg registers 1341 mov r1, r10 1342 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1343 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1344 mvncc r1, #0 @ (less than) r1<- -1 1345 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1346.LOP_CMPL_FLOAT_finish: 1347 mov r3, rINST, lsr #8 @ r3<- AA 1348 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1349 SET_VREG(r1, r3) @ vAA<- r1 1350 GET_INST_OPCODE(ip) @ extract opcode from rINST 1351 GOTO_OPCODE(ip) @ jump to next instruction 1352 1353/* ------------------------------ */ 1354 .balign 64 1355.L_OP_CMPG_FLOAT: /* 0x2e */ 1356/* File: armv5te/OP_CMPG_FLOAT.S */ 1357/* File: armv5te/OP_CMPL_FLOAT.S */ 1358 /* 1359 * Compare two floating-point values. Puts 0, 1, or -1 into the 1360 * destination register based on the results of the comparison. 1361 * 1362 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1363 * on what value we'd like to return when one of the operands is NaN. 1364 * 1365 * The operation we're implementing is: 1366 * if (x == y) 1367 * return 0; 1368 * else if (x < y) 1369 * return -1; 1370 * else if (x > y) 1371 * return 1; 1372 * else 1373 * return {-1,1}; // one or both operands was NaN 1374 * 1375 * The straightforward implementation requires 3 calls to functions 1376 * that return a result in r0. We can do it with two calls if our 1377 * EABI library supports __aeabi_cfcmple (only one if we want to check 1378 * for NaN directly): 1379 * check x <= y 1380 * if <, return -1 1381 * if ==, return 0 1382 * check y <= x 1383 * if <, return 1 1384 * return {-1,1} 1385 * 1386 * for: cmpl-float, cmpg-float 1387 */ 1388 /* op vAA, vBB, vCC */ 1389 FETCH(r0, 1) @ r0<- CCBB 1390 and r2, r0, #255 @ r2<- BB 1391 mov r3, r0, lsr #8 @ r3<- CC 1392 GET_VREG(r9, r2) @ r9<- vBB 1393 GET_VREG(r10, r3) @ r10<- vCC 1394 mov r0, r9 @ copy to arg registers 1395 mov r1, r10 1396 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1397 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1398 mvncc r1, #0 @ (less than) r1<- -1 1399 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1400.LOP_CMPG_FLOAT_finish: 1401 mov r3, rINST, lsr #8 @ r3<- AA 1402 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1403 SET_VREG(r1, r3) @ vAA<- r1 1404 GET_INST_OPCODE(ip) @ extract opcode from rINST 1405 GOTO_OPCODE(ip) @ jump to next instruction 1406 1407 1408/* ------------------------------ */ 1409 .balign 64 1410.L_OP_CMPL_DOUBLE: /* 0x2f */ 1411/* File: armv5te/OP_CMPL_DOUBLE.S */ 1412 /* 1413 * Compare two floating-point values. Puts 0, 1, or -1 into the 1414 * destination register based on the results of the comparison. 1415 * 1416 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1417 * on what value we'd like to return when one of the operands is NaN. 1418 * 1419 * See OP_CMPL_FLOAT for an explanation. 1420 * 1421 * For: cmpl-double, cmpg-double 1422 */ 1423 /* op vAA, vBB, vCC */ 1424 FETCH(r0, 1) @ r0<- CCBB 1425 and r9, r0, #255 @ r9<- BB 1426 mov r10, r0, lsr #8 @ r10<- CC 1427 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1428 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1429 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1430 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1431 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1432 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1433 mvncc r1, #0 @ (less than) r1<- -1 1434 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1435.LOP_CMPL_DOUBLE_finish: 1436 mov r3, rINST, lsr #8 @ r3<- AA 1437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1438 SET_VREG(r1, r3) @ vAA<- r1 1439 GET_INST_OPCODE(ip) @ extract opcode from rINST 1440 GOTO_OPCODE(ip) @ jump to next instruction 1441 1442/* ------------------------------ */ 1443 .balign 64 1444.L_OP_CMPG_DOUBLE: /* 0x30 */ 1445/* File: armv5te/OP_CMPG_DOUBLE.S */ 1446/* File: armv5te/OP_CMPL_DOUBLE.S */ 1447 /* 1448 * Compare two floating-point values. Puts 0, 1, or -1 into the 1449 * destination register based on the results of the comparison. 1450 * 1451 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1452 * on what value we'd like to return when one of the operands is NaN. 1453 * 1454 * See OP_CMPL_FLOAT for an explanation. 1455 * 1456 * For: cmpl-double, cmpg-double 1457 */ 1458 /* op vAA, vBB, vCC */ 1459 FETCH(r0, 1) @ r0<- CCBB 1460 and r9, r0, #255 @ r9<- BB 1461 mov r10, r0, lsr #8 @ r10<- CC 1462 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1463 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1464 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1465 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1466 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1467 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1468 mvncc r1, #0 @ (less than) r1<- -1 1469 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1470.LOP_CMPG_DOUBLE_finish: 1471 mov r3, rINST, lsr #8 @ r3<- AA 1472 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1473 SET_VREG(r1, r3) @ vAA<- r1 1474 GET_INST_OPCODE(ip) @ extract opcode from rINST 1475 GOTO_OPCODE(ip) @ jump to next instruction 1476 1477 1478/* ------------------------------ */ 1479 .balign 64 1480.L_OP_CMP_LONG: /* 0x31 */ 1481/* File: armv5te/OP_CMP_LONG.S */ 1482 /* 1483 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1484 * register based on the results of the comparison. 1485 * 1486 * We load the full values with LDM, but in practice many values could 1487 * be resolved by only looking at the high word. This could be made 1488 * faster or slower by splitting the LDM into a pair of LDRs. 1489 * 1490 * If we just wanted to set condition flags, we could do this: 1491 * subs ip, r0, r2 1492 * sbcs ip, r1, r3 1493 * subeqs ip, r0, r2 1494 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1495 * integer value, which we can do with 2 conditional mov/mvn instructions 1496 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1497 * us a constant 5-cycle path plus a branch at the end to the 1498 * instruction epilogue code. The multi-compare approach below needs 1499 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1500 * in the worst case (the 64-bit values are equal). 1501 */ 1502 /* cmp-long vAA, vBB, vCC */ 1503 FETCH(r0, 1) @ r0<- CCBB 1504 mov r9, rINST, lsr #8 @ r9<- AA 1505 and r2, r0, #255 @ r2<- BB 1506 mov r3, r0, lsr #8 @ r3<- CC 1507 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1508 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1509 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1510 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1511 cmp r1, r3 @ compare (vBB+1, vCC+1) 1512 blt .LOP_CMP_LONG_less @ signed compare on high part 1513 bgt .LOP_CMP_LONG_greater 1514 subs r1, r0, r2 @ r1<- r0 - r2 1515 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1516 bne .LOP_CMP_LONG_less 1517 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1518 1519/* ------------------------------ */ 1520 .balign 64 1521.L_OP_IF_EQ: /* 0x32 */ 1522/* File: armv5te/OP_IF_EQ.S */ 1523/* File: armv5te/bincmp.S */ 1524 /* 1525 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1526 * fragment that specifies the *reverse* comparison to perform, e.g. 1527 * for "if-le" you would use "gt". 1528 * 1529 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1530 */ 1531 /* if-cmp vA, vB, +CCCC */ 1532 mov r0, rINST, lsr #8 @ r0<- A+ 1533 mov r1, rINST, lsr #12 @ r1<- B 1534 and r0, r0, #15 1535 GET_VREG(r3, r1) @ r3<- vB 1536 GET_VREG(r2, r0) @ r2<- vA 1537 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1538 cmp r2, r3 @ compare (vA, vB) 1539 bne 1f @ branch to 1 if comparison failed 1540 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1541 movs r9, r9, asl #1 @ convert to bytes, check sign 1542 bmi common_backwardBranch @ yes, do periodic checks 15431: 1544#if defined(WITH_JIT) 1545 GET_JIT_PROF_TABLE(r0) 1546 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1547 b common_testUpdateProfile 1548#else 1549 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1550 GET_INST_OPCODE(ip) @ extract opcode from rINST 1551 GOTO_OPCODE(ip) @ jump to next instruction 1552#endif 1553 1554 1555/* ------------------------------ */ 1556 .balign 64 1557.L_OP_IF_NE: /* 0x33 */ 1558/* File: armv5te/OP_IF_NE.S */ 1559/* File: armv5te/bincmp.S */ 1560 /* 1561 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1562 * fragment that specifies the *reverse* comparison to perform, e.g. 1563 * for "if-le" you would use "gt". 1564 * 1565 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1566 */ 1567 /* if-cmp vA, vB, +CCCC */ 1568 mov r0, rINST, lsr #8 @ r0<- A+ 1569 mov r1, rINST, lsr #12 @ r1<- B 1570 and r0, r0, #15 1571 GET_VREG(r3, r1) @ r3<- vB 1572 GET_VREG(r2, r0) @ r2<- vA 1573 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1574 cmp r2, r3 @ compare (vA, vB) 1575 beq 1f @ branch to 1 if comparison failed 1576 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1577 movs r9, r9, asl #1 @ convert to bytes, check sign 1578 bmi common_backwardBranch @ yes, do periodic checks 15791: 1580#if defined(WITH_JIT) 1581 GET_JIT_PROF_TABLE(r0) 1582 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1583 b common_testUpdateProfile 1584#else 1585 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1586 GET_INST_OPCODE(ip) @ extract opcode from rINST 1587 GOTO_OPCODE(ip) @ jump to next instruction 1588#endif 1589 1590 1591/* ------------------------------ */ 1592 .balign 64 1593.L_OP_IF_LT: /* 0x34 */ 1594/* File: armv5te/OP_IF_LT.S */ 1595/* File: armv5te/bincmp.S */ 1596 /* 1597 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1598 * fragment that specifies the *reverse* comparison to perform, e.g. 1599 * for "if-le" you would use "gt". 1600 * 1601 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1602 */ 1603 /* if-cmp vA, vB, +CCCC */ 1604 mov r0, rINST, lsr #8 @ r0<- A+ 1605 mov r1, rINST, lsr #12 @ r1<- B 1606 and r0, r0, #15 1607 GET_VREG(r3, r1) @ r3<- vB 1608 GET_VREG(r2, r0) @ r2<- vA 1609 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1610 cmp r2, r3 @ compare (vA, vB) 1611 bge 1f @ branch to 1 if comparison failed 1612 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1613 movs r9, r9, asl #1 @ convert to bytes, check sign 1614 bmi common_backwardBranch @ yes, do periodic checks 16151: 1616#if defined(WITH_JIT) 1617 GET_JIT_PROF_TABLE(r0) 1618 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1619 b common_testUpdateProfile 1620#else 1621 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1622 GET_INST_OPCODE(ip) @ extract opcode from rINST 1623 GOTO_OPCODE(ip) @ jump to next instruction 1624#endif 1625 1626 1627/* ------------------------------ */ 1628 .balign 64 1629.L_OP_IF_GE: /* 0x35 */ 1630/* File: armv5te/OP_IF_GE.S */ 1631/* File: armv5te/bincmp.S */ 1632 /* 1633 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1634 * fragment that specifies the *reverse* comparison to perform, e.g. 1635 * for "if-le" you would use "gt". 1636 * 1637 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1638 */ 1639 /* if-cmp vA, vB, +CCCC */ 1640 mov r0, rINST, lsr #8 @ r0<- A+ 1641 mov r1, rINST, lsr #12 @ r1<- B 1642 and r0, r0, #15 1643 GET_VREG(r3, r1) @ r3<- vB 1644 GET_VREG(r2, r0) @ r2<- vA 1645 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1646 cmp r2, r3 @ compare (vA, vB) 1647 blt 1f @ branch to 1 if comparison failed 1648 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1649 movs r9, r9, asl #1 @ convert to bytes, check sign 1650 bmi common_backwardBranch @ yes, do periodic checks 16511: 1652#if defined(WITH_JIT) 1653 GET_JIT_PROF_TABLE(r0) 1654 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1655 b common_testUpdateProfile 1656#else 1657 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1658 GET_INST_OPCODE(ip) @ extract opcode from rINST 1659 GOTO_OPCODE(ip) @ jump to next instruction 1660#endif 1661 1662 1663/* ------------------------------ */ 1664 .balign 64 1665.L_OP_IF_GT: /* 0x36 */ 1666/* File: armv5te/OP_IF_GT.S */ 1667/* File: armv5te/bincmp.S */ 1668 /* 1669 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1670 * fragment that specifies the *reverse* comparison to perform, e.g. 1671 * for "if-le" you would use "gt". 1672 * 1673 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1674 */ 1675 /* if-cmp vA, vB, +CCCC */ 1676 mov r0, rINST, lsr #8 @ r0<- A+ 1677 mov r1, rINST, lsr #12 @ r1<- B 1678 and r0, r0, #15 1679 GET_VREG(r3, r1) @ r3<- vB 1680 GET_VREG(r2, r0) @ r2<- vA 1681 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1682 cmp r2, r3 @ compare (vA, vB) 1683 ble 1f @ branch to 1 if comparison failed 1684 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1685 movs r9, r9, asl #1 @ convert to bytes, check sign 1686 bmi common_backwardBranch @ yes, do periodic checks 16871: 1688#if defined(WITH_JIT) 1689 GET_JIT_PROF_TABLE(r0) 1690 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1691 b common_testUpdateProfile 1692#else 1693 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1694 GET_INST_OPCODE(ip) @ extract opcode from rINST 1695 GOTO_OPCODE(ip) @ jump to next instruction 1696#endif 1697 1698 1699/* ------------------------------ */ 1700 .balign 64 1701.L_OP_IF_LE: /* 0x37 */ 1702/* File: armv5te/OP_IF_LE.S */ 1703/* File: armv5te/bincmp.S */ 1704 /* 1705 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1706 * fragment that specifies the *reverse* comparison to perform, e.g. 1707 * for "if-le" you would use "gt". 1708 * 1709 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1710 */ 1711 /* if-cmp vA, vB, +CCCC */ 1712 mov r0, rINST, lsr #8 @ r0<- A+ 1713 mov r1, rINST, lsr #12 @ r1<- B 1714 and r0, r0, #15 1715 GET_VREG(r3, r1) @ r3<- vB 1716 GET_VREG(r2, r0) @ r2<- vA 1717 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1718 cmp r2, r3 @ compare (vA, vB) 1719 bgt 1f @ branch to 1 if comparison failed 1720 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1721 movs r9, r9, asl #1 @ convert to bytes, check sign 1722 bmi common_backwardBranch @ yes, do periodic checks 17231: 1724#if defined(WITH_JIT) 1725 GET_JIT_PROF_TABLE(r0) 1726 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1727 b common_testUpdateProfile 1728#else 1729 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1730 GET_INST_OPCODE(ip) @ extract opcode from rINST 1731 GOTO_OPCODE(ip) @ jump to next instruction 1732#endif 1733 1734 1735/* ------------------------------ */ 1736 .balign 64 1737.L_OP_IF_EQZ: /* 0x38 */ 1738/* File: armv5te/OP_IF_EQZ.S */ 1739/* File: armv5te/zcmp.S */ 1740 /* 1741 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1742 * fragment that specifies the *reverse* comparison to perform, e.g. 1743 * for "if-le" you would use "gt". 1744 * 1745 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1746 */ 1747 /* if-cmp vAA, +BBBB */ 1748 mov r0, rINST, lsr #8 @ r0<- AA 1749 GET_VREG(r2, r0) @ r2<- vAA 1750 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1751 cmp r2, #0 @ compare (vA, 0) 1752 bne 1f @ branch to 1 if comparison failed 1753 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1754 movs r9, r9, asl #1 @ convert to bytes, check sign 1755 bmi common_backwardBranch @ backward branch, do periodic checks 17561: 1757#if defined(WITH_JIT) 1758 GET_JIT_PROF_TABLE(r0) 1759 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1760 cmp r0,#0 1761 bne common_updateProfile 1762 GET_INST_OPCODE(ip) @ extract opcode from rINST 1763 GOTO_OPCODE(ip) @ jump to next instruction 1764#else 1765 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1766 GET_INST_OPCODE(ip) @ extract opcode from rINST 1767 GOTO_OPCODE(ip) @ jump to next instruction 1768#endif 1769 1770 1771/* ------------------------------ */ 1772 .balign 64 1773.L_OP_IF_NEZ: /* 0x39 */ 1774/* File: armv5te/OP_IF_NEZ.S */ 1775/* File: armv5te/zcmp.S */ 1776 /* 1777 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1778 * fragment that specifies the *reverse* comparison to perform, e.g. 1779 * for "if-le" you would use "gt". 1780 * 1781 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1782 */ 1783 /* if-cmp vAA, +BBBB */ 1784 mov r0, rINST, lsr #8 @ r0<- AA 1785 GET_VREG(r2, r0) @ r2<- vAA 1786 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1787 cmp r2, #0 @ compare (vA, 0) 1788 beq 1f @ branch to 1 if comparison failed 1789 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1790 movs r9, r9, asl #1 @ convert to bytes, check sign 1791 bmi common_backwardBranch @ backward branch, do periodic checks 17921: 1793#if defined(WITH_JIT) 1794 GET_JIT_PROF_TABLE(r0) 1795 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1796 cmp r0,#0 1797 bne common_updateProfile 1798 GET_INST_OPCODE(ip) @ extract opcode from rINST 1799 GOTO_OPCODE(ip) @ jump to next instruction 1800#else 1801 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1802 GET_INST_OPCODE(ip) @ extract opcode from rINST 1803 GOTO_OPCODE(ip) @ jump to next instruction 1804#endif 1805 1806 1807/* ------------------------------ */ 1808 .balign 64 1809.L_OP_IF_LTZ: /* 0x3a */ 1810/* File: armv5te/OP_IF_LTZ.S */ 1811/* File: armv5te/zcmp.S */ 1812 /* 1813 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1814 * fragment that specifies the *reverse* comparison to perform, e.g. 1815 * for "if-le" you would use "gt". 1816 * 1817 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1818 */ 1819 /* if-cmp vAA, +BBBB */ 1820 mov r0, rINST, lsr #8 @ r0<- AA 1821 GET_VREG(r2, r0) @ r2<- vAA 1822 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1823 cmp r2, #0 @ compare (vA, 0) 1824 bge 1f @ branch to 1 if comparison failed 1825 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1826 movs r9, r9, asl #1 @ convert to bytes, check sign 1827 bmi common_backwardBranch @ backward branch, do periodic checks 18281: 1829#if defined(WITH_JIT) 1830 GET_JIT_PROF_TABLE(r0) 1831 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1832 cmp r0,#0 1833 bne common_updateProfile 1834 GET_INST_OPCODE(ip) @ extract opcode from rINST 1835 GOTO_OPCODE(ip) @ jump to next instruction 1836#else 1837 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1838 GET_INST_OPCODE(ip) @ extract opcode from rINST 1839 GOTO_OPCODE(ip) @ jump to next instruction 1840#endif 1841 1842 1843/* ------------------------------ */ 1844 .balign 64 1845.L_OP_IF_GEZ: /* 0x3b */ 1846/* File: armv5te/OP_IF_GEZ.S */ 1847/* File: armv5te/zcmp.S */ 1848 /* 1849 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1850 * fragment that specifies the *reverse* comparison to perform, e.g. 1851 * for "if-le" you would use "gt". 1852 * 1853 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1854 */ 1855 /* if-cmp vAA, +BBBB */ 1856 mov r0, rINST, lsr #8 @ r0<- AA 1857 GET_VREG(r2, r0) @ r2<- vAA 1858 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1859 cmp r2, #0 @ compare (vA, 0) 1860 blt 1f @ branch to 1 if comparison failed 1861 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1862 movs r9, r9, asl #1 @ convert to bytes, check sign 1863 bmi common_backwardBranch @ backward branch, do periodic checks 18641: 1865#if defined(WITH_JIT) 1866 GET_JIT_PROF_TABLE(r0) 1867 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1868 cmp r0,#0 1869 bne common_updateProfile 1870 GET_INST_OPCODE(ip) @ extract opcode from rINST 1871 GOTO_OPCODE(ip) @ jump to next instruction 1872#else 1873 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1874 GET_INST_OPCODE(ip) @ extract opcode from rINST 1875 GOTO_OPCODE(ip) @ jump to next instruction 1876#endif 1877 1878 1879/* ------------------------------ */ 1880 .balign 64 1881.L_OP_IF_GTZ: /* 0x3c */ 1882/* File: armv5te/OP_IF_GTZ.S */ 1883/* File: armv5te/zcmp.S */ 1884 /* 1885 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1886 * fragment that specifies the *reverse* comparison to perform, e.g. 1887 * for "if-le" you would use "gt". 1888 * 1889 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1890 */ 1891 /* if-cmp vAA, +BBBB */ 1892 mov r0, rINST, lsr #8 @ r0<- AA 1893 GET_VREG(r2, r0) @ r2<- vAA 1894 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1895 cmp r2, #0 @ compare (vA, 0) 1896 ble 1f @ branch to 1 if comparison failed 1897 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1898 movs r9, r9, asl #1 @ convert to bytes, check sign 1899 bmi common_backwardBranch @ backward branch, do periodic checks 19001: 1901#if defined(WITH_JIT) 1902 GET_JIT_PROF_TABLE(r0) 1903 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1904 cmp r0,#0 1905 bne common_updateProfile 1906 GET_INST_OPCODE(ip) @ extract opcode from rINST 1907 GOTO_OPCODE(ip) @ jump to next instruction 1908#else 1909 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1910 GET_INST_OPCODE(ip) @ extract opcode from rINST 1911 GOTO_OPCODE(ip) @ jump to next instruction 1912#endif 1913 1914 1915/* ------------------------------ */ 1916 .balign 64 1917.L_OP_IF_LEZ: /* 0x3d */ 1918/* File: armv5te/OP_IF_LEZ.S */ 1919/* File: armv5te/zcmp.S */ 1920 /* 1921 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1922 * fragment that specifies the *reverse* comparison to perform, e.g. 1923 * for "if-le" you would use "gt". 1924 * 1925 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1926 */ 1927 /* if-cmp vAA, +BBBB */ 1928 mov r0, rINST, lsr #8 @ r0<- AA 1929 GET_VREG(r2, r0) @ r2<- vAA 1930 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1931 cmp r2, #0 @ compare (vA, 0) 1932 bgt 1f @ branch to 1 if comparison failed 1933 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1934 movs r9, r9, asl #1 @ convert to bytes, check sign 1935 bmi common_backwardBranch @ backward branch, do periodic checks 19361: 1937#if defined(WITH_JIT) 1938 GET_JIT_PROF_TABLE(r0) 1939 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1940 cmp r0,#0 1941 bne common_updateProfile 1942 GET_INST_OPCODE(ip) @ extract opcode from rINST 1943 GOTO_OPCODE(ip) @ jump to next instruction 1944#else 1945 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1946 GET_INST_OPCODE(ip) @ extract opcode from rINST 1947 GOTO_OPCODE(ip) @ jump to next instruction 1948#endif 1949 1950 1951/* ------------------------------ */ 1952 .balign 64 1953.L_OP_UNUSED_3E: /* 0x3e */ 1954/* File: armv5te/OP_UNUSED_3E.S */ 1955/* File: armv5te/unused.S */ 1956 bl common_abort 1957 1958 1959/* ------------------------------ */ 1960 .balign 64 1961.L_OP_UNUSED_3F: /* 0x3f */ 1962/* File: armv5te/OP_UNUSED_3F.S */ 1963/* File: armv5te/unused.S */ 1964 bl common_abort 1965 1966 1967/* ------------------------------ */ 1968 .balign 64 1969.L_OP_UNUSED_40: /* 0x40 */ 1970/* File: armv5te/OP_UNUSED_40.S */ 1971/* File: armv5te/unused.S */ 1972 bl common_abort 1973 1974 1975/* ------------------------------ */ 1976 .balign 64 1977.L_OP_UNUSED_41: /* 0x41 */ 1978/* File: armv5te/OP_UNUSED_41.S */ 1979/* File: armv5te/unused.S */ 1980 bl common_abort 1981 1982 1983/* ------------------------------ */ 1984 .balign 64 1985.L_OP_UNUSED_42: /* 0x42 */ 1986/* File: armv5te/OP_UNUSED_42.S */ 1987/* File: armv5te/unused.S */ 1988 bl common_abort 1989 1990 1991/* ------------------------------ */ 1992 .balign 64 1993.L_OP_UNUSED_43: /* 0x43 */ 1994/* File: armv5te/OP_UNUSED_43.S */ 1995/* File: armv5te/unused.S */ 1996 bl common_abort 1997 1998 1999/* ------------------------------ */ 2000 .balign 64 2001.L_OP_AGET: /* 0x44 */ 2002/* File: armv5te/OP_AGET.S */ 2003 /* 2004 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2005 * 2006 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2007 * instructions. We use a pair of FETCH_Bs instead. 2008 * 2009 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2010 */ 2011 /* op vAA, vBB, vCC */ 2012 FETCH_B(r2, 1, 0) @ r2<- BB 2013 mov r9, rINST, lsr #8 @ r9<- AA 2014 FETCH_B(r3, 1, 1) @ r3<- CC 2015 GET_VREG(r0, r2) @ r0<- vBB (array object) 2016 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2017 cmp r0, #0 @ null array object? 2018 beq common_errNullObject @ yes, bail 2019 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2020 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2021 cmp r1, r3 @ compare unsigned index, length 2022 bcs common_errArrayIndex @ index >= length, bail 2023 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2024 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2025 GET_INST_OPCODE(ip) @ extract opcode from rINST 2026 SET_VREG(r2, r9) @ vAA<- r2 2027 GOTO_OPCODE(ip) @ jump to next instruction 2028 2029/* ------------------------------ */ 2030 .balign 64 2031.L_OP_AGET_WIDE: /* 0x45 */ 2032/* File: armv4t/OP_AGET_WIDE.S */ 2033 /* 2034 * Array get, 64 bits. vAA <- vBB[vCC]. 2035 * 2036 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2037 */ 2038 /* aget-wide vAA, vBB, vCC */ 2039 FETCH(r0, 1) @ r0<- CCBB 2040 mov r9, rINST, lsr #8 @ r9<- AA 2041 and r2, r0, #255 @ r2<- BB 2042 mov r3, r0, lsr #8 @ r3<- CC 2043 GET_VREG(r0, r2) @ r0<- vBB (array object) 2044 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2045 cmp r0, #0 @ null array object? 2046 beq common_errNullObject @ yes, bail 2047 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2048 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2049 cmp r1, r3 @ compare unsigned index, length 2050 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2051 b common_errArrayIndex @ index >= length, bail 2052 @ May want to swap the order of these two branches depending on how the 2053 @ branch prediction (if any) handles conditional forward branches vs. 2054 @ unconditional forward branches. 2055 2056/* ------------------------------ */ 2057 .balign 64 2058.L_OP_AGET_OBJECT: /* 0x46 */ 2059/* File: armv5te/OP_AGET_OBJECT.S */ 2060/* File: armv5te/OP_AGET.S */ 2061 /* 2062 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2063 * 2064 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2065 * instructions. We use a pair of FETCH_Bs instead. 2066 * 2067 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2068 */ 2069 /* op vAA, vBB, vCC */ 2070 FETCH_B(r2, 1, 0) @ r2<- BB 2071 mov r9, rINST, lsr #8 @ r9<- AA 2072 FETCH_B(r3, 1, 1) @ r3<- CC 2073 GET_VREG(r0, r2) @ r0<- vBB (array object) 2074 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2075 cmp r0, #0 @ null array object? 2076 beq common_errNullObject @ yes, bail 2077 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2078 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2079 cmp r1, r3 @ compare unsigned index, length 2080 bcs common_errArrayIndex @ index >= length, bail 2081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2082 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2083 GET_INST_OPCODE(ip) @ extract opcode from rINST 2084 SET_VREG(r2, r9) @ vAA<- r2 2085 GOTO_OPCODE(ip) @ jump to next instruction 2086 2087 2088/* ------------------------------ */ 2089 .balign 64 2090.L_OP_AGET_BOOLEAN: /* 0x47 */ 2091/* File: armv5te/OP_AGET_BOOLEAN.S */ 2092/* File: armv5te/OP_AGET.S */ 2093 /* 2094 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2095 * 2096 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2097 * instructions. We use a pair of FETCH_Bs instead. 2098 * 2099 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2100 */ 2101 /* op vAA, vBB, vCC */ 2102 FETCH_B(r2, 1, 0) @ r2<- BB 2103 mov r9, rINST, lsr #8 @ r9<- AA 2104 FETCH_B(r3, 1, 1) @ r3<- CC 2105 GET_VREG(r0, r2) @ r0<- vBB (array object) 2106 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2107 cmp r0, #0 @ null array object? 2108 beq common_errNullObject @ yes, bail 2109 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2110 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2111 cmp r1, r3 @ compare unsigned index, length 2112 bcs common_errArrayIndex @ index >= length, bail 2113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2114 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2115 GET_INST_OPCODE(ip) @ extract opcode from rINST 2116 SET_VREG(r2, r9) @ vAA<- r2 2117 GOTO_OPCODE(ip) @ jump to next instruction 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 .balign 64 2154.L_OP_AGET_CHAR: /* 0x49 */ 2155/* File: armv5te/OP_AGET_CHAR.S */ 2156/* File: armv5te/OP_AGET.S */ 2157 /* 2158 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2159 * 2160 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2161 * instructions. We use a pair of FETCH_Bs instead. 2162 * 2163 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2164 */ 2165 /* op vAA, vBB, vCC */ 2166 FETCH_B(r2, 1, 0) @ r2<- BB 2167 mov r9, rINST, lsr #8 @ r9<- AA 2168 FETCH_B(r3, 1, 1) @ r3<- CC 2169 GET_VREG(r0, r2) @ r0<- vBB (array object) 2170 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2171 cmp r0, #0 @ null array object? 2172 beq common_errNullObject @ yes, bail 2173 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2174 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2175 cmp r1, r3 @ compare unsigned index, length 2176 bcs common_errArrayIndex @ index >= length, bail 2177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2178 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2179 GET_INST_OPCODE(ip) @ extract opcode from rINST 2180 SET_VREG(r2, r9) @ vAA<- r2 2181 GOTO_OPCODE(ip) @ jump to next instruction 2182 2183 2184/* ------------------------------ */ 2185 .balign 64 2186.L_OP_AGET_SHORT: /* 0x4a */ 2187/* File: armv5te/OP_AGET_SHORT.S */ 2188/* File: armv5te/OP_AGET.S */ 2189 /* 2190 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2191 * 2192 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2193 * instructions. We use a pair of FETCH_Bs instead. 2194 * 2195 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2196 */ 2197 /* op vAA, vBB, vCC */ 2198 FETCH_B(r2, 1, 0) @ r2<- BB 2199 mov r9, rINST, lsr #8 @ r9<- AA 2200 FETCH_B(r3, 1, 1) @ r3<- CC 2201 GET_VREG(r0, r2) @ r0<- vBB (array object) 2202 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2203 cmp r0, #0 @ null array object? 2204 beq common_errNullObject @ yes, bail 2205 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2206 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2207 cmp r1, r3 @ compare unsigned index, length 2208 bcs common_errArrayIndex @ index >= length, bail 2209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2210 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2211 GET_INST_OPCODE(ip) @ extract opcode from rINST 2212 SET_VREG(r2, r9) @ vAA<- r2 2213 GOTO_OPCODE(ip) @ jump to next instruction 2214 2215 2216/* ------------------------------ */ 2217 .balign 64 2218.L_OP_APUT: /* 0x4b */ 2219/* File: armv5te/OP_APUT.S */ 2220 /* 2221 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2222 * 2223 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2224 * instructions. We use a pair of FETCH_Bs instead. 2225 * 2226 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2227 */ 2228 /* op vAA, vBB, vCC */ 2229 FETCH_B(r2, 1, 0) @ r2<- BB 2230 mov r9, rINST, lsr #8 @ r9<- AA 2231 FETCH_B(r3, 1, 1) @ r3<- CC 2232 GET_VREG(r0, r2) @ r0<- vBB (array object) 2233 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2234 cmp r0, #0 @ null array object? 2235 beq common_errNullObject @ yes, bail 2236 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2237 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2238 cmp r1, r3 @ compare unsigned index, length 2239 bcs common_errArrayIndex @ index >= length, bail 2240 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2241 GET_VREG(r2, r9) @ r2<- vAA 2242 GET_INST_OPCODE(ip) @ extract opcode from rINST 2243 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2244 GOTO_OPCODE(ip) @ jump to next instruction 2245 2246/* ------------------------------ */ 2247 .balign 64 2248.L_OP_APUT_WIDE: /* 0x4c */ 2249/* File: armv4t/OP_APUT_WIDE.S */ 2250 /* 2251 * Array put, 64 bits. vBB[vCC] <- vAA. 2252 */ 2253 /* aput-wide vAA, vBB, vCC */ 2254 FETCH(r0, 1) @ r0<- CCBB 2255 mov r9, rINST, lsr #8 @ r9<- AA 2256 and r2, r0, #255 @ r2<- BB 2257 mov r3, r0, lsr #8 @ r3<- CC 2258 GET_VREG(r0, r2) @ r0<- vBB (array object) 2259 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2260 cmp r0, #0 @ null array object? 2261 beq common_errNullObject @ yes, bail 2262 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2263 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2264 cmp r1, r3 @ compare unsigned index, length 2265 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2266 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2267 b common_errArrayIndex @ index >= length, bail 2268 @ May want to swap the order of these two branches depending on how the 2269 @ branch prediction (if any) handles conditional forward branches vs. 2270 @ unconditional forward branches. 2271 2272/* ------------------------------ */ 2273 .balign 64 2274.L_OP_APUT_OBJECT: /* 0x4d */ 2275/* File: armv5te/OP_APUT_OBJECT.S */ 2276 /* 2277 * Store an object into an array. vBB[vCC] <- vAA. 2278 * 2279 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2280 * instructions. We use a pair of FETCH_Bs instead. 2281 */ 2282 /* op vAA, vBB, vCC */ 2283 FETCH(r0, 1) @ r0<- CCBB 2284 mov r9, rINST, lsr #8 @ r9<- AA 2285 and r2, r0, #255 @ r2<- BB 2286 mov r3, r0, lsr #8 @ r3<- CC 2287 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2288 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2289 cmp rINST, #0 @ null array object? 2290 GET_VREG(r9, r9) @ r9<- vAA 2291 beq common_errNullObject @ yes, bail 2292 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2293 add r10, rINST, r0, lsl #2 @ r10<- arrayObj + index*width 2294 cmp r0, r3 @ compare unsigned index, length 2295 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2296 b common_errArrayIndex @ index >= length, bail 2297 2298 2299/* ------------------------------ */ 2300 .balign 64 2301.L_OP_APUT_BOOLEAN: /* 0x4e */ 2302/* File: armv5te/OP_APUT_BOOLEAN.S */ 2303/* File: armv5te/OP_APUT.S */ 2304 /* 2305 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2306 * 2307 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2308 * instructions. We use a pair of FETCH_Bs instead. 2309 * 2310 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2311 */ 2312 /* op vAA, vBB, vCC */ 2313 FETCH_B(r2, 1, 0) @ r2<- BB 2314 mov r9, rINST, lsr #8 @ r9<- AA 2315 FETCH_B(r3, 1, 1) @ r3<- CC 2316 GET_VREG(r0, r2) @ r0<- vBB (array object) 2317 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2318 cmp r0, #0 @ null array object? 2319 beq common_errNullObject @ yes, bail 2320 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2321 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2322 cmp r1, r3 @ compare unsigned index, length 2323 bcs common_errArrayIndex @ index >= length, bail 2324 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2325 GET_VREG(r2, r9) @ r2<- vAA 2326 GET_INST_OPCODE(ip) @ extract opcode from rINST 2327 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2328 GOTO_OPCODE(ip) @ jump to next instruction 2329 2330 2331/* ------------------------------ */ 2332 .balign 64 2333.L_OP_APUT_BYTE: /* 0x4f */ 2334/* File: armv5te/OP_APUT_BYTE.S */ 2335/* File: armv5te/OP_APUT.S */ 2336 /* 2337 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2338 * 2339 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2340 * instructions. We use a pair of FETCH_Bs instead. 2341 * 2342 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2343 */ 2344 /* op vAA, vBB, vCC */ 2345 FETCH_B(r2, 1, 0) @ r2<- BB 2346 mov r9, rINST, lsr #8 @ r9<- AA 2347 FETCH_B(r3, 1, 1) @ r3<- CC 2348 GET_VREG(r0, r2) @ r0<- vBB (array object) 2349 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2350 cmp r0, #0 @ null array object? 2351 beq common_errNullObject @ yes, bail 2352 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2353 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2354 cmp r1, r3 @ compare unsigned index, length 2355 bcs common_errArrayIndex @ index >= length, bail 2356 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2357 GET_VREG(r2, r9) @ r2<- vAA 2358 GET_INST_OPCODE(ip) @ extract opcode from rINST 2359 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2360 GOTO_OPCODE(ip) @ jump to next instruction 2361 2362 2363/* ------------------------------ */ 2364 .balign 64 2365.L_OP_APUT_CHAR: /* 0x50 */ 2366/* File: armv5te/OP_APUT_CHAR.S */ 2367/* File: armv5te/OP_APUT.S */ 2368 /* 2369 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2370 * 2371 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2372 * instructions. We use a pair of FETCH_Bs instead. 2373 * 2374 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2375 */ 2376 /* op vAA, vBB, vCC */ 2377 FETCH_B(r2, 1, 0) @ r2<- BB 2378 mov r9, rINST, lsr #8 @ r9<- AA 2379 FETCH_B(r3, 1, 1) @ r3<- CC 2380 GET_VREG(r0, r2) @ r0<- vBB (array object) 2381 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2382 cmp r0, #0 @ null array object? 2383 beq common_errNullObject @ yes, bail 2384 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2385 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2386 cmp r1, r3 @ compare unsigned index, length 2387 bcs common_errArrayIndex @ index >= length, bail 2388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2389 GET_VREG(r2, r9) @ r2<- vAA 2390 GET_INST_OPCODE(ip) @ extract opcode from rINST 2391 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2392 GOTO_OPCODE(ip) @ jump to next instruction 2393 2394 2395/* ------------------------------ */ 2396 .balign 64 2397.L_OP_APUT_SHORT: /* 0x51 */ 2398/* File: armv5te/OP_APUT_SHORT.S */ 2399/* File: armv5te/OP_APUT.S */ 2400 /* 2401 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2402 * 2403 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2404 * instructions. We use a pair of FETCH_Bs instead. 2405 * 2406 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2407 */ 2408 /* op vAA, vBB, vCC */ 2409 FETCH_B(r2, 1, 0) @ r2<- BB 2410 mov r9, rINST, lsr #8 @ r9<- AA 2411 FETCH_B(r3, 1, 1) @ r3<- CC 2412 GET_VREG(r0, r2) @ r0<- vBB (array object) 2413 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2414 cmp r0, #0 @ null array object? 2415 beq common_errNullObject @ yes, bail 2416 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2417 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2418 cmp r1, r3 @ compare unsigned index, length 2419 bcs common_errArrayIndex @ index >= length, bail 2420 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2421 GET_VREG(r2, r9) @ r2<- vAA 2422 GET_INST_OPCODE(ip) @ extract opcode from rINST 2423 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2424 GOTO_OPCODE(ip) @ jump to next instruction 2425 2426 2427/* ------------------------------ */ 2428 .balign 64 2429.L_OP_IGET: /* 0x52 */ 2430/* File: armv5te/OP_IGET.S */ 2431 /* 2432 * General 32-bit instance field get. 2433 * 2434 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2435 */ 2436 /* op vA, vB, field@CCCC */ 2437 mov r0, rINST, lsr #12 @ r0<- B 2438 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2439 FETCH(r1, 1) @ r1<- field ref CCCC 2440 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2441 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2442 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2443 cmp r0, #0 @ is resolved entry null? 2444 bne .LOP_IGET_finish @ no, already resolved 24458: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2446 EXPORT_PC() @ resolve() could throw 2447 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2448 bl dvmResolveInstField @ r0<- resolved InstField ptr 2449 cmp r0, #0 2450 bne .LOP_IGET_finish 2451 b common_exceptionThrown 2452 2453/* ------------------------------ */ 2454 .balign 64 2455.L_OP_IGET_WIDE: /* 0x53 */ 2456/* File: armv4t/OP_IGET_WIDE.S */ 2457 /* 2458 * Wide 32-bit instance field get. 2459 */ 2460 /* iget-wide vA, vB, field@CCCC */ 2461 mov r0, rINST, lsr #12 @ r0<- B 2462 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2463 FETCH(r1, 1) @ r1<- field ref CCCC 2464 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2465 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2466 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2467 cmp r0, #0 @ is resolved entry null? 2468 bne .LOP_IGET_WIDE_finish @ no, already resolved 24698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2470 EXPORT_PC() @ resolve() could throw 2471 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2472 bl dvmResolveInstField @ r0<- resolved InstField ptr 2473 cmp r0, #0 2474 bne .LOP_IGET_WIDE_finish 2475 b common_exceptionThrown 2476 2477/* ------------------------------ */ 2478 .balign 64 2479.L_OP_IGET_OBJECT: /* 0x54 */ 2480/* File: armv5te/OP_IGET_OBJECT.S */ 2481/* File: armv5te/OP_IGET.S */ 2482 /* 2483 * General 32-bit instance field get. 2484 * 2485 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2486 */ 2487 /* op vA, vB, field@CCCC */ 2488 mov r0, rINST, lsr #12 @ r0<- B 2489 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2490 FETCH(r1, 1) @ r1<- field ref CCCC 2491 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2492 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2493 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2494 cmp r0, #0 @ is resolved entry null? 2495 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2497 EXPORT_PC() @ resolve() could throw 2498 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2499 bl dvmResolveInstField @ r0<- resolved InstField ptr 2500 cmp r0, #0 2501 bne .LOP_IGET_OBJECT_finish 2502 b common_exceptionThrown 2503 2504 2505/* ------------------------------ */ 2506 .balign 64 2507.L_OP_IGET_BOOLEAN: /* 0x55 */ 2508/* File: armv5te/OP_IGET_BOOLEAN.S */ 2509@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2510/* File: armv5te/OP_IGET.S */ 2511 /* 2512 * General 32-bit instance field get. 2513 * 2514 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2515 */ 2516 /* op vA, vB, field@CCCC */ 2517 mov r0, rINST, lsr #12 @ r0<- B 2518 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2519 FETCH(r1, 1) @ r1<- field ref CCCC 2520 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2521 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2522 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2523 cmp r0, #0 @ is resolved entry null? 2524 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2526 EXPORT_PC() @ resolve() could throw 2527 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2528 bl dvmResolveInstField @ r0<- resolved InstField ptr 2529 cmp r0, #0 2530 bne .LOP_IGET_BOOLEAN_finish 2531 b common_exceptionThrown 2532 2533 2534/* ------------------------------ */ 2535 .balign 64 2536.L_OP_IGET_BYTE: /* 0x56 */ 2537/* File: armv5te/OP_IGET_BYTE.S */ 2538@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2539/* File: armv5te/OP_IGET.S */ 2540 /* 2541 * General 32-bit instance field get. 2542 * 2543 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2544 */ 2545 /* op vA, vB, field@CCCC */ 2546 mov r0, rINST, lsr #12 @ r0<- B 2547 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2548 FETCH(r1, 1) @ r1<- field ref CCCC 2549 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2550 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2551 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2552 cmp r0, #0 @ is resolved entry null? 2553 bne .LOP_IGET_BYTE_finish @ no, already resolved 25548: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2555 EXPORT_PC() @ resolve() could throw 2556 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2557 bl dvmResolveInstField @ r0<- resolved InstField ptr 2558 cmp r0, #0 2559 bne .LOP_IGET_BYTE_finish 2560 b common_exceptionThrown 2561 2562 2563/* ------------------------------ */ 2564 .balign 64 2565.L_OP_IGET_CHAR: /* 0x57 */ 2566/* File: armv5te/OP_IGET_CHAR.S */ 2567@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2568/* File: armv5te/OP_IGET.S */ 2569 /* 2570 * General 32-bit instance field get. 2571 * 2572 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2573 */ 2574 /* op vA, vB, field@CCCC */ 2575 mov r0, rINST, lsr #12 @ r0<- B 2576 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2577 FETCH(r1, 1) @ r1<- field ref CCCC 2578 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2579 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2580 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2581 cmp r0, #0 @ is resolved entry null? 2582 bne .LOP_IGET_CHAR_finish @ no, already resolved 25838: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2584 EXPORT_PC() @ resolve() could throw 2585 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2586 bl dvmResolveInstField @ r0<- resolved InstField ptr 2587 cmp r0, #0 2588 bne .LOP_IGET_CHAR_finish 2589 b common_exceptionThrown 2590 2591 2592/* ------------------------------ */ 2593 .balign 64 2594.L_OP_IGET_SHORT: /* 0x58 */ 2595/* File: armv5te/OP_IGET_SHORT.S */ 2596@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2597/* File: armv5te/OP_IGET.S */ 2598 /* 2599 * General 32-bit instance field get. 2600 * 2601 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2602 */ 2603 /* op vA, vB, field@CCCC */ 2604 mov r0, rINST, lsr #12 @ r0<- B 2605 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2606 FETCH(r1, 1) @ r1<- field ref CCCC 2607 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2608 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2609 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2610 cmp r0, #0 @ is resolved entry null? 2611 bne .LOP_IGET_SHORT_finish @ no, already resolved 26128: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2613 EXPORT_PC() @ resolve() could throw 2614 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2615 bl dvmResolveInstField @ r0<- resolved InstField ptr 2616 cmp r0, #0 2617 bne .LOP_IGET_SHORT_finish 2618 b common_exceptionThrown 2619 2620 2621/* ------------------------------ */ 2622 .balign 64 2623.L_OP_IPUT: /* 0x59 */ 2624/* File: armv5te/OP_IPUT.S */ 2625 /* 2626 * General 32-bit instance field put. 2627 * 2628 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2629 */ 2630 /* op vA, vB, field@CCCC */ 2631 mov r0, rINST, lsr #12 @ r0<- B 2632 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2633 FETCH(r1, 1) @ r1<- field ref CCCC 2634 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2635 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2636 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2637 cmp r0, #0 @ is resolved entry null? 2638 bne .LOP_IPUT_finish @ no, already resolved 26398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2640 EXPORT_PC() @ resolve() could throw 2641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2642 bl dvmResolveInstField @ r0<- resolved InstField ptr 2643 cmp r0, #0 @ success? 2644 bne .LOP_IPUT_finish @ yes, finish up 2645 b common_exceptionThrown 2646 2647/* ------------------------------ */ 2648 .balign 64 2649.L_OP_IPUT_WIDE: /* 0x5a */ 2650/* File: armv4t/OP_IPUT_WIDE.S */ 2651 /* iput-wide vA, vB, field@CCCC */ 2652 mov r0, rINST, lsr #12 @ r0<- B 2653 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2654 FETCH(r1, 1) @ r1<- field ref CCCC 2655 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2656 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2657 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2658 cmp r0, #0 @ is resolved entry null? 2659 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26608: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2661 EXPORT_PC() @ resolve() could throw 2662 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2663 bl dvmResolveInstField @ r0<- resolved InstField ptr 2664 cmp r0, #0 @ success? 2665 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2666 b common_exceptionThrown 2667 2668/* ------------------------------ */ 2669 .balign 64 2670.L_OP_IPUT_OBJECT: /* 0x5b */ 2671/* File: armv5te/OP_IPUT_OBJECT.S */ 2672 /* 2673 * 32-bit instance field put. 2674 * 2675 * for: iput-object, iput-object-volatile 2676 */ 2677 /* op vA, vB, field@CCCC */ 2678 mov r0, rINST, lsr #12 @ r0<- B 2679 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2680 FETCH(r1, 1) @ r1<- field ref CCCC 2681 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2682 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2683 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2684 cmp r0, #0 @ is resolved entry null? 2685 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2687 EXPORT_PC() @ resolve() could throw 2688 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2689 bl dvmResolveInstField @ r0<- resolved InstField ptr 2690 cmp r0, #0 @ success? 2691 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2692 b common_exceptionThrown 2693 2694/* ------------------------------ */ 2695 .balign 64 2696.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2697/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2698@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2699/* File: armv5te/OP_IPUT.S */ 2700 /* 2701 * General 32-bit instance field put. 2702 * 2703 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2704 */ 2705 /* op vA, vB, field@CCCC */ 2706 mov r0, rINST, lsr #12 @ r0<- B 2707 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2708 FETCH(r1, 1) @ r1<- field ref CCCC 2709 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2710 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2711 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2712 cmp r0, #0 @ is resolved entry null? 2713 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27148: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2715 EXPORT_PC() @ resolve() could throw 2716 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2717 bl dvmResolveInstField @ r0<- resolved InstField ptr 2718 cmp r0, #0 @ success? 2719 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2720 b common_exceptionThrown 2721 2722 2723/* ------------------------------ */ 2724 .balign 64 2725.L_OP_IPUT_BYTE: /* 0x5d */ 2726/* File: armv5te/OP_IPUT_BYTE.S */ 2727@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2728/* File: armv5te/OP_IPUT.S */ 2729 /* 2730 * General 32-bit instance field put. 2731 * 2732 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2733 */ 2734 /* op vA, vB, field@CCCC */ 2735 mov r0, rINST, lsr #12 @ r0<- B 2736 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2737 FETCH(r1, 1) @ r1<- field ref CCCC 2738 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2739 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2740 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2741 cmp r0, #0 @ is resolved entry null? 2742 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27438: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2744 EXPORT_PC() @ resolve() could throw 2745 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2746 bl dvmResolveInstField @ r0<- resolved InstField ptr 2747 cmp r0, #0 @ success? 2748 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2749 b common_exceptionThrown 2750 2751 2752/* ------------------------------ */ 2753 .balign 64 2754.L_OP_IPUT_CHAR: /* 0x5e */ 2755/* File: armv5te/OP_IPUT_CHAR.S */ 2756@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2757/* File: armv5te/OP_IPUT.S */ 2758 /* 2759 * General 32-bit instance field put. 2760 * 2761 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2762 */ 2763 /* op vA, vB, field@CCCC */ 2764 mov r0, rINST, lsr #12 @ r0<- B 2765 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2766 FETCH(r1, 1) @ r1<- field ref CCCC 2767 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2768 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2769 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2770 cmp r0, #0 @ is resolved entry null? 2771 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2773 EXPORT_PC() @ resolve() could throw 2774 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2775 bl dvmResolveInstField @ r0<- resolved InstField ptr 2776 cmp r0, #0 @ success? 2777 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2778 b common_exceptionThrown 2779 2780 2781/* ------------------------------ */ 2782 .balign 64 2783.L_OP_IPUT_SHORT: /* 0x5f */ 2784/* File: armv5te/OP_IPUT_SHORT.S */ 2785@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2786/* File: armv5te/OP_IPUT.S */ 2787 /* 2788 * General 32-bit instance field put. 2789 * 2790 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2791 */ 2792 /* op vA, vB, field@CCCC */ 2793 mov r0, rINST, lsr #12 @ r0<- B 2794 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2795 FETCH(r1, 1) @ r1<- field ref CCCC 2796 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2797 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2798 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2799 cmp r0, #0 @ is resolved entry null? 2800 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28018: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2802 EXPORT_PC() @ resolve() could throw 2803 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2804 bl dvmResolveInstField @ r0<- resolved InstField ptr 2805 cmp r0, #0 @ success? 2806 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2807 b common_exceptionThrown 2808 2809 2810/* ------------------------------ */ 2811 .balign 64 2812.L_OP_SGET: /* 0x60 */ 2813/* File: armv5te/OP_SGET.S */ 2814 /* 2815 * General 32-bit SGET handler. 2816 * 2817 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2818 */ 2819 /* op vAA, field@BBBB */ 2820 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2821 FETCH(r1, 1) @ r1<- field ref BBBB 2822 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2823 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2824 cmp r0, #0 @ is resolved entry null? 2825 beq .LOP_SGET_resolve @ yes, do resolve 2826.LOP_SGET_finish: @ field ptr in r0 2827 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2828 @ no-op @ acquiring load 2829 mov r2, rINST, lsr #8 @ r2<- AA 2830 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2831 SET_VREG(r1, r2) @ fp[AA]<- r1 2832 GET_INST_OPCODE(ip) @ extract opcode from rINST 2833 GOTO_OPCODE(ip) @ jump to next instruction 2834 2835/* ------------------------------ */ 2836 .balign 64 2837.L_OP_SGET_WIDE: /* 0x61 */ 2838/* File: armv4t/OP_SGET_WIDE.S */ 2839 /* 2840 * 64-bit SGET handler. 2841 */ 2842 /* sget-wide vAA, field@BBBB */ 2843 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2844 FETCH(r1, 1) @ r1<- field ref BBBB 2845 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2846 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2847 cmp r0, #0 @ is resolved entry null? 2848 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2849.LOP_SGET_WIDE_finish: 2850 mov r9, rINST, lsr #8 @ r9<- AA 2851 add r0, r0, #offStaticField_value @ r0<- pointer to data 2852 .if 0 2853 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2854 .else 2855 ldmia r0, {r0-r1} @ r0/r1<- field value (aligned) 2856 .endif 2857 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2859 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2860 GET_INST_OPCODE(ip) @ extract opcode from rINST 2861 GOTO_OPCODE(ip) @ jump to next instruction 2862 2863/* ------------------------------ */ 2864 .balign 64 2865.L_OP_SGET_OBJECT: /* 0x62 */ 2866/* File: armv5te/OP_SGET_OBJECT.S */ 2867/* File: armv5te/OP_SGET.S */ 2868 /* 2869 * General 32-bit SGET handler. 2870 * 2871 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2872 */ 2873 /* op vAA, field@BBBB */ 2874 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2875 FETCH(r1, 1) @ r1<- field ref BBBB 2876 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2877 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2878 cmp r0, #0 @ is resolved entry null? 2879 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2880.LOP_SGET_OBJECT_finish: @ field ptr in r0 2881 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2882 @ no-op @ acquiring load 2883 mov r2, rINST, lsr #8 @ r2<- AA 2884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2885 SET_VREG(r1, r2) @ fp[AA]<- r1 2886 GET_INST_OPCODE(ip) @ extract opcode from rINST 2887 GOTO_OPCODE(ip) @ jump to next instruction 2888 2889 2890/* ------------------------------ */ 2891 .balign 64 2892.L_OP_SGET_BOOLEAN: /* 0x63 */ 2893/* File: armv5te/OP_SGET_BOOLEAN.S */ 2894/* File: armv5te/OP_SGET.S */ 2895 /* 2896 * General 32-bit SGET handler. 2897 * 2898 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2899 */ 2900 /* op vAA, field@BBBB */ 2901 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2902 FETCH(r1, 1) @ r1<- field ref BBBB 2903 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2904 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2905 cmp r0, #0 @ is resolved entry null? 2906 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2907.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2908 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2909 @ no-op @ acquiring load 2910 mov r2, rINST, lsr #8 @ r2<- AA 2911 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2912 SET_VREG(r1, r2) @ fp[AA]<- r1 2913 GET_INST_OPCODE(ip) @ extract opcode from rINST 2914 GOTO_OPCODE(ip) @ jump to next instruction 2915 2916 2917/* ------------------------------ */ 2918 .balign 64 2919.L_OP_SGET_BYTE: /* 0x64 */ 2920/* File: armv5te/OP_SGET_BYTE.S */ 2921/* File: armv5te/OP_SGET.S */ 2922 /* 2923 * General 32-bit SGET handler. 2924 * 2925 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2926 */ 2927 /* op vAA, field@BBBB */ 2928 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2929 FETCH(r1, 1) @ r1<- field ref BBBB 2930 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2931 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2932 cmp r0, #0 @ is resolved entry null? 2933 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2934.LOP_SGET_BYTE_finish: @ field ptr in r0 2935 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2936 @ no-op @ acquiring load 2937 mov r2, rINST, lsr #8 @ r2<- AA 2938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2939 SET_VREG(r1, r2) @ fp[AA]<- r1 2940 GET_INST_OPCODE(ip) @ extract opcode from rINST 2941 GOTO_OPCODE(ip) @ jump to next instruction 2942 2943 2944/* ------------------------------ */ 2945 .balign 64 2946.L_OP_SGET_CHAR: /* 0x65 */ 2947/* File: armv5te/OP_SGET_CHAR.S */ 2948/* File: armv5te/OP_SGET.S */ 2949 /* 2950 * General 32-bit SGET handler. 2951 * 2952 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2953 */ 2954 /* op vAA, field@BBBB */ 2955 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2956 FETCH(r1, 1) @ r1<- field ref BBBB 2957 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2958 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2959 cmp r0, #0 @ is resolved entry null? 2960 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2961.LOP_SGET_CHAR_finish: @ field ptr in r0 2962 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2963 @ no-op @ acquiring load 2964 mov r2, rINST, lsr #8 @ r2<- AA 2965 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2966 SET_VREG(r1, r2) @ fp[AA]<- r1 2967 GET_INST_OPCODE(ip) @ extract opcode from rINST 2968 GOTO_OPCODE(ip) @ jump to next instruction 2969 2970 2971/* ------------------------------ */ 2972 .balign 64 2973.L_OP_SGET_SHORT: /* 0x66 */ 2974/* File: armv5te/OP_SGET_SHORT.S */ 2975/* File: armv5te/OP_SGET.S */ 2976 /* 2977 * General 32-bit SGET handler. 2978 * 2979 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2980 */ 2981 /* op vAA, field@BBBB */ 2982 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2983 FETCH(r1, 1) @ r1<- field ref BBBB 2984 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2985 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2986 cmp r0, #0 @ is resolved entry null? 2987 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2988.LOP_SGET_SHORT_finish: @ field ptr in r0 2989 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2990 @ no-op @ acquiring load 2991 mov r2, rINST, lsr #8 @ r2<- AA 2992 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2993 SET_VREG(r1, r2) @ fp[AA]<- r1 2994 GET_INST_OPCODE(ip) @ extract opcode from rINST 2995 GOTO_OPCODE(ip) @ jump to next instruction 2996 2997 2998/* ------------------------------ */ 2999 .balign 64 3000.L_OP_SPUT: /* 0x67 */ 3001/* File: armv5te/OP_SPUT.S */ 3002 /* 3003 * General 32-bit SPUT handler. 3004 * 3005 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3006 */ 3007 /* op vAA, field@BBBB */ 3008 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3009 FETCH(r1, 1) @ r1<- field ref BBBB 3010 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3011 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3012 cmp r0, #0 @ is resolved entry null? 3013 beq .LOP_SPUT_resolve @ yes, do resolve 3014.LOP_SPUT_finish: @ field ptr in r0 3015 mov r2, rINST, lsr #8 @ r2<- AA 3016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3017 GET_VREG(r1, r2) @ r1<- fp[AA] 3018 GET_INST_OPCODE(ip) @ extract opcode from rINST 3019 @ no-op @ releasing store 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: armv4t/OP_SPUT_WIDE.S */ 3027 /* 3028 * 64-bit SPUT handler. 3029 */ 3030 /* sput-wide vAA, field@BBBB */ 3031 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3032 FETCH(r1, 1) @ r1<- field ref BBBB 3033 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3034 mov r9, rINST, lsr #8 @ r9<- AA 3035 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3036 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3037 cmp r2, #0 @ is resolved entry null? 3038 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3039.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3041 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3042 GET_INST_OPCODE(r10) @ extract opcode from rINST 3043 add r2, r2, #offStaticField_value @ r2<- pointer to data 3044 .if 0 3045 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3046 .else 3047 stmia r2, {r0-r1} @ field<- vAA/vAA+1 3048 .endif 3049 GOTO_OPCODE(r10) @ jump to next instruction 3050 3051/* ------------------------------ */ 3052 .balign 64 3053.L_OP_SPUT_OBJECT: /* 0x69 */ 3054/* File: armv5te/OP_SPUT_OBJECT.S */ 3055 /* 3056 * 32-bit SPUT handler for objects 3057 * 3058 * for: sput-object, sput-object-volatile 3059 */ 3060 /* op vAA, field@BBBB */ 3061 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3062 FETCH(r1, 1) @ r1<- field ref BBBB 3063 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3064 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3065 cmp r0, #0 @ is resolved entry null? 3066 bne .LOP_SPUT_OBJECT_finish @ no, continue 3067 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3068 EXPORT_PC() @ resolve() could throw, so export now 3069 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3070 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3071 cmp r0, #0 @ success? 3072 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3073 b common_exceptionThrown @ no, handle exception 3074 3075 3076/* ------------------------------ */ 3077 .balign 64 3078.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3079/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3080/* File: armv5te/OP_SPUT.S */ 3081 /* 3082 * General 32-bit SPUT handler. 3083 * 3084 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3085 */ 3086 /* op vAA, field@BBBB */ 3087 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3088 FETCH(r1, 1) @ r1<- field ref BBBB 3089 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3090 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3091 cmp r0, #0 @ is resolved entry null? 3092 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3093.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3094 mov r2, rINST, lsr #8 @ r2<- AA 3095 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3096 GET_VREG(r1, r2) @ r1<- fp[AA] 3097 GET_INST_OPCODE(ip) @ extract opcode from rINST 3098 @ no-op @ releasing store 3099 str r1, [r0, #offStaticField_value] @ field<- vAA 3100 GOTO_OPCODE(ip) @ jump to next instruction 3101 3102 3103/* ------------------------------ */ 3104 .balign 64 3105.L_OP_SPUT_BYTE: /* 0x6b */ 3106/* File: armv5te/OP_SPUT_BYTE.S */ 3107/* File: armv5te/OP_SPUT.S */ 3108 /* 3109 * General 32-bit SPUT handler. 3110 * 3111 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3112 */ 3113 /* op vAA, field@BBBB */ 3114 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3115 FETCH(r1, 1) @ r1<- field ref BBBB 3116 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3117 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3118 cmp r0, #0 @ is resolved entry null? 3119 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3120.LOP_SPUT_BYTE_finish: @ field ptr in r0 3121 mov r2, rINST, lsr #8 @ r2<- AA 3122 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3123 GET_VREG(r1, r2) @ r1<- fp[AA] 3124 GET_INST_OPCODE(ip) @ extract opcode from rINST 3125 @ no-op @ releasing store 3126 str r1, [r0, #offStaticField_value] @ field<- vAA 3127 GOTO_OPCODE(ip) @ jump to next instruction 3128 3129 3130/* ------------------------------ */ 3131 .balign 64 3132.L_OP_SPUT_CHAR: /* 0x6c */ 3133/* File: armv5te/OP_SPUT_CHAR.S */ 3134/* File: armv5te/OP_SPUT.S */ 3135 /* 3136 * General 32-bit SPUT handler. 3137 * 3138 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3139 */ 3140 /* op vAA, field@BBBB */ 3141 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3142 FETCH(r1, 1) @ r1<- field ref BBBB 3143 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3144 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3145 cmp r0, #0 @ is resolved entry null? 3146 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3147.LOP_SPUT_CHAR_finish: @ field ptr in r0 3148 mov r2, rINST, lsr #8 @ r2<- AA 3149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3150 GET_VREG(r1, r2) @ r1<- fp[AA] 3151 GET_INST_OPCODE(ip) @ extract opcode from rINST 3152 @ no-op @ releasing store 3153 str r1, [r0, #offStaticField_value] @ field<- vAA 3154 GOTO_OPCODE(ip) @ jump to next instruction 3155 3156 3157/* ------------------------------ */ 3158 .balign 64 3159.L_OP_SPUT_SHORT: /* 0x6d */ 3160/* File: armv5te/OP_SPUT_SHORT.S */ 3161/* File: armv5te/OP_SPUT.S */ 3162 /* 3163 * General 32-bit SPUT handler. 3164 * 3165 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3166 */ 3167 /* op vAA, field@BBBB */ 3168 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3169 FETCH(r1, 1) @ r1<- field ref BBBB 3170 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3171 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3172 cmp r0, #0 @ is resolved entry null? 3173 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3174.LOP_SPUT_SHORT_finish: @ field ptr in r0 3175 mov r2, rINST, lsr #8 @ r2<- AA 3176 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3177 GET_VREG(r1, r2) @ r1<- fp[AA] 3178 GET_INST_OPCODE(ip) @ extract opcode from rINST 3179 @ no-op @ releasing store 3180 str r1, [r0, #offStaticField_value] @ field<- vAA 3181 GOTO_OPCODE(ip) @ jump to next instruction 3182 3183 3184/* ------------------------------ */ 3185 .balign 64 3186.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3187/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3188 /* 3189 * Handle a virtual method call. 3190 * 3191 * for: invoke-virtual, invoke-virtual/range 3192 */ 3193 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3194 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3195 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3196 FETCH(r1, 1) @ r1<- BBBB 3197 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3198 FETCH(r10, 2) @ r10<- GFED or CCCC 3199 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3200 .if (!0) 3201 and r10, r10, #15 @ r10<- D (or stays CCCC) 3202 .endif 3203 cmp r0, #0 @ already resolved? 3204 EXPORT_PC() @ must export for invoke 3205 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3206 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3207 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3208 mov r2, #METHOD_VIRTUAL @ resolver method type 3209 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3210 cmp r0, #0 @ got null? 3211 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3212 b common_exceptionThrown @ yes, handle exception 3213 3214/* ------------------------------ */ 3215 .balign 64 3216.L_OP_INVOKE_SUPER: /* 0x6f */ 3217/* File: armv5te/OP_INVOKE_SUPER.S */ 3218 /* 3219 * Handle a "super" method call. 3220 * 3221 * for: invoke-super, invoke-super/range 3222 */ 3223 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3224 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3225 FETCH(r10, 2) @ r10<- GFED or CCCC 3226 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3227 .if (!0) 3228 and r10, r10, #15 @ r10<- D (or stays CCCC) 3229 .endif 3230 FETCH(r1, 1) @ r1<- BBBB 3231 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3232 GET_VREG(r2, r10) @ r2<- "this" ptr 3233 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3234 cmp r2, #0 @ null "this"? 3235 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3236 beq common_errNullObject @ null "this", throw exception 3237 cmp r0, #0 @ already resolved? 3238 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3239 EXPORT_PC() @ must export for invoke 3240 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3241 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3242 3243/* ------------------------------ */ 3244 .balign 64 3245.L_OP_INVOKE_DIRECT: /* 0x70 */ 3246/* File: armv5te/OP_INVOKE_DIRECT.S */ 3247 /* 3248 * Handle a direct method call. 3249 * 3250 * (We could defer the "is 'this' pointer null" test to the common 3251 * method invocation code, and use a flag to indicate that static 3252 * calls don't count. If we do this as part of copying the arguments 3253 * out we could avoiding loading the first arg twice.) 3254 * 3255 * for: invoke-direct, invoke-direct/range 3256 */ 3257 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3258 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3259 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3260 FETCH(r1, 1) @ r1<- BBBB 3261 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3262 FETCH(r10, 2) @ r10<- GFED or CCCC 3263 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3264 .if (!0) 3265 and r10, r10, #15 @ r10<- D (or stays CCCC) 3266 .endif 3267 cmp r0, #0 @ already resolved? 3268 EXPORT_PC() @ must export for invoke 3269 GET_VREG(r2, r10) @ r2<- "this" ptr 3270 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3271.LOP_INVOKE_DIRECT_finish: 3272 cmp r2, #0 @ null "this" ref? 3273 bne common_invokeMethodNoRange @ no, continue on 3274 b common_errNullObject @ yes, throw exception 3275 3276/* ------------------------------ */ 3277 .balign 64 3278.L_OP_INVOKE_STATIC: /* 0x71 */ 3279/* File: armv5te/OP_INVOKE_STATIC.S */ 3280 /* 3281 * Handle a static method call. 3282 * 3283 * for: invoke-static, invoke-static/range 3284 */ 3285 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3286 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3287 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3288 FETCH(r1, 1) @ r1<- BBBB 3289 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3290 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3291 cmp r0, #0 @ already resolved? 3292 EXPORT_PC() @ must export for invoke 3293 bne common_invokeMethodNoRange @ yes, continue on 32940: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3295 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3296 mov r2, #METHOD_STATIC @ resolver method type 3297 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3298 cmp r0, #0 @ got null? 3299 bne common_invokeMethodNoRange @ no, continue 3300 b common_exceptionThrown @ yes, handle exception 3301 3302/* ------------------------------ */ 3303 .balign 64 3304.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3305/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3306 /* 3307 * Handle an interface method call. 3308 * 3309 * for: invoke-interface, invoke-interface/range 3310 */ 3311 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3312 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3313 FETCH(r2, 2) @ r2<- FEDC or CCCC 3314 FETCH(r1, 1) @ r1<- BBBB 3315 .if (!0) 3316 and r2, r2, #15 @ r2<- C (or stays CCCC) 3317 .endif 3318 EXPORT_PC() @ must export for invoke 3319 GET_VREG(r0, r2) @ r0<- first arg ("this") 3320 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3321 cmp r0, #0 @ null obj? 3322 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3323 beq common_errNullObject @ yes, fail 3324 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3325 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3326 cmp r0, #0 @ failed? 3327 beq common_exceptionThrown @ yes, handle exception 3328 b common_invokeMethodNoRange @ jump to common handler 3329 3330/* ------------------------------ */ 3331 .balign 64 3332.L_OP_UNUSED_73: /* 0x73 */ 3333/* File: armv5te/OP_UNUSED_73.S */ 3334/* File: armv5te/unused.S */ 3335 bl common_abort 3336 3337 3338/* ------------------------------ */ 3339 .balign 64 3340.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3341/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3342/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3343 /* 3344 * Handle a virtual method call. 3345 * 3346 * for: invoke-virtual, invoke-virtual/range 3347 */ 3348 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3349 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3350 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3351 FETCH(r1, 1) @ r1<- BBBB 3352 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3353 FETCH(r10, 2) @ r10<- GFED or CCCC 3354 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3355 .if (!1) 3356 and r10, r10, #15 @ r10<- D (or stays CCCC) 3357 .endif 3358 cmp r0, #0 @ already resolved? 3359 EXPORT_PC() @ must export for invoke 3360 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3361 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3362 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3363 mov r2, #METHOD_VIRTUAL @ resolver method type 3364 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3365 cmp r0, #0 @ got null? 3366 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3367 b common_exceptionThrown @ yes, handle exception 3368 3369 3370/* ------------------------------ */ 3371 .balign 64 3372.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3373/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3374/* File: armv5te/OP_INVOKE_SUPER.S */ 3375 /* 3376 * Handle a "super" method call. 3377 * 3378 * for: invoke-super, invoke-super/range 3379 */ 3380 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3381 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3382 FETCH(r10, 2) @ r10<- GFED or CCCC 3383 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3384 .if (!1) 3385 and r10, r10, #15 @ r10<- D (or stays CCCC) 3386 .endif 3387 FETCH(r1, 1) @ r1<- BBBB 3388 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3389 GET_VREG(r2, r10) @ r2<- "this" ptr 3390 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3391 cmp r2, #0 @ null "this"? 3392 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3393 beq common_errNullObject @ null "this", throw exception 3394 cmp r0, #0 @ already resolved? 3395 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3396 EXPORT_PC() @ must export for invoke 3397 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3398 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3399 3400 3401/* ------------------------------ */ 3402 .balign 64 3403.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3404/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3405/* File: armv5te/OP_INVOKE_DIRECT.S */ 3406 /* 3407 * Handle a direct method call. 3408 * 3409 * (We could defer the "is 'this' pointer null" test to the common 3410 * method invocation code, and use a flag to indicate that static 3411 * calls don't count. If we do this as part of copying the arguments 3412 * out we could avoiding loading the first arg twice.) 3413 * 3414 * for: invoke-direct, invoke-direct/range 3415 */ 3416 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3417 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3418 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3419 FETCH(r1, 1) @ r1<- BBBB 3420 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3421 FETCH(r10, 2) @ r10<- GFED or CCCC 3422 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3423 .if (!1) 3424 and r10, r10, #15 @ r10<- D (or stays CCCC) 3425 .endif 3426 cmp r0, #0 @ already resolved? 3427 EXPORT_PC() @ must export for invoke 3428 GET_VREG(r2, r10) @ r2<- "this" ptr 3429 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3430.LOP_INVOKE_DIRECT_RANGE_finish: 3431 cmp r2, #0 @ null "this" ref? 3432 bne common_invokeMethodRange @ no, continue on 3433 b common_errNullObject @ yes, throw exception 3434 3435 3436/* ------------------------------ */ 3437 .balign 64 3438.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3439/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3440/* File: armv5te/OP_INVOKE_STATIC.S */ 3441 /* 3442 * Handle a static method call. 3443 * 3444 * for: invoke-static, invoke-static/range 3445 */ 3446 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3447 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3448 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3449 FETCH(r1, 1) @ r1<- BBBB 3450 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3451 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3452 cmp r0, #0 @ already resolved? 3453 EXPORT_PC() @ must export for invoke 3454 bne common_invokeMethodRange @ yes, continue on 34550: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3456 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3457 mov r2, #METHOD_STATIC @ resolver method type 3458 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3459 cmp r0, #0 @ got null? 3460 bne common_invokeMethodRange @ no, continue 3461 b common_exceptionThrown @ yes, handle exception 3462 3463 3464/* ------------------------------ */ 3465 .balign 64 3466.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3467/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3468/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3469 /* 3470 * Handle an interface method call. 3471 * 3472 * for: invoke-interface, invoke-interface/range 3473 */ 3474 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3475 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3476 FETCH(r2, 2) @ r2<- FEDC or CCCC 3477 FETCH(r1, 1) @ r1<- BBBB 3478 .if (!1) 3479 and r2, r2, #15 @ r2<- C (or stays CCCC) 3480 .endif 3481 EXPORT_PC() @ must export for invoke 3482 GET_VREG(r0, r2) @ r0<- first arg ("this") 3483 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3484 cmp r0, #0 @ null obj? 3485 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3486 beq common_errNullObject @ yes, fail 3487 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3488 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3489 cmp r0, #0 @ failed? 3490 beq common_exceptionThrown @ yes, handle exception 3491 b common_invokeMethodRange @ jump to common handler 3492 3493 3494/* ------------------------------ */ 3495 .balign 64 3496.L_OP_UNUSED_79: /* 0x79 */ 3497/* File: armv5te/OP_UNUSED_79.S */ 3498/* File: armv5te/unused.S */ 3499 bl common_abort 3500 3501 3502/* ------------------------------ */ 3503 .balign 64 3504.L_OP_UNUSED_7A: /* 0x7a */ 3505/* File: armv5te/OP_UNUSED_7A.S */ 3506/* File: armv5te/unused.S */ 3507 bl common_abort 3508 3509 3510/* ------------------------------ */ 3511 .balign 64 3512.L_OP_NEG_INT: /* 0x7b */ 3513/* File: armv5te/OP_NEG_INT.S */ 3514/* File: armv5te/unop.S */ 3515 /* 3516 * Generic 32-bit unary operation. Provide an "instr" line that 3517 * specifies an instruction that performs "result = op r0". 3518 * This could be an ARM instruction or a function call. 3519 * 3520 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3521 * int-to-byte, int-to-char, int-to-short 3522 */ 3523 /* unop vA, vB */ 3524 mov r3, rINST, lsr #12 @ r3<- B 3525 mov r9, rINST, lsr #8 @ r9<- A+ 3526 GET_VREG(r0, r3) @ r0<- vB 3527 and r9, r9, #15 3528 @ optional op; may set condition codes 3529 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3530 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3531 GET_INST_OPCODE(ip) @ extract opcode from rINST 3532 SET_VREG(r0, r9) @ vAA<- r0 3533 GOTO_OPCODE(ip) @ jump to next instruction 3534 /* 9-10 instructions */ 3535 3536 3537/* ------------------------------ */ 3538 .balign 64 3539.L_OP_NOT_INT: /* 0x7c */ 3540/* File: armv5te/OP_NOT_INT.S */ 3541/* File: armv5te/unop.S */ 3542 /* 3543 * Generic 32-bit unary operation. Provide an "instr" line that 3544 * specifies an instruction that performs "result = op r0". 3545 * This could be an ARM instruction or a function call. 3546 * 3547 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3548 * int-to-byte, int-to-char, int-to-short 3549 */ 3550 /* unop vA, vB */ 3551 mov r3, rINST, lsr #12 @ r3<- B 3552 mov r9, rINST, lsr #8 @ r9<- A+ 3553 GET_VREG(r0, r3) @ r0<- vB 3554 and r9, r9, #15 3555 @ optional op; may set condition codes 3556 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3557 mvn r0, r0 @ r0<- op, r0-r3 changed 3558 GET_INST_OPCODE(ip) @ extract opcode from rINST 3559 SET_VREG(r0, r9) @ vAA<- r0 3560 GOTO_OPCODE(ip) @ jump to next instruction 3561 /* 9-10 instructions */ 3562 3563 3564/* ------------------------------ */ 3565 .balign 64 3566.L_OP_NEG_LONG: /* 0x7d */ 3567/* File: armv5te/OP_NEG_LONG.S */ 3568/* File: armv5te/unopWide.S */ 3569 /* 3570 * Generic 64-bit unary operation. Provide an "instr" line that 3571 * specifies an instruction that performs "result = op r0/r1". 3572 * This could be an ARM instruction or a function call. 3573 * 3574 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3575 */ 3576 /* unop vA, vB */ 3577 mov r9, rINST, lsr #8 @ r9<- A+ 3578 mov r3, rINST, lsr #12 @ r3<- B 3579 and r9, r9, #15 3580 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3581 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3582 ldmia r3, {r0-r1} @ r0/r1<- vAA 3583 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3584 rsbs r0, r0, #0 @ optional op; may set condition codes 3585 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3586 GET_INST_OPCODE(ip) @ extract opcode from rINST 3587 stmia r9, {r0-r1} @ vAA<- r0/r1 3588 GOTO_OPCODE(ip) @ jump to next instruction 3589 /* 12-13 instructions */ 3590 3591 3592/* ------------------------------ */ 3593 .balign 64 3594.L_OP_NOT_LONG: /* 0x7e */ 3595/* File: armv5te/OP_NOT_LONG.S */ 3596/* File: armv5te/unopWide.S */ 3597 /* 3598 * Generic 64-bit unary operation. Provide an "instr" line that 3599 * specifies an instruction that performs "result = op r0/r1". 3600 * This could be an ARM instruction or a function call. 3601 * 3602 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3603 */ 3604 /* unop vA, vB */ 3605 mov r9, rINST, lsr #8 @ r9<- A+ 3606 mov r3, rINST, lsr #12 @ r3<- B 3607 and r9, r9, #15 3608 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3609 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3610 ldmia r3, {r0-r1} @ r0/r1<- vAA 3611 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3612 mvn r0, r0 @ optional op; may set condition codes 3613 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3614 GET_INST_OPCODE(ip) @ extract opcode from rINST 3615 stmia r9, {r0-r1} @ vAA<- r0/r1 3616 GOTO_OPCODE(ip) @ jump to next instruction 3617 /* 12-13 instructions */ 3618 3619 3620/* ------------------------------ */ 3621 .balign 64 3622.L_OP_NEG_FLOAT: /* 0x7f */ 3623/* File: armv5te/OP_NEG_FLOAT.S */ 3624/* File: armv5te/unop.S */ 3625 /* 3626 * Generic 32-bit unary operation. Provide an "instr" line that 3627 * specifies an instruction that performs "result = op r0". 3628 * This could be an ARM instruction or a function call. 3629 * 3630 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3631 * int-to-byte, int-to-char, int-to-short 3632 */ 3633 /* unop vA, vB */ 3634 mov r3, rINST, lsr #12 @ r3<- B 3635 mov r9, rINST, lsr #8 @ r9<- A+ 3636 GET_VREG(r0, r3) @ r0<- vB 3637 and r9, r9, #15 3638 @ optional op; may set condition codes 3639 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3640 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3641 GET_INST_OPCODE(ip) @ extract opcode from rINST 3642 SET_VREG(r0, r9) @ vAA<- r0 3643 GOTO_OPCODE(ip) @ jump to next instruction 3644 /* 9-10 instructions */ 3645 3646 3647/* ------------------------------ */ 3648 .balign 64 3649.L_OP_NEG_DOUBLE: /* 0x80 */ 3650/* File: armv5te/OP_NEG_DOUBLE.S */ 3651/* File: armv5te/unopWide.S */ 3652 /* 3653 * Generic 64-bit unary operation. Provide an "instr" line that 3654 * specifies an instruction that performs "result = op r0/r1". 3655 * This could be an ARM instruction or a function call. 3656 * 3657 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3658 */ 3659 /* unop vA, vB */ 3660 mov r9, rINST, lsr #8 @ r9<- A+ 3661 mov r3, rINST, lsr #12 @ r3<- B 3662 and r9, r9, #15 3663 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3664 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3665 ldmia r3, {r0-r1} @ r0/r1<- vAA 3666 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3667 @ optional op; may set condition codes 3668 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3669 GET_INST_OPCODE(ip) @ extract opcode from rINST 3670 stmia r9, {r0-r1} @ vAA<- r0/r1 3671 GOTO_OPCODE(ip) @ jump to next instruction 3672 /* 12-13 instructions */ 3673 3674 3675/* ------------------------------ */ 3676 .balign 64 3677.L_OP_INT_TO_LONG: /* 0x81 */ 3678/* File: armv5te/OP_INT_TO_LONG.S */ 3679/* File: armv5te/unopWider.S */ 3680 /* 3681 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3682 * that specifies an instruction that performs "result = op r0", where 3683 * "result" is a 64-bit quantity in r0/r1. 3684 * 3685 * For: int-to-long, int-to-double, float-to-long, float-to-double 3686 */ 3687 /* unop vA, vB */ 3688 mov r9, rINST, lsr #8 @ r9<- A+ 3689 mov r3, rINST, lsr #12 @ r3<- B 3690 and r9, r9, #15 3691 GET_VREG(r0, r3) @ r0<- vB 3692 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3693 @ optional op; may set condition codes 3694 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3695 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3696 GET_INST_OPCODE(ip) @ extract opcode from rINST 3697 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3698 GOTO_OPCODE(ip) @ jump to next instruction 3699 /* 10-11 instructions */ 3700 3701 3702/* ------------------------------ */ 3703 .balign 64 3704.L_OP_INT_TO_FLOAT: /* 0x82 */ 3705/* File: armv5te/OP_INT_TO_FLOAT.S */ 3706/* File: armv5te/unop.S */ 3707 /* 3708 * Generic 32-bit unary operation. Provide an "instr" line that 3709 * specifies an instruction that performs "result = op r0". 3710 * This could be an ARM instruction or a function call. 3711 * 3712 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3713 * int-to-byte, int-to-char, int-to-short 3714 */ 3715 /* unop vA, vB */ 3716 mov r3, rINST, lsr #12 @ r3<- B 3717 mov r9, rINST, lsr #8 @ r9<- A+ 3718 GET_VREG(r0, r3) @ r0<- vB 3719 and r9, r9, #15 3720 @ optional op; may set condition codes 3721 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3722 bl __aeabi_i2f @ r0<- op, r0-r3 changed 3723 GET_INST_OPCODE(ip) @ extract opcode from rINST 3724 SET_VREG(r0, r9) @ vAA<- r0 3725 GOTO_OPCODE(ip) @ jump to next instruction 3726 /* 9-10 instructions */ 3727 3728 3729/* ------------------------------ */ 3730 .balign 64 3731.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3732/* File: armv5te/OP_INT_TO_DOUBLE.S */ 3733/* File: armv5te/unopWider.S */ 3734 /* 3735 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3736 * that specifies an instruction that performs "result = op r0", where 3737 * "result" is a 64-bit quantity in r0/r1. 3738 * 3739 * For: int-to-long, int-to-double, float-to-long, float-to-double 3740 */ 3741 /* unop vA, vB */ 3742 mov r9, rINST, lsr #8 @ r9<- A+ 3743 mov r3, rINST, lsr #12 @ r3<- B 3744 and r9, r9, #15 3745 GET_VREG(r0, r3) @ r0<- vB 3746 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3747 @ optional op; may set condition codes 3748 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3749 bl __aeabi_i2d @ r0<- op, r0-r3 changed 3750 GET_INST_OPCODE(ip) @ extract opcode from rINST 3751 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3752 GOTO_OPCODE(ip) @ jump to next instruction 3753 /* 10-11 instructions */ 3754 3755 3756/* ------------------------------ */ 3757 .balign 64 3758.L_OP_LONG_TO_INT: /* 0x84 */ 3759/* File: armv5te/OP_LONG_TO_INT.S */ 3760/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3761/* File: armv5te/OP_MOVE.S */ 3762 /* for move, move-object, long-to-int */ 3763 /* op vA, vB */ 3764 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3765 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3766 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3767 GET_VREG(r2, r1) @ r2<- fp[B] 3768 and r0, r0, #15 3769 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3770 SET_VREG(r2, r0) @ fp[A]<- r2 3771 GOTO_OPCODE(ip) @ execute next instruction 3772 3773 3774/* ------------------------------ */ 3775 .balign 64 3776.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3777/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3778/* File: armv5te/unopNarrower.S */ 3779 /* 3780 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3781 * that specifies an instruction that performs "result = op r0/r1", where 3782 * "result" is a 32-bit quantity in r0. 3783 * 3784 * For: long-to-float, double-to-int, double-to-float 3785 * 3786 * (This would work for long-to-int, but that instruction is actually 3787 * an exact match for OP_MOVE.) 3788 */ 3789 /* unop vA, vB */ 3790 mov r3, rINST, lsr #12 @ r3<- B 3791 mov r9, rINST, lsr #8 @ r9<- A+ 3792 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3793 and r9, r9, #15 3794 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3795 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3796 @ optional op; may set condition codes 3797 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3798 GET_INST_OPCODE(ip) @ extract opcode from rINST 3799 SET_VREG(r0, r9) @ vA<- r0 3800 GOTO_OPCODE(ip) @ jump to next instruction 3801 /* 10-11 instructions */ 3802 3803 3804/* ------------------------------ */ 3805 .balign 64 3806.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3807/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3808/* File: armv5te/unopWide.S */ 3809 /* 3810 * Generic 64-bit unary operation. Provide an "instr" line that 3811 * specifies an instruction that performs "result = op r0/r1". 3812 * This could be an ARM instruction or a function call. 3813 * 3814 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3815 */ 3816 /* unop vA, vB */ 3817 mov r9, rINST, lsr #8 @ r9<- A+ 3818 mov r3, rINST, lsr #12 @ r3<- B 3819 and r9, r9, #15 3820 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3821 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3822 ldmia r3, {r0-r1} @ r0/r1<- vAA 3823 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3824 @ optional op; may set condition codes 3825 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3826 GET_INST_OPCODE(ip) @ extract opcode from rINST 3827 stmia r9, {r0-r1} @ vAA<- r0/r1 3828 GOTO_OPCODE(ip) @ jump to next instruction 3829 /* 12-13 instructions */ 3830 3831 3832/* ------------------------------ */ 3833 .balign 64 3834.L_OP_FLOAT_TO_INT: /* 0x87 */ 3835/* File: armv5te/OP_FLOAT_TO_INT.S */ 3836/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3837/* File: armv5te/unop.S */ 3838 /* 3839 * Generic 32-bit unary operation. Provide an "instr" line that 3840 * specifies an instruction that performs "result = op r0". 3841 * This could be an ARM instruction or a function call. 3842 * 3843 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3844 * int-to-byte, int-to-char, int-to-short 3845 */ 3846 /* unop vA, vB */ 3847 mov r3, rINST, lsr #12 @ r3<- B 3848 mov r9, rINST, lsr #8 @ r9<- A+ 3849 GET_VREG(r0, r3) @ r0<- vB 3850 and r9, r9, #15 3851 @ optional op; may set condition codes 3852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3853 bl __aeabi_f2iz @ r0<- op, r0-r3 changed 3854 GET_INST_OPCODE(ip) @ extract opcode from rINST 3855 SET_VREG(r0, r9) @ vAA<- r0 3856 GOTO_OPCODE(ip) @ jump to next instruction 3857 /* 9-10 instructions */ 3858 3859 3860#if 0 3861@include "armv5te/unop.S" {"instr":"bl f2i_doconv"} 3862@break 3863/* 3864 * Convert the float in r0 to an int in r0. 3865 * 3866 * We have to clip values to int min/max per the specification. The 3867 * expected common case is a "reasonable" value that converts directly 3868 * to modest integer. The EABI convert function isn't doing this for us. 3869 */ 3870f2i_doconv: 3871 stmfd sp!, {r4, lr} 3872 mov r1, #0x4f000000 @ (float)maxint 3873 mov r4, r0 3874 bl __aeabi_fcmpge @ is arg >= maxint? 3875 cmp r0, #0 @ nonzero == yes 3876 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3877 ldmnefd sp!, {r4, pc} 3878 3879 mov r0, r4 @ recover arg 3880 mov r1, #0xcf000000 @ (float)minint 3881 bl __aeabi_fcmple @ is arg <= minint? 3882 cmp r0, #0 @ nonzero == yes 3883 movne r0, #0x80000000 @ return minint (80000000) 3884 ldmnefd sp!, {r4, pc} 3885 3886 mov r0, r4 @ recover arg 3887 mov r1, r4 3888 bl __aeabi_fcmpeq @ is arg == self? 3889 cmp r0, #0 @ zero == no 3890 ldmeqfd sp!, {r4, pc} @ return zero for NaN 3891 3892 mov r0, r4 @ recover arg 3893 bl __aeabi_f2iz @ convert float to int 3894 ldmfd sp!, {r4, pc} 3895#endif 3896 3897/* ------------------------------ */ 3898 .balign 64 3899.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3900/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3901@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3902/* File: armv5te/unopWider.S */ 3903 /* 3904 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3905 * that specifies an instruction that performs "result = op r0", where 3906 * "result" is a 64-bit quantity in r0/r1. 3907 * 3908 * For: int-to-long, int-to-double, float-to-long, float-to-double 3909 */ 3910 /* unop vA, vB */ 3911 mov r9, rINST, lsr #8 @ r9<- A+ 3912 mov r3, rINST, lsr #12 @ r3<- B 3913 and r9, r9, #15 3914 GET_VREG(r0, r3) @ r0<- vB 3915 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3916 @ optional op; may set condition codes 3917 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3918 bl f2l_doconv @ r0<- op, r0-r3 changed 3919 GET_INST_OPCODE(ip) @ extract opcode from rINST 3920 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3921 GOTO_OPCODE(ip) @ jump to next instruction 3922 /* 10-11 instructions */ 3923 3924 3925 3926/* ------------------------------ */ 3927 .balign 64 3928.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3929/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */ 3930/* File: armv5te/unopWider.S */ 3931 /* 3932 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3933 * that specifies an instruction that performs "result = op r0", where 3934 * "result" is a 64-bit quantity in r0/r1. 3935 * 3936 * For: int-to-long, int-to-double, float-to-long, float-to-double 3937 */ 3938 /* unop vA, vB */ 3939 mov r9, rINST, lsr #8 @ r9<- A+ 3940 mov r3, rINST, lsr #12 @ r3<- B 3941 and r9, r9, #15 3942 GET_VREG(r0, r3) @ r0<- vB 3943 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3944 @ optional op; may set condition codes 3945 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3946 bl __aeabi_f2d @ r0<- op, r0-r3 changed 3947 GET_INST_OPCODE(ip) @ extract opcode from rINST 3948 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3949 GOTO_OPCODE(ip) @ jump to next instruction 3950 /* 10-11 instructions */ 3951 3952 3953/* ------------------------------ */ 3954 .balign 64 3955.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3956/* File: armv5te/OP_DOUBLE_TO_INT.S */ 3957/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3958/* File: armv5te/unopNarrower.S */ 3959 /* 3960 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3961 * that specifies an instruction that performs "result = op r0/r1", where 3962 * "result" is a 32-bit quantity in r0. 3963 * 3964 * For: long-to-float, double-to-int, double-to-float 3965 * 3966 * (This would work for long-to-int, but that instruction is actually 3967 * an exact match for OP_MOVE.) 3968 */ 3969 /* unop vA, vB */ 3970 mov r3, rINST, lsr #12 @ r3<- B 3971 mov r9, rINST, lsr #8 @ r9<- A+ 3972 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3973 and r9, r9, #15 3974 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3975 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3976 @ optional op; may set condition codes 3977 bl __aeabi_d2iz @ r0<- op, r0-r3 changed 3978 GET_INST_OPCODE(ip) @ extract opcode from rINST 3979 SET_VREG(r0, r9) @ vA<- r0 3980 GOTO_OPCODE(ip) @ jump to next instruction 3981 /* 10-11 instructions */ 3982 3983 3984#if 0 3985@include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"} 3986@break 3987/* 3988 * Convert the double in r0/r1 to an int in r0. 3989 * 3990 * We have to clip values to int min/max per the specification. The 3991 * expected common case is a "reasonable" value that converts directly 3992 * to modest integer. The EABI convert function isn't doing this for us. 3993 */ 3994d2i_doconv: 3995 stmfd sp!, {r4, r5, lr} @ save regs 3996 mov r2, #0x80000000 @ maxint, as a double (low word) 3997 mov r2, r2, asr #9 @ 0xffc00000 3998 sub sp, sp, #4 @ align for EABI 3999 mvn r3, #0xbe000000 @ maxint, as a double (high word) 4000 sub r3, r3, #0x00200000 @ 0x41dfffff 4001 mov r4, r0 @ save a copy of r0 4002 mov r5, r1 @ and r1 4003 bl __aeabi_dcmpge @ is arg >= maxint? 4004 cmp r0, #0 @ nonzero == yes 4005 mvnne r0, #0x80000000 @ return maxint (0x7fffffff) 4006 bne 1f 4007 4008 mov r0, r4 @ recover arg 4009 mov r1, r5 4010 mov r3, #0xc1000000 @ minint, as a double (high word) 4011 add r3, r3, #0x00e00000 @ 0xc1e00000 4012 mov r2, #0 @ minint, as a double (low word) 4013 bl __aeabi_dcmple @ is arg <= minint? 4014 cmp r0, #0 @ nonzero == yes 4015 movne r0, #0x80000000 @ return minint (80000000) 4016 bne 1f 4017 4018 mov r0, r4 @ recover arg 4019 mov r1, r5 4020 mov r2, r4 @ compare against self 4021 mov r3, r5 4022 bl __aeabi_dcmpeq @ is arg == self? 4023 cmp r0, #0 @ zero == no 4024 beq 1f @ return zero for NaN 4025 4026 mov r0, r4 @ recover arg 4027 mov r1, r5 4028 bl __aeabi_d2iz @ convert double to int 4029 40301: 4031 add sp, sp, #4 4032 ldmfd sp!, {r4, r5, pc} 4033#endif 4034 4035/* ------------------------------ */ 4036 .balign 64 4037.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 4038/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 4039@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 4040/* File: armv5te/unopWide.S */ 4041 /* 4042 * Generic 64-bit unary operation. Provide an "instr" line that 4043 * specifies an instruction that performs "result = op r0/r1". 4044 * This could be an ARM instruction or a function call. 4045 * 4046 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 4047 */ 4048 /* unop vA, vB */ 4049 mov r9, rINST, lsr #8 @ r9<- A+ 4050 mov r3, rINST, lsr #12 @ r3<- B 4051 and r9, r9, #15 4052 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4053 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 4054 ldmia r3, {r0-r1} @ r0/r1<- vAA 4055 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4056 @ optional op; may set condition codes 4057 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 4058 GET_INST_OPCODE(ip) @ extract opcode from rINST 4059 stmia r9, {r0-r1} @ vAA<- r0/r1 4060 GOTO_OPCODE(ip) @ jump to next instruction 4061 /* 12-13 instructions */ 4062 4063 4064 4065/* ------------------------------ */ 4066 .balign 64 4067.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 4068/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */ 4069/* File: armv5te/unopNarrower.S */ 4070 /* 4071 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 4072 * that specifies an instruction that performs "result = op r0/r1", where 4073 * "result" is a 32-bit quantity in r0. 4074 * 4075 * For: long-to-float, double-to-int, double-to-float 4076 * 4077 * (This would work for long-to-int, but that instruction is actually 4078 * an exact match for OP_MOVE.) 4079 */ 4080 /* unop vA, vB */ 4081 mov r3, rINST, lsr #12 @ r3<- B 4082 mov r9, rINST, lsr #8 @ r9<- A+ 4083 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4084 and r9, r9, #15 4085 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 4086 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4087 @ optional op; may set condition codes 4088 bl __aeabi_d2f @ r0<- op, r0-r3 changed 4089 GET_INST_OPCODE(ip) @ extract opcode from rINST 4090 SET_VREG(r0, r9) @ vA<- r0 4091 GOTO_OPCODE(ip) @ jump to next instruction 4092 /* 10-11 instructions */ 4093 4094 4095/* ------------------------------ */ 4096 .balign 64 4097.L_OP_INT_TO_BYTE: /* 0x8d */ 4098/* File: armv5te/OP_INT_TO_BYTE.S */ 4099/* File: armv5te/unop.S */ 4100 /* 4101 * Generic 32-bit unary operation. Provide an "instr" line that 4102 * specifies an instruction that performs "result = op r0". 4103 * This could be an ARM instruction or a function call. 4104 * 4105 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4106 * int-to-byte, int-to-char, int-to-short 4107 */ 4108 /* unop vA, vB */ 4109 mov r3, rINST, lsr #12 @ r3<- B 4110 mov r9, rINST, lsr #8 @ r9<- A+ 4111 GET_VREG(r0, r3) @ r0<- vB 4112 and r9, r9, #15 4113 mov r0, r0, asl #24 @ optional op; may set condition codes 4114 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4115 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4116 GET_INST_OPCODE(ip) @ extract opcode from rINST 4117 SET_VREG(r0, r9) @ vAA<- r0 4118 GOTO_OPCODE(ip) @ jump to next instruction 4119 /* 9-10 instructions */ 4120 4121 4122/* ------------------------------ */ 4123 .balign 64 4124.L_OP_INT_TO_CHAR: /* 0x8e */ 4125/* File: armv5te/OP_INT_TO_CHAR.S */ 4126/* File: armv5te/unop.S */ 4127 /* 4128 * Generic 32-bit unary operation. Provide an "instr" line that 4129 * specifies an instruction that performs "result = op r0". 4130 * This could be an ARM instruction or a function call. 4131 * 4132 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4133 * int-to-byte, int-to-char, int-to-short 4134 */ 4135 /* unop vA, vB */ 4136 mov r3, rINST, lsr #12 @ r3<- B 4137 mov r9, rINST, lsr #8 @ r9<- A+ 4138 GET_VREG(r0, r3) @ r0<- vB 4139 and r9, r9, #15 4140 mov r0, r0, asl #16 @ optional op; may set condition codes 4141 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4142 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4143 GET_INST_OPCODE(ip) @ extract opcode from rINST 4144 SET_VREG(r0, r9) @ vAA<- r0 4145 GOTO_OPCODE(ip) @ jump to next instruction 4146 /* 9-10 instructions */ 4147 4148 4149/* ------------------------------ */ 4150 .balign 64 4151.L_OP_INT_TO_SHORT: /* 0x8f */ 4152/* File: armv5te/OP_INT_TO_SHORT.S */ 4153/* File: armv5te/unop.S */ 4154 /* 4155 * Generic 32-bit unary operation. Provide an "instr" line that 4156 * specifies an instruction that performs "result = op r0". 4157 * This could be an ARM instruction or a function call. 4158 * 4159 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4160 * int-to-byte, int-to-char, int-to-short 4161 */ 4162 /* unop vA, vB */ 4163 mov r3, rINST, lsr #12 @ r3<- B 4164 mov r9, rINST, lsr #8 @ r9<- A+ 4165 GET_VREG(r0, r3) @ r0<- vB 4166 and r9, r9, #15 4167 mov r0, r0, asl #16 @ optional op; may set condition codes 4168 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4169 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4170 GET_INST_OPCODE(ip) @ extract opcode from rINST 4171 SET_VREG(r0, r9) @ vAA<- r0 4172 GOTO_OPCODE(ip) @ jump to next instruction 4173 /* 9-10 instructions */ 4174 4175 4176/* ------------------------------ */ 4177 .balign 64 4178.L_OP_ADD_INT: /* 0x90 */ 4179/* File: armv5te/OP_ADD_INT.S */ 4180/* File: armv5te/binop.S */ 4181 /* 4182 * Generic 32-bit binary operation. Provide an "instr" line that 4183 * specifies an instruction that performs "result = r0 op r1". 4184 * This could be an ARM instruction or a function call. (If the result 4185 * comes back in a register other than r0, you can override "result".) 4186 * 4187 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4188 * vCC (r1). Useful for integer division and modulus. Note that we 4189 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4190 * handles it correctly. 4191 * 4192 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4193 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4194 * mul-float, div-float, rem-float 4195 */ 4196 /* binop vAA, vBB, vCC */ 4197 FETCH(r0, 1) @ r0<- CCBB 4198 mov r9, rINST, lsr #8 @ r9<- AA 4199 mov r3, r0, lsr #8 @ r3<- CC 4200 and r2, r0, #255 @ r2<- BB 4201 GET_VREG(r1, r3) @ r1<- vCC 4202 GET_VREG(r0, r2) @ r0<- vBB 4203 .if 0 4204 cmp r1, #0 @ is second operand zero? 4205 beq common_errDivideByZero 4206 .endif 4207 4208 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4209 @ optional op; may set condition codes 4210 add r0, r0, r1 @ r0<- op, r0-r3 changed 4211 GET_INST_OPCODE(ip) @ extract opcode from rINST 4212 SET_VREG(r0, r9) @ vAA<- r0 4213 GOTO_OPCODE(ip) @ jump to next instruction 4214 /* 11-14 instructions */ 4215 4216 4217/* ------------------------------ */ 4218 .balign 64 4219.L_OP_SUB_INT: /* 0x91 */ 4220/* File: armv5te/OP_SUB_INT.S */ 4221/* File: armv5te/binop.S */ 4222 /* 4223 * Generic 32-bit binary operation. Provide an "instr" line that 4224 * specifies an instruction that performs "result = r0 op r1". 4225 * This could be an ARM instruction or a function call. (If the result 4226 * comes back in a register other than r0, you can override "result".) 4227 * 4228 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4229 * vCC (r1). Useful for integer division and modulus. Note that we 4230 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4231 * handles it correctly. 4232 * 4233 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4234 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4235 * mul-float, div-float, rem-float 4236 */ 4237 /* binop vAA, vBB, vCC */ 4238 FETCH(r0, 1) @ r0<- CCBB 4239 mov r9, rINST, lsr #8 @ r9<- AA 4240 mov r3, r0, lsr #8 @ r3<- CC 4241 and r2, r0, #255 @ r2<- BB 4242 GET_VREG(r1, r3) @ r1<- vCC 4243 GET_VREG(r0, r2) @ r0<- vBB 4244 .if 0 4245 cmp r1, #0 @ is second operand zero? 4246 beq common_errDivideByZero 4247 .endif 4248 4249 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4250 @ optional op; may set condition codes 4251 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4252 GET_INST_OPCODE(ip) @ extract opcode from rINST 4253 SET_VREG(r0, r9) @ vAA<- r0 4254 GOTO_OPCODE(ip) @ jump to next instruction 4255 /* 11-14 instructions */ 4256 4257 4258/* ------------------------------ */ 4259 .balign 64 4260.L_OP_MUL_INT: /* 0x92 */ 4261/* File: armv5te/OP_MUL_INT.S */ 4262/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4263/* File: armv5te/binop.S */ 4264 /* 4265 * Generic 32-bit binary operation. Provide an "instr" line that 4266 * specifies an instruction that performs "result = r0 op r1". 4267 * This could be an ARM instruction or a function call. (If the result 4268 * comes back in a register other than r0, you can override "result".) 4269 * 4270 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4271 * vCC (r1). Useful for integer division and modulus. Note that we 4272 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4273 * handles it correctly. 4274 * 4275 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4276 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4277 * mul-float, div-float, rem-float 4278 */ 4279 /* binop vAA, vBB, vCC */ 4280 FETCH(r0, 1) @ r0<- CCBB 4281 mov r9, rINST, lsr #8 @ r9<- AA 4282 mov r3, r0, lsr #8 @ r3<- CC 4283 and r2, r0, #255 @ r2<- BB 4284 GET_VREG(r1, r3) @ r1<- vCC 4285 GET_VREG(r0, r2) @ r0<- vBB 4286 .if 0 4287 cmp r1, #0 @ is second operand zero? 4288 beq common_errDivideByZero 4289 .endif 4290 4291 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4292 @ optional op; may set condition codes 4293 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4294 GET_INST_OPCODE(ip) @ extract opcode from rINST 4295 SET_VREG(r0, r9) @ vAA<- r0 4296 GOTO_OPCODE(ip) @ jump to next instruction 4297 /* 11-14 instructions */ 4298 4299 4300/* ------------------------------ */ 4301 .balign 64 4302.L_OP_DIV_INT: /* 0x93 */ 4303/* File: armv5te/OP_DIV_INT.S */ 4304/* File: armv5te/binop.S */ 4305 /* 4306 * Generic 32-bit binary operation. Provide an "instr" line that 4307 * specifies an instruction that performs "result = r0 op r1". 4308 * This could be an ARM instruction or a function call. (If the result 4309 * comes back in a register other than r0, you can override "result".) 4310 * 4311 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4312 * vCC (r1). Useful for integer division and modulus. Note that we 4313 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4314 * handles it correctly. 4315 * 4316 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4317 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4318 * mul-float, div-float, rem-float 4319 */ 4320 /* binop vAA, vBB, vCC */ 4321 FETCH(r0, 1) @ r0<- CCBB 4322 mov r9, rINST, lsr #8 @ r9<- AA 4323 mov r3, r0, lsr #8 @ r3<- CC 4324 and r2, r0, #255 @ r2<- BB 4325 GET_VREG(r1, r3) @ r1<- vCC 4326 GET_VREG(r0, r2) @ r0<- vBB 4327 .if 1 4328 cmp r1, #0 @ is second operand zero? 4329 beq common_errDivideByZero 4330 .endif 4331 4332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4333 @ optional op; may set condition codes 4334 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4335 GET_INST_OPCODE(ip) @ extract opcode from rINST 4336 SET_VREG(r0, r9) @ vAA<- r0 4337 GOTO_OPCODE(ip) @ jump to next instruction 4338 /* 11-14 instructions */ 4339 4340 4341/* ------------------------------ */ 4342 .balign 64 4343.L_OP_REM_INT: /* 0x94 */ 4344/* File: armv5te/OP_REM_INT.S */ 4345/* idivmod returns quotient in r0 and remainder in r1 */ 4346/* File: armv5te/binop.S */ 4347 /* 4348 * Generic 32-bit binary operation. Provide an "instr" line that 4349 * specifies an instruction that performs "result = r0 op r1". 4350 * This could be an ARM instruction or a function call. (If the result 4351 * comes back in a register other than r0, you can override "result".) 4352 * 4353 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4354 * vCC (r1). Useful for integer division and modulus. Note that we 4355 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4356 * handles it correctly. 4357 * 4358 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4359 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4360 * mul-float, div-float, rem-float 4361 */ 4362 /* binop vAA, vBB, vCC */ 4363 FETCH(r0, 1) @ r0<- CCBB 4364 mov r9, rINST, lsr #8 @ r9<- AA 4365 mov r3, r0, lsr #8 @ r3<- CC 4366 and r2, r0, #255 @ r2<- BB 4367 GET_VREG(r1, r3) @ r1<- vCC 4368 GET_VREG(r0, r2) @ r0<- vBB 4369 .if 1 4370 cmp r1, #0 @ is second operand zero? 4371 beq common_errDivideByZero 4372 .endif 4373 4374 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4375 @ optional op; may set condition codes 4376 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4377 GET_INST_OPCODE(ip) @ extract opcode from rINST 4378 SET_VREG(r1, r9) @ vAA<- r1 4379 GOTO_OPCODE(ip) @ jump to next instruction 4380 /* 11-14 instructions */ 4381 4382 4383/* ------------------------------ */ 4384 .balign 64 4385.L_OP_AND_INT: /* 0x95 */ 4386/* File: armv5te/OP_AND_INT.S */ 4387/* File: armv5te/binop.S */ 4388 /* 4389 * Generic 32-bit binary operation. Provide an "instr" line that 4390 * specifies an instruction that performs "result = r0 op r1". 4391 * This could be an ARM instruction or a function call. (If the result 4392 * comes back in a register other than r0, you can override "result".) 4393 * 4394 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4395 * vCC (r1). Useful for integer division and modulus. Note that we 4396 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4397 * handles it correctly. 4398 * 4399 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4400 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4401 * mul-float, div-float, rem-float 4402 */ 4403 /* binop vAA, vBB, vCC */ 4404 FETCH(r0, 1) @ r0<- CCBB 4405 mov r9, rINST, lsr #8 @ r9<- AA 4406 mov r3, r0, lsr #8 @ r3<- CC 4407 and r2, r0, #255 @ r2<- BB 4408 GET_VREG(r1, r3) @ r1<- vCC 4409 GET_VREG(r0, r2) @ r0<- vBB 4410 .if 0 4411 cmp r1, #0 @ is second operand zero? 4412 beq common_errDivideByZero 4413 .endif 4414 4415 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4416 @ optional op; may set condition codes 4417 and r0, r0, r1 @ r0<- op, r0-r3 changed 4418 GET_INST_OPCODE(ip) @ extract opcode from rINST 4419 SET_VREG(r0, r9) @ vAA<- r0 4420 GOTO_OPCODE(ip) @ jump to next instruction 4421 /* 11-14 instructions */ 4422 4423 4424/* ------------------------------ */ 4425 .balign 64 4426.L_OP_OR_INT: /* 0x96 */ 4427/* File: armv5te/OP_OR_INT.S */ 4428/* File: armv5te/binop.S */ 4429 /* 4430 * Generic 32-bit binary operation. Provide an "instr" line that 4431 * specifies an instruction that performs "result = r0 op r1". 4432 * This could be an ARM instruction or a function call. (If the result 4433 * comes back in a register other than r0, you can override "result".) 4434 * 4435 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4436 * vCC (r1). Useful for integer division and modulus. Note that we 4437 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4438 * handles it correctly. 4439 * 4440 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4441 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4442 * mul-float, div-float, rem-float 4443 */ 4444 /* binop vAA, vBB, vCC */ 4445 FETCH(r0, 1) @ r0<- CCBB 4446 mov r9, rINST, lsr #8 @ r9<- AA 4447 mov r3, r0, lsr #8 @ r3<- CC 4448 and r2, r0, #255 @ r2<- BB 4449 GET_VREG(r1, r3) @ r1<- vCC 4450 GET_VREG(r0, r2) @ r0<- vBB 4451 .if 0 4452 cmp r1, #0 @ is second operand zero? 4453 beq common_errDivideByZero 4454 .endif 4455 4456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4457 @ optional op; may set condition codes 4458 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4459 GET_INST_OPCODE(ip) @ extract opcode from rINST 4460 SET_VREG(r0, r9) @ vAA<- r0 4461 GOTO_OPCODE(ip) @ jump to next instruction 4462 /* 11-14 instructions */ 4463 4464 4465/* ------------------------------ */ 4466 .balign 64 4467.L_OP_XOR_INT: /* 0x97 */ 4468/* File: armv5te/OP_XOR_INT.S */ 4469/* File: armv5te/binop.S */ 4470 /* 4471 * Generic 32-bit binary operation. Provide an "instr" line that 4472 * specifies an instruction that performs "result = r0 op r1". 4473 * This could be an ARM instruction or a function call. (If the result 4474 * comes back in a register other than r0, you can override "result".) 4475 * 4476 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4477 * vCC (r1). Useful for integer division and modulus. Note that we 4478 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4479 * handles it correctly. 4480 * 4481 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4482 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4483 * mul-float, div-float, rem-float 4484 */ 4485 /* binop vAA, vBB, vCC */ 4486 FETCH(r0, 1) @ r0<- CCBB 4487 mov r9, rINST, lsr #8 @ r9<- AA 4488 mov r3, r0, lsr #8 @ r3<- CC 4489 and r2, r0, #255 @ r2<- BB 4490 GET_VREG(r1, r3) @ r1<- vCC 4491 GET_VREG(r0, r2) @ r0<- vBB 4492 .if 0 4493 cmp r1, #0 @ is second operand zero? 4494 beq common_errDivideByZero 4495 .endif 4496 4497 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4498 @ optional op; may set condition codes 4499 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4500 GET_INST_OPCODE(ip) @ extract opcode from rINST 4501 SET_VREG(r0, r9) @ vAA<- r0 4502 GOTO_OPCODE(ip) @ jump to next instruction 4503 /* 11-14 instructions */ 4504 4505 4506/* ------------------------------ */ 4507 .balign 64 4508.L_OP_SHL_INT: /* 0x98 */ 4509/* File: armv5te/OP_SHL_INT.S */ 4510/* File: armv5te/binop.S */ 4511 /* 4512 * Generic 32-bit binary operation. Provide an "instr" line that 4513 * specifies an instruction that performs "result = r0 op r1". 4514 * This could be an ARM instruction or a function call. (If the result 4515 * comes back in a register other than r0, you can override "result".) 4516 * 4517 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4518 * vCC (r1). Useful for integer division and modulus. Note that we 4519 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4520 * handles it correctly. 4521 * 4522 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4523 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4524 * mul-float, div-float, rem-float 4525 */ 4526 /* binop vAA, vBB, vCC */ 4527 FETCH(r0, 1) @ r0<- CCBB 4528 mov r9, rINST, lsr #8 @ r9<- AA 4529 mov r3, r0, lsr #8 @ r3<- CC 4530 and r2, r0, #255 @ r2<- BB 4531 GET_VREG(r1, r3) @ r1<- vCC 4532 GET_VREG(r0, r2) @ r0<- vBB 4533 .if 0 4534 cmp r1, #0 @ is second operand zero? 4535 beq common_errDivideByZero 4536 .endif 4537 4538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4539 and r1, r1, #31 @ optional op; may set condition codes 4540 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4541 GET_INST_OPCODE(ip) @ extract opcode from rINST 4542 SET_VREG(r0, r9) @ vAA<- r0 4543 GOTO_OPCODE(ip) @ jump to next instruction 4544 /* 11-14 instructions */ 4545 4546 4547/* ------------------------------ */ 4548 .balign 64 4549.L_OP_SHR_INT: /* 0x99 */ 4550/* File: armv5te/OP_SHR_INT.S */ 4551/* File: armv5te/binop.S */ 4552 /* 4553 * Generic 32-bit binary operation. Provide an "instr" line that 4554 * specifies an instruction that performs "result = r0 op r1". 4555 * This could be an ARM instruction or a function call. (If the result 4556 * comes back in a register other than r0, you can override "result".) 4557 * 4558 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4559 * vCC (r1). Useful for integer division and modulus. Note that we 4560 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4561 * handles it correctly. 4562 * 4563 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4564 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4565 * mul-float, div-float, rem-float 4566 */ 4567 /* binop vAA, vBB, vCC */ 4568 FETCH(r0, 1) @ r0<- CCBB 4569 mov r9, rINST, lsr #8 @ r9<- AA 4570 mov r3, r0, lsr #8 @ r3<- CC 4571 and r2, r0, #255 @ r2<- BB 4572 GET_VREG(r1, r3) @ r1<- vCC 4573 GET_VREG(r0, r2) @ r0<- vBB 4574 .if 0 4575 cmp r1, #0 @ is second operand zero? 4576 beq common_errDivideByZero 4577 .endif 4578 4579 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4580 and r1, r1, #31 @ optional op; may set condition codes 4581 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4582 GET_INST_OPCODE(ip) @ extract opcode from rINST 4583 SET_VREG(r0, r9) @ vAA<- r0 4584 GOTO_OPCODE(ip) @ jump to next instruction 4585 /* 11-14 instructions */ 4586 4587 4588/* ------------------------------ */ 4589 .balign 64 4590.L_OP_USHR_INT: /* 0x9a */ 4591/* File: armv5te/OP_USHR_INT.S */ 4592/* File: armv5te/binop.S */ 4593 /* 4594 * Generic 32-bit binary operation. Provide an "instr" line that 4595 * specifies an instruction that performs "result = r0 op r1". 4596 * This could be an ARM instruction or a function call. (If the result 4597 * comes back in a register other than r0, you can override "result".) 4598 * 4599 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4600 * vCC (r1). Useful for integer division and modulus. Note that we 4601 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4602 * handles it correctly. 4603 * 4604 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4605 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4606 * mul-float, div-float, rem-float 4607 */ 4608 /* binop vAA, vBB, vCC */ 4609 FETCH(r0, 1) @ r0<- CCBB 4610 mov r9, rINST, lsr #8 @ r9<- AA 4611 mov r3, r0, lsr #8 @ r3<- CC 4612 and r2, r0, #255 @ r2<- BB 4613 GET_VREG(r1, r3) @ r1<- vCC 4614 GET_VREG(r0, r2) @ r0<- vBB 4615 .if 0 4616 cmp r1, #0 @ is second operand zero? 4617 beq common_errDivideByZero 4618 .endif 4619 4620 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4621 and r1, r1, #31 @ optional op; may set condition codes 4622 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4623 GET_INST_OPCODE(ip) @ extract opcode from rINST 4624 SET_VREG(r0, r9) @ vAA<- r0 4625 GOTO_OPCODE(ip) @ jump to next instruction 4626 /* 11-14 instructions */ 4627 4628 4629/* ------------------------------ */ 4630 .balign 64 4631.L_OP_ADD_LONG: /* 0x9b */ 4632/* File: armv5te/OP_ADD_LONG.S */ 4633/* File: armv5te/binopWide.S */ 4634 /* 4635 * Generic 64-bit binary operation. Provide an "instr" line that 4636 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4637 * This could be an ARM instruction or a function call. (If the result 4638 * comes back in a register other than r0, you can override "result".) 4639 * 4640 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4641 * vCC (r1). Useful for integer division and modulus. 4642 * 4643 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4644 * xor-long, add-double, sub-double, mul-double, div-double, 4645 * rem-double 4646 * 4647 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4648 */ 4649 /* binop vAA, vBB, vCC */ 4650 FETCH(r0, 1) @ r0<- CCBB 4651 mov r9, rINST, lsr #8 @ r9<- AA 4652 and r2, r0, #255 @ r2<- BB 4653 mov r3, r0, lsr #8 @ r3<- CC 4654 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4655 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4656 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4657 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4658 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4659 .if 0 4660 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4661 beq common_errDivideByZero 4662 .endif 4663 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4664 4665 adds r0, r0, r2 @ optional op; may set condition codes 4666 adc r1, r1, r3 @ result<- op, r0-r3 changed 4667 GET_INST_OPCODE(ip) @ extract opcode from rINST 4668 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4669 GOTO_OPCODE(ip) @ jump to next instruction 4670 /* 14-17 instructions */ 4671 4672 4673/* ------------------------------ */ 4674 .balign 64 4675.L_OP_SUB_LONG: /* 0x9c */ 4676/* File: armv5te/OP_SUB_LONG.S */ 4677/* File: armv5te/binopWide.S */ 4678 /* 4679 * Generic 64-bit binary operation. Provide an "instr" line that 4680 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4681 * This could be an ARM instruction or a function call. (If the result 4682 * comes back in a register other than r0, you can override "result".) 4683 * 4684 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4685 * vCC (r1). Useful for integer division and modulus. 4686 * 4687 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4688 * xor-long, add-double, sub-double, mul-double, div-double, 4689 * rem-double 4690 * 4691 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4692 */ 4693 /* binop vAA, vBB, vCC */ 4694 FETCH(r0, 1) @ r0<- CCBB 4695 mov r9, rINST, lsr #8 @ r9<- AA 4696 and r2, r0, #255 @ r2<- BB 4697 mov r3, r0, lsr #8 @ r3<- CC 4698 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4699 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4700 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4701 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4702 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4703 .if 0 4704 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4705 beq common_errDivideByZero 4706 .endif 4707 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4708 4709 subs r0, r0, r2 @ optional op; may set condition codes 4710 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4711 GET_INST_OPCODE(ip) @ extract opcode from rINST 4712 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4713 GOTO_OPCODE(ip) @ jump to next instruction 4714 /* 14-17 instructions */ 4715 4716 4717/* ------------------------------ */ 4718 .balign 64 4719.L_OP_MUL_LONG: /* 0x9d */ 4720/* File: armv5te/OP_MUL_LONG.S */ 4721 /* 4722 * Signed 64-bit integer multiply. 4723 * 4724 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4725 * WX 4726 * x YZ 4727 * -------- 4728 * ZW ZX 4729 * YW YX 4730 * 4731 * The low word of the result holds ZX, the high word holds 4732 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4733 * it doesn't fit in the low 64 bits. 4734 * 4735 * Unlike most ARM math operations, multiply instructions have 4736 * restrictions on using the same register more than once (Rd and Rm 4737 * cannot be the same). 4738 */ 4739 /* mul-long vAA, vBB, vCC */ 4740 FETCH(r0, 1) @ r0<- CCBB 4741 and r2, r0, #255 @ r2<- BB 4742 mov r3, r0, lsr #8 @ r3<- CC 4743 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4744 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4745 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4746 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4747 mul ip, r2, r1 @ ip<- ZxW 4748 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4749 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4750 mov r0, rINST, lsr #8 @ r0<- AA 4751 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4752 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4753 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4754 b .LOP_MUL_LONG_finish 4755 4756/* ------------------------------ */ 4757 .balign 64 4758.L_OP_DIV_LONG: /* 0x9e */ 4759/* File: armv5te/OP_DIV_LONG.S */ 4760/* File: armv5te/binopWide.S */ 4761 /* 4762 * Generic 64-bit binary operation. Provide an "instr" line that 4763 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4764 * This could be an ARM instruction or a function call. (If the result 4765 * comes back in a register other than r0, you can override "result".) 4766 * 4767 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4768 * vCC (r1). Useful for integer division and modulus. 4769 * 4770 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4771 * xor-long, add-double, sub-double, mul-double, div-double, 4772 * rem-double 4773 * 4774 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4775 */ 4776 /* binop vAA, vBB, vCC */ 4777 FETCH(r0, 1) @ r0<- CCBB 4778 mov r9, rINST, lsr #8 @ r9<- AA 4779 and r2, r0, #255 @ r2<- BB 4780 mov r3, r0, lsr #8 @ r3<- CC 4781 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4782 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4783 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4784 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4785 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4786 .if 1 4787 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4788 beq common_errDivideByZero 4789 .endif 4790 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4791 4792 @ optional op; may set condition codes 4793 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4794 GET_INST_OPCODE(ip) @ extract opcode from rINST 4795 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4796 GOTO_OPCODE(ip) @ jump to next instruction 4797 /* 14-17 instructions */ 4798 4799 4800/* ------------------------------ */ 4801 .balign 64 4802.L_OP_REM_LONG: /* 0x9f */ 4803/* File: armv5te/OP_REM_LONG.S */ 4804/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4805/* File: armv5te/binopWide.S */ 4806 /* 4807 * Generic 64-bit binary operation. Provide an "instr" line that 4808 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4809 * This could be an ARM instruction or a function call. (If the result 4810 * comes back in a register other than r0, you can override "result".) 4811 * 4812 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4813 * vCC (r1). Useful for integer division and modulus. 4814 * 4815 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4816 * xor-long, add-double, sub-double, mul-double, div-double, 4817 * rem-double 4818 * 4819 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4820 */ 4821 /* binop vAA, vBB, vCC */ 4822 FETCH(r0, 1) @ r0<- CCBB 4823 mov r9, rINST, lsr #8 @ r9<- AA 4824 and r2, r0, #255 @ r2<- BB 4825 mov r3, r0, lsr #8 @ r3<- CC 4826 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4827 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4828 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4829 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4830 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4831 .if 1 4832 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4833 beq common_errDivideByZero 4834 .endif 4835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4836 4837 @ optional op; may set condition codes 4838 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4839 GET_INST_OPCODE(ip) @ extract opcode from rINST 4840 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4841 GOTO_OPCODE(ip) @ jump to next instruction 4842 /* 14-17 instructions */ 4843 4844 4845/* ------------------------------ */ 4846 .balign 64 4847.L_OP_AND_LONG: /* 0xa0 */ 4848/* File: armv5te/OP_AND_LONG.S */ 4849/* File: armv5te/binopWide.S */ 4850 /* 4851 * Generic 64-bit binary operation. Provide an "instr" line that 4852 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4853 * This could be an ARM instruction or a function call. (If the result 4854 * comes back in a register other than r0, you can override "result".) 4855 * 4856 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4857 * vCC (r1). Useful for integer division and modulus. 4858 * 4859 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4860 * xor-long, add-double, sub-double, mul-double, div-double, 4861 * rem-double 4862 * 4863 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4864 */ 4865 /* binop vAA, vBB, vCC */ 4866 FETCH(r0, 1) @ r0<- CCBB 4867 mov r9, rINST, lsr #8 @ r9<- AA 4868 and r2, r0, #255 @ r2<- BB 4869 mov r3, r0, lsr #8 @ r3<- CC 4870 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4871 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4872 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4873 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4874 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4875 .if 0 4876 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4877 beq common_errDivideByZero 4878 .endif 4879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4880 4881 and r0, r0, r2 @ optional op; may set condition codes 4882 and r1, r1, r3 @ result<- op, r0-r3 changed 4883 GET_INST_OPCODE(ip) @ extract opcode from rINST 4884 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4885 GOTO_OPCODE(ip) @ jump to next instruction 4886 /* 14-17 instructions */ 4887 4888 4889/* ------------------------------ */ 4890 .balign 64 4891.L_OP_OR_LONG: /* 0xa1 */ 4892/* File: armv5te/OP_OR_LONG.S */ 4893/* File: armv5te/binopWide.S */ 4894 /* 4895 * Generic 64-bit binary operation. Provide an "instr" line that 4896 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4897 * This could be an ARM instruction or a function call. (If the result 4898 * comes back in a register other than r0, you can override "result".) 4899 * 4900 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4901 * vCC (r1). Useful for integer division and modulus. 4902 * 4903 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4904 * xor-long, add-double, sub-double, mul-double, div-double, 4905 * rem-double 4906 * 4907 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4908 */ 4909 /* binop vAA, vBB, vCC */ 4910 FETCH(r0, 1) @ r0<- CCBB 4911 mov r9, rINST, lsr #8 @ r9<- AA 4912 and r2, r0, #255 @ r2<- BB 4913 mov r3, r0, lsr #8 @ r3<- CC 4914 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4915 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4916 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4917 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4918 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4919 .if 0 4920 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4921 beq common_errDivideByZero 4922 .endif 4923 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4924 4925 orr r0, r0, r2 @ optional op; may set condition codes 4926 orr r1, r1, r3 @ result<- op, r0-r3 changed 4927 GET_INST_OPCODE(ip) @ extract opcode from rINST 4928 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4929 GOTO_OPCODE(ip) @ jump to next instruction 4930 /* 14-17 instructions */ 4931 4932 4933/* ------------------------------ */ 4934 .balign 64 4935.L_OP_XOR_LONG: /* 0xa2 */ 4936/* File: armv5te/OP_XOR_LONG.S */ 4937/* File: armv5te/binopWide.S */ 4938 /* 4939 * Generic 64-bit binary operation. Provide an "instr" line that 4940 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4941 * This could be an ARM instruction or a function call. (If the result 4942 * comes back in a register other than r0, you can override "result".) 4943 * 4944 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4945 * vCC (r1). Useful for integer division and modulus. 4946 * 4947 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4948 * xor-long, add-double, sub-double, mul-double, div-double, 4949 * rem-double 4950 * 4951 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4952 */ 4953 /* binop vAA, vBB, vCC */ 4954 FETCH(r0, 1) @ r0<- CCBB 4955 mov r9, rINST, lsr #8 @ r9<- AA 4956 and r2, r0, #255 @ r2<- BB 4957 mov r3, r0, lsr #8 @ r3<- CC 4958 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4959 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4960 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4961 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4962 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4963 .if 0 4964 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4965 beq common_errDivideByZero 4966 .endif 4967 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4968 4969 eor r0, r0, r2 @ optional op; may set condition codes 4970 eor r1, r1, r3 @ result<- op, r0-r3 changed 4971 GET_INST_OPCODE(ip) @ extract opcode from rINST 4972 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4973 GOTO_OPCODE(ip) @ jump to next instruction 4974 /* 14-17 instructions */ 4975 4976 4977/* ------------------------------ */ 4978 .balign 64 4979.L_OP_SHL_LONG: /* 0xa3 */ 4980/* File: armv5te/OP_SHL_LONG.S */ 4981 /* 4982 * Long integer shift. This is different from the generic 32/64-bit 4983 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4984 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4985 * 6 bits of the shift distance. 4986 */ 4987 /* shl-long vAA, vBB, vCC */ 4988 FETCH(r0, 1) @ r0<- CCBB 4989 mov r9, rINST, lsr #8 @ r9<- AA 4990 and r3, r0, #255 @ r3<- BB 4991 mov r0, r0, lsr #8 @ r0<- CC 4992 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4993 GET_VREG(r2, r0) @ r2<- vCC 4994 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4995 and r2, r2, #63 @ r2<- r2 & 0x3f 4996 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4997 4998 mov r1, r1, asl r2 @ r1<- r1 << r2 4999 rsb r3, r2, #32 @ r3<- 32 - r2 5000 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5001 subs ip, r2, #32 @ ip<- r2 - 32 5002 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5004 b .LOP_SHL_LONG_finish 5005 5006/* ------------------------------ */ 5007 .balign 64 5008.L_OP_SHR_LONG: /* 0xa4 */ 5009/* File: armv5te/OP_SHR_LONG.S */ 5010 /* 5011 * Long integer shift. This is different from the generic 32/64-bit 5012 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5013 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5014 * 6 bits of the shift distance. 5015 */ 5016 /* shr-long vAA, vBB, vCC */ 5017 FETCH(r0, 1) @ r0<- CCBB 5018 mov r9, rINST, lsr #8 @ r9<- AA 5019 and r3, r0, #255 @ r3<- BB 5020 mov r0, r0, lsr #8 @ r0<- CC 5021 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5022 GET_VREG(r2, r0) @ r2<- vCC 5023 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5024 and r2, r2, #63 @ r0<- r0 & 0x3f 5025 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5026 5027 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5028 rsb r3, r2, #32 @ r3<- 32 - r2 5029 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5030 subs ip, r2, #32 @ ip<- r2 - 32 5031 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 5032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5033 b .LOP_SHR_LONG_finish 5034 5035/* ------------------------------ */ 5036 .balign 64 5037.L_OP_USHR_LONG: /* 0xa5 */ 5038/* File: armv5te/OP_USHR_LONG.S */ 5039 /* 5040 * Long integer shift. This is different from the generic 32/64-bit 5041 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5042 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5043 * 6 bits of the shift distance. 5044 */ 5045 /* ushr-long vAA, vBB, vCC */ 5046 FETCH(r0, 1) @ r0<- CCBB 5047 mov r9, rINST, lsr #8 @ r9<- AA 5048 and r3, r0, #255 @ r3<- BB 5049 mov r0, r0, lsr #8 @ r0<- CC 5050 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5051 GET_VREG(r2, r0) @ r2<- vCC 5052 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5053 and r2, r2, #63 @ r0<- r0 & 0x3f 5054 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5055 5056 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5057 rsb r3, r2, #32 @ r3<- 32 - r2 5058 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5059 subs ip, r2, #32 @ ip<- r2 - 32 5060 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 5061 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5062 b .LOP_USHR_LONG_finish 5063 5064/* ------------------------------ */ 5065 .balign 64 5066.L_OP_ADD_FLOAT: /* 0xa6 */ 5067/* File: armv5te/OP_ADD_FLOAT.S */ 5068/* File: armv5te/binop.S */ 5069 /* 5070 * Generic 32-bit binary operation. Provide an "instr" line that 5071 * specifies an instruction that performs "result = r0 op r1". 5072 * This could be an ARM instruction or a function call. (If the result 5073 * comes back in a register other than r0, you can override "result".) 5074 * 5075 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5076 * vCC (r1). Useful for integer division and modulus. Note that we 5077 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5078 * handles it correctly. 5079 * 5080 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5081 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5082 * mul-float, div-float, rem-float 5083 */ 5084 /* binop vAA, vBB, vCC */ 5085 FETCH(r0, 1) @ r0<- CCBB 5086 mov r9, rINST, lsr #8 @ r9<- AA 5087 mov r3, r0, lsr #8 @ r3<- CC 5088 and r2, r0, #255 @ r2<- BB 5089 GET_VREG(r1, r3) @ r1<- vCC 5090 GET_VREG(r0, r2) @ r0<- vBB 5091 .if 0 5092 cmp r1, #0 @ is second operand zero? 5093 beq common_errDivideByZero 5094 .endif 5095 5096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5097 @ optional op; may set condition codes 5098 bl __aeabi_fadd @ r0<- op, r0-r3 changed 5099 GET_INST_OPCODE(ip) @ extract opcode from rINST 5100 SET_VREG(r0, r9) @ vAA<- r0 5101 GOTO_OPCODE(ip) @ jump to next instruction 5102 /* 11-14 instructions */ 5103 5104 5105/* ------------------------------ */ 5106 .balign 64 5107.L_OP_SUB_FLOAT: /* 0xa7 */ 5108/* File: armv5te/OP_SUB_FLOAT.S */ 5109/* File: armv5te/binop.S */ 5110 /* 5111 * Generic 32-bit binary operation. Provide an "instr" line that 5112 * specifies an instruction that performs "result = r0 op r1". 5113 * This could be an ARM instruction or a function call. (If the result 5114 * comes back in a register other than r0, you can override "result".) 5115 * 5116 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5117 * vCC (r1). Useful for integer division and modulus. Note that we 5118 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5119 * handles it correctly. 5120 * 5121 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5122 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5123 * mul-float, div-float, rem-float 5124 */ 5125 /* binop vAA, vBB, vCC */ 5126 FETCH(r0, 1) @ r0<- CCBB 5127 mov r9, rINST, lsr #8 @ r9<- AA 5128 mov r3, r0, lsr #8 @ r3<- CC 5129 and r2, r0, #255 @ r2<- BB 5130 GET_VREG(r1, r3) @ r1<- vCC 5131 GET_VREG(r0, r2) @ r0<- vBB 5132 .if 0 5133 cmp r1, #0 @ is second operand zero? 5134 beq common_errDivideByZero 5135 .endif 5136 5137 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5138 @ optional op; may set condition codes 5139 bl __aeabi_fsub @ r0<- op, r0-r3 changed 5140 GET_INST_OPCODE(ip) @ extract opcode from rINST 5141 SET_VREG(r0, r9) @ vAA<- r0 5142 GOTO_OPCODE(ip) @ jump to next instruction 5143 /* 11-14 instructions */ 5144 5145 5146/* ------------------------------ */ 5147 .balign 64 5148.L_OP_MUL_FLOAT: /* 0xa8 */ 5149/* File: armv5te/OP_MUL_FLOAT.S */ 5150/* File: armv5te/binop.S */ 5151 /* 5152 * Generic 32-bit binary operation. Provide an "instr" line that 5153 * specifies an instruction that performs "result = r0 op r1". 5154 * This could be an ARM instruction or a function call. (If the result 5155 * comes back in a register other than r0, you can override "result".) 5156 * 5157 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5158 * vCC (r1). Useful for integer division and modulus. Note that we 5159 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5160 * handles it correctly. 5161 * 5162 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5163 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5164 * mul-float, div-float, rem-float 5165 */ 5166 /* binop vAA, vBB, vCC */ 5167 FETCH(r0, 1) @ r0<- CCBB 5168 mov r9, rINST, lsr #8 @ r9<- AA 5169 mov r3, r0, lsr #8 @ r3<- CC 5170 and r2, r0, #255 @ r2<- BB 5171 GET_VREG(r1, r3) @ r1<- vCC 5172 GET_VREG(r0, r2) @ r0<- vBB 5173 .if 0 5174 cmp r1, #0 @ is second operand zero? 5175 beq common_errDivideByZero 5176 .endif 5177 5178 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5179 @ optional op; may set condition codes 5180 bl __aeabi_fmul @ r0<- op, r0-r3 changed 5181 GET_INST_OPCODE(ip) @ extract opcode from rINST 5182 SET_VREG(r0, r9) @ vAA<- r0 5183 GOTO_OPCODE(ip) @ jump to next instruction 5184 /* 11-14 instructions */ 5185 5186 5187/* ------------------------------ */ 5188 .balign 64 5189.L_OP_DIV_FLOAT: /* 0xa9 */ 5190/* File: armv5te/OP_DIV_FLOAT.S */ 5191/* File: armv5te/binop.S */ 5192 /* 5193 * Generic 32-bit binary operation. Provide an "instr" line that 5194 * specifies an instruction that performs "result = r0 op r1". 5195 * This could be an ARM instruction or a function call. (If the result 5196 * comes back in a register other than r0, you can override "result".) 5197 * 5198 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5199 * vCC (r1). Useful for integer division and modulus. Note that we 5200 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5201 * handles it correctly. 5202 * 5203 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5204 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5205 * mul-float, div-float, rem-float 5206 */ 5207 /* binop vAA, vBB, vCC */ 5208 FETCH(r0, 1) @ r0<- CCBB 5209 mov r9, rINST, lsr #8 @ r9<- AA 5210 mov r3, r0, lsr #8 @ r3<- CC 5211 and r2, r0, #255 @ r2<- BB 5212 GET_VREG(r1, r3) @ r1<- vCC 5213 GET_VREG(r0, r2) @ r0<- vBB 5214 .if 0 5215 cmp r1, #0 @ is second operand zero? 5216 beq common_errDivideByZero 5217 .endif 5218 5219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5220 @ optional op; may set condition codes 5221 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 5222 GET_INST_OPCODE(ip) @ extract opcode from rINST 5223 SET_VREG(r0, r9) @ vAA<- r0 5224 GOTO_OPCODE(ip) @ jump to next instruction 5225 /* 11-14 instructions */ 5226 5227 5228/* ------------------------------ */ 5229 .balign 64 5230.L_OP_REM_FLOAT: /* 0xaa */ 5231/* File: armv5te/OP_REM_FLOAT.S */ 5232/* EABI doesn't define a float remainder function, but libm does */ 5233/* File: armv5te/binop.S */ 5234 /* 5235 * Generic 32-bit binary operation. Provide an "instr" line that 5236 * specifies an instruction that performs "result = r0 op r1". 5237 * This could be an ARM instruction or a function call. (If the result 5238 * comes back in a register other than r0, you can override "result".) 5239 * 5240 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5241 * vCC (r1). Useful for integer division and modulus. Note that we 5242 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5243 * handles it correctly. 5244 * 5245 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5246 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5247 * mul-float, div-float, rem-float 5248 */ 5249 /* binop vAA, vBB, vCC */ 5250 FETCH(r0, 1) @ r0<- CCBB 5251 mov r9, rINST, lsr #8 @ r9<- AA 5252 mov r3, r0, lsr #8 @ r3<- CC 5253 and r2, r0, #255 @ r2<- BB 5254 GET_VREG(r1, r3) @ r1<- vCC 5255 GET_VREG(r0, r2) @ r0<- vBB 5256 .if 0 5257 cmp r1, #0 @ is second operand zero? 5258 beq common_errDivideByZero 5259 .endif 5260 5261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5262 @ optional op; may set condition codes 5263 bl fmodf @ r0<- op, r0-r3 changed 5264 GET_INST_OPCODE(ip) @ extract opcode from rINST 5265 SET_VREG(r0, r9) @ vAA<- r0 5266 GOTO_OPCODE(ip) @ jump to next instruction 5267 /* 11-14 instructions */ 5268 5269 5270/* ------------------------------ */ 5271 .balign 64 5272.L_OP_ADD_DOUBLE: /* 0xab */ 5273/* File: armv5te/OP_ADD_DOUBLE.S */ 5274/* File: armv5te/binopWide.S */ 5275 /* 5276 * Generic 64-bit binary operation. Provide an "instr" line that 5277 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5278 * This could be an ARM instruction or a function call. (If the result 5279 * comes back in a register other than r0, you can override "result".) 5280 * 5281 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5282 * vCC (r1). Useful for integer division and modulus. 5283 * 5284 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5285 * xor-long, add-double, sub-double, mul-double, div-double, 5286 * rem-double 5287 * 5288 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5289 */ 5290 /* binop vAA, vBB, vCC */ 5291 FETCH(r0, 1) @ r0<- CCBB 5292 mov r9, rINST, lsr #8 @ r9<- AA 5293 and r2, r0, #255 @ r2<- BB 5294 mov r3, r0, lsr #8 @ r3<- CC 5295 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5296 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5297 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5298 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5299 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5300 .if 0 5301 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5302 beq common_errDivideByZero 5303 .endif 5304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5305 5306 @ optional op; may set condition codes 5307 bl __aeabi_dadd @ result<- op, r0-r3 changed 5308 GET_INST_OPCODE(ip) @ extract opcode from rINST 5309 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5310 GOTO_OPCODE(ip) @ jump to next instruction 5311 /* 14-17 instructions */ 5312 5313 5314/* ------------------------------ */ 5315 .balign 64 5316.L_OP_SUB_DOUBLE: /* 0xac */ 5317/* File: armv5te/OP_SUB_DOUBLE.S */ 5318/* File: armv5te/binopWide.S */ 5319 /* 5320 * Generic 64-bit binary operation. Provide an "instr" line that 5321 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5322 * This could be an ARM instruction or a function call. (If the result 5323 * comes back in a register other than r0, you can override "result".) 5324 * 5325 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5326 * vCC (r1). Useful for integer division and modulus. 5327 * 5328 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5329 * xor-long, add-double, sub-double, mul-double, div-double, 5330 * rem-double 5331 * 5332 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5333 */ 5334 /* binop vAA, vBB, vCC */ 5335 FETCH(r0, 1) @ r0<- CCBB 5336 mov r9, rINST, lsr #8 @ r9<- AA 5337 and r2, r0, #255 @ r2<- BB 5338 mov r3, r0, lsr #8 @ r3<- CC 5339 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5340 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5341 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5342 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5343 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5344 .if 0 5345 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5346 beq common_errDivideByZero 5347 .endif 5348 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5349 5350 @ optional op; may set condition codes 5351 bl __aeabi_dsub @ result<- op, r0-r3 changed 5352 GET_INST_OPCODE(ip) @ extract opcode from rINST 5353 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5354 GOTO_OPCODE(ip) @ jump to next instruction 5355 /* 14-17 instructions */ 5356 5357 5358/* ------------------------------ */ 5359 .balign 64 5360.L_OP_MUL_DOUBLE: /* 0xad */ 5361/* File: armv5te/OP_MUL_DOUBLE.S */ 5362/* File: armv5te/binopWide.S */ 5363 /* 5364 * Generic 64-bit binary operation. Provide an "instr" line that 5365 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5366 * This could be an ARM instruction or a function call. (If the result 5367 * comes back in a register other than r0, you can override "result".) 5368 * 5369 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5370 * vCC (r1). Useful for integer division and modulus. 5371 * 5372 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5373 * xor-long, add-double, sub-double, mul-double, div-double, 5374 * rem-double 5375 * 5376 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5377 */ 5378 /* binop vAA, vBB, vCC */ 5379 FETCH(r0, 1) @ r0<- CCBB 5380 mov r9, rINST, lsr #8 @ r9<- AA 5381 and r2, r0, #255 @ r2<- BB 5382 mov r3, r0, lsr #8 @ r3<- CC 5383 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5384 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5385 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5386 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5387 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5388 .if 0 5389 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5390 beq common_errDivideByZero 5391 .endif 5392 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5393 5394 @ optional op; may set condition codes 5395 bl __aeabi_dmul @ result<- op, r0-r3 changed 5396 GET_INST_OPCODE(ip) @ extract opcode from rINST 5397 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5398 GOTO_OPCODE(ip) @ jump to next instruction 5399 /* 14-17 instructions */ 5400 5401 5402/* ------------------------------ */ 5403 .balign 64 5404.L_OP_DIV_DOUBLE: /* 0xae */ 5405/* File: armv5te/OP_DIV_DOUBLE.S */ 5406/* File: armv5te/binopWide.S */ 5407 /* 5408 * Generic 64-bit binary operation. Provide an "instr" line that 5409 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5410 * This could be an ARM instruction or a function call. (If the result 5411 * comes back in a register other than r0, you can override "result".) 5412 * 5413 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5414 * vCC (r1). Useful for integer division and modulus. 5415 * 5416 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5417 * xor-long, add-double, sub-double, mul-double, div-double, 5418 * rem-double 5419 * 5420 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5421 */ 5422 /* binop vAA, vBB, vCC */ 5423 FETCH(r0, 1) @ r0<- CCBB 5424 mov r9, rINST, lsr #8 @ r9<- AA 5425 and r2, r0, #255 @ r2<- BB 5426 mov r3, r0, lsr #8 @ r3<- CC 5427 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5428 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5429 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5430 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5431 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5432 .if 0 5433 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5434 beq common_errDivideByZero 5435 .endif 5436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5437 5438 @ optional op; may set condition codes 5439 bl __aeabi_ddiv @ result<- op, r0-r3 changed 5440 GET_INST_OPCODE(ip) @ extract opcode from rINST 5441 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5442 GOTO_OPCODE(ip) @ jump to next instruction 5443 /* 14-17 instructions */ 5444 5445 5446/* ------------------------------ */ 5447 .balign 64 5448.L_OP_REM_DOUBLE: /* 0xaf */ 5449/* File: armv5te/OP_REM_DOUBLE.S */ 5450/* EABI doesn't define a double remainder function, but libm does */ 5451/* File: armv5te/binopWide.S */ 5452 /* 5453 * Generic 64-bit binary operation. Provide an "instr" line that 5454 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5455 * This could be an ARM instruction or a function call. (If the result 5456 * comes back in a register other than r0, you can override "result".) 5457 * 5458 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5459 * vCC (r1). Useful for integer division and modulus. 5460 * 5461 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5462 * xor-long, add-double, sub-double, mul-double, div-double, 5463 * rem-double 5464 * 5465 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5466 */ 5467 /* binop vAA, vBB, vCC */ 5468 FETCH(r0, 1) @ r0<- CCBB 5469 mov r9, rINST, lsr #8 @ r9<- AA 5470 and r2, r0, #255 @ r2<- BB 5471 mov r3, r0, lsr #8 @ r3<- CC 5472 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5473 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5474 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5475 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5476 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5477 .if 0 5478 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5479 beq common_errDivideByZero 5480 .endif 5481 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5482 5483 @ optional op; may set condition codes 5484 bl fmod @ result<- op, r0-r3 changed 5485 GET_INST_OPCODE(ip) @ extract opcode from rINST 5486 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5487 GOTO_OPCODE(ip) @ jump to next instruction 5488 /* 14-17 instructions */ 5489 5490 5491/* ------------------------------ */ 5492 .balign 64 5493.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5494/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5495/* File: armv5te/binop2addr.S */ 5496 /* 5497 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5498 * that specifies an instruction that performs "result = r0 op r1". 5499 * This could be an ARM instruction or a function call. (If the result 5500 * comes back in a register other than r0, you can override "result".) 5501 * 5502 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5503 * vCC (r1). Useful for integer division and modulus. 5504 * 5505 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5506 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5507 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5508 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5509 */ 5510 /* binop/2addr vA, vB */ 5511 mov r9, rINST, lsr #8 @ r9<- A+ 5512 mov r3, rINST, lsr #12 @ r3<- B 5513 and r9, r9, #15 5514 GET_VREG(r1, r3) @ r1<- vB 5515 GET_VREG(r0, r9) @ r0<- vA 5516 .if 0 5517 cmp r1, #0 @ is second operand zero? 5518 beq common_errDivideByZero 5519 .endif 5520 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5521 5522 @ optional op; may set condition codes 5523 add r0, r0, r1 @ r0<- op, r0-r3 changed 5524 GET_INST_OPCODE(ip) @ extract opcode from rINST 5525 SET_VREG(r0, r9) @ vAA<- r0 5526 GOTO_OPCODE(ip) @ jump to next instruction 5527 /* 10-13 instructions */ 5528 5529 5530/* ------------------------------ */ 5531 .balign 64 5532.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5533/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5534/* File: armv5te/binop2addr.S */ 5535 /* 5536 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5537 * that specifies an instruction that performs "result = r0 op r1". 5538 * This could be an ARM instruction or a function call. (If the result 5539 * comes back in a register other than r0, you can override "result".) 5540 * 5541 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5542 * vCC (r1). Useful for integer division and modulus. 5543 * 5544 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5545 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5546 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5547 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5548 */ 5549 /* binop/2addr vA, vB */ 5550 mov r9, rINST, lsr #8 @ r9<- A+ 5551 mov r3, rINST, lsr #12 @ r3<- B 5552 and r9, r9, #15 5553 GET_VREG(r1, r3) @ r1<- vB 5554 GET_VREG(r0, r9) @ r0<- vA 5555 .if 0 5556 cmp r1, #0 @ is second operand zero? 5557 beq common_errDivideByZero 5558 .endif 5559 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5560 5561 @ optional op; may set condition codes 5562 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5563 GET_INST_OPCODE(ip) @ extract opcode from rINST 5564 SET_VREG(r0, r9) @ vAA<- r0 5565 GOTO_OPCODE(ip) @ jump to next instruction 5566 /* 10-13 instructions */ 5567 5568 5569/* ------------------------------ */ 5570 .balign 64 5571.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5572/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5573/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5574/* File: armv5te/binop2addr.S */ 5575 /* 5576 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5577 * that specifies an instruction that performs "result = r0 op r1". 5578 * This could be an ARM instruction or a function call. (If the result 5579 * comes back in a register other than r0, you can override "result".) 5580 * 5581 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5582 * vCC (r1). Useful for integer division and modulus. 5583 * 5584 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5585 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5586 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5587 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5588 */ 5589 /* binop/2addr vA, vB */ 5590 mov r9, rINST, lsr #8 @ r9<- A+ 5591 mov r3, rINST, lsr #12 @ r3<- B 5592 and r9, r9, #15 5593 GET_VREG(r1, r3) @ r1<- vB 5594 GET_VREG(r0, r9) @ r0<- vA 5595 .if 0 5596 cmp r1, #0 @ is second operand zero? 5597 beq common_errDivideByZero 5598 .endif 5599 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5600 5601 @ optional op; may set condition codes 5602 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5603 GET_INST_OPCODE(ip) @ extract opcode from rINST 5604 SET_VREG(r0, r9) @ vAA<- r0 5605 GOTO_OPCODE(ip) @ jump to next instruction 5606 /* 10-13 instructions */ 5607 5608 5609/* ------------------------------ */ 5610 .balign 64 5611.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5612/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5613/* File: armv5te/binop2addr.S */ 5614 /* 5615 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5616 * that specifies an instruction that performs "result = r0 op r1". 5617 * This could be an ARM instruction or a function call. (If the result 5618 * comes back in a register other than r0, you can override "result".) 5619 * 5620 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5621 * vCC (r1). Useful for integer division and modulus. 5622 * 5623 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5624 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5625 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5626 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5627 */ 5628 /* binop/2addr vA, vB */ 5629 mov r9, rINST, lsr #8 @ r9<- A+ 5630 mov r3, rINST, lsr #12 @ r3<- B 5631 and r9, r9, #15 5632 GET_VREG(r1, r3) @ r1<- vB 5633 GET_VREG(r0, r9) @ r0<- vA 5634 .if 1 5635 cmp r1, #0 @ is second operand zero? 5636 beq common_errDivideByZero 5637 .endif 5638 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5639 5640 @ optional op; may set condition codes 5641 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5642 GET_INST_OPCODE(ip) @ extract opcode from rINST 5643 SET_VREG(r0, r9) @ vAA<- r0 5644 GOTO_OPCODE(ip) @ jump to next instruction 5645 /* 10-13 instructions */ 5646 5647 5648/* ------------------------------ */ 5649 .balign 64 5650.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5651/* File: armv5te/OP_REM_INT_2ADDR.S */ 5652/* idivmod returns quotient in r0 and remainder in r1 */ 5653/* File: armv5te/binop2addr.S */ 5654 /* 5655 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5656 * that specifies an instruction that performs "result = r0 op r1". 5657 * This could be an ARM instruction or a function call. (If the result 5658 * comes back in a register other than r0, you can override "result".) 5659 * 5660 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5661 * vCC (r1). Useful for integer division and modulus. 5662 * 5663 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5664 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5665 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5666 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5667 */ 5668 /* binop/2addr vA, vB */ 5669 mov r9, rINST, lsr #8 @ r9<- A+ 5670 mov r3, rINST, lsr #12 @ r3<- B 5671 and r9, r9, #15 5672 GET_VREG(r1, r3) @ r1<- vB 5673 GET_VREG(r0, r9) @ r0<- vA 5674 .if 1 5675 cmp r1, #0 @ is second operand zero? 5676 beq common_errDivideByZero 5677 .endif 5678 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5679 5680 @ optional op; may set condition codes 5681 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5682 GET_INST_OPCODE(ip) @ extract opcode from rINST 5683 SET_VREG(r1, r9) @ vAA<- r1 5684 GOTO_OPCODE(ip) @ jump to next instruction 5685 /* 10-13 instructions */ 5686 5687 5688/* ------------------------------ */ 5689 .balign 64 5690.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5691/* File: armv5te/OP_AND_INT_2ADDR.S */ 5692/* File: armv5te/binop2addr.S */ 5693 /* 5694 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5695 * that specifies an instruction that performs "result = r0 op r1". 5696 * This could be an ARM instruction or a function call. (If the result 5697 * comes back in a register other than r0, you can override "result".) 5698 * 5699 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5700 * vCC (r1). Useful for integer division and modulus. 5701 * 5702 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5703 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5704 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5705 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5706 */ 5707 /* binop/2addr vA, vB */ 5708 mov r9, rINST, lsr #8 @ r9<- A+ 5709 mov r3, rINST, lsr #12 @ r3<- B 5710 and r9, r9, #15 5711 GET_VREG(r1, r3) @ r1<- vB 5712 GET_VREG(r0, r9) @ r0<- vA 5713 .if 0 5714 cmp r1, #0 @ is second operand zero? 5715 beq common_errDivideByZero 5716 .endif 5717 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5718 5719 @ optional op; may set condition codes 5720 and r0, r0, r1 @ r0<- op, r0-r3 changed 5721 GET_INST_OPCODE(ip) @ extract opcode from rINST 5722 SET_VREG(r0, r9) @ vAA<- r0 5723 GOTO_OPCODE(ip) @ jump to next instruction 5724 /* 10-13 instructions */ 5725 5726 5727/* ------------------------------ */ 5728 .balign 64 5729.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5730/* File: armv5te/OP_OR_INT_2ADDR.S */ 5731/* File: armv5te/binop2addr.S */ 5732 /* 5733 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5734 * that specifies an instruction that performs "result = r0 op r1". 5735 * This could be an ARM instruction or a function call. (If the result 5736 * comes back in a register other than r0, you can override "result".) 5737 * 5738 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5739 * vCC (r1). Useful for integer division and modulus. 5740 * 5741 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5742 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5743 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5744 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5745 */ 5746 /* binop/2addr vA, vB */ 5747 mov r9, rINST, lsr #8 @ r9<- A+ 5748 mov r3, rINST, lsr #12 @ r3<- B 5749 and r9, r9, #15 5750 GET_VREG(r1, r3) @ r1<- vB 5751 GET_VREG(r0, r9) @ r0<- vA 5752 .if 0 5753 cmp r1, #0 @ is second operand zero? 5754 beq common_errDivideByZero 5755 .endif 5756 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5757 5758 @ optional op; may set condition codes 5759 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5760 GET_INST_OPCODE(ip) @ extract opcode from rINST 5761 SET_VREG(r0, r9) @ vAA<- r0 5762 GOTO_OPCODE(ip) @ jump to next instruction 5763 /* 10-13 instructions */ 5764 5765 5766/* ------------------------------ */ 5767 .balign 64 5768.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5769/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5770/* File: armv5te/binop2addr.S */ 5771 /* 5772 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5773 * that specifies an instruction that performs "result = r0 op r1". 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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5781 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5782 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5783 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5784 */ 5785 /* binop/2addr vA, vB */ 5786 mov r9, rINST, lsr #8 @ r9<- A+ 5787 mov r3, rINST, lsr #12 @ r3<- B 5788 and r9, r9, #15 5789 GET_VREG(r1, r3) @ r1<- vB 5790 GET_VREG(r0, r9) @ r0<- vA 5791 .if 0 5792 cmp r1, #0 @ is second operand zero? 5793 beq common_errDivideByZero 5794 .endif 5795 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5796 5797 @ optional op; may set condition codes 5798 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5799 GET_INST_OPCODE(ip) @ extract opcode from rINST 5800 SET_VREG(r0, r9) @ vAA<- r0 5801 GOTO_OPCODE(ip) @ jump to next instruction 5802 /* 10-13 instructions */ 5803 5804 5805/* ------------------------------ */ 5806 .balign 64 5807.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5808/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5809/* File: armv5te/binop2addr.S */ 5810 /* 5811 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5812 * that specifies an instruction that performs "result = r0 op r1". 5813 * This could be an ARM instruction or a function call. (If the result 5814 * comes back in a register other than r0, you can override "result".) 5815 * 5816 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5817 * vCC (r1). Useful for integer division and modulus. 5818 * 5819 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5820 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5821 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5822 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5823 */ 5824 /* binop/2addr vA, vB */ 5825 mov r9, rINST, lsr #8 @ r9<- A+ 5826 mov r3, rINST, lsr #12 @ r3<- B 5827 and r9, r9, #15 5828 GET_VREG(r1, r3) @ r1<- vB 5829 GET_VREG(r0, r9) @ r0<- vA 5830 .if 0 5831 cmp r1, #0 @ is second operand zero? 5832 beq common_errDivideByZero 5833 .endif 5834 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5835 5836 and r1, r1, #31 @ optional op; may set condition codes 5837 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5838 GET_INST_OPCODE(ip) @ extract opcode from rINST 5839 SET_VREG(r0, r9) @ vAA<- r0 5840 GOTO_OPCODE(ip) @ jump to next instruction 5841 /* 10-13 instructions */ 5842 5843 5844/* ------------------------------ */ 5845 .balign 64 5846.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5847/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5848/* File: armv5te/binop2addr.S */ 5849 /* 5850 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5851 * that specifies an instruction that performs "result = r0 op r1". 5852 * This could be an ARM instruction or a function call. (If the result 5853 * comes back in a register other than r0, you can override "result".) 5854 * 5855 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5856 * vCC (r1). Useful for integer division and modulus. 5857 * 5858 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5859 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5860 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5861 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5862 */ 5863 /* binop/2addr vA, vB */ 5864 mov r9, rINST, lsr #8 @ r9<- A+ 5865 mov r3, rINST, lsr #12 @ r3<- B 5866 and r9, r9, #15 5867 GET_VREG(r1, r3) @ r1<- vB 5868 GET_VREG(r0, r9) @ r0<- vA 5869 .if 0 5870 cmp r1, #0 @ is second operand zero? 5871 beq common_errDivideByZero 5872 .endif 5873 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5874 5875 and r1, r1, #31 @ optional op; may set condition codes 5876 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5877 GET_INST_OPCODE(ip) @ extract opcode from rINST 5878 SET_VREG(r0, r9) @ vAA<- r0 5879 GOTO_OPCODE(ip) @ jump to next instruction 5880 /* 10-13 instructions */ 5881 5882 5883/* ------------------------------ */ 5884 .balign 64 5885.L_OP_USHR_INT_2ADDR: /* 0xba */ 5886/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5887/* File: armv5te/binop2addr.S */ 5888 /* 5889 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5890 * that specifies an instruction that performs "result = r0 op r1". 5891 * This could be an ARM instruction or a function call. (If the result 5892 * comes back in a register other than r0, you can override "result".) 5893 * 5894 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5895 * vCC (r1). Useful for integer division and modulus. 5896 * 5897 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5898 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5899 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5900 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5901 */ 5902 /* binop/2addr vA, vB */ 5903 mov r9, rINST, lsr #8 @ r9<- A+ 5904 mov r3, rINST, lsr #12 @ r3<- B 5905 and r9, r9, #15 5906 GET_VREG(r1, r3) @ r1<- vB 5907 GET_VREG(r0, r9) @ r0<- vA 5908 .if 0 5909 cmp r1, #0 @ is second operand zero? 5910 beq common_errDivideByZero 5911 .endif 5912 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5913 5914 and r1, r1, #31 @ optional op; may set condition codes 5915 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5916 GET_INST_OPCODE(ip) @ extract opcode from rINST 5917 SET_VREG(r0, r9) @ vAA<- r0 5918 GOTO_OPCODE(ip) @ jump to next instruction 5919 /* 10-13 instructions */ 5920 5921 5922/* ------------------------------ */ 5923 .balign 64 5924.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5925/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5926/* File: armv5te/binopWide2addr.S */ 5927 /* 5928 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5929 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5930 * This could be an ARM instruction or a function call. (If the result 5931 * comes back in a register other than r0, you can override "result".) 5932 * 5933 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5934 * vCC (r1). Useful for integer division and modulus. 5935 * 5936 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5937 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5938 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5939 * rem-double/2addr 5940 */ 5941 /* binop/2addr vA, vB */ 5942 mov r9, rINST, lsr #8 @ r9<- A+ 5943 mov r1, rINST, lsr #12 @ r1<- B 5944 and r9, r9, #15 5945 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5946 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5947 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5948 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5949 .if 0 5950 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5951 beq common_errDivideByZero 5952 .endif 5953 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5954 5955 adds r0, r0, r2 @ optional op; may set condition codes 5956 adc r1, r1, r3 @ result<- op, r0-r3 changed 5957 GET_INST_OPCODE(ip) @ extract opcode from rINST 5958 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5959 GOTO_OPCODE(ip) @ jump to next instruction 5960 /* 12-15 instructions */ 5961 5962 5963/* ------------------------------ */ 5964 .balign 64 5965.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5966/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5967/* File: armv5te/binopWide2addr.S */ 5968 /* 5969 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5970 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5971 * This could be an ARM instruction or a function call. (If the result 5972 * comes back in a register other than r0, you can override "result".) 5973 * 5974 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5975 * vCC (r1). Useful for integer division and modulus. 5976 * 5977 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5978 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5979 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5980 * rem-double/2addr 5981 */ 5982 /* binop/2addr vA, vB */ 5983 mov r9, rINST, lsr #8 @ r9<- A+ 5984 mov r1, rINST, lsr #12 @ r1<- B 5985 and r9, r9, #15 5986 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5987 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5988 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5989 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5990 .if 0 5991 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5992 beq common_errDivideByZero 5993 .endif 5994 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5995 5996 subs r0, r0, r2 @ optional op; may set condition codes 5997 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5998 GET_INST_OPCODE(ip) @ extract opcode from rINST 5999 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6000 GOTO_OPCODE(ip) @ jump to next instruction 6001 /* 12-15 instructions */ 6002 6003 6004/* ------------------------------ */ 6005 .balign 64 6006.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 6007/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 6008 /* 6009 * Signed 64-bit integer multiply, "/2addr" version. 6010 * 6011 * See OP_MUL_LONG for an explanation. 6012 * 6013 * We get a little tight on registers, so to avoid looking up &fp[A] 6014 * again we stuff it into rINST. 6015 */ 6016 /* mul-long/2addr vA, vB */ 6017 mov r9, rINST, lsr #8 @ r9<- A+ 6018 mov r1, rINST, lsr #12 @ r1<- B 6019 and r9, r9, #15 6020 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6021 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 6022 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6023 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 6024 mul ip, r2, r1 @ ip<- ZxW 6025 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 6026 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 6027 mov r0, rINST @ r0<- &fp[A] (free up rINST) 6028 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6029 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 6030 GET_INST_OPCODE(ip) @ extract opcode from rINST 6031 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 6032 GOTO_OPCODE(ip) @ jump to next instruction 6033 6034/* ------------------------------ */ 6035 .balign 64 6036.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 6037/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 6038/* File: armv5te/binopWide2addr.S */ 6039 /* 6040 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6041 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6042 * This could be an ARM instruction or a function call. (If the result 6043 * comes back in a register other than r0, you can override "result".) 6044 * 6045 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6046 * vCC (r1). Useful for integer division and modulus. 6047 * 6048 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6049 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6050 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6051 * rem-double/2addr 6052 */ 6053 /* binop/2addr vA, vB */ 6054 mov r9, rINST, lsr #8 @ r9<- A+ 6055 mov r1, rINST, lsr #12 @ r1<- B 6056 and r9, r9, #15 6057 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6058 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6059 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6060 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6061 .if 1 6062 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6063 beq common_errDivideByZero 6064 .endif 6065 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6066 6067 @ optional op; may set condition codes 6068 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6069 GET_INST_OPCODE(ip) @ extract opcode from rINST 6070 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6071 GOTO_OPCODE(ip) @ jump to next instruction 6072 /* 12-15 instructions */ 6073 6074 6075/* ------------------------------ */ 6076 .balign 64 6077.L_OP_REM_LONG_2ADDR: /* 0xbf */ 6078/* File: armv5te/OP_REM_LONG_2ADDR.S */ 6079/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 6080/* File: armv5te/binopWide2addr.S */ 6081 /* 6082 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6083 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6084 * This could be an ARM instruction or a function call. (If the result 6085 * comes back in a register other than r0, you can override "result".) 6086 * 6087 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6088 * vCC (r1). Useful for integer division and modulus. 6089 * 6090 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6091 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6092 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6093 * rem-double/2addr 6094 */ 6095 /* binop/2addr vA, vB */ 6096 mov r9, rINST, lsr #8 @ r9<- A+ 6097 mov r1, rINST, lsr #12 @ r1<- B 6098 and r9, r9, #15 6099 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6100 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6101 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6102 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6103 .if 1 6104 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6105 beq common_errDivideByZero 6106 .endif 6107 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6108 6109 @ optional op; may set condition codes 6110 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6111 GET_INST_OPCODE(ip) @ extract opcode from rINST 6112 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 6113 GOTO_OPCODE(ip) @ jump to next instruction 6114 /* 12-15 instructions */ 6115 6116 6117/* ------------------------------ */ 6118 .balign 64 6119.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 6120/* File: armv5te/OP_AND_LONG_2ADDR.S */ 6121/* File: armv5te/binopWide2addr.S */ 6122 /* 6123 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6124 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6125 * This could be an ARM instruction or a function call. (If the result 6126 * comes back in a register other than r0, you can override "result".) 6127 * 6128 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6129 * vCC (r1). Useful for integer division and modulus. 6130 * 6131 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6132 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6133 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6134 * rem-double/2addr 6135 */ 6136 /* binop/2addr vA, vB */ 6137 mov r9, rINST, lsr #8 @ r9<- A+ 6138 mov r1, rINST, lsr #12 @ r1<- B 6139 and r9, r9, #15 6140 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6141 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6142 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6143 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6144 .if 0 6145 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6146 beq common_errDivideByZero 6147 .endif 6148 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6149 6150 and r0, r0, r2 @ optional op; may set condition codes 6151 and r1, r1, r3 @ result<- op, r0-r3 changed 6152 GET_INST_OPCODE(ip) @ extract opcode from rINST 6153 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6154 GOTO_OPCODE(ip) @ jump to next instruction 6155 /* 12-15 instructions */ 6156 6157 6158/* ------------------------------ */ 6159 .balign 64 6160.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6161/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6162/* File: armv5te/binopWide2addr.S */ 6163 /* 6164 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6165 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6166 * This could be an ARM instruction or a function call. (If the result 6167 * comes back in a register other than r0, you can override "result".) 6168 * 6169 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6170 * vCC (r1). Useful for integer division and modulus. 6171 * 6172 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6173 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6174 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6175 * rem-double/2addr 6176 */ 6177 /* binop/2addr vA, vB */ 6178 mov r9, rINST, lsr #8 @ r9<- A+ 6179 mov r1, rINST, lsr #12 @ r1<- B 6180 and r9, r9, #15 6181 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6182 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6183 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6184 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6185 .if 0 6186 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6187 beq common_errDivideByZero 6188 .endif 6189 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6190 6191 orr r0, r0, r2 @ optional op; may set condition codes 6192 orr r1, r1, r3 @ result<- op, r0-r3 changed 6193 GET_INST_OPCODE(ip) @ extract opcode from rINST 6194 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6195 GOTO_OPCODE(ip) @ jump to next instruction 6196 /* 12-15 instructions */ 6197 6198 6199/* ------------------------------ */ 6200 .balign 64 6201.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6202/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6203/* File: armv5te/binopWide2addr.S */ 6204 /* 6205 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6206 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6207 * This could be an ARM instruction or a function call. (If the result 6208 * comes back in a register other than r0, you can override "result".) 6209 * 6210 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6211 * vCC (r1). Useful for integer division and modulus. 6212 * 6213 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6214 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6215 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6216 * rem-double/2addr 6217 */ 6218 /* binop/2addr vA, vB */ 6219 mov r9, rINST, lsr #8 @ r9<- A+ 6220 mov r1, rINST, lsr #12 @ r1<- B 6221 and r9, r9, #15 6222 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6223 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6224 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6225 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6226 .if 0 6227 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6228 beq common_errDivideByZero 6229 .endif 6230 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6231 6232 eor r0, r0, r2 @ optional op; may set condition codes 6233 eor r1, r1, r3 @ result<- op, r0-r3 changed 6234 GET_INST_OPCODE(ip) @ extract opcode from rINST 6235 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6236 GOTO_OPCODE(ip) @ jump to next instruction 6237 /* 12-15 instructions */ 6238 6239 6240/* ------------------------------ */ 6241 .balign 64 6242.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6243/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6244 /* 6245 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6246 * 32-bit shift distance. 6247 */ 6248 /* shl-long/2addr vA, vB */ 6249 mov r9, rINST, lsr #8 @ r9<- A+ 6250 mov r3, rINST, lsr #12 @ r3<- B 6251 and r9, r9, #15 6252 GET_VREG(r2, r3) @ r2<- vB 6253 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6254 and r2, r2, #63 @ r2<- r2 & 0x3f 6255 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6256 6257 mov r1, r1, asl r2 @ r1<- r1 << r2 6258 rsb r3, r2, #32 @ r3<- 32 - r2 6259 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6260 subs ip, r2, #32 @ ip<- r2 - 32 6261 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6262 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6263 mov r0, r0, asl r2 @ r0<- r0 << r2 6264 b .LOP_SHL_LONG_2ADDR_finish 6265 6266/* ------------------------------ */ 6267 .balign 64 6268.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6269/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6270 /* 6271 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6272 * 32-bit shift distance. 6273 */ 6274 /* shr-long/2addr vA, vB */ 6275 mov r9, rINST, lsr #8 @ r9<- A+ 6276 mov r3, rINST, lsr #12 @ r3<- B 6277 and r9, r9, #15 6278 GET_VREG(r2, r3) @ r2<- vB 6279 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6280 and r2, r2, #63 @ r2<- r2 & 0x3f 6281 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6282 6283 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6284 rsb r3, r2, #32 @ r3<- 32 - r2 6285 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6286 subs ip, r2, #32 @ ip<- r2 - 32 6287 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6288 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6289 mov r1, r1, asr r2 @ r1<- r1 >> r2 6290 b .LOP_SHR_LONG_2ADDR_finish 6291 6292/* ------------------------------ */ 6293 .balign 64 6294.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6295/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6296 /* 6297 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6298 * 32-bit shift distance. 6299 */ 6300 /* ushr-long/2addr vA, vB */ 6301 mov r9, rINST, lsr #8 @ r9<- A+ 6302 mov r3, rINST, lsr #12 @ r3<- B 6303 and r9, r9, #15 6304 GET_VREG(r2, r3) @ r2<- vB 6305 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6306 and r2, r2, #63 @ r2<- r2 & 0x3f 6307 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6308 6309 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6310 rsb r3, r2, #32 @ r3<- 32 - r2 6311 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6312 subs ip, r2, #32 @ ip<- r2 - 32 6313 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6314 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6315 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6316 b .LOP_USHR_LONG_2ADDR_finish 6317 6318/* ------------------------------ */ 6319 .balign 64 6320.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6321/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */ 6322/* File: armv5te/binop2addr.S */ 6323 /* 6324 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6325 * that specifies an instruction that performs "result = r0 op r1". 6326 * This could be an ARM instruction or a function call. (If the result 6327 * comes back in a register other than r0, you can override "result".) 6328 * 6329 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6330 * vCC (r1). Useful for integer division and modulus. 6331 * 6332 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6333 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6334 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6335 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6336 */ 6337 /* binop/2addr vA, vB */ 6338 mov r9, rINST, lsr #8 @ r9<- A+ 6339 mov r3, rINST, lsr #12 @ r3<- B 6340 and r9, r9, #15 6341 GET_VREG(r1, r3) @ r1<- vB 6342 GET_VREG(r0, r9) @ r0<- vA 6343 .if 0 6344 cmp r1, #0 @ is second operand zero? 6345 beq common_errDivideByZero 6346 .endif 6347 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6348 6349 @ optional op; may set condition codes 6350 bl __aeabi_fadd @ r0<- op, r0-r3 changed 6351 GET_INST_OPCODE(ip) @ extract opcode from rINST 6352 SET_VREG(r0, r9) @ vAA<- r0 6353 GOTO_OPCODE(ip) @ jump to next instruction 6354 /* 10-13 instructions */ 6355 6356 6357/* ------------------------------ */ 6358 .balign 64 6359.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6360/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */ 6361/* File: armv5te/binop2addr.S */ 6362 /* 6363 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6364 * that specifies an instruction that performs "result = r0 op r1". 6365 * This could be an ARM instruction or a function call. (If the result 6366 * comes back in a register other than r0, you can override "result".) 6367 * 6368 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6369 * vCC (r1). Useful for integer division and modulus. 6370 * 6371 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6372 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6373 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6374 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6375 */ 6376 /* binop/2addr vA, vB */ 6377 mov r9, rINST, lsr #8 @ r9<- A+ 6378 mov r3, rINST, lsr #12 @ r3<- B 6379 and r9, r9, #15 6380 GET_VREG(r1, r3) @ r1<- vB 6381 GET_VREG(r0, r9) @ r0<- vA 6382 .if 0 6383 cmp r1, #0 @ is second operand zero? 6384 beq common_errDivideByZero 6385 .endif 6386 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6387 6388 @ optional op; may set condition codes 6389 bl __aeabi_fsub @ r0<- op, r0-r3 changed 6390 GET_INST_OPCODE(ip) @ extract opcode from rINST 6391 SET_VREG(r0, r9) @ vAA<- r0 6392 GOTO_OPCODE(ip) @ jump to next instruction 6393 /* 10-13 instructions */ 6394 6395 6396/* ------------------------------ */ 6397 .balign 64 6398.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6399/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */ 6400/* File: armv5te/binop2addr.S */ 6401 /* 6402 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6403 * that specifies an instruction that performs "result = r0 op r1". 6404 * This could be an ARM instruction or a function call. (If the result 6405 * comes back in a register other than r0, you can override "result".) 6406 * 6407 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6408 * vCC (r1). Useful for integer division and modulus. 6409 * 6410 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6411 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6412 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6413 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6414 */ 6415 /* binop/2addr vA, vB */ 6416 mov r9, rINST, lsr #8 @ r9<- A+ 6417 mov r3, rINST, lsr #12 @ r3<- B 6418 and r9, r9, #15 6419 GET_VREG(r1, r3) @ r1<- vB 6420 GET_VREG(r0, r9) @ r0<- vA 6421 .if 0 6422 cmp r1, #0 @ is second operand zero? 6423 beq common_errDivideByZero 6424 .endif 6425 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6426 6427 @ optional op; may set condition codes 6428 bl __aeabi_fmul @ r0<- op, r0-r3 changed 6429 GET_INST_OPCODE(ip) @ extract opcode from rINST 6430 SET_VREG(r0, r9) @ vAA<- r0 6431 GOTO_OPCODE(ip) @ jump to next instruction 6432 /* 10-13 instructions */ 6433 6434 6435/* ------------------------------ */ 6436 .balign 64 6437.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6438/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */ 6439/* File: armv5te/binop2addr.S */ 6440 /* 6441 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6442 * that specifies an instruction that performs "result = r0 op r1". 6443 * This could be an ARM instruction or a function call. (If the result 6444 * comes back in a register other than r0, you can override "result".) 6445 * 6446 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6447 * vCC (r1). Useful for integer division and modulus. 6448 * 6449 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6450 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6451 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6452 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6453 */ 6454 /* binop/2addr vA, vB */ 6455 mov r9, rINST, lsr #8 @ r9<- A+ 6456 mov r3, rINST, lsr #12 @ r3<- B 6457 and r9, r9, #15 6458 GET_VREG(r1, r3) @ r1<- vB 6459 GET_VREG(r0, r9) @ r0<- vA 6460 .if 0 6461 cmp r1, #0 @ is second operand zero? 6462 beq common_errDivideByZero 6463 .endif 6464 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6465 6466 @ optional op; may set condition codes 6467 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 6468 GET_INST_OPCODE(ip) @ extract opcode from rINST 6469 SET_VREG(r0, r9) @ vAA<- r0 6470 GOTO_OPCODE(ip) @ jump to next instruction 6471 /* 10-13 instructions */ 6472 6473 6474/* ------------------------------ */ 6475 .balign 64 6476.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6477/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6478/* EABI doesn't define a float remainder function, but libm does */ 6479/* File: armv5te/binop2addr.S */ 6480 /* 6481 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6482 * that specifies an instruction that performs "result = r0 op r1". 6483 * This could be an ARM instruction or a function call. (If the result 6484 * comes back in a register other than r0, you can override "result".) 6485 * 6486 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6487 * vCC (r1). Useful for integer division and modulus. 6488 * 6489 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6490 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6491 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6492 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6493 */ 6494 /* binop/2addr vA, vB */ 6495 mov r9, rINST, lsr #8 @ r9<- A+ 6496 mov r3, rINST, lsr #12 @ r3<- B 6497 and r9, r9, #15 6498 GET_VREG(r1, r3) @ r1<- vB 6499 GET_VREG(r0, r9) @ r0<- vA 6500 .if 0 6501 cmp r1, #0 @ is second operand zero? 6502 beq common_errDivideByZero 6503 .endif 6504 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6505 6506 @ optional op; may set condition codes 6507 bl fmodf @ r0<- op, r0-r3 changed 6508 GET_INST_OPCODE(ip) @ extract opcode from rINST 6509 SET_VREG(r0, r9) @ vAA<- r0 6510 GOTO_OPCODE(ip) @ jump to next instruction 6511 /* 10-13 instructions */ 6512 6513 6514/* ------------------------------ */ 6515 .balign 64 6516.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6517/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */ 6518/* File: armv5te/binopWide2addr.S */ 6519 /* 6520 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6521 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6522 * This could be an ARM instruction or a function call. (If the result 6523 * comes back in a register other than r0, you can override "result".) 6524 * 6525 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6526 * vCC (r1). Useful for integer division and modulus. 6527 * 6528 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6529 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6530 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6531 * rem-double/2addr 6532 */ 6533 /* binop/2addr vA, vB */ 6534 mov r9, rINST, lsr #8 @ r9<- A+ 6535 mov r1, rINST, lsr #12 @ r1<- B 6536 and r9, r9, #15 6537 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6538 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6539 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6540 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6541 .if 0 6542 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6543 beq common_errDivideByZero 6544 .endif 6545 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6546 6547 @ optional op; may set condition codes 6548 bl __aeabi_dadd @ result<- op, r0-r3 changed 6549 GET_INST_OPCODE(ip) @ extract opcode from rINST 6550 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6551 GOTO_OPCODE(ip) @ jump to next instruction 6552 /* 12-15 instructions */ 6553 6554 6555/* ------------------------------ */ 6556 .balign 64 6557.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6558/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */ 6559/* File: armv5te/binopWide2addr.S */ 6560 /* 6561 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6562 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6563 * This could be an ARM instruction or a function call. (If the result 6564 * comes back in a register other than r0, you can override "result".) 6565 * 6566 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6567 * vCC (r1). Useful for integer division and modulus. 6568 * 6569 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6570 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6571 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6572 * rem-double/2addr 6573 */ 6574 /* binop/2addr vA, vB */ 6575 mov r9, rINST, lsr #8 @ r9<- A+ 6576 mov r1, rINST, lsr #12 @ r1<- B 6577 and r9, r9, #15 6578 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6579 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6580 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6581 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6582 .if 0 6583 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6584 beq common_errDivideByZero 6585 .endif 6586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6587 6588 @ optional op; may set condition codes 6589 bl __aeabi_dsub @ result<- op, r0-r3 changed 6590 GET_INST_OPCODE(ip) @ extract opcode from rINST 6591 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6592 GOTO_OPCODE(ip) @ jump to next instruction 6593 /* 12-15 instructions */ 6594 6595 6596/* ------------------------------ */ 6597 .balign 64 6598.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6599/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */ 6600/* File: armv5te/binopWide2addr.S */ 6601 /* 6602 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6603 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6604 * This could be an ARM instruction or a function call. (If the result 6605 * comes back in a register other than r0, you can override "result".) 6606 * 6607 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6608 * vCC (r1). Useful for integer division and modulus. 6609 * 6610 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6611 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6612 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6613 * rem-double/2addr 6614 */ 6615 /* binop/2addr vA, vB */ 6616 mov r9, rINST, lsr #8 @ r9<- A+ 6617 mov r1, rINST, lsr #12 @ r1<- B 6618 and r9, r9, #15 6619 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6620 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6621 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6622 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6623 .if 0 6624 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6625 beq common_errDivideByZero 6626 .endif 6627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6628 6629 @ optional op; may set condition codes 6630 bl __aeabi_dmul @ result<- op, r0-r3 changed 6631 GET_INST_OPCODE(ip) @ extract opcode from rINST 6632 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6633 GOTO_OPCODE(ip) @ jump to next instruction 6634 /* 12-15 instructions */ 6635 6636 6637/* ------------------------------ */ 6638 .balign 64 6639.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6640/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */ 6641/* File: armv5te/binopWide2addr.S */ 6642 /* 6643 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6644 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6645 * This could be an ARM instruction or a function call. (If the result 6646 * comes back in a register other than r0, you can override "result".) 6647 * 6648 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6649 * vCC (r1). Useful for integer division and modulus. 6650 * 6651 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6652 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6653 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6654 * rem-double/2addr 6655 */ 6656 /* binop/2addr vA, vB */ 6657 mov r9, rINST, lsr #8 @ r9<- A+ 6658 mov r1, rINST, lsr #12 @ r1<- B 6659 and r9, r9, #15 6660 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6661 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6662 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6663 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6664 .if 0 6665 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6666 beq common_errDivideByZero 6667 .endif 6668 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6669 6670 @ optional op; may set condition codes 6671 bl __aeabi_ddiv @ result<- op, r0-r3 changed 6672 GET_INST_OPCODE(ip) @ extract opcode from rINST 6673 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6674 GOTO_OPCODE(ip) @ jump to next instruction 6675 /* 12-15 instructions */ 6676 6677 6678/* ------------------------------ */ 6679 .balign 64 6680.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6681/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6682/* EABI doesn't define a double remainder function, but libm does */ 6683/* File: armv5te/binopWide2addr.S */ 6684 /* 6685 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6686 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6687 * This could be an ARM instruction or a function call. (If the result 6688 * comes back in a register other than r0, you can override "result".) 6689 * 6690 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6691 * vCC (r1). Useful for integer division and modulus. 6692 * 6693 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6694 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6695 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6696 * rem-double/2addr 6697 */ 6698 /* binop/2addr vA, vB */ 6699 mov r9, rINST, lsr #8 @ r9<- A+ 6700 mov r1, rINST, lsr #12 @ r1<- B 6701 and r9, r9, #15 6702 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6703 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6704 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6705 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6706 .if 0 6707 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6708 beq common_errDivideByZero 6709 .endif 6710 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6711 6712 @ optional op; may set condition codes 6713 bl fmod @ result<- op, r0-r3 changed 6714 GET_INST_OPCODE(ip) @ extract opcode from rINST 6715 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6716 GOTO_OPCODE(ip) @ jump to next instruction 6717 /* 12-15 instructions */ 6718 6719 6720/* ------------------------------ */ 6721 .balign 64 6722.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6723/* File: armv5te/OP_ADD_INT_LIT16.S */ 6724/* File: armv5te/binopLit16.S */ 6725 /* 6726 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6727 * that specifies an instruction that performs "result = r0 op r1". 6728 * This could be an ARM instruction or a function call. (If the result 6729 * comes back in a register other than r0, you can override "result".) 6730 * 6731 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6732 * vCC (r1). Useful for integer division and modulus. 6733 * 6734 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6735 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6736 */ 6737 /* binop/lit16 vA, vB, #+CCCC */ 6738 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6739 mov r2, rINST, lsr #12 @ r2<- B 6740 mov r9, rINST, lsr #8 @ r9<- A+ 6741 GET_VREG(r0, r2) @ r0<- vB 6742 and r9, r9, #15 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 add r0, r0, r1 @ r0<- op, r0-r3 changed 6750 GET_INST_OPCODE(ip) @ extract opcode from rINST 6751 SET_VREG(r0, r9) @ vAA<- r0 6752 GOTO_OPCODE(ip) @ jump to next instruction 6753 /* 10-13 instructions */ 6754 6755 6756/* ------------------------------ */ 6757 .balign 64 6758.L_OP_RSUB_INT: /* 0xd1 */ 6759/* File: armv5te/OP_RSUB_INT.S */ 6760/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6761/* File: armv5te/binopLit16.S */ 6762 /* 6763 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6764 * that specifies an instruction that performs "result = r0 op r1". 6765 * This could be an ARM instruction or a function call. (If the result 6766 * comes back in a register other than r0, you can override "result".) 6767 * 6768 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6769 * vCC (r1). Useful for integer division and modulus. 6770 * 6771 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6772 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6773 */ 6774 /* binop/lit16 vA, vB, #+CCCC */ 6775 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6776 mov r2, rINST, lsr #12 @ r2<- B 6777 mov r9, rINST, lsr #8 @ r9<- A+ 6778 GET_VREG(r0, r2) @ r0<- vB 6779 and r9, r9, #15 6780 .if 0 6781 cmp r1, #0 @ is second operand zero? 6782 beq common_errDivideByZero 6783 .endif 6784 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6785 6786 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6787 GET_INST_OPCODE(ip) @ extract opcode from rINST 6788 SET_VREG(r0, r9) @ vAA<- r0 6789 GOTO_OPCODE(ip) @ jump to next instruction 6790 /* 10-13 instructions */ 6791 6792 6793/* ------------------------------ */ 6794 .balign 64 6795.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6796/* File: armv5te/OP_MUL_INT_LIT16.S */ 6797/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6798/* File: armv5te/binopLit16.S */ 6799 /* 6800 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6801 * that specifies an instruction that performs "result = r0 op r1". 6802 * This could be an ARM instruction or a function call. (If the result 6803 * comes back in a register other than r0, you can override "result".) 6804 * 6805 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6806 * vCC (r1). Useful for integer division and modulus. 6807 * 6808 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6809 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6810 */ 6811 /* binop/lit16 vA, vB, #+CCCC */ 6812 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6813 mov r2, rINST, lsr #12 @ r2<- B 6814 mov r9, rINST, lsr #8 @ r9<- A+ 6815 GET_VREG(r0, r2) @ r0<- vB 6816 and r9, r9, #15 6817 .if 0 6818 cmp r1, #0 @ is second operand zero? 6819 beq common_errDivideByZero 6820 .endif 6821 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6822 6823 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6824 GET_INST_OPCODE(ip) @ extract opcode from rINST 6825 SET_VREG(r0, r9) @ vAA<- r0 6826 GOTO_OPCODE(ip) @ jump to next instruction 6827 /* 10-13 instructions */ 6828 6829 6830/* ------------------------------ */ 6831 .balign 64 6832.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6833/* File: armv5te/OP_DIV_INT_LIT16.S */ 6834/* File: armv5te/binopLit16.S */ 6835 /* 6836 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6837 * that specifies an instruction that performs "result = r0 op r1". 6838 * This could be an ARM instruction or a function call. (If the result 6839 * comes back in a register other than r0, you can override "result".) 6840 * 6841 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6842 * vCC (r1). Useful for integer division and modulus. 6843 * 6844 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6845 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6846 */ 6847 /* binop/lit16 vA, vB, #+CCCC */ 6848 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6849 mov r2, rINST, lsr #12 @ r2<- B 6850 mov r9, rINST, lsr #8 @ r9<- A+ 6851 GET_VREG(r0, r2) @ r0<- vB 6852 and r9, r9, #15 6853 .if 1 6854 cmp r1, #0 @ is second operand zero? 6855 beq common_errDivideByZero 6856 .endif 6857 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6858 6859 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6860 GET_INST_OPCODE(ip) @ extract opcode from rINST 6861 SET_VREG(r0, r9) @ vAA<- r0 6862 GOTO_OPCODE(ip) @ jump to next instruction 6863 /* 10-13 instructions */ 6864 6865 6866/* ------------------------------ */ 6867 .balign 64 6868.L_OP_REM_INT_LIT16: /* 0xd4 */ 6869/* File: armv5te/OP_REM_INT_LIT16.S */ 6870/* idivmod returns quotient in r0 and remainder in r1 */ 6871/* File: armv5te/binopLit16.S */ 6872 /* 6873 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6874 * that specifies an instruction that performs "result = r0 op r1". 6875 * This could be an ARM instruction or a function call. (If the result 6876 * comes back in a register other than r0, you can override "result".) 6877 * 6878 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6879 * vCC (r1). Useful for integer division and modulus. 6880 * 6881 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6882 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6883 */ 6884 /* binop/lit16 vA, vB, #+CCCC */ 6885 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6886 mov r2, rINST, lsr #12 @ r2<- B 6887 mov r9, rINST, lsr #8 @ r9<- A+ 6888 GET_VREG(r0, r2) @ r0<- vB 6889 and r9, r9, #15 6890 .if 1 6891 cmp r1, #0 @ is second operand zero? 6892 beq common_errDivideByZero 6893 .endif 6894 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6895 6896 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6897 GET_INST_OPCODE(ip) @ extract opcode from rINST 6898 SET_VREG(r1, r9) @ vAA<- r1 6899 GOTO_OPCODE(ip) @ jump to next instruction 6900 /* 10-13 instructions */ 6901 6902 6903/* ------------------------------ */ 6904 .balign 64 6905.L_OP_AND_INT_LIT16: /* 0xd5 */ 6906/* File: armv5te/OP_AND_INT_LIT16.S */ 6907/* File: armv5te/binopLit16.S */ 6908 /* 6909 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6910 * that specifies an instruction that performs "result = r0 op r1". 6911 * This could be an ARM instruction or a function call. (If the result 6912 * comes back in a register other than r0, you can override "result".) 6913 * 6914 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6915 * vCC (r1). Useful for integer division and modulus. 6916 * 6917 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6918 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6919 */ 6920 /* binop/lit16 vA, vB, #+CCCC */ 6921 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6922 mov r2, rINST, lsr #12 @ r2<- B 6923 mov r9, rINST, lsr #8 @ r9<- A+ 6924 GET_VREG(r0, r2) @ r0<- vB 6925 and r9, r9, #15 6926 .if 0 6927 cmp r1, #0 @ is second operand zero? 6928 beq common_errDivideByZero 6929 .endif 6930 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6931 6932 and r0, r0, r1 @ r0<- op, r0-r3 changed 6933 GET_INST_OPCODE(ip) @ extract opcode from rINST 6934 SET_VREG(r0, r9) @ vAA<- r0 6935 GOTO_OPCODE(ip) @ jump to next instruction 6936 /* 10-13 instructions */ 6937 6938 6939/* ------------------------------ */ 6940 .balign 64 6941.L_OP_OR_INT_LIT16: /* 0xd6 */ 6942/* File: armv5te/OP_OR_INT_LIT16.S */ 6943/* File: armv5te/binopLit16.S */ 6944 /* 6945 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6946 * that specifies an instruction that performs "result = r0 op r1". 6947 * This could be an ARM instruction or a function call. (If the result 6948 * comes back in a register other than r0, you can override "result".) 6949 * 6950 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6951 * vCC (r1). Useful for integer division and modulus. 6952 * 6953 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6954 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6955 */ 6956 /* binop/lit16 vA, vB, #+CCCC */ 6957 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6958 mov r2, rINST, lsr #12 @ r2<- B 6959 mov r9, rINST, lsr #8 @ r9<- A+ 6960 GET_VREG(r0, r2) @ r0<- vB 6961 and r9, r9, #15 6962 .if 0 6963 cmp r1, #0 @ is second operand zero? 6964 beq common_errDivideByZero 6965 .endif 6966 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6967 6968 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6969 GET_INST_OPCODE(ip) @ extract opcode from rINST 6970 SET_VREG(r0, r9) @ vAA<- r0 6971 GOTO_OPCODE(ip) @ jump to next instruction 6972 /* 10-13 instructions */ 6973 6974 6975/* ------------------------------ */ 6976 .balign 64 6977.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6978/* File: armv5te/OP_XOR_INT_LIT16.S */ 6979/* File: armv5te/binopLit16.S */ 6980 /* 6981 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6982 * that specifies an instruction that performs "result = r0 op r1". 6983 * This could be an ARM instruction or a function call. (If the result 6984 * comes back in a register other than r0, you can override "result".) 6985 * 6986 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6987 * vCC (r1). Useful for integer division and modulus. 6988 * 6989 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6990 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6991 */ 6992 /* binop/lit16 vA, vB, #+CCCC */ 6993 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6994 mov r2, rINST, lsr #12 @ r2<- B 6995 mov r9, rINST, lsr #8 @ r9<- A+ 6996 GET_VREG(r0, r2) @ r0<- vB 6997 and r9, r9, #15 6998 .if 0 6999 cmp r1, #0 @ is second operand zero? 7000 beq common_errDivideByZero 7001 .endif 7002 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7003 7004 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7005 GET_INST_OPCODE(ip) @ extract opcode from rINST 7006 SET_VREG(r0, r9) @ vAA<- r0 7007 GOTO_OPCODE(ip) @ jump to next instruction 7008 /* 10-13 instructions */ 7009 7010 7011/* ------------------------------ */ 7012 .balign 64 7013.L_OP_ADD_INT_LIT8: /* 0xd8 */ 7014/* File: armv5te/OP_ADD_INT_LIT8.S */ 7015/* File: armv5te/binopLit8.S */ 7016 /* 7017 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7018 * that specifies an instruction that performs "result = r0 op r1". 7019 * This could be an ARM instruction or a function call. (If the result 7020 * comes back in a register other than r0, you can override "result".) 7021 * 7022 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7023 * vCC (r1). Useful for integer division and modulus. 7024 * 7025 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7026 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7027 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7028 */ 7029 /* binop/lit8 vAA, vBB, #+CC */ 7030 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7031 mov r9, rINST, lsr #8 @ r9<- AA 7032 and r2, r3, #255 @ r2<- BB 7033 GET_VREG(r0, r2) @ r0<- vBB 7034 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7035 .if 0 7036 @cmp r1, #0 @ is second operand zero? 7037 beq common_errDivideByZero 7038 .endif 7039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7040 7041 @ optional op; may set condition codes 7042 add r0, r0, r1 @ r0<- op, r0-r3 changed 7043 GET_INST_OPCODE(ip) @ extract opcode from rINST 7044 SET_VREG(r0, r9) @ vAA<- r0 7045 GOTO_OPCODE(ip) @ jump to next instruction 7046 /* 10-12 instructions */ 7047 7048 7049/* ------------------------------ */ 7050 .balign 64 7051.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 7052/* File: armv5te/OP_RSUB_INT_LIT8.S */ 7053/* File: armv5te/binopLit8.S */ 7054 /* 7055 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7056 * that specifies an instruction that performs "result = r0 op r1". 7057 * This could be an ARM instruction or a function call. (If the result 7058 * comes back in a register other than r0, you can override "result".) 7059 * 7060 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7061 * vCC (r1). Useful for integer division and modulus. 7062 * 7063 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7064 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7065 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7066 */ 7067 /* binop/lit8 vAA, vBB, #+CC */ 7068 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7069 mov r9, rINST, lsr #8 @ r9<- AA 7070 and r2, r3, #255 @ r2<- BB 7071 GET_VREG(r0, r2) @ r0<- vBB 7072 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7073 .if 0 7074 @cmp r1, #0 @ is second operand zero? 7075 beq common_errDivideByZero 7076 .endif 7077 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7078 7079 @ optional op; may set condition codes 7080 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 7081 GET_INST_OPCODE(ip) @ extract opcode from rINST 7082 SET_VREG(r0, r9) @ vAA<- r0 7083 GOTO_OPCODE(ip) @ jump to next instruction 7084 /* 10-12 instructions */ 7085 7086 7087/* ------------------------------ */ 7088 .balign 64 7089.L_OP_MUL_INT_LIT8: /* 0xda */ 7090/* File: armv5te/OP_MUL_INT_LIT8.S */ 7091/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 7092/* File: armv5te/binopLit8.S */ 7093 /* 7094 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7095 * that specifies an instruction that performs "result = r0 op r1". 7096 * This could be an ARM instruction or a function call. (If the result 7097 * comes back in a register other than r0, you can override "result".) 7098 * 7099 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7100 * vCC (r1). Useful for integer division and modulus. 7101 * 7102 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7103 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7104 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7105 */ 7106 /* binop/lit8 vAA, vBB, #+CC */ 7107 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7108 mov r9, rINST, lsr #8 @ r9<- AA 7109 and r2, r3, #255 @ r2<- BB 7110 GET_VREG(r0, r2) @ r0<- vBB 7111 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7112 .if 0 7113 @cmp r1, #0 @ is second operand zero? 7114 beq common_errDivideByZero 7115 .endif 7116 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7117 7118 @ optional op; may set condition codes 7119 mul r0, r1, r0 @ r0<- op, r0-r3 changed 7120 GET_INST_OPCODE(ip) @ extract opcode from rINST 7121 SET_VREG(r0, r9) @ vAA<- r0 7122 GOTO_OPCODE(ip) @ jump to next instruction 7123 /* 10-12 instructions */ 7124 7125 7126/* ------------------------------ */ 7127 .balign 64 7128.L_OP_DIV_INT_LIT8: /* 0xdb */ 7129/* File: armv5te/OP_DIV_INT_LIT8.S */ 7130/* File: armv5te/binopLit8.S */ 7131 /* 7132 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7133 * that specifies an instruction that performs "result = r0 op r1". 7134 * This could be an ARM instruction or a function call. (If the result 7135 * comes back in a register other than r0, you can override "result".) 7136 * 7137 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7138 * vCC (r1). Useful for integer division and modulus. 7139 * 7140 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7141 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7142 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7143 */ 7144 /* binop/lit8 vAA, vBB, #+CC */ 7145 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7146 mov r9, rINST, lsr #8 @ r9<- AA 7147 and r2, r3, #255 @ r2<- BB 7148 GET_VREG(r0, r2) @ r0<- vBB 7149 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7150 .if 1 7151 @cmp r1, #0 @ is second operand zero? 7152 beq common_errDivideByZero 7153 .endif 7154 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7155 7156 @ optional op; may set condition codes 7157 bl __aeabi_idiv @ r0<- op, r0-r3 changed 7158 GET_INST_OPCODE(ip) @ extract opcode from rINST 7159 SET_VREG(r0, r9) @ vAA<- r0 7160 GOTO_OPCODE(ip) @ jump to next instruction 7161 /* 10-12 instructions */ 7162 7163 7164/* ------------------------------ */ 7165 .balign 64 7166.L_OP_REM_INT_LIT8: /* 0xdc */ 7167/* File: armv5te/OP_REM_INT_LIT8.S */ 7168/* idivmod returns quotient in r0 and remainder in r1 */ 7169/* File: armv5te/binopLit8.S */ 7170 /* 7171 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7172 * that specifies an instruction that performs "result = r0 op r1". 7173 * This could be an ARM instruction or a function call. (If the result 7174 * comes back in a register other than r0, you can override "result".) 7175 * 7176 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7177 * vCC (r1). Useful for integer division and modulus. 7178 * 7179 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7180 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7181 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7182 */ 7183 /* binop/lit8 vAA, vBB, #+CC */ 7184 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7185 mov r9, rINST, lsr #8 @ r9<- AA 7186 and r2, r3, #255 @ r2<- BB 7187 GET_VREG(r0, r2) @ r0<- vBB 7188 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7189 .if 1 7190 @cmp r1, #0 @ is second operand zero? 7191 beq common_errDivideByZero 7192 .endif 7193 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7194 7195 @ optional op; may set condition codes 7196 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 7197 GET_INST_OPCODE(ip) @ extract opcode from rINST 7198 SET_VREG(r1, r9) @ vAA<- r1 7199 GOTO_OPCODE(ip) @ jump to next instruction 7200 /* 10-12 instructions */ 7201 7202 7203/* ------------------------------ */ 7204 .balign 64 7205.L_OP_AND_INT_LIT8: /* 0xdd */ 7206/* File: armv5te/OP_AND_INT_LIT8.S */ 7207/* File: armv5te/binopLit8.S */ 7208 /* 7209 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7210 * that specifies an instruction that performs "result = r0 op r1". 7211 * This could be an ARM instruction or a function call. (If the result 7212 * comes back in a register other than r0, you can override "result".) 7213 * 7214 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7215 * vCC (r1). Useful for integer division and modulus. 7216 * 7217 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7218 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7219 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7220 */ 7221 /* binop/lit8 vAA, vBB, #+CC */ 7222 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7223 mov r9, rINST, lsr #8 @ r9<- AA 7224 and r2, r3, #255 @ r2<- BB 7225 GET_VREG(r0, r2) @ r0<- vBB 7226 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7227 .if 0 7228 @cmp r1, #0 @ is second operand zero? 7229 beq common_errDivideByZero 7230 .endif 7231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7232 7233 @ optional op; may set condition codes 7234 and r0, r0, r1 @ r0<- op, r0-r3 changed 7235 GET_INST_OPCODE(ip) @ extract opcode from rINST 7236 SET_VREG(r0, r9) @ vAA<- r0 7237 GOTO_OPCODE(ip) @ jump to next instruction 7238 /* 10-12 instructions */ 7239 7240 7241/* ------------------------------ */ 7242 .balign 64 7243.L_OP_OR_INT_LIT8: /* 0xde */ 7244/* File: armv5te/OP_OR_INT_LIT8.S */ 7245/* File: armv5te/binopLit8.S */ 7246 /* 7247 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7248 * that specifies an instruction that performs "result = r0 op r1". 7249 * This could be an ARM instruction or a function call. (If the result 7250 * comes back in a register other than r0, you can override "result".) 7251 * 7252 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7253 * vCC (r1). Useful for integer division and modulus. 7254 * 7255 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7256 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7257 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7258 */ 7259 /* binop/lit8 vAA, vBB, #+CC */ 7260 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7261 mov r9, rINST, lsr #8 @ r9<- AA 7262 and r2, r3, #255 @ r2<- BB 7263 GET_VREG(r0, r2) @ r0<- vBB 7264 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7265 .if 0 7266 @cmp r1, #0 @ is second operand zero? 7267 beq common_errDivideByZero 7268 .endif 7269 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7270 7271 @ optional op; may set condition codes 7272 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7273 GET_INST_OPCODE(ip) @ extract opcode from rINST 7274 SET_VREG(r0, r9) @ vAA<- r0 7275 GOTO_OPCODE(ip) @ jump to next instruction 7276 /* 10-12 instructions */ 7277 7278 7279/* ------------------------------ */ 7280 .balign 64 7281.L_OP_XOR_INT_LIT8: /* 0xdf */ 7282/* File: armv5te/OP_XOR_INT_LIT8.S */ 7283/* File: armv5te/binopLit8.S */ 7284 /* 7285 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7286 * that specifies an instruction that performs "result = r0 op r1". 7287 * This could be an ARM instruction or a function call. (If the result 7288 * comes back in a register other than r0, you can override "result".) 7289 * 7290 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7291 * vCC (r1). Useful for integer division and modulus. 7292 * 7293 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7294 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7295 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7296 */ 7297 /* binop/lit8 vAA, vBB, #+CC */ 7298 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7299 mov r9, rINST, lsr #8 @ r9<- AA 7300 and r2, r3, #255 @ r2<- BB 7301 GET_VREG(r0, r2) @ r0<- vBB 7302 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7303 .if 0 7304 @cmp r1, #0 @ is second operand zero? 7305 beq common_errDivideByZero 7306 .endif 7307 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7308 7309 @ optional op; may set condition codes 7310 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7311 GET_INST_OPCODE(ip) @ extract opcode from rINST 7312 SET_VREG(r0, r9) @ vAA<- r0 7313 GOTO_OPCODE(ip) @ jump to next instruction 7314 /* 10-12 instructions */ 7315 7316 7317/* ------------------------------ */ 7318 .balign 64 7319.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7320/* File: armv5te/OP_SHL_INT_LIT8.S */ 7321/* File: armv5te/binopLit8.S */ 7322 /* 7323 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7324 * that specifies an instruction that performs "result = r0 op r1". 7325 * This could be an ARM instruction or a function call. (If the result 7326 * comes back in a register other than r0, you can override "result".) 7327 * 7328 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7329 * vCC (r1). Useful for integer division and modulus. 7330 * 7331 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7332 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7333 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7334 */ 7335 /* binop/lit8 vAA, vBB, #+CC */ 7336 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7337 mov r9, rINST, lsr #8 @ r9<- AA 7338 and r2, r3, #255 @ r2<- BB 7339 GET_VREG(r0, r2) @ r0<- vBB 7340 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7341 .if 0 7342 @cmp r1, #0 @ is second operand zero? 7343 beq common_errDivideByZero 7344 .endif 7345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7346 7347 and r1, r1, #31 @ optional op; may set condition codes 7348 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7349 GET_INST_OPCODE(ip) @ extract opcode from rINST 7350 SET_VREG(r0, r9) @ vAA<- r0 7351 GOTO_OPCODE(ip) @ jump to next instruction 7352 /* 10-12 instructions */ 7353 7354 7355/* ------------------------------ */ 7356 .balign 64 7357.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7358/* File: armv5te/OP_SHR_INT_LIT8.S */ 7359/* File: armv5te/binopLit8.S */ 7360 /* 7361 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7362 * that specifies an instruction that performs "result = r0 op r1". 7363 * This could be an ARM instruction or a function call. (If the result 7364 * comes back in a register other than r0, you can override "result".) 7365 * 7366 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7367 * vCC (r1). Useful for integer division and modulus. 7368 * 7369 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7370 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7371 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7372 */ 7373 /* binop/lit8 vAA, vBB, #+CC */ 7374 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7375 mov r9, rINST, lsr #8 @ r9<- AA 7376 and r2, r3, #255 @ r2<- BB 7377 GET_VREG(r0, r2) @ r0<- vBB 7378 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7379 .if 0 7380 @cmp r1, #0 @ is second operand zero? 7381 beq common_errDivideByZero 7382 .endif 7383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7384 7385 and r1, r1, #31 @ optional op; may set condition codes 7386 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7387 GET_INST_OPCODE(ip) @ extract opcode from rINST 7388 SET_VREG(r0, r9) @ vAA<- r0 7389 GOTO_OPCODE(ip) @ jump to next instruction 7390 /* 10-12 instructions */ 7391 7392 7393/* ------------------------------ */ 7394 .balign 64 7395.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7396/* File: armv5te/OP_USHR_INT_LIT8.S */ 7397/* File: armv5te/binopLit8.S */ 7398 /* 7399 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7400 * that specifies an instruction that performs "result = r0 op r1". 7401 * This could be an ARM instruction or a function call. (If the result 7402 * comes back in a register other than r0, you can override "result".) 7403 * 7404 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7405 * vCC (r1). Useful for integer division and modulus. 7406 * 7407 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7408 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7409 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7410 */ 7411 /* binop/lit8 vAA, vBB, #+CC */ 7412 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7413 mov r9, rINST, lsr #8 @ r9<- AA 7414 and r2, r3, #255 @ r2<- BB 7415 GET_VREG(r0, r2) @ r0<- vBB 7416 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7417 .if 0 7418 @cmp r1, #0 @ is second operand zero? 7419 beq common_errDivideByZero 7420 .endif 7421 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7422 7423 and r1, r1, #31 @ optional op; may set condition codes 7424 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7425 GET_INST_OPCODE(ip) @ extract opcode from rINST 7426 SET_VREG(r0, r9) @ vAA<- r0 7427 GOTO_OPCODE(ip) @ jump to next instruction 7428 /* 10-12 instructions */ 7429 7430 7431/* ------------------------------ */ 7432 .balign 64 7433.L_OP_IGET_VOLATILE: /* 0xe3 */ 7434/* File: armv5te/OP_IGET_VOLATILE.S */ 7435/* File: armv5te/OP_IGET.S */ 7436 /* 7437 * General 32-bit instance field get. 7438 * 7439 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7440 */ 7441 /* op vA, vB, field@CCCC */ 7442 mov r0, rINST, lsr #12 @ r0<- B 7443 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7444 FETCH(r1, 1) @ r1<- field ref CCCC 7445 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7446 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7447 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7448 cmp r0, #0 @ is resolved entry null? 7449 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 74508: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7451 EXPORT_PC() @ resolve() could throw 7452 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7453 bl dvmResolveInstField @ r0<- resolved InstField ptr 7454 cmp r0, #0 7455 bne .LOP_IGET_VOLATILE_finish 7456 b common_exceptionThrown 7457 7458 7459/* ------------------------------ */ 7460 .balign 64 7461.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7462/* File: armv5te/OP_IPUT_VOLATILE.S */ 7463/* File: armv5te/OP_IPUT.S */ 7464 /* 7465 * General 32-bit instance field put. 7466 * 7467 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7468 */ 7469 /* op vA, vB, field@CCCC */ 7470 mov r0, rINST, lsr #12 @ r0<- B 7471 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7472 FETCH(r1, 1) @ r1<- field ref CCCC 7473 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7474 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7475 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7476 cmp r0, #0 @ is resolved entry null? 7477 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 74788: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7479 EXPORT_PC() @ resolve() could throw 7480 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7481 bl dvmResolveInstField @ r0<- resolved InstField ptr 7482 cmp r0, #0 @ success? 7483 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7484 b common_exceptionThrown 7485 7486 7487/* ------------------------------ */ 7488 .balign 64 7489.L_OP_SGET_VOLATILE: /* 0xe5 */ 7490/* File: armv5te/OP_SGET_VOLATILE.S */ 7491/* File: armv5te/OP_SGET.S */ 7492 /* 7493 * General 32-bit SGET handler. 7494 * 7495 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7496 */ 7497 /* op vAA, field@BBBB */ 7498 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7499 FETCH(r1, 1) @ r1<- field ref BBBB 7500 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7501 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7502 cmp r0, #0 @ is resolved entry null? 7503 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7504.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7505 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7506 SMP_DMB @ acquiring load 7507 mov r2, rINST, lsr #8 @ r2<- AA 7508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7509 SET_VREG(r1, r2) @ fp[AA]<- r1 7510 GET_INST_OPCODE(ip) @ extract opcode from rINST 7511 GOTO_OPCODE(ip) @ jump to next instruction 7512 7513 7514/* ------------------------------ */ 7515 .balign 64 7516.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7517/* File: armv5te/OP_SPUT_VOLATILE.S */ 7518/* File: armv5te/OP_SPUT.S */ 7519 /* 7520 * General 32-bit SPUT handler. 7521 * 7522 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7523 */ 7524 /* op vAA, field@BBBB */ 7525 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7526 FETCH(r1, 1) @ r1<- field ref BBBB 7527 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7528 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7529 cmp r0, #0 @ is resolved entry null? 7530 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7531.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7532 mov r2, rINST, lsr #8 @ r2<- AA 7533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7534 GET_VREG(r1, r2) @ r1<- fp[AA] 7535 GET_INST_OPCODE(ip) @ extract opcode from rINST 7536 SMP_DMB @ releasing store 7537 str r1, [r0, #offStaticField_value] @ field<- vAA 7538 GOTO_OPCODE(ip) @ jump to next instruction 7539 7540 7541/* ------------------------------ */ 7542 .balign 64 7543.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7544/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7545/* File: armv5te/OP_IGET.S */ 7546 /* 7547 * General 32-bit instance field get. 7548 * 7549 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7550 */ 7551 /* op vA, vB, field@CCCC */ 7552 mov r0, rINST, lsr #12 @ r0<- B 7553 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7554 FETCH(r1, 1) @ r1<- field ref CCCC 7555 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7556 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7557 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7558 cmp r0, #0 @ is resolved entry null? 7559 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 75608: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7561 EXPORT_PC() @ resolve() could throw 7562 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7563 bl dvmResolveInstField @ r0<- resolved InstField ptr 7564 cmp r0, #0 7565 bne .LOP_IGET_OBJECT_VOLATILE_finish 7566 b common_exceptionThrown 7567 7568 7569/* ------------------------------ */ 7570 .balign 64 7571.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7572/* File: armv4t/OP_IGET_WIDE_VOLATILE.S */ 7573/* File: armv4t/OP_IGET_WIDE.S */ 7574 /* 7575 * Wide 32-bit instance field get. 7576 */ 7577 /* iget-wide vA, vB, field@CCCC */ 7578 mov r0, rINST, lsr #12 @ r0<- B 7579 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7580 FETCH(r1, 1) @ r1<- field ref CCCC 7581 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7582 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7583 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7584 cmp r0, #0 @ is resolved entry null? 7585 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 75868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7587 EXPORT_PC() @ resolve() could throw 7588 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7589 bl dvmResolveInstField @ r0<- resolved InstField ptr 7590 cmp r0, #0 7591 bne .LOP_IGET_WIDE_VOLATILE_finish 7592 b common_exceptionThrown 7593 7594 7595/* ------------------------------ */ 7596 .balign 64 7597.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7598/* File: armv4t/OP_IPUT_WIDE_VOLATILE.S */ 7599/* File: armv4t/OP_IPUT_WIDE.S */ 7600 /* iput-wide vA, vB, field@CCCC */ 7601 mov r0, rINST, lsr #12 @ r0<- B 7602 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7603 FETCH(r1, 1) @ r1<- field ref CCCC 7604 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7605 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7606 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7607 cmp r0, #0 @ is resolved entry null? 7608 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 76098: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7610 EXPORT_PC() @ resolve() could throw 7611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7612 bl dvmResolveInstField @ r0<- resolved InstField ptr 7613 cmp r0, #0 @ success? 7614 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7615 b common_exceptionThrown 7616 7617 7618/* ------------------------------ */ 7619 .balign 64 7620.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7621/* File: armv4t/OP_SGET_WIDE_VOLATILE.S */ 7622/* File: armv4t/OP_SGET_WIDE.S */ 7623 /* 7624 * 64-bit SGET handler. 7625 */ 7626 /* sget-wide vAA, field@BBBB */ 7627 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7628 FETCH(r1, 1) @ r1<- field ref BBBB 7629 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7630 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7631 cmp r0, #0 @ is resolved entry null? 7632 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7633.LOP_SGET_WIDE_VOLATILE_finish: 7634 mov r9, rINST, lsr #8 @ r9<- AA 7635 add r0, r0, #offStaticField_value @ r0<- pointer to data 7636 .if 1 7637 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7638 .else 7639 ldmia r0, {r0-r1} @ r0/r1<- field value (aligned) 7640 .endif 7641 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7642 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7643 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7644 GET_INST_OPCODE(ip) @ extract opcode from rINST 7645 GOTO_OPCODE(ip) @ jump to next instruction 7646 7647 7648/* ------------------------------ */ 7649 .balign 64 7650.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7651/* File: armv4t/OP_SPUT_WIDE_VOLATILE.S */ 7652/* File: armv4t/OP_SPUT_WIDE.S */ 7653 /* 7654 * 64-bit SPUT handler. 7655 */ 7656 /* sput-wide vAA, field@BBBB */ 7657 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7658 FETCH(r1, 1) @ r1<- field ref BBBB 7659 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7660 mov r9, rINST, lsr #8 @ r9<- AA 7661 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7662 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7663 cmp r2, #0 @ is resolved entry null? 7664 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7665.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7666 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7667 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7668 GET_INST_OPCODE(r10) @ extract opcode from rINST 7669 add r2, r2, #offStaticField_value @ r2<- pointer to data 7670 .if 1 7671 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7672 .else 7673 stmia r2, {r0-r1} @ field<- vAA/vAA+1 7674 .endif 7675 GOTO_OPCODE(r10) @ jump to next instruction 7676 7677 7678/* ------------------------------ */ 7679 .balign 64 7680.L_OP_BREAKPOINT: /* 0xec */ 7681/* File: armv5te/OP_BREAKPOINT.S */ 7682/* File: armv5te/unused.S */ 7683 bl common_abort 7684 7685 7686/* ------------------------------ */ 7687 .balign 64 7688.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7689/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7690 /* 7691 * Handle a throw-verification-error instruction. This throws an 7692 * exception for an error discovered during verification. The 7693 * exception is indicated by AA, with some detail provided by BBBB. 7694 */ 7695 /* op AA, ref@BBBB */ 7696 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7697 FETCH(r2, 1) @ r2<- BBBB 7698 EXPORT_PC() @ export the PC 7699 mov r1, rINST, lsr #8 @ r1<- AA 7700 bl dvmThrowVerificationError @ always throws 7701 b common_exceptionThrown @ handle exception 7702 7703/* ------------------------------ */ 7704 .balign 64 7705.L_OP_EXECUTE_INLINE: /* 0xee */ 7706/* File: armv5te/OP_EXECUTE_INLINE.S */ 7707 /* 7708 * Execute a "native inline" instruction. 7709 * 7710 * We need to call an InlineOp4Func: 7711 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7712 * 7713 * The first four args are in r0-r3, pointer to return value storage 7714 * is on the stack. The function's return value is a flag that tells 7715 * us if an exception was thrown. 7716 */ 7717 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7718 FETCH(r10, 1) @ r10<- BBBB 7719 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7720 EXPORT_PC() @ can throw 7721 sub sp, sp, #8 @ make room for arg, +64 bit align 7722 mov r0, rINST, lsr #12 @ r0<- B 7723 str r1, [sp] @ push &glue->retval 7724 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7725 add sp, sp, #8 @ pop stack 7726 cmp r0, #0 @ test boolean result of inline 7727 beq common_exceptionThrown @ returned false, handle exception 7728 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7729 GET_INST_OPCODE(ip) @ extract opcode from rINST 7730 GOTO_OPCODE(ip) @ jump to next instruction 7731 7732/* ------------------------------ */ 7733 .balign 64 7734.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7735/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7736 /* 7737 * Execute a "native inline" instruction, using "/range" semantics. 7738 * Same idea as execute-inline, but we get the args differently. 7739 * 7740 * We need to call an InlineOp4Func: 7741 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7742 * 7743 * The first four args are in r0-r3, pointer to return value storage 7744 * is on the stack. The function's return value is a flag that tells 7745 * us if an exception was thrown. 7746 */ 7747 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7748 FETCH(r10, 1) @ r10<- BBBB 7749 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7750 EXPORT_PC() @ can throw 7751 sub sp, sp, #8 @ make room for arg, +64 bit align 7752 mov r0, rINST, lsr #8 @ r0<- AA 7753 str r1, [sp] @ push &glue->retval 7754 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7755 add sp, sp, #8 @ pop stack 7756 cmp r0, #0 @ test boolean result of inline 7757 beq common_exceptionThrown @ returned false, handle exception 7758 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7759 GET_INST_OPCODE(ip) @ extract opcode from rINST 7760 GOTO_OPCODE(ip) @ jump to next instruction 7761 7762/* ------------------------------ */ 7763 .balign 64 7764.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7765/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7766 /* 7767 * invoke-direct-empty is a no-op in a "standard" interpreter. 7768 */ 7769 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7770 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7771 GOTO_OPCODE(ip) @ execute it 7772 7773/* ------------------------------ */ 7774 .balign 64 7775.L_OP_UNUSED_F1: /* 0xf1 */ 7776/* File: armv5te/OP_UNUSED_F1.S */ 7777/* File: armv5te/unused.S */ 7778 bl common_abort 7779 7780 7781/* ------------------------------ */ 7782 .balign 64 7783.L_OP_IGET_QUICK: /* 0xf2 */ 7784/* File: armv5te/OP_IGET_QUICK.S */ 7785 /* For: iget-quick, iget-object-quick */ 7786 /* op vA, vB, offset@CCCC */ 7787 mov r2, rINST, lsr #12 @ r2<- B 7788 GET_VREG(r3, r2) @ r3<- object we're operating on 7789 FETCH(r1, 1) @ r1<- field byte offset 7790 cmp r3, #0 @ check object for null 7791 mov r2, rINST, lsr #8 @ r2<- A(+) 7792 beq common_errNullObject @ object was null 7793 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7794 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7795 and r2, r2, #15 7796 GET_INST_OPCODE(ip) @ extract opcode from rINST 7797 SET_VREG(r0, r2) @ fp[A]<- r0 7798 GOTO_OPCODE(ip) @ jump to next instruction 7799 7800/* ------------------------------ */ 7801 .balign 64 7802.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7803/* File: armv4t/OP_IGET_WIDE_QUICK.S */ 7804 /* iget-wide-quick vA, vB, offset@CCCC */ 7805 mov r2, rINST, lsr #12 @ r2<- B 7806 GET_VREG(r3, r2) @ r3<- object we're operating on 7807 FETCH(r1, 1) @ r1<- field byte offset 7808 cmp r3, #0 @ check object for null 7809 mov r2, rINST, lsr #8 @ r2<- A(+) 7810 beq common_errNullObject @ object was null 7811 add r9, r3, r1 @ r9<- object + offset 7812 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64 bits, aligned) 7813 and r2, r2, #15 @ r2<- A 7814 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7815 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7816 GET_INST_OPCODE(ip) @ extract opcode from rINST 7817 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7818 GOTO_OPCODE(ip) @ jump to next instruction 7819 7820/* ------------------------------ */ 7821 .balign 64 7822.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7823/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7824/* File: armv5te/OP_IGET_QUICK.S */ 7825 /* For: iget-quick, iget-object-quick */ 7826 /* op vA, vB, offset@CCCC */ 7827 mov r2, rINST, lsr #12 @ r2<- B 7828 GET_VREG(r3, r2) @ r3<- object we're operating on 7829 FETCH(r1, 1) @ r1<- field byte offset 7830 cmp r3, #0 @ check object for null 7831 mov r2, rINST, lsr #8 @ r2<- A(+) 7832 beq common_errNullObject @ object was null 7833 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7834 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7835 and r2, r2, #15 7836 GET_INST_OPCODE(ip) @ extract opcode from rINST 7837 SET_VREG(r0, r2) @ fp[A]<- r0 7838 GOTO_OPCODE(ip) @ jump to next instruction 7839 7840 7841/* ------------------------------ */ 7842 .balign 64 7843.L_OP_IPUT_QUICK: /* 0xf5 */ 7844/* File: armv5te/OP_IPUT_QUICK.S */ 7845 /* For: iput-quick */ 7846 /* op vA, vB, offset@CCCC */ 7847 mov r2, rINST, lsr #12 @ r2<- B 7848 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7849 FETCH(r1, 1) @ r1<- field byte offset 7850 cmp r3, #0 @ check object for null 7851 mov r2, rINST, lsr #8 @ r2<- A(+) 7852 beq common_errNullObject @ object was null 7853 and r2, r2, #15 7854 GET_VREG(r0, r2) @ r0<- fp[A] 7855 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7856 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7857 GET_INST_OPCODE(ip) @ extract opcode from rINST 7858 GOTO_OPCODE(ip) @ jump to next instruction 7859 7860/* ------------------------------ */ 7861 .balign 64 7862.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7863/* File: armv4t/OP_IPUT_WIDE_QUICK.S */ 7864 /* iput-wide-quick vA, vB, offset@CCCC */ 7865 mov r0, rINST, lsr #8 @ r0<- A(+) 7866 mov r1, rINST, lsr #12 @ r1<- B 7867 and r0, r0, #15 7868 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7869 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7870 cmp r2, #0 @ check object for null 7871 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7872 beq common_errNullObject @ object was null 7873 FETCH(r3, 1) @ r3<- field byte offset 7874 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7875 add r2, r2, r3 @ r2<- object + byte offset 7876 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1 7877 GET_INST_OPCODE(ip) @ extract opcode from rINST 7878 GOTO_OPCODE(ip) @ jump to next instruction 7879 7880/* ------------------------------ */ 7881 .balign 64 7882.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7883/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7884 /* For: iput-object-quick */ 7885 /* op vA, vB, offset@CCCC */ 7886 mov r2, rINST, lsr #12 @ r2<- B 7887 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7888 FETCH(r1, 1) @ r1<- field byte offset 7889 cmp r3, #0 @ check object for null 7890 mov r2, rINST, lsr #8 @ r2<- A(+) 7891 beq common_errNullObject @ object was null 7892 and r2, r2, #15 7893 GET_VREG(r0, r2) @ r0<- fp[A] 7894 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7895 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7896 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7897 cmp r0, #0 7898 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7899 GET_INST_OPCODE(ip) @ extract opcode from rINST 7900 GOTO_OPCODE(ip) @ jump to next instruction 7901 7902/* ------------------------------ */ 7903 .balign 64 7904.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7905/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7906 /* 7907 * Handle an optimized virtual method call. 7908 * 7909 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7910 */ 7911 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7912 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7913 FETCH(r3, 2) @ r3<- FEDC or CCCC 7914 FETCH(r1, 1) @ r1<- BBBB 7915 .if (!0) 7916 and r3, r3, #15 @ r3<- C (or stays CCCC) 7917 .endif 7918 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7919 cmp r2, #0 @ is "this" null? 7920 beq common_errNullObject @ null "this", throw exception 7921 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7922 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7923 EXPORT_PC() @ invoke must export 7924 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7925 bl common_invokeMethodNoRange @ continue on 7926 7927/* ------------------------------ */ 7928 .balign 64 7929.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7930/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7931/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7932 /* 7933 * Handle an optimized virtual method call. 7934 * 7935 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7936 */ 7937 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7938 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7939 FETCH(r3, 2) @ r3<- FEDC or CCCC 7940 FETCH(r1, 1) @ r1<- BBBB 7941 .if (!1) 7942 and r3, r3, #15 @ r3<- C (or stays CCCC) 7943 .endif 7944 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7945 cmp r2, #0 @ is "this" null? 7946 beq common_errNullObject @ null "this", throw exception 7947 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7948 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7949 EXPORT_PC() @ invoke must export 7950 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7951 bl common_invokeMethodRange @ continue on 7952 7953 7954/* ------------------------------ */ 7955 .balign 64 7956.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7957/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7958 /* 7959 * Handle an optimized "super" method call. 7960 * 7961 * for: [opt] invoke-super-quick, invoke-super-quick/range 7962 */ 7963 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7964 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7965 FETCH(r10, 2) @ r10<- GFED or CCCC 7966 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7967 .if (!0) 7968 and r10, r10, #15 @ r10<- D (or stays CCCC) 7969 .endif 7970 FETCH(r1, 1) @ r1<- BBBB 7971 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7972 EXPORT_PC() @ must export for invoke 7973 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7974 GET_VREG(r3, r10) @ r3<- "this" 7975 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7976 cmp r3, #0 @ null "this" ref? 7977 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7978 beq common_errNullObject @ "this" is null, throw exception 7979 bl common_invokeMethodNoRange @ continue on 7980 7981/* ------------------------------ */ 7982 .balign 64 7983.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7984/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7985/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7986 /* 7987 * Handle an optimized "super" method call. 7988 * 7989 * for: [opt] invoke-super-quick, invoke-super-quick/range 7990 */ 7991 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7992 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7993 FETCH(r10, 2) @ r10<- GFED or CCCC 7994 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7995 .if (!1) 7996 and r10, r10, #15 @ r10<- D (or stays CCCC) 7997 .endif 7998 FETCH(r1, 1) @ r1<- BBBB 7999 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 8000 EXPORT_PC() @ must export for invoke 8001 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 8002 GET_VREG(r3, r10) @ r3<- "this" 8003 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 8004 cmp r3, #0 @ null "this" ref? 8005 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 8006 beq common_errNullObject @ "this" is null, throw exception 8007 bl common_invokeMethodRange @ continue on 8008 8009 8010/* ------------------------------ */ 8011 .balign 64 8012.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 8013/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 8014/* File: armv5te/OP_IPUT_OBJECT.S */ 8015 /* 8016 * 32-bit instance field put. 8017 * 8018 * for: iput-object, iput-object-volatile 8019 */ 8020 /* op vA, vB, field@CCCC */ 8021 mov r0, rINST, lsr #12 @ r0<- B 8022 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8023 FETCH(r1, 1) @ r1<- field ref CCCC 8024 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8025 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 8026 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8027 cmp r0, #0 @ is resolved entry null? 8028 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 80298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8030 EXPORT_PC() @ resolve() could throw 8031 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8032 bl dvmResolveInstField @ r0<- resolved InstField ptr 8033 cmp r0, #0 @ success? 8034 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 8035 b common_exceptionThrown 8036 8037 8038/* ------------------------------ */ 8039 .balign 64 8040.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 8041/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 8042/* File: armv5te/OP_SGET.S */ 8043 /* 8044 * General 32-bit SGET handler. 8045 * 8046 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 8047 */ 8048 /* op vAA, field@BBBB */ 8049 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8050 FETCH(r1, 1) @ r1<- field ref BBBB 8051 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8052 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8053 cmp r0, #0 @ is resolved entry null? 8054 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 8055.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 8056 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8057 SMP_DMB @ acquiring load 8058 mov r2, rINST, lsr #8 @ r2<- AA 8059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8060 SET_VREG(r1, r2) @ fp[AA]<- r1 8061 GET_INST_OPCODE(ip) @ extract opcode from rINST 8062 GOTO_OPCODE(ip) @ jump to next instruction 8063 8064 8065/* ------------------------------ */ 8066 .balign 64 8067.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 8068/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 8069/* File: armv5te/OP_SPUT_OBJECT.S */ 8070 /* 8071 * 32-bit SPUT handler for objects 8072 * 8073 * for: sput-object, sput-object-volatile 8074 */ 8075 /* op vAA, field@BBBB */ 8076 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8077 FETCH(r1, 1) @ r1<- field ref BBBB 8078 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8079 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8080 cmp r0, #0 @ is resolved entry null? 8081 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 8082 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8083 EXPORT_PC() @ resolve() could throw, so export now 8084 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 8085 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8086 cmp r0, #0 @ success? 8087 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 8088 b common_exceptionThrown @ no, handle exception 8089 8090 8091 8092/* ------------------------------ */ 8093 .balign 64 8094.L_OP_UNUSED_FF: /* 0xff */ 8095/* File: armv5te/OP_UNUSED_FF.S */ 8096/* File: armv5te/unused.S */ 8097 bl common_abort 8098 8099 8100 8101 .balign 64 8102 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 8103 .global dvmAsmInstructionEnd 8104dvmAsmInstructionEnd: 8105 8106/* 8107 * =========================================================================== 8108 * Sister implementations 8109 * =========================================================================== 8110 */ 8111 .global dvmAsmSisterStart 8112 .type dvmAsmSisterStart, %function 8113 .text 8114 .balign 4 8115dvmAsmSisterStart: 8116 8117/* continuation for OP_CONST_STRING */ 8118 8119 /* 8120 * Continuation if the String has not yet been resolved. 8121 * r1: BBBB (String ref) 8122 * r9: target register 8123 */ 8124.LOP_CONST_STRING_resolve: 8125 EXPORT_PC() 8126 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8127 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8128 bl dvmResolveString @ r0<- String reference 8129 cmp r0, #0 @ failed? 8130 beq common_exceptionThrown @ yup, handle the exception 8131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8132 GET_INST_OPCODE(ip) @ extract opcode from rINST 8133 SET_VREG(r0, r9) @ vAA<- r0 8134 GOTO_OPCODE(ip) @ jump to next instruction 8135 8136/* continuation for OP_CONST_STRING_JUMBO */ 8137 8138 /* 8139 * Continuation if the String has not yet been resolved. 8140 * r1: BBBBBBBB (String ref) 8141 * r9: target register 8142 */ 8143.LOP_CONST_STRING_JUMBO_resolve: 8144 EXPORT_PC() 8145 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8146 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8147 bl dvmResolveString @ r0<- String reference 8148 cmp r0, #0 @ failed? 8149 beq common_exceptionThrown @ yup, handle the exception 8150 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 8151 GET_INST_OPCODE(ip) @ extract opcode from rINST 8152 SET_VREG(r0, r9) @ vAA<- r0 8153 GOTO_OPCODE(ip) @ jump to next instruction 8154 8155/* continuation for OP_CONST_CLASS */ 8156 8157 /* 8158 * Continuation if the Class has not yet been resolved. 8159 * r1: BBBB (Class ref) 8160 * r9: target register 8161 */ 8162.LOP_CONST_CLASS_resolve: 8163 EXPORT_PC() 8164 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8165 mov r2, #1 @ r2<- true 8166 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8167 bl dvmResolveClass @ r0<- Class reference 8168 cmp r0, #0 @ failed? 8169 beq common_exceptionThrown @ yup, handle the exception 8170 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8171 GET_INST_OPCODE(ip) @ extract opcode from rINST 8172 SET_VREG(r0, r9) @ vAA<- r0 8173 GOTO_OPCODE(ip) @ jump to next instruction 8174 8175/* continuation for OP_CHECK_CAST */ 8176 8177 /* 8178 * Trivial test failed, need to perform full check. This is common. 8179 * r0 holds obj->clazz 8180 * r1 holds class resolved from BBBB 8181 * r9 holds object 8182 */ 8183.LOP_CHECK_CAST_fullcheck: 8184 bl dvmInstanceofNonTrivial @ r0<- boolean result 8185 cmp r0, #0 @ failed? 8186 bne .LOP_CHECK_CAST_okay @ no, success 8187 8188 @ A cast has failed. We need to throw a ClassCastException with the 8189 @ class of the object that failed to be cast. 8190 EXPORT_PC() @ about to throw 8191 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 8192 ldr r0, .LstrClassCastExceptionPtr 8193 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 8194 bl dvmThrowExceptionWithClassMessage 8195 b common_exceptionThrown 8196 8197 /* 8198 * Resolution required. This is the least-likely path. 8199 * 8200 * r2 holds BBBB 8201 * r9 holds object 8202 */ 8203.LOP_CHECK_CAST_resolve: 8204 EXPORT_PC() @ resolve() could throw 8205 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8206 mov r1, r2 @ r1<- BBBB 8207 mov r2, #0 @ r2<- false 8208 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8209 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8210 cmp r0, #0 @ got null? 8211 beq common_exceptionThrown @ yes, handle exception 8212 mov r1, r0 @ r1<- class resolved from BBB 8213 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8214 b .LOP_CHECK_CAST_resolved @ pick up where we left off 8215 8216.LstrClassCastExceptionPtr: 8217 .word .LstrClassCastException 8218 8219/* continuation for OP_INSTANCE_OF */ 8220 8221 /* 8222 * Trivial test failed, need to perform full check. This is common. 8223 * r0 holds obj->clazz 8224 * r1 holds class resolved from BBBB 8225 * r9 holds A 8226 */ 8227.LOP_INSTANCE_OF_fullcheck: 8228 bl dvmInstanceofNonTrivial @ r0<- boolean result 8229 @ fall through to OP_INSTANCE_OF_store 8230 8231 /* 8232 * r0 holds boolean result 8233 * r9 holds A 8234 */ 8235.LOP_INSTANCE_OF_store: 8236 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8237 SET_VREG(r0, r9) @ vA<- r0 8238 GET_INST_OPCODE(ip) @ extract opcode from rINST 8239 GOTO_OPCODE(ip) @ jump to next instruction 8240 8241 /* 8242 * Trivial test succeeded, save and bail. 8243 * r9 holds A 8244 */ 8245.LOP_INSTANCE_OF_trivial: 8246 mov r0, #1 @ indicate success 8247 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 8248 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8249 SET_VREG(r0, r9) @ vA<- r0 8250 GET_INST_OPCODE(ip) @ extract opcode from rINST 8251 GOTO_OPCODE(ip) @ jump to next instruction 8252 8253 /* 8254 * Resolution required. This is the least-likely path. 8255 * 8256 * r3 holds BBBB 8257 * r9 holds A 8258 */ 8259.LOP_INSTANCE_OF_resolve: 8260 EXPORT_PC() @ resolve() could throw 8261 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8262 mov r1, r3 @ r1<- BBBB 8263 mov r2, #1 @ r2<- true 8264 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8265 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8266 cmp r0, #0 @ got null? 8267 beq common_exceptionThrown @ yes, handle exception 8268 mov r1, r0 @ r1<- class resolved from BBB 8269 mov r3, rINST, lsr #12 @ r3<- B 8270 GET_VREG(r0, r3) @ r0<- vB (object) 8271 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 8272 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 8273 8274/* continuation for OP_NEW_INSTANCE */ 8275 8276 .balign 32 @ minimize cache lines 8277.LOP_NEW_INSTANCE_finish: @ r0=new object 8278 mov r3, rINST, lsr #8 @ r3<- AA 8279 cmp r0, #0 @ failed? 8280 beq common_exceptionThrown @ yes, handle the exception 8281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8282 GET_INST_OPCODE(ip) @ extract opcode from rINST 8283 SET_VREG(r0, r3) @ vAA<- r0 8284 GOTO_OPCODE(ip) @ jump to next instruction 8285 8286 /* 8287 * Class initialization required. 8288 * 8289 * r0 holds class object 8290 */ 8291.LOP_NEW_INSTANCE_needinit: 8292 mov r9, r0 @ save r0 8293 bl dvmInitClass @ initialize class 8294 cmp r0, #0 @ check boolean result 8295 mov r0, r9 @ restore r0 8296 bne .LOP_NEW_INSTANCE_initialized @ success, continue 8297 b common_exceptionThrown @ failed, deal with init exception 8298 8299 /* 8300 * Resolution required. This is the least-likely path. 8301 * 8302 * r1 holds BBBB 8303 */ 8304.LOP_NEW_INSTANCE_resolve: 8305 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8306 mov r2, #0 @ r2<- false 8307 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8308 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8309 cmp r0, #0 @ got null? 8310 bne .LOP_NEW_INSTANCE_resolved @ no, continue 8311 b common_exceptionThrown @ yes, handle exception 8312 8313.LstrInstantiationErrorPtr: 8314 .word .LstrInstantiationError 8315 8316/* continuation for OP_NEW_ARRAY */ 8317 8318 8319 /* 8320 * Resolve class. (This is an uncommon case.) 8321 * 8322 * r1 holds array length 8323 * r2 holds class ref CCCC 8324 */ 8325.LOP_NEW_ARRAY_resolve: 8326 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8327 mov r9, r1 @ r9<- length (save) 8328 mov r1, r2 @ r1<- CCCC 8329 mov r2, #0 @ r2<- false 8330 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8331 bl dvmResolveClass @ r0<- call(clazz, ref) 8332 cmp r0, #0 @ got null? 8333 mov r1, r9 @ r1<- length (restore) 8334 beq common_exceptionThrown @ yes, handle exception 8335 @ fall through to OP_NEW_ARRAY_finish 8336 8337 /* 8338 * Finish allocation. 8339 * 8340 * r0 holds class 8341 * r1 holds array length 8342 */ 8343.LOP_NEW_ARRAY_finish: 8344 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8345 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8346 cmp r0, #0 @ failed? 8347 mov r2, rINST, lsr #8 @ r2<- A+ 8348 beq common_exceptionThrown @ yes, handle the exception 8349 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8350 and r2, r2, #15 @ r2<- A 8351 GET_INST_OPCODE(ip) @ extract opcode from rINST 8352 SET_VREG(r0, r2) @ vA<- r0 8353 GOTO_OPCODE(ip) @ jump to next instruction 8354 8355/* continuation for OP_FILLED_NEW_ARRAY */ 8356 8357 /* 8358 * On entry: 8359 * r0 holds array class 8360 * r10 holds AA or BA 8361 */ 8362.LOP_FILLED_NEW_ARRAY_continue: 8363 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8364 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8365 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8366 .if 0 8367 mov r1, r10 @ r1<- AA (length) 8368 .else 8369 mov r1, r10, lsr #4 @ r1<- B (length) 8370 .endif 8371 cmp rINST, #'I' @ array of ints? 8372 cmpne rINST, #'L' @ array of objects? 8373 cmpne rINST, #'[' @ array of arrays? 8374 mov r9, r1 @ save length in r9 8375 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8376 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8377 cmp r0, #0 @ null return? 8378 beq common_exceptionThrown @ alloc failed, handle exception 8379 8380 FETCH(r1, 2) @ r1<- FEDC or CCCC 8381 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8382 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8383 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8384 subs r9, r9, #1 @ length--, check for neg 8385 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8386 bmi 2f @ was zero, bail 8387 8388 @ copy values from registers into the array 8389 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8390 .if 0 8391 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 83921: ldr r3, [r2], #4 @ r3<- *r2++ 8393 subs r9, r9, #1 @ count-- 8394 str r3, [r0], #4 @ *contents++ = vX 8395 bpl 1b 8396 @ continue at 2 8397 .else 8398 cmp r9, #4 @ length was initially 5? 8399 and r2, r10, #15 @ r2<- A 8400 bne 1f @ <= 4 args, branch 8401 GET_VREG(r3, r2) @ r3<- vA 8402 sub r9, r9, #1 @ count-- 8403 str r3, [r0, #16] @ contents[4] = vA 84041: and r2, r1, #15 @ r2<- F/E/D/C 8405 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8406 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8407 subs r9, r9, #1 @ count-- 8408 str r3, [r0], #4 @ *contents++ = vX 8409 bpl 1b 8410 @ continue at 2 8411 .endif 8412 84132: 8414 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8415 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8416 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8417 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8418 cmp r1, #'I' @ Is int array? 8419 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8420 GOTO_OPCODE(ip) @ execute it 8421 8422 /* 8423 * Throw an exception indicating that we have not implemented this 8424 * mode of filled-new-array. 8425 */ 8426.LOP_FILLED_NEW_ARRAY_notimpl: 8427 ldr r0, .L_strInternalError 8428 ldr r1, .L_strFilledNewArrayNotImpl 8429 bl dvmThrowException 8430 b common_exceptionThrown 8431 8432 .if (!0) @ define in one or the other, not both 8433.L_strFilledNewArrayNotImpl: 8434 .word .LstrFilledNewArrayNotImpl 8435.L_strInternalError: 8436 .word .LstrInternalError 8437 .endif 8438 8439/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8440 8441 /* 8442 * On entry: 8443 * r0 holds array class 8444 * r10 holds AA or BA 8445 */ 8446.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8447 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8448 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8449 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8450 .if 1 8451 mov r1, r10 @ r1<- AA (length) 8452 .else 8453 mov r1, r10, lsr #4 @ r1<- B (length) 8454 .endif 8455 cmp rINST, #'I' @ array of ints? 8456 cmpne rINST, #'L' @ array of objects? 8457 cmpne rINST, #'[' @ array of arrays? 8458 mov r9, r1 @ save length in r9 8459 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8460 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8461 cmp r0, #0 @ null return? 8462 beq common_exceptionThrown @ alloc failed, handle exception 8463 8464 FETCH(r1, 2) @ r1<- FEDC or CCCC 8465 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8466 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8467 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8468 subs r9, r9, #1 @ length--, check for neg 8469 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8470 bmi 2f @ was zero, bail 8471 8472 @ copy values from registers into the array 8473 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8474 .if 1 8475 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 84761: ldr r3, [r2], #4 @ r3<- *r2++ 8477 subs r9, r9, #1 @ count-- 8478 str r3, [r0], #4 @ *contents++ = vX 8479 bpl 1b 8480 @ continue at 2 8481 .else 8482 cmp r9, #4 @ length was initially 5? 8483 and r2, r10, #15 @ r2<- A 8484 bne 1f @ <= 4 args, branch 8485 GET_VREG(r3, r2) @ r3<- vA 8486 sub r9, r9, #1 @ count-- 8487 str r3, [r0, #16] @ contents[4] = vA 84881: and r2, r1, #15 @ r2<- F/E/D/C 8489 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8490 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8491 subs r9, r9, #1 @ count-- 8492 str r3, [r0], #4 @ *contents++ = vX 8493 bpl 1b 8494 @ continue at 2 8495 .endif 8496 84972: 8498 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8499 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8500 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8501 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8502 cmp r1, #'I' @ Is int array? 8503 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8504 GOTO_OPCODE(ip) @ execute it 8505 8506 /* 8507 * Throw an exception indicating that we have not implemented this 8508 * mode of filled-new-array. 8509 */ 8510.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8511 ldr r0, .L_strInternalError 8512 ldr r1, .L_strFilledNewArrayNotImpl 8513 bl dvmThrowException 8514 b common_exceptionThrown 8515 8516 .if (!1) @ define in one or the other, not both 8517.L_strFilledNewArrayNotImpl: 8518 .word .LstrFilledNewArrayNotImpl 8519.L_strInternalError: 8520 .word .LstrInternalError 8521 .endif 8522 8523/* continuation for OP_CMPL_FLOAT */ 8524 8525 @ Test for NaN with a second comparison. EABI forbids testing bit 8526 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8527 @ make the library call. 8528.LOP_CMPL_FLOAT_gt_or_nan: 8529 mov r1, r9 @ reverse order 8530 mov r0, r10 8531 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8532 @bleq common_abort 8533 movcc r1, #1 @ (greater than) r1<- 1 8534 bcc .LOP_CMPL_FLOAT_finish 8535 mvn r1, #0 @ r1<- 1 or -1 for NaN 8536 b .LOP_CMPL_FLOAT_finish 8537 8538 8539#if 0 /* "clasic" form */ 8540 FETCH(r0, 1) @ r0<- CCBB 8541 and r2, r0, #255 @ r2<- BB 8542 mov r3, r0, lsr #8 @ r3<- CC 8543 GET_VREG(r9, r2) @ r9<- vBB 8544 GET_VREG(r10, r3) @ r10<- vCC 8545 mov r0, r9 @ r0<- vBB 8546 mov r1, r10 @ r1<- vCC 8547 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8548 cmp r0, #0 @ equal? 8549 movne r1, #0 @ yes, result is 0 8550 bne OP_CMPL_FLOAT_finish 8551 mov r0, r9 @ r0<- vBB 8552 mov r1, r10 @ r1<- vCC 8553 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8554 cmp r0, #0 @ less than? 8555 b OP_CMPL_FLOAT_continue 8556@%break 8557 8558OP_CMPL_FLOAT_continue: 8559 mvnne r1, #0 @ yes, result is -1 8560 bne OP_CMPL_FLOAT_finish 8561 mov r0, r9 @ r0<- vBB 8562 mov r1, r10 @ r1<- vCC 8563 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8564 cmp r0, #0 @ greater than? 8565 beq OP_CMPL_FLOAT_nan @ no, must be NaN 8566 mov r1, #1 @ yes, result is 1 8567 @ fall through to _finish 8568 8569OP_CMPL_FLOAT_finish: 8570 mov r3, rINST, lsr #8 @ r3<- AA 8571 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8572 SET_VREG(r1, r3) @ vAA<- r1 8573 GET_INST_OPCODE(ip) @ extract opcode from rINST 8574 GOTO_OPCODE(ip) @ jump to next instruction 8575 8576 /* 8577 * This is expected to be uncommon, so we double-branch (once to here, 8578 * again back to _finish). 8579 */ 8580OP_CMPL_FLOAT_nan: 8581 mvn r1, #0 @ r1<- 1 or -1 for NaN 8582 b OP_CMPL_FLOAT_finish 8583 8584#endif 8585 8586/* continuation for OP_CMPG_FLOAT */ 8587 8588 @ Test for NaN with a second comparison. EABI forbids testing bit 8589 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8590 @ make the library call. 8591.LOP_CMPG_FLOAT_gt_or_nan: 8592 mov r1, r9 @ reverse order 8593 mov r0, r10 8594 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8595 @bleq common_abort 8596 movcc r1, #1 @ (greater than) r1<- 1 8597 bcc .LOP_CMPG_FLOAT_finish 8598 mov r1, #1 @ r1<- 1 or -1 for NaN 8599 b .LOP_CMPG_FLOAT_finish 8600 8601 8602#if 0 /* "clasic" form */ 8603 FETCH(r0, 1) @ r0<- CCBB 8604 and r2, r0, #255 @ r2<- BB 8605 mov r3, r0, lsr #8 @ r3<- CC 8606 GET_VREG(r9, r2) @ r9<- vBB 8607 GET_VREG(r10, r3) @ r10<- vCC 8608 mov r0, r9 @ r0<- vBB 8609 mov r1, r10 @ r1<- vCC 8610 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8611 cmp r0, #0 @ equal? 8612 movne r1, #0 @ yes, result is 0 8613 bne OP_CMPG_FLOAT_finish 8614 mov r0, r9 @ r0<- vBB 8615 mov r1, r10 @ r1<- vCC 8616 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8617 cmp r0, #0 @ less than? 8618 b OP_CMPG_FLOAT_continue 8619@%break 8620 8621OP_CMPG_FLOAT_continue: 8622 mvnne r1, #0 @ yes, result is -1 8623 bne OP_CMPG_FLOAT_finish 8624 mov r0, r9 @ r0<- vBB 8625 mov r1, r10 @ r1<- vCC 8626 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8627 cmp r0, #0 @ greater than? 8628 beq OP_CMPG_FLOAT_nan @ no, must be NaN 8629 mov r1, #1 @ yes, result is 1 8630 @ fall through to _finish 8631 8632OP_CMPG_FLOAT_finish: 8633 mov r3, rINST, lsr #8 @ r3<- AA 8634 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8635 SET_VREG(r1, r3) @ vAA<- r1 8636 GET_INST_OPCODE(ip) @ extract opcode from rINST 8637 GOTO_OPCODE(ip) @ jump to next instruction 8638 8639 /* 8640 * This is expected to be uncommon, so we double-branch (once to here, 8641 * again back to _finish). 8642 */ 8643OP_CMPG_FLOAT_nan: 8644 mov r1, #1 @ r1<- 1 or -1 for NaN 8645 b OP_CMPG_FLOAT_finish 8646 8647#endif 8648 8649/* continuation for OP_CMPL_DOUBLE */ 8650 8651 @ Test for NaN with a second comparison. EABI forbids testing bit 8652 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8653 @ make the library call. 8654.LOP_CMPL_DOUBLE_gt_or_nan: 8655 ldmia r10, {r0-r1} @ reverse order 8656 ldmia r9, {r2-r3} 8657 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8658 @bleq common_abort 8659 movcc r1, #1 @ (greater than) r1<- 1 8660 bcc .LOP_CMPL_DOUBLE_finish 8661 mvn r1, #0 @ r1<- 1 or -1 for NaN 8662 b .LOP_CMPL_DOUBLE_finish 8663 8664/* continuation for OP_CMPG_DOUBLE */ 8665 8666 @ Test for NaN with a second comparison. EABI forbids testing bit 8667 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8668 @ make the library call. 8669.LOP_CMPG_DOUBLE_gt_or_nan: 8670 ldmia r10, {r0-r1} @ reverse order 8671 ldmia r9, {r2-r3} 8672 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8673 @bleq common_abort 8674 movcc r1, #1 @ (greater than) r1<- 1 8675 bcc .LOP_CMPG_DOUBLE_finish 8676 mov r1, #1 @ r1<- 1 or -1 for NaN 8677 b .LOP_CMPG_DOUBLE_finish 8678 8679/* continuation for OP_CMP_LONG */ 8680 8681.LOP_CMP_LONG_less: 8682 mvn r1, #0 @ r1<- -1 8683 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8684 @ instead, we just replicate the tail end. 8685 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8686 SET_VREG(r1, r9) @ vAA<- r1 8687 GET_INST_OPCODE(ip) @ extract opcode from rINST 8688 GOTO_OPCODE(ip) @ jump to next instruction 8689 8690.LOP_CMP_LONG_greater: 8691 mov r1, #1 @ r1<- 1 8692 @ fall through to _finish 8693 8694.LOP_CMP_LONG_finish: 8695 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8696 SET_VREG(r1, r9) @ vAA<- r1 8697 GET_INST_OPCODE(ip) @ extract opcode from rINST 8698 GOTO_OPCODE(ip) @ jump to next instruction 8699 8700/* continuation for OP_AGET_WIDE */ 8701 8702.LOP_AGET_WIDE_finish: 8703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8704 add r0, r0, #offArrayObject_contents 8705 ldmia r0, {r2-r3} @ r2/r3 <- vBB[vCC] 8706 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8707 GET_INST_OPCODE(ip) @ extract opcode from rINST 8708 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8709 GOTO_OPCODE(ip) @ jump to next instruction 8710 8711/* continuation for OP_APUT_WIDE */ 8712 8713.LOP_APUT_WIDE_finish: 8714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8715 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8716 GET_INST_OPCODE(ip) @ extract opcode from rINST 8717 add r0, #offArrayObject_contents 8718 stmia r0, {r2-r3} @ vBB[vCC] <- r2/r3 8719 GOTO_OPCODE(ip) @ jump to next instruction 8720 8721/* continuation for OP_APUT_OBJECT */ 8722 /* 8723 * On entry: 8724 * rINST = vBB (arrayObj) 8725 * r9 = vAA (obj) 8726 * r10 = offset into array (vBB + vCC * width) 8727 */ 8728.LOP_APUT_OBJECT_finish: 8729 cmp r9, #0 @ storing null reference? 8730 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8731 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8732 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8733 bl dvmCanPutArrayElement @ test object type vs. array type 8734 cmp r0, #0 @ okay? 8735 beq common_errArrayStore @ no 8736 mov r1, rINST @ r1<- arrayObj 8737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8738 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8739 add r10, #offArrayObject_contents @ r0<- pointer to slot 8740 GET_INST_OPCODE(ip) @ extract opcode from rINST 8741 str r9, [r10] @ vBB[vCC]<- vAA 8742 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8743 GOTO_OPCODE(ip) @ jump to next instruction 8744.LOP_APUT_OBJECT_skip_check: 8745 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8746 GET_INST_OPCODE(ip) @ extract opcode from rINST 8747 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8748 GOTO_OPCODE(ip) @ jump to next instruction 8749 8750/* continuation for OP_IGET */ 8751 8752 /* 8753 * Currently: 8754 * r0 holds resolved field 8755 * r9 holds object 8756 */ 8757.LOP_IGET_finish: 8758 @bl common_squeak0 8759 cmp r9, #0 @ check object for null 8760 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8761 beq common_errNullObject @ object was null 8762 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8763 @ no-op @ acquiring load 8764 mov r2, rINST, lsr #8 @ r2<- A+ 8765 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8766 and r2, r2, #15 @ r2<- A 8767 GET_INST_OPCODE(ip) @ extract opcode from rINST 8768 SET_VREG(r0, r2) @ fp[A]<- r0 8769 GOTO_OPCODE(ip) @ jump to next instruction 8770 8771/* continuation for OP_IGET_WIDE */ 8772 8773 /* 8774 * Currently: 8775 * r0 holds resolved field 8776 * r9 holds object 8777 */ 8778.LOP_IGET_WIDE_finish: 8779 cmp r9, #0 @ check object for null 8780 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8781 beq common_errNullObject @ object was null 8782 .if 0 8783 add r0, r9, r3 @ r0<- address of field 8784 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8785 .else 8786 add r9, r9, r3 @ r9<- obj + field offset 8787 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok) 8788 .endif 8789 mov r2, rINST, lsr #8 @ r2<- A+ 8790 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8791 and r2, r2, #15 @ r2<- A 8792 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8793 GET_INST_OPCODE(ip) @ extract opcode from rINST 8794 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8795 GOTO_OPCODE(ip) @ jump to next instruction 8796 8797/* continuation for OP_IGET_OBJECT */ 8798 8799 /* 8800 * Currently: 8801 * r0 holds resolved field 8802 * r9 holds object 8803 */ 8804.LOP_IGET_OBJECT_finish: 8805 @bl common_squeak0 8806 cmp r9, #0 @ check object for null 8807 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8808 beq common_errNullObject @ object was null 8809 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8810 @ no-op @ acquiring load 8811 mov r2, rINST, lsr #8 @ r2<- A+ 8812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8813 and r2, r2, #15 @ r2<- A 8814 GET_INST_OPCODE(ip) @ extract opcode from rINST 8815 SET_VREG(r0, r2) @ fp[A]<- r0 8816 GOTO_OPCODE(ip) @ jump to next instruction 8817 8818/* continuation for OP_IGET_BOOLEAN */ 8819 8820 /* 8821 * Currently: 8822 * r0 holds resolved field 8823 * r9 holds object 8824 */ 8825.LOP_IGET_BOOLEAN_finish: 8826 @bl common_squeak1 8827 cmp r9, #0 @ check object for null 8828 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8829 beq common_errNullObject @ object was null 8830 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8831 @ no-op @ acquiring load 8832 mov r2, rINST, lsr #8 @ r2<- A+ 8833 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8834 and r2, r2, #15 @ r2<- A 8835 GET_INST_OPCODE(ip) @ extract opcode from rINST 8836 SET_VREG(r0, r2) @ fp[A]<- r0 8837 GOTO_OPCODE(ip) @ jump to next instruction 8838 8839/* continuation for OP_IGET_BYTE */ 8840 8841 /* 8842 * Currently: 8843 * r0 holds resolved field 8844 * r9 holds object 8845 */ 8846.LOP_IGET_BYTE_finish: 8847 @bl common_squeak2 8848 cmp r9, #0 @ check object for null 8849 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8850 beq common_errNullObject @ object was null 8851 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8852 @ no-op @ acquiring load 8853 mov r2, rINST, lsr #8 @ r2<- A+ 8854 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8855 and r2, r2, #15 @ r2<- A 8856 GET_INST_OPCODE(ip) @ extract opcode from rINST 8857 SET_VREG(r0, r2) @ fp[A]<- r0 8858 GOTO_OPCODE(ip) @ jump to next instruction 8859 8860/* continuation for OP_IGET_CHAR */ 8861 8862 /* 8863 * Currently: 8864 * r0 holds resolved field 8865 * r9 holds object 8866 */ 8867.LOP_IGET_CHAR_finish: 8868 @bl common_squeak3 8869 cmp r9, #0 @ check object for null 8870 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8871 beq common_errNullObject @ object was null 8872 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8873 @ no-op @ acquiring load 8874 mov r2, rINST, lsr #8 @ r2<- A+ 8875 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8876 and r2, r2, #15 @ r2<- A 8877 GET_INST_OPCODE(ip) @ extract opcode from rINST 8878 SET_VREG(r0, r2) @ fp[A]<- r0 8879 GOTO_OPCODE(ip) @ jump to next instruction 8880 8881/* continuation for OP_IGET_SHORT */ 8882 8883 /* 8884 * Currently: 8885 * r0 holds resolved field 8886 * r9 holds object 8887 */ 8888.LOP_IGET_SHORT_finish: 8889 @bl common_squeak4 8890 cmp r9, #0 @ check object for null 8891 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8892 beq common_errNullObject @ object was null 8893 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8894 @ no-op @ acquiring load 8895 mov r2, rINST, lsr #8 @ r2<- A+ 8896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8897 and r2, r2, #15 @ r2<- A 8898 GET_INST_OPCODE(ip) @ extract opcode from rINST 8899 SET_VREG(r0, r2) @ fp[A]<- r0 8900 GOTO_OPCODE(ip) @ jump to next instruction 8901 8902/* continuation for OP_IPUT */ 8903 8904 /* 8905 * Currently: 8906 * r0 holds resolved field 8907 * r9 holds object 8908 */ 8909.LOP_IPUT_finish: 8910 @bl common_squeak0 8911 mov r1, rINST, lsr #8 @ r1<- A+ 8912 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8913 and r1, r1, #15 @ r1<- A 8914 cmp r9, #0 @ check object for null 8915 GET_VREG(r0, r1) @ r0<- fp[A] 8916 beq common_errNullObject @ object was null 8917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8918 GET_INST_OPCODE(ip) @ extract opcode from rINST 8919 @ no-op @ releasing store 8920 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8921 GOTO_OPCODE(ip) @ jump to next instruction 8922 8923/* continuation for OP_IPUT_WIDE */ 8924 8925 /* 8926 * Currently: 8927 * r0 holds resolved field 8928 * r9 holds object 8929 */ 8930.LOP_IPUT_WIDE_finish: 8931 mov r2, rINST, lsr #8 @ r2<- A+ 8932 cmp r9, #0 @ check object for null 8933 and r2, r2, #15 @ r2<- A 8934 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8935 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8936 beq common_errNullObject @ object was null 8937 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8938 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8939 GET_INST_OPCODE(r10) @ extract opcode from rINST 8940 add r2, r9, r3 @ r2<- object + byte offset 8941 .if 0 8942 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8943 .else 8944 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1 8945 .endif 8946 GOTO_OPCODE(r10) @ jump to next instruction 8947 8948/* continuation for OP_IPUT_OBJECT */ 8949 8950 /* 8951 * Currently: 8952 * r0 holds resolved field 8953 * r9 holds object 8954 */ 8955.LOP_IPUT_OBJECT_finish: 8956 @bl common_squeak0 8957 mov r1, rINST, lsr #8 @ r1<- A+ 8958 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8959 and r1, r1, #15 @ r1<- A 8960 cmp r9, #0 @ check object for null 8961 GET_VREG(r0, r1) @ r0<- fp[A] 8962 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8963 beq common_errNullObject @ object was null 8964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8965 GET_INST_OPCODE(ip) @ extract opcode from rINST 8966 @ no-op @ releasing store 8967 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8968 cmp r0, #0 @ stored a null reference? 8969 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8970 GOTO_OPCODE(ip) @ jump to next instruction 8971 8972/* continuation for OP_IPUT_BOOLEAN */ 8973 8974 /* 8975 * Currently: 8976 * r0 holds resolved field 8977 * r9 holds object 8978 */ 8979.LOP_IPUT_BOOLEAN_finish: 8980 @bl common_squeak1 8981 mov r1, rINST, lsr #8 @ r1<- A+ 8982 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8983 and r1, r1, #15 @ r1<- A 8984 cmp r9, #0 @ check object for null 8985 GET_VREG(r0, r1) @ r0<- fp[A] 8986 beq common_errNullObject @ object was null 8987 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8988 GET_INST_OPCODE(ip) @ extract opcode from rINST 8989 @ no-op @ releasing store 8990 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8991 GOTO_OPCODE(ip) @ jump to next instruction 8992 8993/* continuation for OP_IPUT_BYTE */ 8994 8995 /* 8996 * Currently: 8997 * r0 holds resolved field 8998 * r9 holds object 8999 */ 9000.LOP_IPUT_BYTE_finish: 9001 @bl common_squeak2 9002 mov r1, rINST, lsr #8 @ r1<- A+ 9003 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9004 and r1, r1, #15 @ r1<- A 9005 cmp r9, #0 @ check object for null 9006 GET_VREG(r0, r1) @ r0<- fp[A] 9007 beq common_errNullObject @ object was null 9008 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9009 GET_INST_OPCODE(ip) @ extract opcode from rINST 9010 @ no-op @ releasing store 9011 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9012 GOTO_OPCODE(ip) @ jump to next instruction 9013 9014/* continuation for OP_IPUT_CHAR */ 9015 9016 /* 9017 * Currently: 9018 * r0 holds resolved field 9019 * r9 holds object 9020 */ 9021.LOP_IPUT_CHAR_finish: 9022 @bl common_squeak3 9023 mov r1, rINST, lsr #8 @ r1<- A+ 9024 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9025 and r1, r1, #15 @ r1<- A 9026 cmp r9, #0 @ check object for null 9027 GET_VREG(r0, r1) @ r0<- fp[A] 9028 beq common_errNullObject @ object was null 9029 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9030 GET_INST_OPCODE(ip) @ extract opcode from rINST 9031 @ no-op @ releasing store 9032 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9033 GOTO_OPCODE(ip) @ jump to next instruction 9034 9035/* continuation for OP_IPUT_SHORT */ 9036 9037 /* 9038 * Currently: 9039 * r0 holds resolved field 9040 * r9 holds object 9041 */ 9042.LOP_IPUT_SHORT_finish: 9043 @bl common_squeak4 9044 mov r1, rINST, lsr #8 @ r1<- A+ 9045 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9046 and r1, r1, #15 @ r1<- A 9047 cmp r9, #0 @ check object for null 9048 GET_VREG(r0, r1) @ r0<- fp[A] 9049 beq common_errNullObject @ object was null 9050 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9051 GET_INST_OPCODE(ip) @ extract opcode from rINST 9052 @ no-op @ releasing store 9053 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9054 GOTO_OPCODE(ip) @ jump to next instruction 9055 9056/* continuation for OP_SGET */ 9057 9058 /* 9059 * Continuation if the field has not yet been resolved. 9060 * r1: BBBB field ref 9061 */ 9062.LOP_SGET_resolve: 9063 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9064 EXPORT_PC() @ resolve() could throw, so export now 9065 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9066 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9067 cmp r0, #0 @ success? 9068 bne .LOP_SGET_finish @ yes, finish 9069 b common_exceptionThrown @ no, handle exception 9070 9071/* continuation for OP_SGET_WIDE */ 9072 9073 /* 9074 * Continuation if the field has not yet been resolved. 9075 * r1: BBBB field ref 9076 * 9077 * Returns StaticField pointer in r0. 9078 */ 9079.LOP_SGET_WIDE_resolve: 9080 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9081 EXPORT_PC() @ resolve() could throw, so export now 9082 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9083 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9084 cmp r0, #0 @ success? 9085 bne .LOP_SGET_WIDE_finish @ yes, finish 9086 b common_exceptionThrown @ no, handle exception 9087 9088/* continuation for OP_SGET_OBJECT */ 9089 9090 /* 9091 * Continuation if the field has not yet been resolved. 9092 * r1: BBBB field ref 9093 */ 9094.LOP_SGET_OBJECT_resolve: 9095 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9096 EXPORT_PC() @ resolve() could throw, so export now 9097 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9098 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9099 cmp r0, #0 @ success? 9100 bne .LOP_SGET_OBJECT_finish @ yes, finish 9101 b common_exceptionThrown @ no, handle exception 9102 9103/* continuation for OP_SGET_BOOLEAN */ 9104 9105 /* 9106 * Continuation if the field has not yet been resolved. 9107 * r1: BBBB field ref 9108 */ 9109.LOP_SGET_BOOLEAN_resolve: 9110 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9111 EXPORT_PC() @ resolve() could throw, so export now 9112 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9113 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9114 cmp r0, #0 @ success? 9115 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 9116 b common_exceptionThrown @ no, handle exception 9117 9118/* continuation for OP_SGET_BYTE */ 9119 9120 /* 9121 * Continuation if the field has not yet been resolved. 9122 * r1: BBBB field ref 9123 */ 9124.LOP_SGET_BYTE_resolve: 9125 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9126 EXPORT_PC() @ resolve() could throw, so export now 9127 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9128 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9129 cmp r0, #0 @ success? 9130 bne .LOP_SGET_BYTE_finish @ yes, finish 9131 b common_exceptionThrown @ no, handle exception 9132 9133/* continuation for OP_SGET_CHAR */ 9134 9135 /* 9136 * Continuation if the field has not yet been resolved. 9137 * r1: BBBB field ref 9138 */ 9139.LOP_SGET_CHAR_resolve: 9140 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9141 EXPORT_PC() @ resolve() could throw, so export now 9142 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9143 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9144 cmp r0, #0 @ success? 9145 bne .LOP_SGET_CHAR_finish @ yes, finish 9146 b common_exceptionThrown @ no, handle exception 9147 9148/* continuation for OP_SGET_SHORT */ 9149 9150 /* 9151 * Continuation if the field has not yet been resolved. 9152 * r1: BBBB field ref 9153 */ 9154.LOP_SGET_SHORT_resolve: 9155 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9156 EXPORT_PC() @ resolve() could throw, so export now 9157 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9158 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9159 cmp r0, #0 @ success? 9160 bne .LOP_SGET_SHORT_finish @ yes, finish 9161 b common_exceptionThrown @ no, handle exception 9162 9163/* continuation for OP_SPUT */ 9164 9165 /* 9166 * Continuation if the field has not yet been resolved. 9167 * r1: BBBB field ref 9168 */ 9169.LOP_SPUT_resolve: 9170 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9171 EXPORT_PC() @ resolve() could throw, so export now 9172 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9173 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9174 cmp r0, #0 @ success? 9175 bne .LOP_SPUT_finish @ yes, finish 9176 b common_exceptionThrown @ no, handle exception 9177 9178/* continuation for OP_SPUT_WIDE */ 9179 9180 /* 9181 * Continuation if the field has not yet been resolved. 9182 * r1: BBBB field ref 9183 * r9: &fp[AA] 9184 * 9185 * Returns StaticField pointer in r2. 9186 */ 9187.LOP_SPUT_WIDE_resolve: 9188 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9189 EXPORT_PC() @ resolve() could throw, so export now 9190 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9191 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9192 cmp r0, #0 @ success? 9193 mov r2, r0 @ copy to r2 9194 bne .LOP_SPUT_WIDE_finish @ yes, finish 9195 b common_exceptionThrown @ no, handle exception 9196 9197/* continuation for OP_SPUT_OBJECT */ 9198.LOP_SPUT_OBJECT_finish: @ field ptr in r0 9199 mov r2, rINST, lsr #8 @ r2<- AA 9200 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9201 GET_VREG(r1, r2) @ r1<- fp[AA] 9202 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9203 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9204 GET_INST_OPCODE(ip) @ extract opcode from rINST 9205 @ no-op @ releasing store 9206 str r1, [r0, #offStaticField_value] @ field<- vAA 9207 cmp r1, #0 @ stored a null object? 9208 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9209 GOTO_OPCODE(ip) @ jump to next instruction 9210 9211/* continuation for OP_SPUT_BOOLEAN */ 9212 9213 /* 9214 * Continuation if the field has not yet been resolved. 9215 * r1: BBBB field ref 9216 */ 9217.LOP_SPUT_BOOLEAN_resolve: 9218 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9219 EXPORT_PC() @ resolve() could throw, so export now 9220 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9221 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9222 cmp r0, #0 @ success? 9223 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 9224 b common_exceptionThrown @ no, handle exception 9225 9226/* continuation for OP_SPUT_BYTE */ 9227 9228 /* 9229 * Continuation if the field has not yet been resolved. 9230 * r1: BBBB field ref 9231 */ 9232.LOP_SPUT_BYTE_resolve: 9233 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9234 EXPORT_PC() @ resolve() could throw, so export now 9235 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9236 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9237 cmp r0, #0 @ success? 9238 bne .LOP_SPUT_BYTE_finish @ yes, finish 9239 b common_exceptionThrown @ no, handle exception 9240 9241/* continuation for OP_SPUT_CHAR */ 9242 9243 /* 9244 * Continuation if the field has not yet been resolved. 9245 * r1: BBBB field ref 9246 */ 9247.LOP_SPUT_CHAR_resolve: 9248 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9249 EXPORT_PC() @ resolve() could throw, so export now 9250 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9251 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9252 cmp r0, #0 @ success? 9253 bne .LOP_SPUT_CHAR_finish @ yes, finish 9254 b common_exceptionThrown @ no, handle exception 9255 9256/* continuation for OP_SPUT_SHORT */ 9257 9258 /* 9259 * Continuation if the field has not yet been resolved. 9260 * r1: BBBB field ref 9261 */ 9262.LOP_SPUT_SHORT_resolve: 9263 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9264 EXPORT_PC() @ resolve() could throw, so export now 9265 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9266 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9267 cmp r0, #0 @ success? 9268 bne .LOP_SPUT_SHORT_finish @ yes, finish 9269 b common_exceptionThrown @ no, handle exception 9270 9271/* continuation for OP_INVOKE_VIRTUAL */ 9272 9273 /* 9274 * At this point: 9275 * r0 = resolved base method 9276 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9277 */ 9278.LOP_INVOKE_VIRTUAL_continue: 9279 GET_VREG(r1, r10) @ r1<- "this" ptr 9280 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9281 cmp r1, #0 @ is "this" null? 9282 beq common_errNullObject @ null "this", throw exception 9283 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9284 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9285 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9286 bl common_invokeMethodNoRange @ continue on 9287 9288/* continuation for OP_INVOKE_SUPER */ 9289 9290 /* 9291 * At this point: 9292 * r0 = resolved base method 9293 * r9 = method->clazz 9294 */ 9295.LOP_INVOKE_SUPER_continue: 9296 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9297 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9298 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9299 EXPORT_PC() @ must export for invoke 9300 cmp r2, r3 @ compare (methodIndex, vtableCount) 9301 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 9302 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9303 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9304 bl common_invokeMethodNoRange @ continue on 9305 9306.LOP_INVOKE_SUPER_resolve: 9307 mov r0, r9 @ r0<- method->clazz 9308 mov r2, #METHOD_VIRTUAL @ resolver method type 9309 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9310 cmp r0, #0 @ got null? 9311 bne .LOP_INVOKE_SUPER_continue @ no, continue 9312 b common_exceptionThrown @ yes, handle exception 9313 9314 /* 9315 * Throw a NoSuchMethodError with the method name as the message. 9316 * r0 = resolved base method 9317 */ 9318.LOP_INVOKE_SUPER_nsm: 9319 ldr r1, [r0, #offMethod_name] @ r1<- method name 9320 b common_errNoSuchMethod 9321 9322/* continuation for OP_INVOKE_DIRECT */ 9323 9324 /* 9325 * On entry: 9326 * r1 = reference (BBBB or CCCC) 9327 * r10 = "this" register 9328 */ 9329.LOP_INVOKE_DIRECT_resolve: 9330 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9331 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9332 mov r2, #METHOD_DIRECT @ resolver method type 9333 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9334 cmp r0, #0 @ got null? 9335 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9336 bne .LOP_INVOKE_DIRECT_finish @ no, continue 9337 b common_exceptionThrown @ yes, handle exception 9338 9339/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 9340 9341 /* 9342 * At this point: 9343 * r0 = resolved base method 9344 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9345 */ 9346.LOP_INVOKE_VIRTUAL_RANGE_continue: 9347 GET_VREG(r1, r10) @ r1<- "this" ptr 9348 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9349 cmp r1, #0 @ is "this" null? 9350 beq common_errNullObject @ null "this", throw exception 9351 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9352 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9353 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9354 bl common_invokeMethodRange @ continue on 9355 9356/* continuation for OP_INVOKE_SUPER_RANGE */ 9357 9358 /* 9359 * At this point: 9360 * r0 = resolved base method 9361 * r9 = method->clazz 9362 */ 9363.LOP_INVOKE_SUPER_RANGE_continue: 9364 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9365 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9366 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9367 EXPORT_PC() @ must export for invoke 9368 cmp r2, r3 @ compare (methodIndex, vtableCount) 9369 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 9370 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9371 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9372 bl common_invokeMethodRange @ continue on 9373 9374.LOP_INVOKE_SUPER_RANGE_resolve: 9375 mov r0, r9 @ r0<- method->clazz 9376 mov r2, #METHOD_VIRTUAL @ resolver method type 9377 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9378 cmp r0, #0 @ got null? 9379 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 9380 b common_exceptionThrown @ yes, handle exception 9381 9382 /* 9383 * Throw a NoSuchMethodError with the method name as the message. 9384 * r0 = resolved base method 9385 */ 9386.LOP_INVOKE_SUPER_RANGE_nsm: 9387 ldr r1, [r0, #offMethod_name] @ r1<- method name 9388 b common_errNoSuchMethod 9389 9390/* continuation for OP_INVOKE_DIRECT_RANGE */ 9391 9392 /* 9393 * On entry: 9394 * r1 = reference (BBBB or CCCC) 9395 * r10 = "this" register 9396 */ 9397.LOP_INVOKE_DIRECT_RANGE_resolve: 9398 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9399 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9400 mov r2, #METHOD_DIRECT @ resolver method type 9401 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9402 cmp r0, #0 @ got null? 9403 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9404 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 9405 b common_exceptionThrown @ yes, handle exception 9406 9407/* continuation for OP_FLOAT_TO_LONG */ 9408/* 9409 * Convert the float in r0 to a long in r0/r1. 9410 * 9411 * We have to clip values to long min/max per the specification. The 9412 * expected common case is a "reasonable" value that converts directly 9413 * to modest integer. The EABI convert function isn't doing this for us. 9414 */ 9415f2l_doconv: 9416 stmfd sp!, {r4, lr} 9417 mov r1, #0x5f000000 @ (float)maxlong 9418 mov r4, r0 9419 bl __aeabi_fcmpge @ is arg >= maxlong? 9420 cmp r0, #0 @ nonzero == yes 9421 mvnne r0, #0 @ return maxlong (7fffffff) 9422 mvnne r1, #0x80000000 9423 ldmnefd sp!, {r4, pc} 9424 9425 mov r0, r4 @ recover arg 9426 mov r1, #0xdf000000 @ (float)minlong 9427 bl __aeabi_fcmple @ is arg <= minlong? 9428 cmp r0, #0 @ nonzero == yes 9429 movne r0, #0 @ return minlong (80000000) 9430 movne r1, #0x80000000 9431 ldmnefd sp!, {r4, pc} 9432 9433 mov r0, r4 @ recover arg 9434 mov r1, r4 9435 bl __aeabi_fcmpeq @ is arg == self? 9436 cmp r0, #0 @ zero == no 9437 moveq r1, #0 @ return zero for NaN 9438 ldmeqfd sp!, {r4, pc} 9439 9440 mov r0, r4 @ recover arg 9441 bl __aeabi_f2lz @ convert float to long 9442 ldmfd sp!, {r4, pc} 9443 9444/* continuation for OP_DOUBLE_TO_LONG */ 9445/* 9446 * Convert the double in r0/r1 to a long in r0/r1. 9447 * 9448 * We have to clip values to long min/max per the specification. The 9449 * expected common case is a "reasonable" value that converts directly 9450 * to modest integer. The EABI convert function isn't doing this for us. 9451 */ 9452d2l_doconv: 9453 stmfd sp!, {r4, r5, lr} @ save regs 9454 mov r3, #0x43000000 @ maxlong, as a double (high word) 9455 add r3, #0x00e00000 @ 0x43e00000 9456 mov r2, #0 @ maxlong, as a double (low word) 9457 sub sp, sp, #4 @ align for EABI 9458 mov r4, r0 @ save a copy of r0 9459 mov r5, r1 @ and r1 9460 bl __aeabi_dcmpge @ is arg >= maxlong? 9461 cmp r0, #0 @ nonzero == yes 9462 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9463 mvnne r1, #0x80000000 9464 bne 1f 9465 9466 mov r0, r4 @ recover arg 9467 mov r1, r5 9468 mov r3, #0xc3000000 @ minlong, as a double (high word) 9469 add r3, #0x00e00000 @ 0xc3e00000 9470 mov r2, #0 @ minlong, as a double (low word) 9471 bl __aeabi_dcmple @ is arg <= minlong? 9472 cmp r0, #0 @ nonzero == yes 9473 movne r0, #0 @ return minlong (8000000000000000) 9474 movne r1, #0x80000000 9475 bne 1f 9476 9477 mov r0, r4 @ recover arg 9478 mov r1, r5 9479 mov r2, r4 @ compare against self 9480 mov r3, r5 9481 bl __aeabi_dcmpeq @ is arg == self? 9482 cmp r0, #0 @ zero == no 9483 moveq r1, #0 @ return zero for NaN 9484 beq 1f 9485 9486 mov r0, r4 @ recover arg 9487 mov r1, r5 9488 bl __aeabi_d2lz @ convert double to long 9489 94901: 9491 add sp, sp, #4 9492 ldmfd sp!, {r4, r5, pc} 9493 9494/* continuation for OP_MUL_LONG */ 9495 9496.LOP_MUL_LONG_finish: 9497 GET_INST_OPCODE(ip) @ extract opcode from rINST 9498 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9499 GOTO_OPCODE(ip) @ jump to next instruction 9500 9501/* continuation for OP_SHL_LONG */ 9502 9503.LOP_SHL_LONG_finish: 9504 mov r0, r0, asl r2 @ r0<- r0 << r2 9505 GET_INST_OPCODE(ip) @ extract opcode from rINST 9506 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9507 GOTO_OPCODE(ip) @ jump to next instruction 9508 9509/* continuation for OP_SHR_LONG */ 9510 9511.LOP_SHR_LONG_finish: 9512 mov r1, r1, asr r2 @ r1<- r1 >> r2 9513 GET_INST_OPCODE(ip) @ extract opcode from rINST 9514 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9515 GOTO_OPCODE(ip) @ jump to next instruction 9516 9517/* continuation for OP_USHR_LONG */ 9518 9519.LOP_USHR_LONG_finish: 9520 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9521 GET_INST_OPCODE(ip) @ extract opcode from rINST 9522 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9523 GOTO_OPCODE(ip) @ jump to next instruction 9524 9525/* continuation for OP_SHL_LONG_2ADDR */ 9526 9527.LOP_SHL_LONG_2ADDR_finish: 9528 GET_INST_OPCODE(ip) @ extract opcode from rINST 9529 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9530 GOTO_OPCODE(ip) @ jump to next instruction 9531 9532/* continuation for OP_SHR_LONG_2ADDR */ 9533 9534.LOP_SHR_LONG_2ADDR_finish: 9535 GET_INST_OPCODE(ip) @ extract opcode from rINST 9536 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9537 GOTO_OPCODE(ip) @ jump to next instruction 9538 9539/* continuation for OP_USHR_LONG_2ADDR */ 9540 9541.LOP_USHR_LONG_2ADDR_finish: 9542 GET_INST_OPCODE(ip) @ extract opcode from rINST 9543 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9544 GOTO_OPCODE(ip) @ jump to next instruction 9545 9546/* continuation for OP_IGET_VOLATILE */ 9547 9548 /* 9549 * Currently: 9550 * r0 holds resolved field 9551 * r9 holds object 9552 */ 9553.LOP_IGET_VOLATILE_finish: 9554 @bl common_squeak0 9555 cmp r9, #0 @ check object for null 9556 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9557 beq common_errNullObject @ object was null 9558 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9559 SMP_DMB @ acquiring load 9560 mov r2, rINST, lsr #8 @ r2<- A+ 9561 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9562 and r2, r2, #15 @ r2<- A 9563 GET_INST_OPCODE(ip) @ extract opcode from rINST 9564 SET_VREG(r0, r2) @ fp[A]<- r0 9565 GOTO_OPCODE(ip) @ jump to next instruction 9566 9567/* continuation for OP_IPUT_VOLATILE */ 9568 9569 /* 9570 * Currently: 9571 * r0 holds resolved field 9572 * r9 holds object 9573 */ 9574.LOP_IPUT_VOLATILE_finish: 9575 @bl common_squeak0 9576 mov r1, rINST, lsr #8 @ r1<- A+ 9577 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9578 and r1, r1, #15 @ r1<- A 9579 cmp r9, #0 @ check object for null 9580 GET_VREG(r0, r1) @ r0<- fp[A] 9581 beq common_errNullObject @ object was null 9582 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9583 GET_INST_OPCODE(ip) @ extract opcode from rINST 9584 SMP_DMB @ releasing store 9585 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9586 GOTO_OPCODE(ip) @ jump to next instruction 9587 9588/* continuation for OP_SGET_VOLATILE */ 9589 9590 /* 9591 * Continuation if the field has not yet been resolved. 9592 * r1: BBBB field ref 9593 */ 9594.LOP_SGET_VOLATILE_resolve: 9595 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9596 EXPORT_PC() @ resolve() could throw, so export now 9597 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9598 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9599 cmp r0, #0 @ success? 9600 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9601 b common_exceptionThrown @ no, handle exception 9602 9603/* continuation for OP_SPUT_VOLATILE */ 9604 9605 /* 9606 * Continuation if the field has not yet been resolved. 9607 * r1: BBBB field ref 9608 */ 9609.LOP_SPUT_VOLATILE_resolve: 9610 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9611 EXPORT_PC() @ resolve() could throw, so export now 9612 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9613 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9614 cmp r0, #0 @ success? 9615 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9616 b common_exceptionThrown @ no, handle exception 9617 9618/* continuation for OP_IGET_OBJECT_VOLATILE */ 9619 9620 /* 9621 * Currently: 9622 * r0 holds resolved field 9623 * r9 holds object 9624 */ 9625.LOP_IGET_OBJECT_VOLATILE_finish: 9626 @bl common_squeak0 9627 cmp r9, #0 @ check object for null 9628 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9629 beq common_errNullObject @ object was null 9630 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9631 SMP_DMB @ acquiring load 9632 mov r2, rINST, lsr #8 @ r2<- A+ 9633 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9634 and r2, r2, #15 @ r2<- A 9635 GET_INST_OPCODE(ip) @ extract opcode from rINST 9636 SET_VREG(r0, r2) @ fp[A]<- r0 9637 GOTO_OPCODE(ip) @ jump to next instruction 9638 9639/* continuation for OP_IGET_WIDE_VOLATILE */ 9640 9641 /* 9642 * Currently: 9643 * r0 holds resolved field 9644 * r9 holds object 9645 */ 9646.LOP_IGET_WIDE_VOLATILE_finish: 9647 cmp r9, #0 @ check object for null 9648 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9649 beq common_errNullObject @ object was null 9650 .if 1 9651 add r0, r9, r3 @ r0<- address of field 9652 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9653 .else 9654 add r9, r9, r3 @ r9<- obj + field offset 9655 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok) 9656 .endif 9657 mov r2, rINST, lsr #8 @ r2<- A+ 9658 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9659 and r2, r2, #15 @ r2<- A 9660 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9661 GET_INST_OPCODE(ip) @ extract opcode from rINST 9662 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9663 GOTO_OPCODE(ip) @ jump to next instruction 9664 9665/* continuation for OP_IPUT_WIDE_VOLATILE */ 9666 9667 /* 9668 * Currently: 9669 * r0 holds resolved field 9670 * r9 holds object 9671 */ 9672.LOP_IPUT_WIDE_VOLATILE_finish: 9673 mov r2, rINST, lsr #8 @ r2<- A+ 9674 cmp r9, #0 @ check object for null 9675 and r2, r2, #15 @ r2<- A 9676 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9677 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9678 beq common_errNullObject @ object was null 9679 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9680 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9681 GET_INST_OPCODE(r10) @ extract opcode from rINST 9682 add r2, r9, r3 @ r2<- object + byte offset 9683 .if 1 9684 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9685 .else 9686 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1 9687 .endif 9688 GOTO_OPCODE(r10) @ jump to next instruction 9689 9690/* continuation for OP_SGET_WIDE_VOLATILE */ 9691 9692 /* 9693 * Continuation if the field has not yet been resolved. 9694 * r1: BBBB field ref 9695 * 9696 * Returns StaticField pointer in r0. 9697 */ 9698.LOP_SGET_WIDE_VOLATILE_resolve: 9699 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9700 EXPORT_PC() @ resolve() could throw, so export now 9701 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9702 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9703 cmp r0, #0 @ success? 9704 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9705 b common_exceptionThrown @ no, handle exception 9706 9707/* continuation for OP_SPUT_WIDE_VOLATILE */ 9708 9709 /* 9710 * Continuation if the field has not yet been resolved. 9711 * r1: BBBB field ref 9712 * r9: &fp[AA] 9713 * 9714 * Returns StaticField pointer in r2. 9715 */ 9716.LOP_SPUT_WIDE_VOLATILE_resolve: 9717 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9718 EXPORT_PC() @ resolve() could throw, so export now 9719 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9720 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9721 cmp r0, #0 @ success? 9722 mov r2, r0 @ copy to r2 9723 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9724 b common_exceptionThrown @ no, handle exception 9725 9726/* continuation for OP_EXECUTE_INLINE */ 9727 9728 /* 9729 * Extract args, call function. 9730 * r0 = #of args (0-4) 9731 * r10 = call index 9732 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9733 * 9734 * Other ideas: 9735 * - Use a jump table from the main piece to jump directly into the 9736 * AND/LDR pairs. Costs a data load, saves a branch. 9737 * - Have five separate pieces that do the loading, so we can work the 9738 * interleave a little better. Increases code size. 9739 */ 9740.LOP_EXECUTE_INLINE_continue: 9741 rsb r0, r0, #4 @ r0<- 4-r0 9742 FETCH(r9, 2) @ r9<- FEDC 9743 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9744 bl common_abort @ (skipped due to ARM prefetch) 97454: and ip, r9, #0xf000 @ isolate F 9746 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 97473: and ip, r9, #0x0f00 @ isolate E 9748 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 97492: and ip, r9, #0x00f0 @ isolate D 9750 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 97511: and ip, r9, #0x000f @ isolate C 9752 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 97530: 9754 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9755 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9756 @ (not reached) 9757 9758.LOP_EXECUTE_INLINE_table: 9759 .word gDvmInlineOpsTable 9760 9761/* continuation for OP_EXECUTE_INLINE_RANGE */ 9762 9763 /* 9764 * Extract args, call function. 9765 * r0 = #of args (0-4) 9766 * r10 = call index 9767 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9768 */ 9769.LOP_EXECUTE_INLINE_RANGE_continue: 9770 rsb r0, r0, #4 @ r0<- 4-r0 9771 FETCH(r9, 2) @ r9<- CCCC 9772 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9773 bl common_abort @ (skipped due to ARM prefetch) 97744: add ip, r9, #3 @ base+3 9775 GET_VREG(r3, ip) @ r3<- vBase[3] 97763: add ip, r9, #2 @ base+2 9777 GET_VREG(r2, ip) @ r2<- vBase[2] 97782: add ip, r9, #1 @ base+1 9779 GET_VREG(r1, ip) @ r1<- vBase[1] 97801: add ip, r9, #0 @ (nop) 9781 GET_VREG(r0, ip) @ r0<- vBase[0] 97820: 9783 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9784 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9785 @ (not reached) 9786 9787.LOP_EXECUTE_INLINE_RANGE_table: 9788 .word gDvmInlineOpsTable 9789 9790/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9791 9792 /* 9793 * Currently: 9794 * r0 holds resolved field 9795 * r9 holds object 9796 */ 9797.LOP_IPUT_OBJECT_VOLATILE_finish: 9798 @bl common_squeak0 9799 mov r1, rINST, lsr #8 @ r1<- A+ 9800 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9801 and r1, r1, #15 @ r1<- A 9802 cmp r9, #0 @ check object for null 9803 GET_VREG(r0, r1) @ r0<- fp[A] 9804 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9805 beq common_errNullObject @ object was null 9806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9807 GET_INST_OPCODE(ip) @ extract opcode from rINST 9808 SMP_DMB @ releasing store 9809 str r0, [r9, r3] @ obj.field (32 bits)<- r0 9810 cmp r0, #0 @ stored a null reference? 9811 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9812 GOTO_OPCODE(ip) @ jump to next instruction 9813 9814/* continuation for OP_SGET_OBJECT_VOLATILE */ 9815 9816 /* 9817 * Continuation if the field has not yet been resolved. 9818 * r1: BBBB field ref 9819 */ 9820.LOP_SGET_OBJECT_VOLATILE_resolve: 9821 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9822 EXPORT_PC() @ resolve() could throw, so export now 9823 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9824 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9825 cmp r0, #0 @ success? 9826 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9827 b common_exceptionThrown @ no, handle exception 9828 9829/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9830.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9831 mov r2, rINST, lsr #8 @ r2<- AA 9832 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9833 GET_VREG(r1, r2) @ r1<- fp[AA] 9834 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9835 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9836 GET_INST_OPCODE(ip) @ extract opcode from rINST 9837 SMP_DMB @ releasing store 9838 str r1, [r0, #offStaticField_value] @ field<- vAA 9839 cmp r1, #0 @ stored a null object? 9840 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9841 GOTO_OPCODE(ip) @ jump to next instruction 9842 9843 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9844 .global dvmAsmSisterEnd 9845dvmAsmSisterEnd: 9846 9847/* File: armv5te/footer.S */ 9848 9849/* 9850 * =========================================================================== 9851 * Common subroutines and data 9852 * =========================================================================== 9853 */ 9854 9855 9856 9857 .text 9858 .align 2 9859 9860#if defined(WITH_JIT) 9861#if defined(WITH_SELF_VERIFICATION) 9862 .global dvmJitToInterpPunt 9863dvmJitToInterpPunt: 9864 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9865 mov r2,#kSVSPunt @ r2<- interpreter entry point 9866 mov r3, #0 9867 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9868 b jitSVShadowRunEnd @ doesn't return 9869 9870 .global dvmJitToInterpSingleStep 9871dvmJitToInterpSingleStep: 9872 str lr,[rGLUE,#offGlue_jitResumeNPC] 9873 str r1,[rGLUE,#offGlue_jitResumeDPC] 9874 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9875 b jitSVShadowRunEnd @ doesn't return 9876 9877 .global dvmJitToInterpNoChainNoProfile 9878dvmJitToInterpNoChainNoProfile: 9879 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9880 mov r0,rPC @ pass our target PC 9881 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9882 mov r3, #0 @ 0 means !inJitCodeCache 9883 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9884 b jitSVShadowRunEnd @ doesn't return 9885 9886 .global dvmJitToInterpTraceSelectNoChain 9887dvmJitToInterpTraceSelectNoChain: 9888 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9889 mov r0,rPC @ pass our target PC 9890 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9891 mov r3, #0 @ 0 means !inJitCodeCache 9892 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9893 b jitSVShadowRunEnd @ doesn't return 9894 9895 .global dvmJitToInterpTraceSelect 9896dvmJitToInterpTraceSelect: 9897 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9898 ldr r0,[lr, #-1] @ pass our target PC 9899 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9900 mov r3, #0 @ 0 means !inJitCodeCache 9901 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9902 b jitSVShadowRunEnd @ doesn't return 9903 9904 .global dvmJitToInterpBackwardBranch 9905dvmJitToInterpBackwardBranch: 9906 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9907 ldr r0,[lr, #-1] @ pass our target PC 9908 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9909 mov r3, #0 @ 0 means !inJitCodeCache 9910 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9911 b jitSVShadowRunEnd @ doesn't return 9912 9913 .global dvmJitToInterpNormal 9914dvmJitToInterpNormal: 9915 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9916 ldr r0,[lr, #-1] @ pass our target PC 9917 mov r2,#kSVSNormal @ r2<- interpreter entry point 9918 mov r3, #0 @ 0 means !inJitCodeCache 9919 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9920 b jitSVShadowRunEnd @ doesn't return 9921 9922 .global dvmJitToInterpNoChain 9923dvmJitToInterpNoChain: 9924 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9925 mov r0,rPC @ pass our target PC 9926 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9927 mov r3, #0 @ 0 means !inJitCodeCache 9928 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9929 b jitSVShadowRunEnd @ doesn't return 9930#else 9931/* 9932 * Return from the translation cache to the interpreter when the compiler is 9933 * having issues translating/executing a Dalvik instruction. We have to skip 9934 * the code cache lookup otherwise it is possible to indefinitely bouce 9935 * between the interpreter and the code cache if the instruction that fails 9936 * to be compiled happens to be at a trace start. 9937 */ 9938 .global dvmJitToInterpPunt 9939dvmJitToInterpPunt: 9940 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9941 mov rPC, r0 9942#if defined(WITH_JIT_TUNING) 9943 mov r0,lr 9944 bl dvmBumpPunt; 9945#endif 9946 EXPORT_PC() 9947 mov r0, #0 9948 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9949 adrl rIBASE, dvmAsmInstructionStart 9950 FETCH_INST() 9951 GET_INST_OPCODE(ip) 9952 GOTO_OPCODE(ip) 9953 9954/* 9955 * Return to the interpreter to handle a single instruction. 9956 * On entry: 9957 * r0 <= PC 9958 * r1 <= PC of resume instruction 9959 * lr <= resume point in translation 9960 */ 9961 .global dvmJitToInterpSingleStep 9962dvmJitToInterpSingleStep: 9963 str lr,[rGLUE,#offGlue_jitResumeNPC] 9964 str r1,[rGLUE,#offGlue_jitResumeDPC] 9965 mov r1,#kInterpEntryInstr 9966 @ enum is 4 byte in aapcs-EABI 9967 str r1, [rGLUE, #offGlue_entryPoint] 9968 mov rPC,r0 9969 EXPORT_PC() 9970 9971 adrl rIBASE, dvmAsmInstructionStart 9972 mov r2,#kJitSingleStep @ Ask for single step and then revert 9973 str r2,[rGLUE,#offGlue_jitState] 9974 mov r1,#1 @ set changeInterp to bail to debug interp 9975 b common_gotoBail 9976 9977/* 9978 * Return from the translation cache and immediately request 9979 * a translation for the exit target. Commonly used for callees. 9980 */ 9981 .global dvmJitToInterpTraceSelectNoChain 9982dvmJitToInterpTraceSelectNoChain: 9983#if defined(WITH_JIT_TUNING) 9984 bl dvmBumpNoChain 9985#endif 9986 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9987 mov r0,rPC 9988 bl dvmJitGetCodeAddr @ Is there a translation? 9989 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9990 mov r1, rPC @ arg1 of translation may need this 9991 mov lr, #0 @ in case target is HANDLER_INTERPRET 9992 cmp r0,#0 @ !0 means translation exists 9993 bxne r0 @ continue native execution if so 9994 b 2f @ branch over to use the interpreter 9995 9996/* 9997 * Return from the translation cache and immediately request 9998 * a translation for the exit target. Commonly used following 9999 * invokes. 10000 */ 10001 .global dvmJitToInterpTraceSelect 10002dvmJitToInterpTraceSelect: 10003 ldr rPC,[lr, #-1] @ get our target PC 10004 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 10005 add rINST,lr,#-5 @ save start of chain branch 10006 add rINST, #-4 @ .. which is 9 bytes back 10007 mov r0,rPC 10008 bl dvmJitGetCodeAddr @ Is there a translation? 10009 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 10010 cmp r0,#0 10011 beq 2f 10012 mov r1,rINST 10013 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 10014 mov r1, rPC @ arg1 of translation may need this 10015 mov lr, #0 @ in case target is HANDLER_INTERPRET 10016 cmp r0,#0 @ successful chain? 10017 bxne r0 @ continue native execution 10018 b toInterpreter @ didn't chain - resume with interpreter 10019 10020/* No translation, so request one if profiling isn't disabled*/ 100212: 10022 adrl rIBASE, dvmAsmInstructionStart 10023 GET_JIT_PROF_TABLE(r0) 10024 FETCH_INST() 10025 cmp r0, #0 10026 movne r2,#kJitTSelectRequestHot @ ask for trace selection 10027 bne common_selectTrace 10028 GET_INST_OPCODE(ip) 10029 GOTO_OPCODE(ip) 10030 10031/* 10032 * Return from the translation cache to the interpreter. 10033 * The return was done with a BLX from thumb mode, and 10034 * the following 32-bit word contains the target rPC value. 10035 * Note that lr (r14) will have its low-order bit set to denote 10036 * its thumb-mode origin. 10037 * 10038 * We'll need to stash our lr origin away, recover the new 10039 * target and then check to see if there is a translation available 10040 * for our new target. If so, we do a translation chain and 10041 * go back to native execution. Otherwise, it's back to the 10042 * interpreter (after treating this entry as a potential 10043 * trace start). 10044 */ 10045 .global dvmJitToInterpNormal 10046dvmJitToInterpNormal: 10047 ldr rPC,[lr, #-1] @ get our target PC 10048 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 10049 add rINST,lr,#-5 @ save start of chain branch 10050 add rINST,#-4 @ .. which is 9 bytes back 10051#if defined(WITH_JIT_TUNING) 10052 bl dvmBumpNormal 10053#endif 10054 mov r0,rPC 10055 bl dvmJitGetCodeAddr @ Is there a translation? 10056 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 10057 cmp r0,#0 10058 beq toInterpreter @ go if not, otherwise do chain 10059 mov r1,rINST 10060 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 10061 mov r1, rPC @ arg1 of translation may need this 10062 mov lr, #0 @ in case target is HANDLER_INTERPRET 10063 cmp r0,#0 @ successful chain? 10064 bxne r0 @ continue native execution 10065 b toInterpreter @ didn't chain - resume with interpreter 10066 10067/* 10068 * Return from the translation cache to the interpreter to do method invocation. 10069 * Check if translation exists for the callee, but don't chain to it. 10070 */ 10071 .global dvmJitToInterpNoChainNoProfile 10072dvmJitToInterpNoChainNoProfile: 10073#if defined(WITH_JIT_TUNING) 10074 bl dvmBumpNoChain 10075#endif 10076 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 10077 mov r0,rPC 10078 bl dvmJitGetCodeAddr @ Is there a translation? 10079 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 10080 mov r1, rPC @ arg1 of translation may need this 10081 mov lr, #0 @ in case target is HANDLER_INTERPRET 10082 cmp r0,#0 10083 bxne r0 @ continue native execution if so 10084 EXPORT_PC() 10085 adrl rIBASE, dvmAsmInstructionStart 10086 FETCH_INST() 10087 GET_INST_OPCODE(ip) @ extract opcode from rINST 10088 GOTO_OPCODE(ip) @ jump to next instruction 10089 10090/* 10091 * Return from the translation cache to the interpreter to do method invocation. 10092 * Check if translation exists for the callee, but don't chain to it. 10093 */ 10094 .global dvmJitToInterpNoChain 10095dvmJitToInterpNoChain: 10096#if defined(WITH_JIT_TUNING) 10097 bl dvmBumpNoChain 10098#endif 10099 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 10100 mov r0,rPC 10101 bl dvmJitGetCodeAddr @ Is there a translation? 10102 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 10103 mov r1, rPC @ arg1 of translation may need this 10104 mov lr, #0 @ in case target is HANDLER_INTERPRET 10105 cmp r0,#0 10106 bxne r0 @ continue native execution if so 10107#endif 10108 10109/* 10110 * No translation, restore interpreter regs and start interpreting. 10111 * rGLUE & rFP were preserved in the translated code, and rPC has 10112 * already been restored by the time we get here. We'll need to set 10113 * up rIBASE & rINST, and load the address of the JitTable into r0. 10114 */ 10115toInterpreter: 10116 EXPORT_PC() 10117 adrl rIBASE, dvmAsmInstructionStart 10118 FETCH_INST() 10119 GET_JIT_PROF_TABLE(r0) 10120 @ NOTE: intended fallthrough 10121 10122/* 10123 * Common code to update potential trace start counter, and initiate 10124 * a trace-build if appropriate. On entry, rPC should point to the 10125 * next instruction to execute, and rINST should be already loaded with 10126 * the next opcode word, and r0 holds a pointer to the jit profile 10127 * table (pJitProfTable). 10128 */ 10129common_testUpdateProfile: 10130 cmp r0,#0 10131 GET_INST_OPCODE(ip) 10132 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 10133 10134common_updateProfile: 10135 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 10136 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 10137 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 10138 GET_INST_OPCODE(ip) 10139 subs r1,r1,#1 @ decrement counter 10140 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 10141 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 10142 10143/* 10144 * Here, we switch to the debug interpreter to request 10145 * trace selection. First, though, check to see if there 10146 * is already a native translation in place (and, if so, 10147 * jump to it now). 10148 */ 10149 GET_JIT_THRESHOLD(r1) 10150 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 10151 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 10152 EXPORT_PC() 10153 mov r0,rPC 10154 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 10155 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 10156 mov r1, rPC @ arg1 of translation may need this 10157 mov lr, #0 @ in case target is HANDLER_INTERPRET 10158 cmp r0,#0 10159#if !defined(WITH_SELF_VERIFICATION) 10160 bxne r0 @ jump to the translation 10161 mov r2,#kJitTSelectRequest @ ask for trace selection 10162 @ fall-through to common_selectTrace 10163#else 10164 moveq r2,#kJitTSelectRequest @ ask for trace selection 10165 beq common_selectTrace 10166 /* 10167 * At this point, we have a target translation. However, if 10168 * that translation is actually the interpret-only pseudo-translation 10169 * we want to treat it the same as no translation. 10170 */ 10171 mov r10, r0 @ save target 10172 bl dvmCompilerGetInterpretTemplate 10173 cmp r0, r10 @ special case? 10174 bne jitSVShadowRunStart @ set up self verification shadow space 10175 @ Need to clear the inJitCodeCache flag 10176 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 10177 mov r3, #0 @ 0 means not in the JIT code cache 10178 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 10179 GET_INST_OPCODE(ip) 10180 GOTO_OPCODE(ip) 10181 /* no return */ 10182#endif 10183 10184/* 10185 * On entry: 10186 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 10187 */ 10188common_selectTrace: 10189 str r2,[rGLUE,#offGlue_jitState] 10190 mov r2,#kInterpEntryInstr @ normal entry reason 10191 str r2,[rGLUE,#offGlue_entryPoint] 10192 mov r1,#1 @ set changeInterp 10193 b common_gotoBail 10194 10195#if defined(WITH_SELF_VERIFICATION) 10196/* 10197 * Save PC and registers to shadow memory for self verification mode 10198 * before jumping to native translation. 10199 * On entry: 10200 * rPC, rFP, rGLUE: the values that they should contain 10201 * r10: the address of the target translation. 10202 */ 10203jitSVShadowRunStart: 10204 mov r0,rPC @ r0<- program counter 10205 mov r1,rFP @ r1<- frame pointer 10206 mov r2,rGLUE @ r2<- InterpState pointer 10207 mov r3,r10 @ r3<- target translation 10208 bl dvmSelfVerificationSaveState @ save registers to shadow space 10209 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 10210 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 10211 bx r10 @ jump to the translation 10212 10213/* 10214 * Restore PC, registers, and interpState to original values 10215 * before jumping back to the interpreter. 10216 */ 10217jitSVShadowRunEnd: 10218 mov r1,rFP @ pass ending fp 10219 bl dvmSelfVerificationRestoreState @ restore pc and fp values 10220 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 10221 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 10222 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 10223 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 10224 cmp r1,#0 @ check for punt condition 10225 beq 1f 10226 mov r2,#kJitSelfVerification @ ask for self verification 10227 str r2,[rGLUE,#offGlue_jitState] 10228 mov r2,#kInterpEntryInstr @ normal entry reason 10229 str r2,[rGLUE,#offGlue_entryPoint] 10230 mov r1,#1 @ set changeInterp 10231 b common_gotoBail 10232 102331: @ exit to interpreter without check 10234 EXPORT_PC() 10235 adrl rIBASE, dvmAsmInstructionStart 10236 FETCH_INST() 10237 GET_INST_OPCODE(ip) 10238 GOTO_OPCODE(ip) 10239#endif 10240 10241#endif 10242 10243/* 10244 * Common code when a backward branch is taken. 10245 * 10246 * TODO: we could avoid a branch by just setting r0 and falling through 10247 * into the common_periodicChecks code, and having a test on r0 at the 10248 * end determine if we should return to the caller or update & branch to 10249 * the next instr. 10250 * 10251 * On entry: 10252 * r9 is PC adjustment *in bytes* 10253 */ 10254common_backwardBranch: 10255 mov r0, #kInterpEntryInstr 10256 bl common_periodicChecks 10257#if defined(WITH_JIT) 10258 GET_JIT_PROF_TABLE(r0) 10259 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 10260 cmp r0,#0 10261 bne common_updateProfile 10262 GET_INST_OPCODE(ip) 10263 GOTO_OPCODE(ip) 10264#else 10265 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 10266 GET_INST_OPCODE(ip) @ extract opcode from rINST 10267 GOTO_OPCODE(ip) @ jump to next instruction 10268#endif 10269 10270 10271/* 10272 * Need to see if the thread needs to be suspended or debugger/profiler 10273 * activity has begun. If so, we suspend the thread or side-exit to 10274 * the debug interpreter as appropriate. 10275 * 10276 * The common case is no activity on any of these, so we want to figure 10277 * that out quickly. If something is up, we can then sort out what. 10278 * 10279 * We want to be fast if the VM was built without debugger or profiler 10280 * support, but we also need to recognize that the system is usually 10281 * shipped with both of these enabled. 10282 * 10283 * TODO: reduce this so we're just checking a single location. 10284 * 10285 * On entry: 10286 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 10287 * r9 is trampoline PC adjustment *in bytes* 10288 */ 10289common_periodicChecks: 10290 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 10291 10292 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 10293 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 10294 10295 ldr ip, [r3] @ ip<- suspendCount (int) 10296 10297 cmp r1, #0 @ debugger enabled? 10298 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 10299 ldr r2, [r2] @ r2<- activeProfilers (int) 10300 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 10301 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 10302 10303 bxeq lr @ all zero, return 10304 10305 /* 10306 * One or more interesting events have happened. Figure out what. 10307 * 10308 * If debugging or profiling are compiled in, we need to disambiguate. 10309 * 10310 * r0 still holds the reentry type. 10311 */ 10312 ldr ip, [r3] @ ip<- suspendCount (int) 10313 cmp ip, #0 @ want suspend? 10314 beq 1f @ no, must be debugger/profiler 10315 10316 stmfd sp!, {r0, lr} @ preserve r0 and lr 10317#if defined(WITH_JIT) 10318 /* 10319 * Refresh the Jit's cached copy of profile table pointer. This pointer 10320 * doubles as the Jit's on/off switch. 10321 */ 10322 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 10323 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 10324 ldr r3, [r3] @ r3 <- pJitProfTable 10325 EXPORT_PC() @ need for precise GC 10326 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 10327#else 10328 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 10329 EXPORT_PC() @ need for precise GC 10330#endif 10331 bl dvmCheckSuspendPending @ do full check, suspend if necessary 10332 ldmfd sp!, {r0, lr} @ restore r0 and lr 10333 10334 /* 10335 * Reload the debugger/profiler enable flags. We're checking to see 10336 * if either of these got set while we were suspended. 10337 * 10338 * We can't really avoid the #ifdefs here, because the fields don't 10339 * exist when the feature is disabled. 10340 */ 10341 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 10342 cmp r1, #0 @ debugger enabled? 10343 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 10344 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 10345 ldr r2, [r2] @ r2<- activeProfilers (int) 10346 10347 orrs r1, r1, r2 10348 beq 2f 10349 103501: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 10351 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 10352 add rPC, rPC, r9 @ update rPC 10353 mov r1, #1 @ "want switch" = true 10354 b common_gotoBail @ side exit 10355 103562: 10357 bx lr @ nothing to do, return 10358 10359 10360/* 10361 * The equivalent of "goto bail", this calls through the "bail handler". 10362 * 10363 * State registers will be saved to the "glue" area before bailing. 10364 * 10365 * On entry: 10366 * r1 is "bool changeInterp", indicating if we want to switch to the 10367 * other interpreter or just bail all the way out 10368 */ 10369common_gotoBail: 10370 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10371 mov r0, rGLUE @ r0<- glue ptr 10372 b dvmMterpStdBail @ call(glue, changeInterp) 10373 10374 @add r1, r1, #1 @ using (boolean+1) 10375 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 10376 @bl _longjmp @ does not return 10377 @bl common_abort 10378 10379 10380/* 10381 * Common code for method invocation with range. 10382 * 10383 * On entry: 10384 * r0 is "Method* methodToCall", the method we're trying to call 10385 */ 10386common_invokeMethodRange: 10387.LinvokeNewRange: 10388 @ prepare to copy args to "outs" area of current frame 10389 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 10390 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 10391 beq .LinvokeArgsDone @ if no args, skip the rest 10392 FETCH(r1, 2) @ r1<- CCCC 10393 10394 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 10395 @ (very few methods have > 10 args; could unroll for common cases) 10396 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 10397 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 10398 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 103991: ldr r1, [r3], #4 @ val = *fp++ 10400 subs r2, r2, #1 @ count-- 10401 str r1, [r10], #4 @ *outs++ = val 10402 bne 1b @ ...while count != 0 10403 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 10404 b .LinvokeArgsDone 10405 10406/* 10407 * Common code for method invocation without range. 10408 * 10409 * On entry: 10410 * r0 is "Method* methodToCall", the method we're trying to call 10411 */ 10412common_invokeMethodNoRange: 10413.LinvokeNewNoRange: 10414 @ prepare to copy args to "outs" area of current frame 10415 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 10416 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 10417 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 10418 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 10419 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 10420 beq .LinvokeArgsDone 10421 10422 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 10423.LinvokeNonRange: 10424 rsb r2, r2, #5 @ r2<- 5-r2 10425 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 10426 bl common_abort @ (skipped due to ARM prefetch) 104275: and ip, rINST, #0x0f00 @ isolate A 10428 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 10429 mov r0, r0 @ nop 10430 str r2, [r10, #-4]! @ *--outs = vA 104314: and ip, r1, #0xf000 @ isolate G 10432 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 10433 mov r0, r0 @ nop 10434 str r2, [r10, #-4]! @ *--outs = vG 104353: and ip, r1, #0x0f00 @ isolate F 10436 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 10437 mov r0, r0 @ nop 10438 str r2, [r10, #-4]! @ *--outs = vF 104392: and ip, r1, #0x00f0 @ isolate E 10440 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 10441 mov r0, r0 @ nop 10442 str r2, [r10, #-4]! @ *--outs = vE 104431: and ip, r1, #0x000f @ isolate D 10444 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 10445 mov r0, r0 @ nop 10446 str r2, [r10, #-4]! @ *--outs = vD 104470: @ fall through to .LinvokeArgsDone 10448 10449.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 10450 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 10451 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 10452 @ find space for the new stack frame, check for overflow 10453 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 10454 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 10455 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 10456@ bl common_dumpRegs 10457 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 10458 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 10459 cmp r3, r9 @ bottom < interpStackEnd? 10460 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 10461 blo .LstackOverflow @ yes, this frame will overflow stack 10462 10463 @ set up newSaveArea 10464#ifdef EASY_GDB 10465 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 10466 str ip, [r10, #offStackSaveArea_prevSave] 10467#endif 10468 str rFP, [r10, #offStackSaveArea_prevFrame] 10469 str rPC, [r10, #offStackSaveArea_savedPc] 10470#if defined(WITH_JIT) 10471 mov r9, #0 10472 str r9, [r10, #offStackSaveArea_returnAddr] 10473#endif 10474 str r0, [r10, #offStackSaveArea_method] 10475 tst r3, #ACC_NATIVE 10476 bne .LinvokeNative 10477 10478 /* 10479 stmfd sp!, {r0-r3} 10480 bl common_printNewline 10481 mov r0, rFP 10482 mov r1, #0 10483 bl dvmDumpFp 10484 ldmfd sp!, {r0-r3} 10485 stmfd sp!, {r0-r3} 10486 mov r0, r1 10487 mov r1, r10 10488 bl dvmDumpFp 10489 bl common_printNewline 10490 ldmfd sp!, {r0-r3} 10491 */ 10492 10493 ldrh r9, [r2] @ r9 <- load INST from new PC 10494 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10495 mov rPC, r2 @ publish new rPC 10496 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10497 10498 @ Update "glue" values for the new method 10499 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10500 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10501 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10502#if defined(WITH_JIT) 10503 GET_JIT_PROF_TABLE(r0) 10504 mov rFP, r1 @ fp = newFp 10505 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10506 mov rINST, r9 @ publish new rINST 10507 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10508 cmp r0,#0 10509 bne common_updateProfile 10510 GOTO_OPCODE(ip) @ jump to next instruction 10511#else 10512 mov rFP, r1 @ fp = newFp 10513 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10514 mov rINST, r9 @ publish new rINST 10515 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10516 GOTO_OPCODE(ip) @ jump to next instruction 10517#endif 10518 10519.LinvokeNative: 10520 @ Prep for the native call 10521 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10522 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10523 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10524 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10525 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10526 mov r9, r3 @ r9<- glue->self (preserve) 10527 10528 mov r2, r0 @ r2<- methodToCall 10529 mov r0, r1 @ r0<- newFp (points to args) 10530 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10531 10532#ifdef ASSIST_DEBUGGER 10533 /* insert fake function header to help gdb find the stack frame */ 10534 b .Lskip 10535 .type dalvik_mterp, %function 10536dalvik_mterp: 10537 .fnstart 10538 MTERP_ENTRY1 10539 MTERP_ENTRY2 10540.Lskip: 10541#endif 10542 10543 @mov lr, pc @ set return addr 10544 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10545 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10546 10547#if defined(WITH_JIT) 10548 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10549#endif 10550 10551 @ native return; r9=self, r10=newSaveArea 10552 @ equivalent to dvmPopJniLocals 10553 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10554 ldr r1, [r9, #offThread_exception] @ check for exception 10555#if defined(WITH_JIT) 10556 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10557#endif 10558 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10559 cmp r1, #0 @ null? 10560 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10561#if defined(WITH_JIT) 10562 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10563#endif 10564 bne common_exceptionThrown @ no, handle exception 10565 10566 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10567 GET_INST_OPCODE(ip) @ extract opcode from rINST 10568 GOTO_OPCODE(ip) @ jump to next instruction 10569 10570.LstackOverflow: @ r0=methodToCall 10571 mov r1, r0 @ r1<- methodToCall 10572 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10573 bl dvmHandleStackOverflow 10574 b common_exceptionThrown 10575#ifdef ASSIST_DEBUGGER 10576 .fnend 10577#endif 10578 10579 10580 /* 10581 * Common code for method invocation, calling through "glue code". 10582 * 10583 * TODO: now that we have range and non-range invoke handlers, this 10584 * needs to be split into two. Maybe just create entry points 10585 * that set r9 and jump here? 10586 * 10587 * On entry: 10588 * r0 is "Method* methodToCall", the method we're trying to call 10589 * r9 is "bool methodCallRange", indicating if this is a /range variant 10590 */ 10591 .if 0 10592.LinvokeOld: 10593 sub sp, sp, #8 @ space for args + pad 10594 FETCH(ip, 2) @ ip<- FEDC or CCCC 10595 mov r2, r0 @ A2<- methodToCall 10596 mov r0, rGLUE @ A0<- glue 10597 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10598 mov r1, r9 @ A1<- methodCallRange 10599 mov r3, rINST, lsr #8 @ A3<- AA 10600 str ip, [sp, #0] @ A4<- ip 10601 bl dvmMterp_invokeMethod @ call the C invokeMethod 10602 add sp, sp, #8 @ remove arg area 10603 b common_resumeAfterGlueCall @ continue to next instruction 10604 .endif 10605 10606 10607 10608/* 10609 * Common code for handling a return instruction. 10610 * 10611 * This does not return. 10612 */ 10613common_returnFromMethod: 10614.LreturnNew: 10615 mov r0, #kInterpEntryReturn 10616 mov r9, #0 10617 bl common_periodicChecks 10618 10619 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10620 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10621 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10622 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10623 @ r2<- method we're returning to 10624 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10625 cmp r2, #0 @ is this a break frame? 10626 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10627 mov r1, #0 @ "want switch" = false 10628 beq common_gotoBail @ break frame, bail out completely 10629 10630 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10631 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10632 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10633 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10634#if defined(WITH_JIT) 10635 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10636 mov rPC, r9 @ publish new rPC 10637 str r1, [rGLUE, #offGlue_methodClassDex] 10638 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10639 cmp r10, #0 @ caller is compiled code 10640 blxne r10 10641 GET_INST_OPCODE(ip) @ extract opcode from rINST 10642 GOTO_OPCODE(ip) @ jump to next instruction 10643#else 10644 GET_INST_OPCODE(ip) @ extract opcode from rINST 10645 mov rPC, r9 @ publish new rPC 10646 str r1, [rGLUE, #offGlue_methodClassDex] 10647 GOTO_OPCODE(ip) @ jump to next instruction 10648#endif 10649 10650 /* 10651 * Return handling, calls through "glue code". 10652 */ 10653 .if 0 10654.LreturnOld: 10655 SAVE_PC_FP_TO_GLUE() @ export state 10656 mov r0, rGLUE @ arg to function 10657 bl dvmMterp_returnFromMethod 10658 b common_resumeAfterGlueCall 10659 .endif 10660 10661 10662/* 10663 * Somebody has thrown an exception. Handle it. 10664 * 10665 * If the exception processing code returns to us (instead of falling 10666 * out of the interpreter), continue with whatever the next instruction 10667 * now happens to be. 10668 * 10669 * This does not return. 10670 */ 10671 .global dvmMterpCommonExceptionThrown 10672dvmMterpCommonExceptionThrown: 10673common_exceptionThrown: 10674.LexceptionNew: 10675 mov r0, #kInterpEntryThrow 10676 mov r9, #0 10677 bl common_periodicChecks 10678 10679 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10680 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10681 mov r1, r10 @ r1<- self 10682 mov r0, r9 @ r0<- exception 10683 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10684 mov r3, #0 @ r3<- NULL 10685 str r3, [r10, #offThread_exception] @ self->exception = NULL 10686 10687 /* set up args and a local for "&fp" */ 10688 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10689 str rFP, [sp, #-4]! @ *--sp = fp 10690 mov ip, sp @ ip<- &fp 10691 mov r3, #0 @ r3<- false 10692 str ip, [sp, #-4]! @ *--sp = &fp 10693 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10694 mov r0, r10 @ r0<- self 10695 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10696 mov r2, r9 @ r2<- exception 10697 sub r1, rPC, r1 @ r1<- pc - method->insns 10698 mov r1, r1, asr #1 @ r1<- offset in code units 10699 10700 /* call, r0 gets catchRelPc (a code-unit offset) */ 10701 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10702 10703 /* fix earlier stack overflow if necessary; may trash rFP */ 10704 ldrb r1, [r10, #offThread_stackOverflowed] 10705 cmp r1, #0 @ did we overflow earlier? 10706 beq 1f @ no, skip ahead 10707 mov rFP, r0 @ save relPc result in rFP 10708 mov r0, r10 @ r0<- self 10709 mov r1, r9 @ r1<- exception 10710 bl dvmCleanupStackOverflow @ call(self) 10711 mov r0, rFP @ restore result 107121: 10713 10714 /* update frame pointer and check result from dvmFindCatchBlock */ 10715 ldr rFP, [sp, #4] @ retrieve the updated rFP 10716 cmp r0, #0 @ is catchRelPc < 0? 10717 add sp, sp, #8 @ restore stack 10718 bmi .LnotCaughtLocally 10719 10720 /* adjust locals to match self->curFrame and updated PC */ 10721 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10722 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10723 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10724 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10725 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10726 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10727 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10728 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10729 10730 /* release the tracked alloc on the exception */ 10731 mov r0, r9 @ r0<- exception 10732 mov r1, r10 @ r1<- self 10733 bl dvmReleaseTrackedAlloc @ release the exception 10734 10735 /* restore the exception if the handler wants it */ 10736 FETCH_INST() @ load rINST from rPC 10737 GET_INST_OPCODE(ip) @ extract opcode from rINST 10738 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10739 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10740 GOTO_OPCODE(ip) @ jump to next instruction 10741 10742.LnotCaughtLocally: @ r9=exception, r10=self 10743 /* fix stack overflow if necessary */ 10744 ldrb r1, [r10, #offThread_stackOverflowed] 10745 cmp r1, #0 @ did we overflow earlier? 10746 movne r0, r10 @ if yes: r0<- self 10747 movne r1, r9 @ if yes: r1<- exception 10748 blne dvmCleanupStackOverflow @ if yes: call(self) 10749 10750 @ may want to show "not caught locally" debug messages here 10751#if DVM_SHOW_EXCEPTION >= 2 10752 /* call __android_log_print(prio, tag, format, ...) */ 10753 /* "Exception %s from %s:%d not caught locally" */ 10754 @ dvmLineNumFromPC(method, pc - method->insns) 10755 ldr r0, [rGLUE, #offGlue_method] 10756 ldr r1, [r0, #offMethod_insns] 10757 sub r1, rPC, r1 10758 asr r1, r1, #1 10759 bl dvmLineNumFromPC 10760 str r0, [sp, #-4]! 10761 @ dvmGetMethodSourceFile(method) 10762 ldr r0, [rGLUE, #offGlue_method] 10763 bl dvmGetMethodSourceFile 10764 str r0, [sp, #-4]! 10765 @ exception->clazz->descriptor 10766 ldr r3, [r9, #offObject_clazz] 10767 ldr r3, [r3, #offClassObject_descriptor] 10768 @ 10769 ldr r2, strExceptionNotCaughtLocally 10770 ldr r1, strLogTag 10771 mov r0, #3 @ LOG_DEBUG 10772 bl __android_log_print 10773#endif 10774 str r9, [r10, #offThread_exception] @ restore exception 10775 mov r0, r9 @ r0<- exception 10776 mov r1, r10 @ r1<- self 10777 bl dvmReleaseTrackedAlloc @ release the exception 10778 mov r1, #0 @ "want switch" = false 10779 b common_gotoBail @ bail out 10780 10781 10782 /* 10783 * Exception handling, calls through "glue code". 10784 */ 10785 .if 0 10786.LexceptionOld: 10787 SAVE_PC_FP_TO_GLUE() @ export state 10788 mov r0, rGLUE @ arg to function 10789 bl dvmMterp_exceptionThrown 10790 b common_resumeAfterGlueCall 10791 .endif 10792 10793 10794/* 10795 * After returning from a "glued" function, pull out the updated 10796 * values and start executing at the next instruction. 10797 */ 10798common_resumeAfterGlueCall: 10799 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10800 FETCH_INST() @ load rINST from rPC 10801 GET_INST_OPCODE(ip) @ extract opcode from rINST 10802 GOTO_OPCODE(ip) @ jump to next instruction 10803 10804/* 10805 * Invalid array index. 10806 */ 10807common_errArrayIndex: 10808 EXPORT_PC() 10809 ldr r0, strArrayIndexException 10810 mov r1, #0 10811 bl dvmThrowException 10812 b common_exceptionThrown 10813 10814/* 10815 * Invalid array value. 10816 */ 10817common_errArrayStore: 10818 EXPORT_PC() 10819 ldr r0, strArrayStoreException 10820 mov r1, #0 10821 bl dvmThrowException 10822 b common_exceptionThrown 10823 10824/* 10825 * Integer divide or mod by zero. 10826 */ 10827common_errDivideByZero: 10828 EXPORT_PC() 10829 ldr r0, strArithmeticException 10830 ldr r1, strDivideByZero 10831 bl dvmThrowException 10832 b common_exceptionThrown 10833 10834/* 10835 * Attempt to allocate an array with a negative size. 10836 */ 10837common_errNegativeArraySize: 10838 EXPORT_PC() 10839 ldr r0, strNegativeArraySizeException 10840 mov r1, #0 10841 bl dvmThrowException 10842 b common_exceptionThrown 10843 10844/* 10845 * Invocation of a non-existent method. 10846 */ 10847common_errNoSuchMethod: 10848 EXPORT_PC() 10849 ldr r0, strNoSuchMethodError 10850 mov r1, #0 10851 bl dvmThrowException 10852 b common_exceptionThrown 10853 10854/* 10855 * We encountered a null object when we weren't expecting one. We 10856 * export the PC, throw a NullPointerException, and goto the exception 10857 * processing code. 10858 */ 10859common_errNullObject: 10860 EXPORT_PC() 10861 ldr r0, strNullPointerException 10862 mov r1, #0 10863 bl dvmThrowException 10864 b common_exceptionThrown 10865 10866/* 10867 * For debugging, cause an immediate fault. The source address will 10868 * be in lr (use a bl instruction to jump here). 10869 */ 10870common_abort: 10871 ldr pc, .LdeadFood 10872.LdeadFood: 10873 .word 0xdeadf00d 10874 10875/* 10876 * Spit out a "we were here", preserving all registers. (The attempt 10877 * to save ip won't work, but we need to save an even number of 10878 * registers for EABI 64-bit stack alignment.) 10879 */ 10880 .macro SQUEAK num 10881common_squeak\num: 10882 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10883 ldr r0, strSqueak 10884 mov r1, #\num 10885 bl printf 10886 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10887 bx lr 10888 .endm 10889 10890 SQUEAK 0 10891 SQUEAK 1 10892 SQUEAK 2 10893 SQUEAK 3 10894 SQUEAK 4 10895 SQUEAK 5 10896 10897/* 10898 * Spit out the number in r0, preserving registers. 10899 */ 10900common_printNum: 10901 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10902 mov r1, r0 10903 ldr r0, strSqueak 10904 bl printf 10905 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10906 bx lr 10907 10908/* 10909 * Print a newline, preserving registers. 10910 */ 10911common_printNewline: 10912 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10913 ldr r0, strNewline 10914 bl printf 10915 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10916 bx lr 10917 10918 /* 10919 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10920 */ 10921common_printHex: 10922 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10923 mov r1, r0 10924 ldr r0, strPrintHex 10925 bl printf 10926 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10927 bx lr 10928 10929/* 10930 * Print the 64-bit quantity in r0-r1, preserving registers. 10931 */ 10932common_printLong: 10933 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10934 mov r3, r1 10935 mov r2, r0 10936 ldr r0, strPrintLong 10937 bl printf 10938 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10939 bx lr 10940 10941/* 10942 * Print full method info. Pass the Method* in r0. Preserves regs. 10943 */ 10944common_printMethod: 10945 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10946 bl dvmMterpPrintMethod 10947 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10948 bx lr 10949 10950/* 10951 * Call a C helper function that dumps regs and possibly some 10952 * additional info. Requires the C function to be compiled in. 10953 */ 10954 .if 0 10955common_dumpRegs: 10956 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10957 bl dvmMterpDumpArmRegs 10958 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10959 bx lr 10960 .endif 10961 10962#if 0 10963/* 10964 * Experiment on VFP mode. 10965 * 10966 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10967 * 10968 * Updates the bits specified by "mask", setting them to the values in "val". 10969 */ 10970setFPSCR: 10971 and r0, r0, r1 @ make sure no stray bits are set 10972 fmrx r2, fpscr @ get VFP reg 10973 mvn r1, r1 @ bit-invert mask 10974 and r2, r2, r1 @ clear masked bits 10975 orr r2, r2, r0 @ set specified bits 10976 fmxr fpscr, r2 @ set VFP reg 10977 mov r0, r2 @ return new value 10978 bx lr 10979 10980 .align 2 10981 .global dvmConfigureFP 10982 .type dvmConfigureFP, %function 10983dvmConfigureFP: 10984 stmfd sp!, {ip, lr} 10985 /* 0x03000000 sets DN/FZ */ 10986 /* 0x00009f00 clears the six exception enable flags */ 10987 bl common_squeak0 10988 mov r0, #0x03000000 @ r0<- 0x03000000 10989 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10990 bl setFPSCR 10991 ldmfd sp!, {ip, pc} 10992#endif 10993 10994 10995/* 10996 * String references, must be close to the code that uses them. 10997 */ 10998 .align 2 10999strArithmeticException: 11000 .word .LstrArithmeticException 11001strArrayIndexException: 11002 .word .LstrArrayIndexException 11003strArrayStoreException: 11004 .word .LstrArrayStoreException 11005strDivideByZero: 11006 .word .LstrDivideByZero 11007strNegativeArraySizeException: 11008 .word .LstrNegativeArraySizeException 11009strNoSuchMethodError: 11010 .word .LstrNoSuchMethodError 11011strNullPointerException: 11012 .word .LstrNullPointerException 11013 11014strLogTag: 11015 .word .LstrLogTag 11016strExceptionNotCaughtLocally: 11017 .word .LstrExceptionNotCaughtLocally 11018 11019strNewline: 11020 .word .LstrNewline 11021strSqueak: 11022 .word .LstrSqueak 11023strPrintHex: 11024 .word .LstrPrintHex 11025strPrintLong: 11026 .word .LstrPrintLong 11027 11028/* 11029 * Zero-terminated ASCII string data. 11030 * 11031 * On ARM we have two choices: do like gcc does, and LDR from a .word 11032 * with the address, or use an ADR pseudo-op to get the address 11033 * directly. ADR saves 4 bytes and an indirection, but it's using a 11034 * PC-relative addressing mode and hence has a limited range, which 11035 * makes it not work well with mergeable string sections. 11036 */ 11037 .section .rodata.str1.4,"aMS",%progbits,1 11038 11039.LstrBadEntryPoint: 11040 .asciz "Bad entry point %d\n" 11041.LstrArithmeticException: 11042 .asciz "Ljava/lang/ArithmeticException;" 11043.LstrArrayIndexException: 11044 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 11045.LstrArrayStoreException: 11046 .asciz "Ljava/lang/ArrayStoreException;" 11047.LstrClassCastException: 11048 .asciz "Ljava/lang/ClassCastException;" 11049.LstrDivideByZero: 11050 .asciz "divide by zero" 11051.LstrFilledNewArrayNotImpl: 11052 .asciz "filled-new-array only implemented for objects and 'int'" 11053.LstrInternalError: 11054 .asciz "Ljava/lang/InternalError;" 11055.LstrInstantiationError: 11056 .asciz "Ljava/lang/InstantiationError;" 11057.LstrNegativeArraySizeException: 11058 .asciz "Ljava/lang/NegativeArraySizeException;" 11059.LstrNoSuchMethodError: 11060 .asciz "Ljava/lang/NoSuchMethodError;" 11061.LstrNullPointerException: 11062 .asciz "Ljava/lang/NullPointerException;" 11063 11064.LstrLogTag: 11065 .asciz "mterp" 11066.LstrExceptionNotCaughtLocally: 11067 .asciz "Exception %s from %s:%d not caught locally\n" 11068 11069.LstrNewline: 11070 .asciz "\n" 11071.LstrSqueak: 11072 .asciz "<%d>" 11073.LstrPrintHex: 11074 .asciz "<0x%x>" 11075.LstrPrintLong: 11076 .asciz "<%lld>" 11077 11078