InterpAsm-armv5te-vfp.S revision 7b133ef7c84e68c3c4042176d830ea5b52e84139
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204#if defined(WITH_JIT) 205#include "../common/jit-config.h" 206#endif 207 208/* File: armv5te/platform.S */ 209/* 210 * =========================================================================== 211 * CPU-version-specific defines 212 * =========================================================================== 213 */ 214 215/* 216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 217 * one-way branch. 218 * 219 * May modify IP. Does not modify LR. 220 */ 221.macro LDR_PC source 222 ldr pc, \source 223.endm 224 225/* 226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 227 * Jump to subroutine. 228 * 229 * May modify IP and LR. 230 */ 231.macro LDR_PC_LR source 232 mov lr, pc 233 ldr pc, \source 234.endm 235 236/* 237 * Macro for "LDMFD SP!, {...regs...,PC}". 238 * 239 * May modify IP and LR. 240 */ 241.macro LDMFD_PC regs 242 ldmfd sp!, {\regs,pc} 243.endm 244 245 246/* File: armv5te/entry.S */ 247/* 248 * Copyright (C) 2008 The Android Open Source Project 249 * 250 * Licensed under the Apache License, Version 2.0 (the "License"); 251 * you may not use this file except in compliance with the License. 252 * You may obtain a copy of the License at 253 * 254 * http://www.apache.org/licenses/LICENSE-2.0 255 * 256 * Unless required by applicable law or agreed to in writing, software 257 * distributed under the License is distributed on an "AS IS" BASIS, 258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 259 * See the License for the specific language governing permissions and 260 * limitations under the License. 261 */ 262/* 263 * Interpreter entry point. 264 */ 265 266/* 267 * We don't have formal stack frames, so gdb scans upward in the code 268 * to find the start of the function (a label with the %function type), 269 * and then looks at the next few instructions to figure out what 270 * got pushed onto the stack. From this it figures out how to restore 271 * the registers, including PC, for the previous stack frame. If gdb 272 * sees a non-function label, it stops scanning, so either we need to 273 * have nothing but assembler-local labels between the entry point and 274 * the break, or we need to fake it out. 275 * 276 * When this is defined, we add some stuff to make gdb less confused. 277 */ 278#define ASSIST_DEBUGGER 1 279 280 .text 281 .align 2 282 .global dvmMterpStdRun 283 .type dvmMterpStdRun, %function 284 285/* 286 * On entry: 287 * r0 MterpGlue* glue 288 * 289 * This function returns a boolean "changeInterp" value. The return comes 290 * via a call to dvmMterpStdBail(). 291 */ 292dvmMterpStdRun: 293#define MTERP_ENTRY1 \ 294 .save {r4-r10,fp,lr}; \ 295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 296#define MTERP_ENTRY2 \ 297 .pad #4; \ 298 sub sp, sp, #4 @ align 64 299 300 .fnstart 301 MTERP_ENTRY1 302 MTERP_ENTRY2 303 304 /* save stack pointer, add magic word for debuggerd */ 305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 306 307 /* set up "named" registers, figure out entry point */ 308 mov rGLUE, r0 @ set rGLUE 309 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 312 cmp r1, #kInterpEntryInstr @ usual case? 313 bne .Lnot_instr @ no, handle it 314 315#if defined(WITH_JIT) 316.Lno_singleStep: 317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 318 /* Entry is always a possible trace start */ 319 GET_JIT_PROF_TABLE(r0) 320 FETCH_INST() 321 mov r1, #0 @ prepare the value for the new state 322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 323 cmp r0,#0 324 bne common_updateProfile 325 GET_INST_OPCODE(ip) 326 GOTO_OPCODE(ip) 327#else 328 /* start executing the instruction at rPC */ 329 FETCH_INST() @ load rINST from rPC 330 GET_INST_OPCODE(ip) @ extract opcode from rINST 331 GOTO_OPCODE(ip) @ jump to next instruction 332#endif 333 334.Lnot_instr: 335 cmp r1, #kInterpEntryReturn @ were we returning from a method? 336 beq common_returnFromMethod 337 338.Lnot_return: 339 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 340 beq common_exceptionThrown 341 342#if defined(WITH_JIT) 343.Lnot_throw: 344 ldr r0,[rGLUE, #offGlue_jitResume] 345 ldr r2,[rGLUE, #offGlue_jitResumePC] 346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 347 bne .Lbad_arg 348 cmp rPC,r2 349 bne .Lno_singleStep @ must have branched, don't resume 350 mov r1, #kInterpEntryInstr 351 strb r1, [rGLUE, #offGlue_entryPoint] 352 ldr rINST, .LdvmCompilerTemplate 353 bx r0 @ re-enter the translation 354.LdvmCompilerTemplate: 355 .word dvmCompilerTemplateStart 356#endif 357 358.Lbad_arg: 359 ldr r0, strBadEntryPoint 360 @ r1 holds value of entryPoint 361 bl printf 362 bl dvmAbort 363 .fnend 364 365 366 .global dvmMterpStdBail 367 .type dvmMterpStdBail, %function 368 369/* 370 * Restore the stack pointer and PC from the save point established on entry. 371 * This is essentially the same as a longjmp, but should be cheaper. The 372 * last instruction causes us to return to whoever called dvmMterpStdRun. 373 * 374 * We pushed some registers on the stack in dvmMterpStdRun, then saved 375 * SP and LR. Here we restore SP, restore the registers, and then restore 376 * LR to PC. 377 * 378 * On entry: 379 * r0 MterpGlue* glue 380 * r1 bool changeInterp 381 */ 382dvmMterpStdBail: 383 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 384 mov r0, r1 @ return the changeInterp value 385 add sp, sp, #4 @ un-align 64 386 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 387 388 389/* 390 * String references. 391 */ 392strBadEntryPoint: 393 .word .LstrBadEntryPoint 394 395 396 397 .global dvmAsmInstructionStart 398 .type dvmAsmInstructionStart, %function 399dvmAsmInstructionStart = .L_OP_NOP 400 .text 401 402/* ------------------------------ */ 403 .balign 64 404.L_OP_NOP: /* 0x00 */ 405/* File: armv5te/OP_NOP.S */ 406 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 407 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 408 GOTO_OPCODE(ip) @ execute it 409 410#ifdef ASSIST_DEBUGGER 411 /* insert fake function header to help gdb find the stack frame */ 412 .type dalvik_inst, %function 413dalvik_inst: 414 .fnstart 415 MTERP_ENTRY1 416 MTERP_ENTRY2 417 .fnend 418#endif 419 420 421/* ------------------------------ */ 422 .balign 64 423.L_OP_MOVE: /* 0x01 */ 424/* File: armv5te/OP_MOVE.S */ 425 /* for move, move-object, long-to-int */ 426 /* op vA, vB */ 427 mov r1, rINST, lsr #12 @ r1<- B from 15:12 428 mov r0, rINST, lsr #8 @ r0<- A from 11:8 429 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 430 GET_VREG(r2, r1) @ r2<- fp[B] 431 and r0, r0, #15 432 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 433 SET_VREG(r2, r0) @ fp[A]<- r2 434 GOTO_OPCODE(ip) @ execute next instruction 435 436 437/* ------------------------------ */ 438 .balign 64 439.L_OP_MOVE_FROM16: /* 0x02 */ 440/* File: armv5te/OP_MOVE_FROM16.S */ 441 /* for: move/from16, move-object/from16 */ 442 /* op vAA, vBBBB */ 443 FETCH(r1, 1) @ r1<- BBBB 444 mov r0, rINST, lsr #8 @ r0<- AA 445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 446 GET_VREG(r2, r1) @ r2<- fp[BBBB] 447 GET_INST_OPCODE(ip) @ extract opcode from rINST 448 SET_VREG(r2, r0) @ fp[AA]<- r2 449 GOTO_OPCODE(ip) @ jump to next instruction 450 451 452/* ------------------------------ */ 453 .balign 64 454.L_OP_MOVE_16: /* 0x03 */ 455/* File: armv5te/OP_MOVE_16.S */ 456 /* for: move/16, move-object/16 */ 457 /* op vAAAA, vBBBB */ 458 FETCH(r1, 2) @ r1<- BBBB 459 FETCH(r0, 1) @ r0<- AAAA 460 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 461 GET_VREG(r2, r1) @ r2<- fp[BBBB] 462 GET_INST_OPCODE(ip) @ extract opcode from rINST 463 SET_VREG(r2, r0) @ fp[AAAA]<- r2 464 GOTO_OPCODE(ip) @ jump to next instruction 465 466 467/* ------------------------------ */ 468 .balign 64 469.L_OP_MOVE_WIDE: /* 0x04 */ 470/* File: armv5te/OP_MOVE_WIDE.S */ 471 /* move-wide vA, vB */ 472 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 473 mov r2, rINST, lsr #8 @ r2<- A(+) 474 mov r3, rINST, lsr #12 @ r3<- B 475 and r2, r2, #15 476 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 477 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 478 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 479 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 480 GET_INST_OPCODE(ip) @ extract opcode from rINST 481 stmia r2, {r0-r1} @ fp[A]<- r0/r1 482 GOTO_OPCODE(ip) @ jump to next instruction 483 484 485/* ------------------------------ */ 486 .balign 64 487.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 488/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 489 /* move-wide/from16 vAA, vBBBB */ 490 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 491 FETCH(r3, 1) @ r3<- BBBB 492 mov r2, rINST, lsr #8 @ r2<- AA 493 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 494 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 495 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 497 GET_INST_OPCODE(ip) @ extract opcode from rINST 498 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 499 GOTO_OPCODE(ip) @ jump to next instruction 500 501 502/* ------------------------------ */ 503 .balign 64 504.L_OP_MOVE_WIDE_16: /* 0x06 */ 505/* File: armv5te/OP_MOVE_WIDE_16.S */ 506 /* move-wide/16 vAAAA, vBBBB */ 507 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 508 FETCH(r3, 2) @ r3<- BBBB 509 FETCH(r2, 1) @ r2<- AAAA 510 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 511 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 512 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 513 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 514 GET_INST_OPCODE(ip) @ extract opcode from rINST 515 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 516 GOTO_OPCODE(ip) @ jump to next instruction 517 518 519/* ------------------------------ */ 520 .balign 64 521.L_OP_MOVE_OBJECT: /* 0x07 */ 522/* File: armv5te/OP_MOVE_OBJECT.S */ 523/* File: armv5te/OP_MOVE.S */ 524 /* for move, move-object, long-to-int */ 525 /* op vA, vB */ 526 mov r1, rINST, lsr #12 @ r1<- B from 15:12 527 mov r0, rINST, lsr #8 @ r0<- A from 11:8 528 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 529 GET_VREG(r2, r1) @ r2<- fp[B] 530 and r0, r0, #15 531 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 532 SET_VREG(r2, r0) @ fp[A]<- r2 533 GOTO_OPCODE(ip) @ execute next instruction 534 535 536 537/* ------------------------------ */ 538 .balign 64 539.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 540/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 541/* File: armv5te/OP_MOVE_FROM16.S */ 542 /* for: move/from16, move-object/from16 */ 543 /* op vAA, vBBBB */ 544 FETCH(r1, 1) @ r1<- BBBB 545 mov r0, rINST, lsr #8 @ r0<- AA 546 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 547 GET_VREG(r2, r1) @ r2<- fp[BBBB] 548 GET_INST_OPCODE(ip) @ extract opcode from rINST 549 SET_VREG(r2, r0) @ fp[AA]<- r2 550 GOTO_OPCODE(ip) @ jump to next instruction 551 552 553 554/* ------------------------------ */ 555 .balign 64 556.L_OP_MOVE_OBJECT_16: /* 0x09 */ 557/* File: armv5te/OP_MOVE_OBJECT_16.S */ 558/* File: armv5te/OP_MOVE_16.S */ 559 /* for: move/16, move-object/16 */ 560 /* op vAAAA, vBBBB */ 561 FETCH(r1, 2) @ r1<- BBBB 562 FETCH(r0, 1) @ r0<- AAAA 563 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 564 GET_VREG(r2, r1) @ r2<- fp[BBBB] 565 GET_INST_OPCODE(ip) @ extract opcode from rINST 566 SET_VREG(r2, r0) @ fp[AAAA]<- r2 567 GOTO_OPCODE(ip) @ jump to next instruction 568 569 570 571/* ------------------------------ */ 572 .balign 64 573.L_OP_MOVE_RESULT: /* 0x0a */ 574/* File: armv5te/OP_MOVE_RESULT.S */ 575 /* for: move-result, move-result-object */ 576 /* op vAA */ 577 mov r2, rINST, lsr #8 @ r2<- AA 578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 579 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 580 GET_INST_OPCODE(ip) @ extract opcode from rINST 581 SET_VREG(r0, r2) @ fp[AA]<- r0 582 GOTO_OPCODE(ip) @ jump to next instruction 583 584 585/* ------------------------------ */ 586 .balign 64 587.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 588/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 589 /* move-result-wide vAA */ 590 mov r2, rINST, lsr #8 @ r2<- AA 591 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 592 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 593 ldmia r3, {r0-r1} @ r0/r1<- retval.j 594 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 595 GET_INST_OPCODE(ip) @ extract opcode from rINST 596 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 597 GOTO_OPCODE(ip) @ jump to next instruction 598 599 600/* ------------------------------ */ 601 .balign 64 602.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 603/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 604/* File: armv5te/OP_MOVE_RESULT.S */ 605 /* for: move-result, move-result-object */ 606 /* op vAA */ 607 mov r2, rINST, lsr #8 @ r2<- AA 608 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 609 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 610 GET_INST_OPCODE(ip) @ extract opcode from rINST 611 SET_VREG(r0, r2) @ fp[AA]<- r0 612 GOTO_OPCODE(ip) @ jump to next instruction 613 614 615 616/* ------------------------------ */ 617 .balign 64 618.L_OP_MOVE_EXCEPTION: /* 0x0d */ 619/* File: armv5te/OP_MOVE_EXCEPTION.S */ 620 /* move-exception vAA */ 621 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 622 mov r2, rINST, lsr #8 @ r2<- AA 623 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 624 mov r1, #0 @ r1<- 0 625 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 626 SET_VREG(r3, r2) @ fp[AA]<- exception obj 627 GET_INST_OPCODE(ip) @ extract opcode from rINST 628 str r1, [r0, #offThread_exception] @ dvmClearException bypass 629 GOTO_OPCODE(ip) @ jump to next instruction 630 631 632/* ------------------------------ */ 633 .balign 64 634.L_OP_RETURN_VOID: /* 0x0e */ 635/* File: armv5te/OP_RETURN_VOID.S */ 636 b common_returnFromMethod 637 638 639/* ------------------------------ */ 640 .balign 64 641.L_OP_RETURN: /* 0x0f */ 642/* File: armv5te/OP_RETURN.S */ 643 /* 644 * Return a 32-bit value. Copies the return value into the "glue" 645 * structure, then jumps to the return handler. 646 * 647 * for: return, return-object 648 */ 649 /* op vAA */ 650 mov r2, rINST, lsr #8 @ r2<- AA 651 GET_VREG(r0, r2) @ r0<- vAA 652 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 653 b common_returnFromMethod 654 655 656/* ------------------------------ */ 657 .balign 64 658.L_OP_RETURN_WIDE: /* 0x10 */ 659/* File: armv5te/OP_RETURN_WIDE.S */ 660 /* 661 * Return a 64-bit value. Copies the return value into the "glue" 662 * structure, then jumps to the return handler. 663 */ 664 /* return-wide vAA */ 665 mov r2, rINST, lsr #8 @ r2<- AA 666 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 667 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 668 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 669 stmia r3, {r0-r1} @ retval<- r0/r1 670 b common_returnFromMethod 671 672 673/* ------------------------------ */ 674 .balign 64 675.L_OP_RETURN_OBJECT: /* 0x11 */ 676/* File: armv5te/OP_RETURN_OBJECT.S */ 677/* File: armv5te/OP_RETURN.S */ 678 /* 679 * Return a 32-bit value. Copies the return value into the "glue" 680 * structure, then jumps to the return handler. 681 * 682 * for: return, return-object 683 */ 684 /* op vAA */ 685 mov r2, rINST, lsr #8 @ r2<- AA 686 GET_VREG(r0, r2) @ r0<- vAA 687 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 688 b common_returnFromMethod 689 690 691 692/* ------------------------------ */ 693 .balign 64 694.L_OP_CONST_4: /* 0x12 */ 695/* File: armv5te/OP_CONST_4.S */ 696 /* const/4 vA, #+B */ 697 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 698 mov r0, rINST, lsr #8 @ r0<- A+ 699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 700 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 701 and r0, r0, #15 702 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 703 SET_VREG(r1, r0) @ fp[A]<- r1 704 GOTO_OPCODE(ip) @ execute next instruction 705 706 707/* ------------------------------ */ 708 .balign 64 709.L_OP_CONST_16: /* 0x13 */ 710/* File: armv5te/OP_CONST_16.S */ 711 /* const/16 vAA, #+BBBB */ 712 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 713 mov r3, rINST, lsr #8 @ r3<- AA 714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 715 SET_VREG(r0, r3) @ vAA<- r0 716 GET_INST_OPCODE(ip) @ extract opcode from rINST 717 GOTO_OPCODE(ip) @ jump to next instruction 718 719 720/* ------------------------------ */ 721 .balign 64 722.L_OP_CONST: /* 0x14 */ 723/* File: armv5te/OP_CONST.S */ 724 /* const vAA, #+BBBBbbbb */ 725 mov r3, rINST, lsr #8 @ r3<- AA 726 FETCH(r0, 1) @ r0<- bbbb (low) 727 FETCH(r1, 2) @ r1<- BBBB (high) 728 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 730 GET_INST_OPCODE(ip) @ extract opcode from rINST 731 SET_VREG(r0, r3) @ vAA<- r0 732 GOTO_OPCODE(ip) @ jump to next instruction 733 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/* ------------------------------ */ 750 .balign 64 751.L_OP_CONST_WIDE_16: /* 0x16 */ 752/* File: armv5te/OP_CONST_WIDE_16.S */ 753 /* const-wide/16 vAA, #+BBBB */ 754 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 755 mov r3, rINST, lsr #8 @ r3<- AA 756 mov r1, r0, asr #31 @ r1<- ssssssss 757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 758 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 759 GET_INST_OPCODE(ip) @ extract opcode from rINST 760 stmia r3, {r0-r1} @ vAA<- r0/r1 761 GOTO_OPCODE(ip) @ jump to next instruction 762 763 764/* ------------------------------ */ 765 .balign 64 766.L_OP_CONST_WIDE_32: /* 0x17 */ 767/* File: armv5te/OP_CONST_WIDE_32.S */ 768 /* const-wide/32 vAA, #+BBBBbbbb */ 769 FETCH(r0, 1) @ r0<- 0000bbbb (low) 770 mov r3, rINST, lsr #8 @ r3<- AA 771 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 772 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 773 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 774 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 775 mov r1, r0, asr #31 @ r1<- ssssssss 776 GET_INST_OPCODE(ip) @ extract opcode from rINST 777 stmia r3, {r0-r1} @ vAA<- r0/r1 778 GOTO_OPCODE(ip) @ jump to next instruction 779 780 781/* ------------------------------ */ 782 .balign 64 783.L_OP_CONST_WIDE: /* 0x18 */ 784/* File: armv5te/OP_CONST_WIDE.S */ 785 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 786 FETCH(r0, 1) @ r0<- bbbb (low) 787 FETCH(r1, 2) @ r1<- BBBB (low middle) 788 FETCH(r2, 3) @ r2<- hhhh (high middle) 789 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 790 FETCH(r3, 4) @ r3<- HHHH (high) 791 mov r9, rINST, lsr #8 @ r9<- AA 792 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 793 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 794 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 795 GET_INST_OPCODE(ip) @ extract opcode from rINST 796 stmia r9, {r0-r1} @ vAA<- r0/r1 797 GOTO_OPCODE(ip) @ jump to next instruction 798 799 800/* ------------------------------ */ 801 .balign 64 802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 804 /* const-wide/high16 vAA, #+BBBB000000000000 */ 805 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 806 mov r3, rINST, lsr #8 @ r3<- AA 807 mov r0, #0 @ r0<- 00000000 808 mov r1, r1, lsl #16 @ r1<- BBBB0000 809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 810 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 811 GET_INST_OPCODE(ip) @ extract opcode from rINST 812 stmia r3, {r0-r1} @ vAA<- r0/r1 813 GOTO_OPCODE(ip) @ jump to next instruction 814 815 816/* ------------------------------ */ 817 .balign 64 818.L_OP_CONST_STRING: /* 0x1a */ 819/* File: armv5te/OP_CONST_STRING.S */ 820 /* const/string vAA, String@BBBB */ 821 FETCH(r1, 1) @ r1<- BBBB 822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 823 mov r9, rINST, lsr #8 @ r9<- AA 824 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 825 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 826 cmp r0, #0 @ not yet resolved? 827 beq .LOP_CONST_STRING_resolve 828 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 829 GET_INST_OPCODE(ip) @ extract opcode from rINST 830 SET_VREG(r0, r9) @ vAA<- r0 831 GOTO_OPCODE(ip) @ jump to next instruction 832 833/* ------------------------------ */ 834 .balign 64 835.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 836/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 837 /* const/string vAA, String@BBBBBBBB */ 838 FETCH(r0, 1) @ r0<- bbbb (low) 839 FETCH(r1, 2) @ r1<- BBBB (high) 840 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 841 mov r9, rINST, lsr #8 @ r9<- AA 842 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 843 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 844 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 845 cmp r0, #0 846 beq .LOP_CONST_STRING_JUMBO_resolve 847 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 848 GET_INST_OPCODE(ip) @ extract opcode from rINST 849 SET_VREG(r0, r9) @ vAA<- r0 850 GOTO_OPCODE(ip) @ jump to next instruction 851 852/* ------------------------------ */ 853 .balign 64 854.L_OP_CONST_CLASS: /* 0x1c */ 855/* File: armv5te/OP_CONST_CLASS.S */ 856 /* const/class vAA, Class@BBBB */ 857 FETCH(r1, 1) @ r1<- BBBB 858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 859 mov r9, rINST, lsr #8 @ r9<- AA 860 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 861 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 862 cmp r0, #0 @ not yet resolved? 863 beq .LOP_CONST_CLASS_resolve 864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 865 GET_INST_OPCODE(ip) @ extract opcode from rINST 866 SET_VREG(r0, r9) @ vAA<- r0 867 GOTO_OPCODE(ip) @ jump to next instruction 868 869/* ------------------------------ */ 870 .balign 64 871.L_OP_MONITOR_ENTER: /* 0x1d */ 872/* File: armv5te/OP_MONITOR_ENTER.S */ 873 /* 874 * Synchronize on an object. 875 */ 876 /* monitor-enter vAA */ 877 mov r2, rINST, lsr #8 @ r2<- AA 878 GET_VREG(r1, r2) @ r1<- vAA (object) 879 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 880 cmp r1, #0 @ null object? 881 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 882 beq common_errNullObject @ null object, throw an exception 883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 884 bl dvmLockObject @ call(self, obj) 885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 886 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 887 ldr r1, [r0, #offThread_exception] @ check for exception 888 cmp r1, #0 889 bne common_exceptionThrown @ exception raised, bail out 890#endif 891 GET_INST_OPCODE(ip) @ extract opcode from rINST 892 GOTO_OPCODE(ip) @ jump to next instruction 893 894 895/* ------------------------------ */ 896 .balign 64 897.L_OP_MONITOR_EXIT: /* 0x1e */ 898/* File: armv5te/OP_MONITOR_EXIT.S */ 899 /* 900 * Unlock an object. 901 * 902 * Exceptions that occur when unlocking a monitor need to appear as 903 * if they happened at the following instruction. See the Dalvik 904 * instruction spec. 905 */ 906 /* monitor-exit vAA */ 907 mov r2, rINST, lsr #8 @ r2<- AA 908 EXPORT_PC() @ before fetch: export the PC 909 GET_VREG(r1, r2) @ r1<- vAA (object) 910 cmp r1, #0 @ null object? 911 beq common_errNullObject @ yes 912 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 913 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 914 cmp r0, #0 @ failed? 915 beq common_exceptionThrown @ yes, exception is pending 916 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 917 GET_INST_OPCODE(ip) @ extract opcode from rINST 918 GOTO_OPCODE(ip) @ jump to next instruction 919 920 921/* ------------------------------ */ 922 .balign 64 923.L_OP_CHECK_CAST: /* 0x1f */ 924/* File: armv5te/OP_CHECK_CAST.S */ 925 /* 926 * Check to see if a cast from one class to another is allowed. 927 */ 928 /* check-cast vAA, class@BBBB */ 929 mov r3, rINST, lsr #8 @ r3<- AA 930 FETCH(r2, 1) @ r2<- BBBB 931 GET_VREG(r9, r3) @ r9<- object 932 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 933 cmp r9, #0 @ is object null? 934 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 935 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 936 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 937 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 938 cmp r1, #0 @ have we resolved this before? 939 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 940.LOP_CHECK_CAST_resolved: 941 cmp r0, r1 @ same class (trivial success)? 942 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 943.LOP_CHECK_CAST_okay: 944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 945 GET_INST_OPCODE(ip) @ extract opcode from rINST 946 GOTO_OPCODE(ip) @ jump to next instruction 947 948/* ------------------------------ */ 949 .balign 64 950.L_OP_INSTANCE_OF: /* 0x20 */ 951/* File: armv5te/OP_INSTANCE_OF.S */ 952 /* 953 * Check to see if an object reference is an instance of a class. 954 * 955 * Most common situation is a non-null object, being compared against 956 * an already-resolved class. 957 */ 958 /* instance-of vA, vB, class@CCCC */ 959 mov r3, rINST, lsr #12 @ r3<- B 960 mov r9, rINST, lsr #8 @ r9<- A+ 961 GET_VREG(r0, r3) @ r0<- vB (object) 962 and r9, r9, #15 @ r9<- A 963 cmp r0, #0 @ is object null? 964 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 965 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 966 FETCH(r3, 1) @ r3<- CCCC 967 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 968 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 969 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 970 cmp r1, #0 @ have we resolved this before? 971 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 972.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 973 cmp r0, r1 @ same class (trivial success)? 974 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 975 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 976 977/* ------------------------------ */ 978 .balign 64 979.L_OP_ARRAY_LENGTH: /* 0x21 */ 980/* File: armv5te/OP_ARRAY_LENGTH.S */ 981 /* 982 * Return the length of an array. 983 */ 984 mov r1, rINST, lsr #12 @ r1<- B 985 mov r2, rINST, lsr #8 @ r2<- A+ 986 GET_VREG(r0, r1) @ r0<- vB (object ref) 987 and r2, r2, #15 @ r2<- A 988 cmp r0, #0 @ is object null? 989 beq common_errNullObject @ yup, fail 990 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 991 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 992 GET_INST_OPCODE(ip) @ extract opcode from rINST 993 SET_VREG(r3, r2) @ vB<- length 994 GOTO_OPCODE(ip) @ jump to next instruction 995 996 997/* ------------------------------ */ 998 .balign 64 999.L_OP_NEW_INSTANCE: /* 0x22 */ 1000/* File: armv5te/OP_NEW_INSTANCE.S */ 1001 /* 1002 * Create a new instance of a class. 1003 */ 1004 /* new-instance vAA, class@BBBB */ 1005 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1006 FETCH(r1, 1) @ r1<- BBBB 1007 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1008 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1009 EXPORT_PC() @ req'd for init, resolve, alloc 1010 cmp r0, #0 @ already resolved? 1011 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1012.LOP_NEW_INSTANCE_resolved: @ r0=class 1013 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1014 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1015 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1016.LOP_NEW_INSTANCE_initialized: @ r0=class 1017 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1018 bl dvmAllocObject @ r0<- new object 1019 b .LOP_NEW_INSTANCE_finish @ continue 1020 1021/* ------------------------------ */ 1022 .balign 64 1023.L_OP_NEW_ARRAY: /* 0x23 */ 1024/* File: armv5te/OP_NEW_ARRAY.S */ 1025 /* 1026 * Allocate an array of objects, specified with the array class 1027 * and a count. 1028 * 1029 * The verifier guarantees that this is an array class, so we don't 1030 * check for it here. 1031 */ 1032 /* new-array vA, vB, class@CCCC */ 1033 mov r0, rINST, lsr #12 @ r0<- B 1034 FETCH(r2, 1) @ r2<- CCCC 1035 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1036 GET_VREG(r1, r0) @ r1<- vB (array length) 1037 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1038 cmp r1, #0 @ check length 1039 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1040 bmi common_errNegativeArraySize @ negative length, bail 1041 cmp r0, #0 @ already resolved? 1042 EXPORT_PC() @ req'd for resolve, alloc 1043 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1044 b .LOP_NEW_ARRAY_resolve @ do resolve now 1045 1046/* ------------------------------ */ 1047 .balign 64 1048.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1049/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1050 /* 1051 * Create a new array with elements filled from registers. 1052 * 1053 * for: filled-new-array, filled-new-array/range 1054 */ 1055 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1056 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1057 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1058 FETCH(r1, 1) @ r1<- BBBB 1059 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1060 EXPORT_PC() @ need for resolve and alloc 1061 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1062 mov r10, rINST, lsr #8 @ r10<- AA or BA 1063 cmp r0, #0 @ already resolved? 1064 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10658: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1066 mov r2, #0 @ r2<- false 1067 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1068 bl dvmResolveClass @ r0<- call(clazz, ref) 1069 cmp r0, #0 @ got null? 1070 beq common_exceptionThrown @ yes, handle exception 1071 b .LOP_FILLED_NEW_ARRAY_continue 1072 1073/* ------------------------------ */ 1074 .balign 64 1075.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1076/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1077/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1078 /* 1079 * Create a new array with elements filled from registers. 1080 * 1081 * for: filled-new-array, filled-new-array/range 1082 */ 1083 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1084 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1085 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1086 FETCH(r1, 1) @ r1<- BBBB 1087 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1088 EXPORT_PC() @ need for resolve and alloc 1089 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1090 mov r10, rINST, lsr #8 @ r10<- AA or BA 1091 cmp r0, #0 @ already resolved? 1092 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10938: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1094 mov r2, #0 @ r2<- false 1095 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1096 bl dvmResolveClass @ r0<- call(clazz, ref) 1097 cmp r0, #0 @ got null? 1098 beq common_exceptionThrown @ yes, handle exception 1099 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1100 1101 1102/* ------------------------------ */ 1103 .balign 64 1104.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1105/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1106 /* fill-array-data vAA, +BBBBBBBB */ 1107 FETCH(r0, 1) @ r0<- bbbb (lo) 1108 FETCH(r1, 2) @ r1<- BBBB (hi) 1109 mov r3, rINST, lsr #8 @ r3<- AA 1110 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1111 GET_VREG(r0, r3) @ r0<- vAA (array object) 1112 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1113 EXPORT_PC(); 1114 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1115 cmp r0, #0 @ 0 means an exception is thrown 1116 beq common_exceptionThrown @ has exception 1117 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1118 GET_INST_OPCODE(ip) @ extract opcode from rINST 1119 GOTO_OPCODE(ip) @ jump to next instruction 1120 1121/* ------------------------------ */ 1122 .balign 64 1123.L_OP_THROW: /* 0x27 */ 1124/* File: armv5te/OP_THROW.S */ 1125 /* 1126 * Throw an exception object in the current thread. 1127 */ 1128 /* throw vAA */ 1129 mov r2, rINST, lsr #8 @ r2<- AA 1130 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1131 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1132 cmp r1, #0 @ null object? 1133 beq common_errNullObject @ yes, throw an NPE instead 1134 @ bypass dvmSetException, just store it 1135 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1136 b common_exceptionThrown 1137 1138 1139/* ------------------------------ */ 1140 .balign 64 1141.L_OP_GOTO: /* 0x28 */ 1142/* File: armv5te/OP_GOTO.S */ 1143 /* 1144 * Unconditional branch, 8-bit offset. 1145 * 1146 * The branch distance is a signed code-unit offset, which we need to 1147 * double to get a byte offset. 1148 */ 1149 /* goto +AA */ 1150 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1151 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1152 mov r9, r9, lsl #1 @ r9<- byte offset 1153 bmi common_backwardBranch @ backward branch, do periodic checks 1154#if defined(WITH_JIT) 1155 GET_JIT_PROF_TABLE(r0) 1156 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1157 cmp r0,#0 1158 bne common_updateProfile 1159 GET_INST_OPCODE(ip) @ extract opcode from rINST 1160 GOTO_OPCODE(ip) @ jump to next instruction 1161#else 1162 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1163 GET_INST_OPCODE(ip) @ extract opcode from rINST 1164 GOTO_OPCODE(ip) @ jump to next instruction 1165#endif 1166 1167/* ------------------------------ */ 1168 .balign 64 1169.L_OP_GOTO_16: /* 0x29 */ 1170/* File: armv5te/OP_GOTO_16.S */ 1171 /* 1172 * Unconditional branch, 16-bit offset. 1173 * 1174 * The branch distance is a signed code-unit offset, which we need to 1175 * double to get a byte offset. 1176 */ 1177 /* goto/16 +AAAA */ 1178 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1179 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1180 bmi common_backwardBranch @ backward branch, do periodic checks 1181#if defined(WITH_JIT) 1182 GET_JIT_PROF_TABLE(r0) 1183 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1184 cmp r0,#0 1185 bne common_updateProfile 1186 GET_INST_OPCODE(ip) @ extract opcode from rINST 1187 GOTO_OPCODE(ip) @ jump to next instruction 1188#else 1189 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1190 GET_INST_OPCODE(ip) @ extract opcode from rINST 1191 GOTO_OPCODE(ip) @ jump to next instruction 1192#endif 1193 1194 1195/* ------------------------------ */ 1196 .balign 64 1197.L_OP_GOTO_32: /* 0x2a */ 1198/* File: armv5te/OP_GOTO_32.S */ 1199 /* 1200 * Unconditional branch, 32-bit offset. 1201 * 1202 * The branch distance is a signed code-unit offset, which we need to 1203 * double to get a byte offset. 1204 * 1205 * Unlike most opcodes, this one is allowed to branch to itself, so 1206 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1207 * instruction doesn't affect the V flag, so we need to clear it 1208 * explicitly. 1209 */ 1210 /* goto/32 +AAAAAAAA */ 1211 FETCH(r0, 1) @ r0<- aaaa (lo) 1212 FETCH(r1, 2) @ r1<- AAAA (hi) 1213 cmp ip, ip @ (clear V flag during stall) 1214 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1215 mov r9, r0, asl #1 @ r9<- byte offset 1216 ble common_backwardBranch @ backward branch, do periodic checks 1217#if defined(WITH_JIT) 1218 GET_JIT_PROF_TABLE(r0) 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 cmp r0,#0 1221 bne common_updateProfile 1222 GET_INST_OPCODE(ip) @ extract opcode from rINST 1223 GOTO_OPCODE(ip) @ jump to next instruction 1224#else 1225 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1226 GET_INST_OPCODE(ip) @ extract opcode from rINST 1227 GOTO_OPCODE(ip) @ jump to next instruction 1228#endif 1229 1230/* ------------------------------ */ 1231 .balign 64 1232.L_OP_PACKED_SWITCH: /* 0x2b */ 1233/* File: armv5te/OP_PACKED_SWITCH.S */ 1234 /* 1235 * Handle a packed-switch or sparse-switch instruction. In both cases 1236 * we decode it and hand it off to a helper function. 1237 * 1238 * We don't really expect backward branches in a switch statement, but 1239 * they're perfectly legal, so we check for them here. 1240 * 1241 * for: packed-switch, sparse-switch 1242 */ 1243 /* op vAA, +BBBB */ 1244 FETCH(r0, 1) @ r0<- bbbb (lo) 1245 FETCH(r1, 2) @ r1<- BBBB (hi) 1246 mov r3, rINST, lsr #8 @ r3<- AA 1247 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1248 GET_VREG(r1, r3) @ r1<- vAA 1249 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1250 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1251 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1252 bmi common_backwardBranch @ backward branch, do periodic checks 1253 beq common_backwardBranch @ (want to use BLE but V is unknown) 1254#if defined(WITH_JIT) 1255 GET_JIT_PROF_TABLE(r0) 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 cmp r0,#0 1258 bne common_updateProfile 1259 GET_INST_OPCODE(ip) @ extract opcode from rINST 1260 GOTO_OPCODE(ip) @ jump to next instruction 1261#else 1262 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1263 GET_INST_OPCODE(ip) @ extract opcode from rINST 1264 GOTO_OPCODE(ip) @ jump to next instruction 1265#endif 1266 1267 1268/* ------------------------------ */ 1269 .balign 64 1270.L_OP_SPARSE_SWITCH: /* 0x2c */ 1271/* File: armv5te/OP_SPARSE_SWITCH.S */ 1272/* File: armv5te/OP_PACKED_SWITCH.S */ 1273 /* 1274 * Handle a packed-switch or sparse-switch instruction. In both cases 1275 * we decode it and hand it off to a helper function. 1276 * 1277 * We don't really expect backward branches in a switch statement, but 1278 * they're perfectly legal, so we check for them here. 1279 * 1280 * for: packed-switch, sparse-switch 1281 */ 1282 /* op vAA, +BBBB */ 1283 FETCH(r0, 1) @ r0<- bbbb (lo) 1284 FETCH(r1, 2) @ r1<- BBBB (hi) 1285 mov r3, rINST, lsr #8 @ r3<- AA 1286 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1287 GET_VREG(r1, r3) @ r1<- vAA 1288 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1289 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1290 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1291 bmi common_backwardBranch @ backward branch, do periodic checks 1292 beq common_backwardBranch @ (want to use BLE but V is unknown) 1293#if defined(WITH_JIT) 1294 GET_JIT_PROF_TABLE(r0) 1295 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1296 cmp r0,#0 1297 bne common_updateProfile 1298 GET_INST_OPCODE(ip) @ extract opcode from rINST 1299 GOTO_OPCODE(ip) @ jump to next instruction 1300#else 1301 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1302 GET_INST_OPCODE(ip) @ extract opcode from rINST 1303 GOTO_OPCODE(ip) @ jump to next instruction 1304#endif 1305 1306 1307 1308/* ------------------------------ */ 1309 .balign 64 1310.L_OP_CMPL_FLOAT: /* 0x2d */ 1311/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1312 /* 1313 * Compare two floating-point values. Puts 0, 1, or -1 into the 1314 * destination register based on the results of the comparison. 1315 * 1316 * int compare(x, y) { 1317 * if (x == y) { 1318 * return 0; 1319 * } else if (x > y) { 1320 * return 1; 1321 * } else if (x < y) { 1322 * return -1; 1323 * } else { 1324 * return -1; 1325 * } 1326 * } 1327 */ 1328 /* op vAA, vBB, vCC */ 1329 FETCH(r0, 1) @ r0<- CCBB 1330 mov r9, rINST, lsr #8 @ r9<- AA 1331 and r2, r0, #255 @ r2<- BB 1332 mov r3, r0, lsr #8 @ r3<- CC 1333 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1334 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1335 flds s0, [r2] @ s0<- vBB 1336 flds s1, [r3] @ s1<- vCC 1337 fcmpes s0, s1 @ compare (vBB, vCC) 1338 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1339 mvn r0, #0 @ r0<- -1 (default) 1340 GET_INST_OPCODE(ip) @ extract opcode from rINST 1341 fmstat @ export status flags 1342 movgt r0, #1 @ (greater than) r1<- 1 1343 moveq r0, #0 @ (equal) r1<- 0 1344 b .LOP_CMPL_FLOAT_finish @ argh 1345 1346 1347/* ------------------------------ */ 1348 .balign 64 1349.L_OP_CMPG_FLOAT: /* 0x2e */ 1350/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1351 /* 1352 * Compare two floating-point values. Puts 0, 1, or -1 into the 1353 * destination register based on the results of the comparison. 1354 * 1355 * int compare(x, y) { 1356 * if (x == y) { 1357 * return 0; 1358 * } else if (x < y) { 1359 * return -1; 1360 * } else if (x > y) { 1361 * return 1; 1362 * } else { 1363 * return 1; 1364 * } 1365 * } 1366 */ 1367 /* op vAA, vBB, vCC */ 1368 FETCH(r0, 1) @ r0<- CCBB 1369 mov r9, rINST, lsr #8 @ r9<- AA 1370 and r2, r0, #255 @ r2<- BB 1371 mov r3, r0, lsr #8 @ r3<- CC 1372 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1373 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1374 flds s0, [r2] @ s0<- vBB 1375 flds s1, [r3] @ s1<- vCC 1376 fcmpes s0, s1 @ compare (vBB, vCC) 1377 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1378 mov r0, #1 @ r0<- 1 (default) 1379 GET_INST_OPCODE(ip) @ extract opcode from rINST 1380 fmstat @ export status flags 1381 mvnmi r0, #0 @ (less than) r1<- -1 1382 moveq r0, #0 @ (equal) r1<- 0 1383 b .LOP_CMPG_FLOAT_finish @ argh 1384 1385 1386/* ------------------------------ */ 1387 .balign 64 1388.L_OP_CMPL_DOUBLE: /* 0x2f */ 1389/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1390 /* 1391 * Compare two floating-point values. Puts 0, 1, or -1 into the 1392 * destination register based on the results of the comparison. 1393 * 1394 * int compare(x, y) { 1395 * if (x == y) { 1396 * return 0; 1397 * } else if (x > y) { 1398 * return 1; 1399 * } else if (x < y) { 1400 * return -1; 1401 * } else { 1402 * return -1; 1403 * } 1404 * } 1405 */ 1406 /* op vAA, vBB, vCC */ 1407 FETCH(r0, 1) @ r0<- CCBB 1408 mov r9, rINST, lsr #8 @ r9<- AA 1409 and r2, r0, #255 @ r2<- BB 1410 mov r3, r0, lsr #8 @ r3<- CC 1411 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1412 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1413 fldd d0, [r2] @ d0<- vBB 1414 fldd d1, [r3] @ d1<- vCC 1415 fcmped d0, d1 @ compare (vBB, vCC) 1416 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1417 mvn r0, #0 @ r0<- -1 (default) 1418 GET_INST_OPCODE(ip) @ extract opcode from rINST 1419 fmstat @ export status flags 1420 movgt r0, #1 @ (greater than) r1<- 1 1421 moveq r0, #0 @ (equal) r1<- 0 1422 b .LOP_CMPL_DOUBLE_finish @ argh 1423 1424 1425/* ------------------------------ */ 1426 .balign 64 1427.L_OP_CMPG_DOUBLE: /* 0x30 */ 1428/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1429 /* 1430 * Compare two floating-point values. Puts 0, 1, or -1 into the 1431 * destination register based on the results of the comparison. 1432 * 1433 * int compare(x, y) { 1434 * if (x == y) { 1435 * return 0; 1436 * } else if (x < y) { 1437 * return -1; 1438 * } else if (x > y) { 1439 * return 1; 1440 * } else { 1441 * return 1; 1442 * } 1443 * } 1444 */ 1445 /* op vAA, vBB, vCC */ 1446 FETCH(r0, 1) @ r0<- CCBB 1447 mov r9, rINST, lsr #8 @ r9<- AA 1448 and r2, r0, #255 @ r2<- BB 1449 mov r3, r0, lsr #8 @ r3<- CC 1450 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1451 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1452 fldd d0, [r2] @ d0<- vBB 1453 fldd d1, [r3] @ d1<- vCC 1454 fcmped d0, d1 @ compare (vBB, vCC) 1455 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1456 mov r0, #1 @ r0<- 1 (default) 1457 GET_INST_OPCODE(ip) @ extract opcode from rINST 1458 fmstat @ export status flags 1459 mvnmi r0, #0 @ (less than) r1<- -1 1460 moveq r0, #0 @ (equal) r1<- 0 1461 b .LOP_CMPG_DOUBLE_finish @ argh 1462 1463 1464/* ------------------------------ */ 1465 .balign 64 1466.L_OP_CMP_LONG: /* 0x31 */ 1467/* File: armv5te/OP_CMP_LONG.S */ 1468 /* 1469 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1470 * register based on the results of the comparison. 1471 * 1472 * We load the full values with LDM, but in practice many values could 1473 * be resolved by only looking at the high word. This could be made 1474 * faster or slower by splitting the LDM into a pair of LDRs. 1475 * 1476 * If we just wanted to set condition flags, we could do this: 1477 * subs ip, r0, r2 1478 * sbcs ip, r1, r3 1479 * subeqs ip, r0, r2 1480 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1481 * integer value, which we can do with 2 conditional mov/mvn instructions 1482 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1483 * us a constant 5-cycle path plus a branch at the end to the 1484 * instruction epilogue code. The multi-compare approach below needs 1485 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1486 * in the worst case (the 64-bit values are equal). 1487 */ 1488 /* cmp-long vAA, vBB, vCC */ 1489 FETCH(r0, 1) @ r0<- CCBB 1490 mov r9, rINST, lsr #8 @ r9<- AA 1491 and r2, r0, #255 @ r2<- BB 1492 mov r3, r0, lsr #8 @ r3<- CC 1493 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1494 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1495 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1496 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1497 cmp r1, r3 @ compare (vBB+1, vCC+1) 1498 blt .LOP_CMP_LONG_less @ signed compare on high part 1499 bgt .LOP_CMP_LONG_greater 1500 subs r1, r0, r2 @ r1<- r0 - r2 1501 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1502 bne .LOP_CMP_LONG_less 1503 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1504 1505/* ------------------------------ */ 1506 .balign 64 1507.L_OP_IF_EQ: /* 0x32 */ 1508/* File: armv5te/OP_IF_EQ.S */ 1509/* File: armv5te/bincmp.S */ 1510 /* 1511 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1512 * fragment that specifies the *reverse* comparison to perform, e.g. 1513 * for "if-le" you would use "gt". 1514 * 1515 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1516 */ 1517 /* if-cmp vA, vB, +CCCC */ 1518 mov r0, rINST, lsr #8 @ r0<- A+ 1519 mov r1, rINST, lsr #12 @ r1<- B 1520 and r0, r0, #15 1521 GET_VREG(r3, r1) @ r3<- vB 1522 GET_VREG(r2, r0) @ r2<- vA 1523 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1524 cmp r2, r3 @ compare (vA, vB) 1525 bne 1f @ branch to 1 if comparison failed 1526 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1527 movs r9, r9, asl #1 @ convert to bytes, check sign 1528 bmi common_backwardBranch @ yes, do periodic checks 15291: 1530#if defined(WITH_JIT) 1531 GET_JIT_PROF_TABLE(r0) 1532 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1533 b common_testUpdateProfile 1534#else 1535 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1536 GET_INST_OPCODE(ip) @ extract opcode from rINST 1537 GOTO_OPCODE(ip) @ jump to next instruction 1538#endif 1539 1540 1541 1542/* ------------------------------ */ 1543 .balign 64 1544.L_OP_IF_NE: /* 0x33 */ 1545/* File: armv5te/OP_IF_NE.S */ 1546/* File: armv5te/bincmp.S */ 1547 /* 1548 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1549 * fragment that specifies the *reverse* comparison to perform, e.g. 1550 * for "if-le" you would use "gt". 1551 * 1552 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1553 */ 1554 /* if-cmp vA, vB, +CCCC */ 1555 mov r0, rINST, lsr #8 @ r0<- A+ 1556 mov r1, rINST, lsr #12 @ r1<- B 1557 and r0, r0, #15 1558 GET_VREG(r3, r1) @ r3<- vB 1559 GET_VREG(r2, r0) @ r2<- vA 1560 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1561 cmp r2, r3 @ compare (vA, vB) 1562 beq 1f @ branch to 1 if comparison failed 1563 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1564 movs r9, r9, asl #1 @ convert to bytes, check sign 1565 bmi common_backwardBranch @ yes, do periodic checks 15661: 1567#if defined(WITH_JIT) 1568 GET_JIT_PROF_TABLE(r0) 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 b common_testUpdateProfile 1571#else 1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1573 GET_INST_OPCODE(ip) @ extract opcode from rINST 1574 GOTO_OPCODE(ip) @ jump to next instruction 1575#endif 1576 1577 1578 1579/* ------------------------------ */ 1580 .balign 64 1581.L_OP_IF_LT: /* 0x34 */ 1582/* File: armv5te/OP_IF_LT.S */ 1583/* File: armv5te/bincmp.S */ 1584 /* 1585 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1586 * fragment that specifies the *reverse* comparison to perform, e.g. 1587 * for "if-le" you would use "gt". 1588 * 1589 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1590 */ 1591 /* if-cmp vA, vB, +CCCC */ 1592 mov r0, rINST, lsr #8 @ r0<- A+ 1593 mov r1, rINST, lsr #12 @ r1<- B 1594 and r0, r0, #15 1595 GET_VREG(r3, r1) @ r3<- vB 1596 GET_VREG(r2, r0) @ r2<- vA 1597 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1598 cmp r2, r3 @ compare (vA, vB) 1599 bge 1f @ branch to 1 if comparison failed 1600 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1601 movs r9, r9, asl #1 @ convert to bytes, check sign 1602 bmi common_backwardBranch @ yes, do periodic checks 16031: 1604#if defined(WITH_JIT) 1605 GET_JIT_PROF_TABLE(r0) 1606 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1607 b common_testUpdateProfile 1608#else 1609 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1610 GET_INST_OPCODE(ip) @ extract opcode from rINST 1611 GOTO_OPCODE(ip) @ jump to next instruction 1612#endif 1613 1614 1615 1616/* ------------------------------ */ 1617 .balign 64 1618.L_OP_IF_GE: /* 0x35 */ 1619/* File: armv5te/OP_IF_GE.S */ 1620/* File: armv5te/bincmp.S */ 1621 /* 1622 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1623 * fragment that specifies the *reverse* comparison to perform, e.g. 1624 * for "if-le" you would use "gt". 1625 * 1626 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1627 */ 1628 /* if-cmp vA, vB, +CCCC */ 1629 mov r0, rINST, lsr #8 @ r0<- A+ 1630 mov r1, rINST, lsr #12 @ r1<- B 1631 and r0, r0, #15 1632 GET_VREG(r3, r1) @ r3<- vB 1633 GET_VREG(r2, r0) @ r2<- vA 1634 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1635 cmp r2, r3 @ compare (vA, vB) 1636 blt 1f @ branch to 1 if comparison failed 1637 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1638 movs r9, r9, asl #1 @ convert to bytes, check sign 1639 bmi common_backwardBranch @ yes, do periodic checks 16401: 1641#if defined(WITH_JIT) 1642 GET_JIT_PROF_TABLE(r0) 1643 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1644 b common_testUpdateProfile 1645#else 1646 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1647 GET_INST_OPCODE(ip) @ extract opcode from rINST 1648 GOTO_OPCODE(ip) @ jump to next instruction 1649#endif 1650 1651 1652 1653/* ------------------------------ */ 1654 .balign 64 1655.L_OP_IF_GT: /* 0x36 */ 1656/* File: armv5te/OP_IF_GT.S */ 1657/* File: armv5te/bincmp.S */ 1658 /* 1659 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1660 * fragment that specifies the *reverse* comparison to perform, e.g. 1661 * for "if-le" you would use "gt". 1662 * 1663 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1664 */ 1665 /* if-cmp vA, vB, +CCCC */ 1666 mov r0, rINST, lsr #8 @ r0<- A+ 1667 mov r1, rINST, lsr #12 @ r1<- B 1668 and r0, r0, #15 1669 GET_VREG(r3, r1) @ r3<- vB 1670 GET_VREG(r2, r0) @ r2<- vA 1671 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1672 cmp r2, r3 @ compare (vA, vB) 1673 ble 1f @ branch to 1 if comparison failed 1674 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1675 movs r9, r9, asl #1 @ convert to bytes, check sign 1676 bmi common_backwardBranch @ yes, do periodic checks 16771: 1678#if defined(WITH_JIT) 1679 GET_JIT_PROF_TABLE(r0) 1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1681 b common_testUpdateProfile 1682#else 1683 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1684 GET_INST_OPCODE(ip) @ extract opcode from rINST 1685 GOTO_OPCODE(ip) @ jump to next instruction 1686#endif 1687 1688 1689 1690/* ------------------------------ */ 1691 .balign 64 1692.L_OP_IF_LE: /* 0x37 */ 1693/* File: armv5te/OP_IF_LE.S */ 1694/* File: armv5te/bincmp.S */ 1695 /* 1696 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1697 * fragment that specifies the *reverse* comparison to perform, e.g. 1698 * for "if-le" you would use "gt". 1699 * 1700 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1701 */ 1702 /* if-cmp vA, vB, +CCCC */ 1703 mov r0, rINST, lsr #8 @ r0<- A+ 1704 mov r1, rINST, lsr #12 @ r1<- B 1705 and r0, r0, #15 1706 GET_VREG(r3, r1) @ r3<- vB 1707 GET_VREG(r2, r0) @ r2<- vA 1708 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1709 cmp r2, r3 @ compare (vA, vB) 1710 bgt 1f @ branch to 1 if comparison failed 1711 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1712 movs r9, r9, asl #1 @ convert to bytes, check sign 1713 bmi common_backwardBranch @ yes, do periodic checks 17141: 1715#if defined(WITH_JIT) 1716 GET_JIT_PROF_TABLE(r0) 1717 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1718 b common_testUpdateProfile 1719#else 1720 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1721 GET_INST_OPCODE(ip) @ extract opcode from rINST 1722 GOTO_OPCODE(ip) @ jump to next instruction 1723#endif 1724 1725 1726 1727/* ------------------------------ */ 1728 .balign 64 1729.L_OP_IF_EQZ: /* 0x38 */ 1730/* File: armv5te/OP_IF_EQZ.S */ 1731/* File: armv5te/zcmp.S */ 1732 /* 1733 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1734 * fragment that specifies the *reverse* comparison to perform, e.g. 1735 * for "if-le" you would use "gt". 1736 * 1737 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1738 */ 1739 /* if-cmp vAA, +BBBB */ 1740 mov r0, rINST, lsr #8 @ r0<- AA 1741 GET_VREG(r2, r0) @ r2<- vAA 1742 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1743 cmp r2, #0 @ compare (vA, 0) 1744 bne 1f @ branch to 1 if comparison failed 1745 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1746 movs r9, r9, asl #1 @ convert to bytes, check sign 1747 bmi common_backwardBranch @ backward branch, do periodic checks 17481: 1749#if defined(WITH_JIT) 1750 GET_JIT_PROF_TABLE(r0) 1751 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1752 cmp r0,#0 1753 bne common_updateProfile 1754 GET_INST_OPCODE(ip) @ extract opcode from rINST 1755 GOTO_OPCODE(ip) @ jump to next instruction 1756#else 1757 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1758 GET_INST_OPCODE(ip) @ extract opcode from rINST 1759 GOTO_OPCODE(ip) @ jump to next instruction 1760#endif 1761 1762 1763 1764/* ------------------------------ */ 1765 .balign 64 1766.L_OP_IF_NEZ: /* 0x39 */ 1767/* File: armv5te/OP_IF_NEZ.S */ 1768/* File: armv5te/zcmp.S */ 1769 /* 1770 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1771 * fragment that specifies the *reverse* comparison to perform, e.g. 1772 * for "if-le" you would use "gt". 1773 * 1774 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1775 */ 1776 /* if-cmp vAA, +BBBB */ 1777 mov r0, rINST, lsr #8 @ r0<- AA 1778 GET_VREG(r2, r0) @ r2<- vAA 1779 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1780 cmp r2, #0 @ compare (vA, 0) 1781 beq 1f @ branch to 1 if comparison failed 1782 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1783 movs r9, r9, asl #1 @ convert to bytes, check sign 1784 bmi common_backwardBranch @ backward branch, do periodic checks 17851: 1786#if defined(WITH_JIT) 1787 GET_JIT_PROF_TABLE(r0) 1788 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1789 cmp r0,#0 1790 bne common_updateProfile 1791 GET_INST_OPCODE(ip) @ extract opcode from rINST 1792 GOTO_OPCODE(ip) @ jump to next instruction 1793#else 1794 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1795 GET_INST_OPCODE(ip) @ extract opcode from rINST 1796 GOTO_OPCODE(ip) @ jump to next instruction 1797#endif 1798 1799 1800 1801/* ------------------------------ */ 1802 .balign 64 1803.L_OP_IF_LTZ: /* 0x3a */ 1804/* File: armv5te/OP_IF_LTZ.S */ 1805/* File: armv5te/zcmp.S */ 1806 /* 1807 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1808 * fragment that specifies the *reverse* comparison to perform, e.g. 1809 * for "if-le" you would use "gt". 1810 * 1811 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1812 */ 1813 /* if-cmp vAA, +BBBB */ 1814 mov r0, rINST, lsr #8 @ r0<- AA 1815 GET_VREG(r2, r0) @ r2<- vAA 1816 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1817 cmp r2, #0 @ compare (vA, 0) 1818 bge 1f @ branch to 1 if comparison failed 1819 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1820 movs r9, r9, asl #1 @ convert to bytes, check sign 1821 bmi common_backwardBranch @ backward branch, do periodic checks 18221: 1823#if defined(WITH_JIT) 1824 GET_JIT_PROF_TABLE(r0) 1825 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1826 cmp r0,#0 1827 bne common_updateProfile 1828 GET_INST_OPCODE(ip) @ extract opcode from rINST 1829 GOTO_OPCODE(ip) @ jump to next instruction 1830#else 1831 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1832 GET_INST_OPCODE(ip) @ extract opcode from rINST 1833 GOTO_OPCODE(ip) @ jump to next instruction 1834#endif 1835 1836 1837 1838/* ------------------------------ */ 1839 .balign 64 1840.L_OP_IF_GEZ: /* 0x3b */ 1841/* File: armv5te/OP_IF_GEZ.S */ 1842/* File: armv5te/zcmp.S */ 1843 /* 1844 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1845 * fragment that specifies the *reverse* comparison to perform, e.g. 1846 * for "if-le" you would use "gt". 1847 * 1848 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1849 */ 1850 /* if-cmp vAA, +BBBB */ 1851 mov r0, rINST, lsr #8 @ r0<- AA 1852 GET_VREG(r2, r0) @ r2<- vAA 1853 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1854 cmp r2, #0 @ compare (vA, 0) 1855 blt 1f @ branch to 1 if comparison failed 1856 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1857 movs r9, r9, asl #1 @ convert to bytes, check sign 1858 bmi common_backwardBranch @ backward branch, do periodic checks 18591: 1860#if defined(WITH_JIT) 1861 GET_JIT_PROF_TABLE(r0) 1862 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1863 cmp r0,#0 1864 bne common_updateProfile 1865 GET_INST_OPCODE(ip) @ extract opcode from rINST 1866 GOTO_OPCODE(ip) @ jump to next instruction 1867#else 1868 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1869 GET_INST_OPCODE(ip) @ extract opcode from rINST 1870 GOTO_OPCODE(ip) @ jump to next instruction 1871#endif 1872 1873 1874 1875/* ------------------------------ */ 1876 .balign 64 1877.L_OP_IF_GTZ: /* 0x3c */ 1878/* File: armv5te/OP_IF_GTZ.S */ 1879/* File: armv5te/zcmp.S */ 1880 /* 1881 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1882 * fragment that specifies the *reverse* comparison to perform, e.g. 1883 * for "if-le" you would use "gt". 1884 * 1885 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1886 */ 1887 /* if-cmp vAA, +BBBB */ 1888 mov r0, rINST, lsr #8 @ r0<- AA 1889 GET_VREG(r2, r0) @ r2<- vAA 1890 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1891 cmp r2, #0 @ compare (vA, 0) 1892 ble 1f @ branch to 1 if comparison failed 1893 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1894 movs r9, r9, asl #1 @ convert to bytes, check sign 1895 bmi common_backwardBranch @ backward branch, do periodic checks 18961: 1897#if defined(WITH_JIT) 1898 GET_JIT_PROF_TABLE(r0) 1899 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1900 cmp r0,#0 1901 bne common_updateProfile 1902 GET_INST_OPCODE(ip) @ extract opcode from rINST 1903 GOTO_OPCODE(ip) @ jump to next instruction 1904#else 1905 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1906 GET_INST_OPCODE(ip) @ extract opcode from rINST 1907 GOTO_OPCODE(ip) @ jump to next instruction 1908#endif 1909 1910 1911 1912/* ------------------------------ */ 1913 .balign 64 1914.L_OP_IF_LEZ: /* 0x3d */ 1915/* File: armv5te/OP_IF_LEZ.S */ 1916/* File: armv5te/zcmp.S */ 1917 /* 1918 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1919 * fragment that specifies the *reverse* comparison to perform, e.g. 1920 * for "if-le" you would use "gt". 1921 * 1922 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1923 */ 1924 /* if-cmp vAA, +BBBB */ 1925 mov r0, rINST, lsr #8 @ r0<- AA 1926 GET_VREG(r2, r0) @ r2<- vAA 1927 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1928 cmp r2, #0 @ compare (vA, 0) 1929 bgt 1f @ branch to 1 if comparison failed 1930 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1931 movs r9, r9, asl #1 @ convert to bytes, check sign 1932 bmi common_backwardBranch @ backward branch, do periodic checks 19331: 1934#if defined(WITH_JIT) 1935 GET_JIT_PROF_TABLE(r0) 1936 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1937 cmp r0,#0 1938 bne common_updateProfile 1939 GET_INST_OPCODE(ip) @ extract opcode from rINST 1940 GOTO_OPCODE(ip) @ jump to next instruction 1941#else 1942 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1943 GET_INST_OPCODE(ip) @ extract opcode from rINST 1944 GOTO_OPCODE(ip) @ jump to next instruction 1945#endif 1946 1947 1948 1949/* ------------------------------ */ 1950 .balign 64 1951.L_OP_UNUSED_3E: /* 0x3e */ 1952/* File: armv5te/OP_UNUSED_3E.S */ 1953/* File: armv5te/unused.S */ 1954 bl common_abort 1955 1956 1957 1958/* ------------------------------ */ 1959 .balign 64 1960.L_OP_UNUSED_3F: /* 0x3f */ 1961/* File: armv5te/OP_UNUSED_3F.S */ 1962/* File: armv5te/unused.S */ 1963 bl common_abort 1964 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/* ------------------------------ */ 1977 .balign 64 1978.L_OP_UNUSED_41: /* 0x41 */ 1979/* File: armv5te/OP_UNUSED_41.S */ 1980/* File: armv5te/unused.S */ 1981 bl common_abort 1982 1983 1984 1985/* ------------------------------ */ 1986 .balign 64 1987.L_OP_UNUSED_42: /* 0x42 */ 1988/* File: armv5te/OP_UNUSED_42.S */ 1989/* File: armv5te/unused.S */ 1990 bl common_abort 1991 1992 1993 1994/* ------------------------------ */ 1995 .balign 64 1996.L_OP_UNUSED_43: /* 0x43 */ 1997/* File: armv5te/OP_UNUSED_43.S */ 1998/* File: armv5te/unused.S */ 1999 bl common_abort 2000 2001 2002 2003/* ------------------------------ */ 2004 .balign 64 2005.L_OP_AGET: /* 0x44 */ 2006/* File: armv5te/OP_AGET.S */ 2007 /* 2008 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2009 * 2010 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2011 * instructions. We use a pair of FETCH_Bs instead. 2012 * 2013 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2014 */ 2015 /* op vAA, vBB, vCC */ 2016 FETCH_B(r2, 1, 0) @ r2<- BB 2017 mov r9, rINST, lsr #8 @ r9<- AA 2018 FETCH_B(r3, 1, 1) @ r3<- CC 2019 GET_VREG(r0, r2) @ r0<- vBB (array object) 2020 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2021 cmp r0, #0 @ null array object? 2022 beq common_errNullObject @ yes, bail 2023 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2024 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2025 cmp r1, r3 @ compare unsigned index, length 2026 bcs common_errArrayIndex @ index >= length, bail 2027 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2028 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2029 GET_INST_OPCODE(ip) @ extract opcode from rINST 2030 SET_VREG(r2, r9) @ vAA<- r2 2031 GOTO_OPCODE(ip) @ jump to next instruction 2032 2033 2034/* ------------------------------ */ 2035 .balign 64 2036.L_OP_AGET_WIDE: /* 0x45 */ 2037/* File: armv5te/OP_AGET_WIDE.S */ 2038 /* 2039 * Array get, 64 bits. vAA <- vBB[vCC]. 2040 * 2041 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2042 */ 2043 /* aget-wide vAA, vBB, vCC */ 2044 FETCH(r0, 1) @ r0<- CCBB 2045 mov r9, rINST, lsr #8 @ r9<- AA 2046 and r2, r0, #255 @ r2<- BB 2047 mov r3, r0, lsr #8 @ r3<- CC 2048 GET_VREG(r0, r2) @ r0<- vBB (array object) 2049 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2050 cmp r0, #0 @ null array object? 2051 beq common_errNullObject @ yes, bail 2052 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2053 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2054 cmp r1, r3 @ compare unsigned index, length 2055 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2056 b common_errArrayIndex @ index >= length, bail 2057 @ May want to swap the order of these two branches depending on how the 2058 @ branch prediction (if any) handles conditional forward branches vs. 2059 @ unconditional forward branches. 2060 2061/* ------------------------------ */ 2062 .balign 64 2063.L_OP_AGET_OBJECT: /* 0x46 */ 2064/* File: armv5te/OP_AGET_OBJECT.S */ 2065/* File: armv5te/OP_AGET.S */ 2066 /* 2067 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2068 * 2069 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2070 * instructions. We use a pair of FETCH_Bs instead. 2071 * 2072 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2073 */ 2074 /* op vAA, vBB, vCC */ 2075 FETCH_B(r2, 1, 0) @ r2<- BB 2076 mov r9, rINST, lsr #8 @ r9<- AA 2077 FETCH_B(r3, 1, 1) @ r3<- CC 2078 GET_VREG(r0, r2) @ r0<- vBB (array object) 2079 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2080 cmp r0, #0 @ null array object? 2081 beq common_errNullObject @ yes, bail 2082 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2083 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2084 cmp r1, r3 @ compare unsigned index, length 2085 bcs common_errArrayIndex @ index >= length, bail 2086 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2087 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2088 GET_INST_OPCODE(ip) @ extract opcode from rINST 2089 SET_VREG(r2, r9) @ vAA<- r2 2090 GOTO_OPCODE(ip) @ jump to next instruction 2091 2092 2093 2094/* ------------------------------ */ 2095 .balign 64 2096.L_OP_AGET_BOOLEAN: /* 0x47 */ 2097/* File: armv5te/OP_AGET_BOOLEAN.S */ 2098/* File: armv5te/OP_AGET.S */ 2099 /* 2100 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2101 * 2102 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2103 * instructions. We use a pair of FETCH_Bs instead. 2104 * 2105 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2106 */ 2107 /* op vAA, vBB, vCC */ 2108 FETCH_B(r2, 1, 0) @ r2<- BB 2109 mov r9, rINST, lsr #8 @ r9<- AA 2110 FETCH_B(r3, 1, 1) @ r3<- CC 2111 GET_VREG(r0, r2) @ r0<- vBB (array object) 2112 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2113 cmp r0, #0 @ null array object? 2114 beq common_errNullObject @ yes, bail 2115 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2116 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2117 cmp r1, r3 @ compare unsigned index, length 2118 bcs common_errArrayIndex @ index >= length, bail 2119 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2120 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2121 GET_INST_OPCODE(ip) @ extract opcode from rINST 2122 SET_VREG(r2, r9) @ vAA<- r2 2123 GOTO_OPCODE(ip) @ jump to next instruction 2124 2125 2126 2127/* ------------------------------ */ 2128 .balign 64 2129.L_OP_AGET_BYTE: /* 0x48 */ 2130/* File: armv5te/OP_AGET_BYTE.S */ 2131/* File: armv5te/OP_AGET.S */ 2132 /* 2133 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2134 * 2135 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2136 * instructions. We use a pair of FETCH_Bs instead. 2137 * 2138 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2139 */ 2140 /* op vAA, vBB, vCC */ 2141 FETCH_B(r2, 1, 0) @ r2<- BB 2142 mov r9, rINST, lsr #8 @ r9<- AA 2143 FETCH_B(r3, 1, 1) @ r3<- CC 2144 GET_VREG(r0, r2) @ r0<- vBB (array object) 2145 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2146 cmp r0, #0 @ null array object? 2147 beq common_errNullObject @ yes, bail 2148 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2149 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2150 cmp r1, r3 @ compare unsigned index, length 2151 bcs common_errArrayIndex @ index >= length, bail 2152 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2153 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2154 GET_INST_OPCODE(ip) @ extract opcode from rINST 2155 SET_VREG(r2, r9) @ vAA<- r2 2156 GOTO_OPCODE(ip) @ jump to next instruction 2157 2158 2159 2160/* ------------------------------ */ 2161 .balign 64 2162.L_OP_AGET_CHAR: /* 0x49 */ 2163/* File: armv5te/OP_AGET_CHAR.S */ 2164/* File: armv5te/OP_AGET.S */ 2165 /* 2166 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2167 * 2168 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2169 * instructions. We use a pair of FETCH_Bs instead. 2170 * 2171 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2172 */ 2173 /* op vAA, vBB, vCC */ 2174 FETCH_B(r2, 1, 0) @ r2<- BB 2175 mov r9, rINST, lsr #8 @ r9<- AA 2176 FETCH_B(r3, 1, 1) @ r3<- CC 2177 GET_VREG(r0, r2) @ r0<- vBB (array object) 2178 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2179 cmp r0, #0 @ null array object? 2180 beq common_errNullObject @ yes, bail 2181 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2182 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2183 cmp r1, r3 @ compare unsigned index, length 2184 bcs common_errArrayIndex @ index >= length, bail 2185 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2186 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2187 GET_INST_OPCODE(ip) @ extract opcode from rINST 2188 SET_VREG(r2, r9) @ vAA<- r2 2189 GOTO_OPCODE(ip) @ jump to next instruction 2190 2191 2192 2193/* ------------------------------ */ 2194 .balign 64 2195.L_OP_AGET_SHORT: /* 0x4a */ 2196/* File: armv5te/OP_AGET_SHORT.S */ 2197/* File: armv5te/OP_AGET.S */ 2198 /* 2199 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2200 * 2201 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2202 * instructions. We use a pair of FETCH_Bs instead. 2203 * 2204 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2205 */ 2206 /* op vAA, vBB, vCC */ 2207 FETCH_B(r2, 1, 0) @ r2<- BB 2208 mov r9, rINST, lsr #8 @ r9<- AA 2209 FETCH_B(r3, 1, 1) @ r3<- CC 2210 GET_VREG(r0, r2) @ r0<- vBB (array object) 2211 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2212 cmp r0, #0 @ null array object? 2213 beq common_errNullObject @ yes, bail 2214 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2215 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2216 cmp r1, r3 @ compare unsigned index, length 2217 bcs common_errArrayIndex @ index >= length, bail 2218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2219 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2220 GET_INST_OPCODE(ip) @ extract opcode from rINST 2221 SET_VREG(r2, r9) @ vAA<- r2 2222 GOTO_OPCODE(ip) @ jump to next instruction 2223 2224 2225 2226/* ------------------------------ */ 2227 .balign 64 2228.L_OP_APUT: /* 0x4b */ 2229/* File: armv5te/OP_APUT.S */ 2230 /* 2231 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2232 * 2233 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2234 * instructions. We use a pair of FETCH_Bs instead. 2235 * 2236 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2237 */ 2238 /* op vAA, vBB, vCC */ 2239 FETCH_B(r2, 1, 0) @ r2<- BB 2240 mov r9, rINST, lsr #8 @ r9<- AA 2241 FETCH_B(r3, 1, 1) @ r3<- CC 2242 GET_VREG(r0, r2) @ r0<- vBB (array object) 2243 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2244 cmp r0, #0 @ null array object? 2245 beq common_errNullObject @ yes, bail 2246 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2247 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2248 cmp r1, r3 @ compare unsigned index, length 2249 bcs common_errArrayIndex @ index >= length, bail 2250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2251 GET_VREG(r2, r9) @ r2<- vAA 2252 GET_INST_OPCODE(ip) @ extract opcode from rINST 2253 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2254 GOTO_OPCODE(ip) @ jump to next instruction 2255 2256 2257/* ------------------------------ */ 2258 .balign 64 2259.L_OP_APUT_WIDE: /* 0x4c */ 2260/* File: armv5te/OP_APUT_WIDE.S */ 2261 /* 2262 * Array put, 64 bits. vBB[vCC] <- vAA. 2263 * 2264 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2265 */ 2266 /* aput-wide vAA, vBB, vCC */ 2267 FETCH(r0, 1) @ r0<- CCBB 2268 mov r9, rINST, lsr #8 @ r9<- AA 2269 and r2, r0, #255 @ r2<- BB 2270 mov r3, r0, lsr #8 @ r3<- CC 2271 GET_VREG(r0, r2) @ r0<- vBB (array object) 2272 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2273 cmp r0, #0 @ null array object? 2274 beq common_errNullObject @ yes, bail 2275 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2276 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2277 cmp r1, r3 @ compare unsigned index, length 2278 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2279 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2280 b common_errArrayIndex @ index >= length, bail 2281 @ May want to swap the order of these two branches depending on how the 2282 @ branch prediction (if any) handles conditional forward branches vs. 2283 @ unconditional forward branches. 2284 2285/* ------------------------------ */ 2286 .balign 64 2287.L_OP_APUT_OBJECT: /* 0x4d */ 2288/* File: armv5te/OP_APUT_OBJECT.S */ 2289 /* 2290 * Store an object into an array. vBB[vCC] <- vAA. 2291 * 2292 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2293 * instructions. We use a pair of FETCH_Bs instead. 2294 */ 2295 /* op vAA, vBB, vCC */ 2296 FETCH(r0, 1) @ r0<- CCBB 2297 mov r9, rINST, lsr #8 @ r9<- AA 2298 and r2, r0, #255 @ r2<- BB 2299 mov r3, r0, lsr #8 @ r3<- CC 2300 GET_VREG(r1, r2) @ r1<- vBB (array object) 2301 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2302 cmp r1, #0 @ null array object? 2303 GET_VREG(r9, r9) @ r9<- vAA 2304 beq common_errNullObject @ yes, bail 2305 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2306 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2307 cmp r0, r3 @ compare unsigned index, length 2308 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2309 b common_errArrayIndex @ index >= length, bail 2310 2311 2312/* ------------------------------ */ 2313 .balign 64 2314.L_OP_APUT_BOOLEAN: /* 0x4e */ 2315/* File: armv5te/OP_APUT_BOOLEAN.S */ 2316/* File: armv5te/OP_APUT.S */ 2317 /* 2318 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2319 * 2320 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2321 * instructions. We use a pair of FETCH_Bs instead. 2322 * 2323 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2324 */ 2325 /* op vAA, vBB, vCC */ 2326 FETCH_B(r2, 1, 0) @ r2<- BB 2327 mov r9, rINST, lsr #8 @ r9<- AA 2328 FETCH_B(r3, 1, 1) @ r3<- CC 2329 GET_VREG(r0, r2) @ r0<- vBB (array object) 2330 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2331 cmp r0, #0 @ null array object? 2332 beq common_errNullObject @ yes, bail 2333 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2334 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2335 cmp r1, r3 @ compare unsigned index, length 2336 bcs common_errArrayIndex @ index >= length, bail 2337 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2338 GET_VREG(r2, r9) @ r2<- vAA 2339 GET_INST_OPCODE(ip) @ extract opcode from rINST 2340 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2341 GOTO_OPCODE(ip) @ jump to next instruction 2342 2343 2344 2345/* ------------------------------ */ 2346 .balign 64 2347.L_OP_APUT_BYTE: /* 0x4f */ 2348/* File: armv5te/OP_APUT_BYTE.S */ 2349/* File: armv5te/OP_APUT.S */ 2350 /* 2351 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2352 * 2353 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2354 * instructions. We use a pair of FETCH_Bs instead. 2355 * 2356 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2357 */ 2358 /* op vAA, vBB, vCC */ 2359 FETCH_B(r2, 1, 0) @ r2<- BB 2360 mov r9, rINST, lsr #8 @ r9<- AA 2361 FETCH_B(r3, 1, 1) @ r3<- CC 2362 GET_VREG(r0, r2) @ r0<- vBB (array object) 2363 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2364 cmp r0, #0 @ null array object? 2365 beq common_errNullObject @ yes, bail 2366 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2367 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2368 cmp r1, r3 @ compare unsigned index, length 2369 bcs common_errArrayIndex @ index >= length, bail 2370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2371 GET_VREG(r2, r9) @ r2<- vAA 2372 GET_INST_OPCODE(ip) @ extract opcode from rINST 2373 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2374 GOTO_OPCODE(ip) @ jump to next instruction 2375 2376 2377 2378/* ------------------------------ */ 2379 .balign 64 2380.L_OP_APUT_CHAR: /* 0x50 */ 2381/* File: armv5te/OP_APUT_CHAR.S */ 2382/* File: armv5te/OP_APUT.S */ 2383 /* 2384 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2385 * 2386 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2387 * instructions. We use a pair of FETCH_Bs instead. 2388 * 2389 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2390 */ 2391 /* op vAA, vBB, vCC */ 2392 FETCH_B(r2, 1, 0) @ r2<- BB 2393 mov r9, rINST, lsr #8 @ r9<- AA 2394 FETCH_B(r3, 1, 1) @ r3<- CC 2395 GET_VREG(r0, r2) @ r0<- vBB (array object) 2396 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2397 cmp r0, #0 @ null array object? 2398 beq common_errNullObject @ yes, bail 2399 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2400 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2401 cmp r1, r3 @ compare unsigned index, length 2402 bcs common_errArrayIndex @ index >= length, bail 2403 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2404 GET_VREG(r2, r9) @ r2<- vAA 2405 GET_INST_OPCODE(ip) @ extract opcode from rINST 2406 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2407 GOTO_OPCODE(ip) @ jump to next instruction 2408 2409 2410 2411/* ------------------------------ */ 2412 .balign 64 2413.L_OP_APUT_SHORT: /* 0x51 */ 2414/* File: armv5te/OP_APUT_SHORT.S */ 2415/* File: armv5te/OP_APUT.S */ 2416 /* 2417 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2418 * 2419 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2420 * instructions. We use a pair of FETCH_Bs instead. 2421 * 2422 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2423 */ 2424 /* op vAA, vBB, vCC */ 2425 FETCH_B(r2, 1, 0) @ r2<- BB 2426 mov r9, rINST, lsr #8 @ r9<- AA 2427 FETCH_B(r3, 1, 1) @ r3<- CC 2428 GET_VREG(r0, r2) @ r0<- vBB (array object) 2429 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2430 cmp r0, #0 @ null array object? 2431 beq common_errNullObject @ yes, bail 2432 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2433 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2434 cmp r1, r3 @ compare unsigned index, length 2435 bcs common_errArrayIndex @ index >= length, bail 2436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2437 GET_VREG(r2, r9) @ r2<- vAA 2438 GET_INST_OPCODE(ip) @ extract opcode from rINST 2439 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2440 GOTO_OPCODE(ip) @ jump to next instruction 2441 2442 2443 2444/* ------------------------------ */ 2445 .balign 64 2446.L_OP_IGET: /* 0x52 */ 2447/* File: armv5te/OP_IGET.S */ 2448 /* 2449 * General 32-bit instance field get. 2450 * 2451 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2452 */ 2453 /* op vA, vB, field@CCCC */ 2454 mov r0, rINST, lsr #12 @ r0<- B 2455 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2456 FETCH(r1, 1) @ r1<- field ref CCCC 2457 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2458 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2459 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2460 cmp r0, #0 @ is resolved entry null? 2461 bne .LOP_IGET_finish @ no, already resolved 24628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2463 EXPORT_PC() @ resolve() could throw 2464 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2465 bl dvmResolveInstField @ r0<- resolved InstField ptr 2466 cmp r0, #0 2467 bne .LOP_IGET_finish 2468 b common_exceptionThrown 2469 2470/* ------------------------------ */ 2471 .balign 64 2472.L_OP_IGET_WIDE: /* 0x53 */ 2473/* File: armv5te/OP_IGET_WIDE.S */ 2474 /* 2475 * Wide 32-bit instance field get. 2476 */ 2477 /* iget-wide vA, vB, field@CCCC */ 2478 mov r0, rINST, lsr #12 @ r0<- B 2479 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2480 FETCH(r1, 1) @ r1<- field ref CCCC 2481 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2482 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2483 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2484 cmp r0, #0 @ is resolved entry null? 2485 bne .LOP_IGET_WIDE_finish @ no, already resolved 24868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2487 EXPORT_PC() @ resolve() could throw 2488 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2489 bl dvmResolveInstField @ r0<- resolved InstField ptr 2490 cmp r0, #0 2491 bne .LOP_IGET_WIDE_finish 2492 b common_exceptionThrown 2493 2494/* ------------------------------ */ 2495 .balign 64 2496.L_OP_IGET_OBJECT: /* 0x54 */ 2497/* File: armv5te/OP_IGET_OBJECT.S */ 2498/* File: armv5te/OP_IGET.S */ 2499 /* 2500 * General 32-bit instance field get. 2501 * 2502 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2503 */ 2504 /* op vA, vB, field@CCCC */ 2505 mov r0, rINST, lsr #12 @ r0<- B 2506 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2507 FETCH(r1, 1) @ r1<- field ref CCCC 2508 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2509 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2510 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2511 cmp r0, #0 @ is resolved entry null? 2512 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2514 EXPORT_PC() @ resolve() could throw 2515 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2516 bl dvmResolveInstField @ r0<- resolved InstField ptr 2517 cmp r0, #0 2518 bne .LOP_IGET_OBJECT_finish 2519 b common_exceptionThrown 2520 2521 2522/* ------------------------------ */ 2523 .balign 64 2524.L_OP_IGET_BOOLEAN: /* 0x55 */ 2525/* File: armv5te/OP_IGET_BOOLEAN.S */ 2526@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2527/* File: armv5te/OP_IGET.S */ 2528 /* 2529 * General 32-bit instance field get. 2530 * 2531 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2532 */ 2533 /* op vA, vB, field@CCCC */ 2534 mov r0, rINST, lsr #12 @ r0<- B 2535 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2536 FETCH(r1, 1) @ r1<- field ref CCCC 2537 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2538 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2539 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2540 cmp r0, #0 @ is resolved entry null? 2541 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25428: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2543 EXPORT_PC() @ resolve() could throw 2544 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2545 bl dvmResolveInstField @ r0<- resolved InstField ptr 2546 cmp r0, #0 2547 bne .LOP_IGET_BOOLEAN_finish 2548 b common_exceptionThrown 2549 2550 2551/* ------------------------------ */ 2552 .balign 64 2553.L_OP_IGET_BYTE: /* 0x56 */ 2554/* File: armv5te/OP_IGET_BYTE.S */ 2555@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2556/* File: armv5te/OP_IGET.S */ 2557 /* 2558 * General 32-bit instance field get. 2559 * 2560 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2561 */ 2562 /* op vA, vB, field@CCCC */ 2563 mov r0, rINST, lsr #12 @ r0<- B 2564 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2565 FETCH(r1, 1) @ r1<- field ref CCCC 2566 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2567 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2568 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2569 cmp r0, #0 @ is resolved entry null? 2570 bne .LOP_IGET_BYTE_finish @ no, already resolved 25718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2572 EXPORT_PC() @ resolve() could throw 2573 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2574 bl dvmResolveInstField @ r0<- resolved InstField ptr 2575 cmp r0, #0 2576 bne .LOP_IGET_BYTE_finish 2577 b common_exceptionThrown 2578 2579 2580/* ------------------------------ */ 2581 .balign 64 2582.L_OP_IGET_CHAR: /* 0x57 */ 2583/* File: armv5te/OP_IGET_CHAR.S */ 2584@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2585/* File: armv5te/OP_IGET.S */ 2586 /* 2587 * General 32-bit instance field get. 2588 * 2589 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2590 */ 2591 /* op vA, vB, field@CCCC */ 2592 mov r0, rINST, lsr #12 @ r0<- B 2593 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2594 FETCH(r1, 1) @ r1<- field ref CCCC 2595 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2596 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2597 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2598 cmp r0, #0 @ is resolved entry null? 2599 bne .LOP_IGET_CHAR_finish @ no, already resolved 26008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2601 EXPORT_PC() @ resolve() could throw 2602 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2603 bl dvmResolveInstField @ r0<- resolved InstField ptr 2604 cmp r0, #0 2605 bne .LOP_IGET_CHAR_finish 2606 b common_exceptionThrown 2607 2608 2609/* ------------------------------ */ 2610 .balign 64 2611.L_OP_IGET_SHORT: /* 0x58 */ 2612/* File: armv5te/OP_IGET_SHORT.S */ 2613@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2614/* File: armv5te/OP_IGET.S */ 2615 /* 2616 * General 32-bit instance field get. 2617 * 2618 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2619 */ 2620 /* op vA, vB, field@CCCC */ 2621 mov r0, rINST, lsr #12 @ r0<- B 2622 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2623 FETCH(r1, 1) @ r1<- field ref CCCC 2624 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2625 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2626 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2627 cmp r0, #0 @ is resolved entry null? 2628 bne .LOP_IGET_SHORT_finish @ no, already resolved 26298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2630 EXPORT_PC() @ resolve() could throw 2631 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2632 bl dvmResolveInstField @ r0<- resolved InstField ptr 2633 cmp r0, #0 2634 bne .LOP_IGET_SHORT_finish 2635 b common_exceptionThrown 2636 2637 2638/* ------------------------------ */ 2639 .balign 64 2640.L_OP_IPUT: /* 0x59 */ 2641/* File: armv5te/OP_IPUT.S */ 2642 /* 2643 * General 32-bit instance field put. 2644 * 2645 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2646 */ 2647 /* op vA, vB, field@CCCC */ 2648 mov r0, rINST, lsr #12 @ r0<- B 2649 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2650 FETCH(r1, 1) @ r1<- field ref CCCC 2651 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2652 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2653 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2654 cmp r0, #0 @ is resolved entry null? 2655 bne .LOP_IPUT_finish @ no, already resolved 26568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2657 EXPORT_PC() @ resolve() could throw 2658 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2659 bl dvmResolveInstField @ r0<- resolved InstField ptr 2660 cmp r0, #0 @ success? 2661 bne .LOP_IPUT_finish @ yes, finish up 2662 b common_exceptionThrown 2663 2664/* ------------------------------ */ 2665 .balign 64 2666.L_OP_IPUT_WIDE: /* 0x5a */ 2667/* File: armv5te/OP_IPUT_WIDE.S */ 2668 /* iput-wide vA, vB, field@CCCC */ 2669 mov r0, rINST, lsr #12 @ r0<- B 2670 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2671 FETCH(r1, 1) @ r1<- field ref CCCC 2672 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2673 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2674 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2675 cmp r0, #0 @ is resolved entry null? 2676 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26778: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2678 EXPORT_PC() @ resolve() could throw 2679 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2680 bl dvmResolveInstField @ r0<- resolved InstField ptr 2681 cmp r0, #0 @ success? 2682 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2683 b common_exceptionThrown 2684 2685/* ------------------------------ */ 2686 .balign 64 2687.L_OP_IPUT_OBJECT: /* 0x5b */ 2688/* File: armv5te/OP_IPUT_OBJECT.S */ 2689/* File: armv5te/OP_IPUT.S */ 2690 /* 2691 * General 32-bit instance field put. 2692 * 2693 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2694 */ 2695 /* op vA, vB, field@CCCC */ 2696 mov r0, rINST, lsr #12 @ r0<- B 2697 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2698 FETCH(r1, 1) @ r1<- field ref CCCC 2699 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2700 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2701 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2702 cmp r0, #0 @ is resolved entry null? 2703 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27048: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2705 EXPORT_PC() @ resolve() could throw 2706 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2707 bl dvmResolveInstField @ r0<- resolved InstField ptr 2708 cmp r0, #0 @ success? 2709 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2710 b common_exceptionThrown 2711 2712 2713/* ------------------------------ */ 2714 .balign 64 2715.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2716/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2717@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2718/* File: armv5te/OP_IPUT.S */ 2719 /* 2720 * General 32-bit instance field put. 2721 * 2722 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2723 */ 2724 /* op vA, vB, field@CCCC */ 2725 mov r0, rINST, lsr #12 @ r0<- B 2726 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2727 FETCH(r1, 1) @ r1<- field ref CCCC 2728 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2729 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2730 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2731 cmp r0, #0 @ is resolved entry null? 2732 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2734 EXPORT_PC() @ resolve() could throw 2735 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2736 bl dvmResolveInstField @ r0<- resolved InstField ptr 2737 cmp r0, #0 @ success? 2738 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2739 b common_exceptionThrown 2740 2741 2742/* ------------------------------ */ 2743 .balign 64 2744.L_OP_IPUT_BYTE: /* 0x5d */ 2745/* File: armv5te/OP_IPUT_BYTE.S */ 2746@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2747/* File: armv5te/OP_IPUT.S */ 2748 /* 2749 * General 32-bit instance field put. 2750 * 2751 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2752 */ 2753 /* op vA, vB, field@CCCC */ 2754 mov r0, rINST, lsr #12 @ r0<- B 2755 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2756 FETCH(r1, 1) @ r1<- field ref CCCC 2757 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2758 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2759 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2760 cmp r0, #0 @ is resolved entry null? 2761 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2763 EXPORT_PC() @ resolve() could throw 2764 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2765 bl dvmResolveInstField @ r0<- resolved InstField ptr 2766 cmp r0, #0 @ success? 2767 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2768 b common_exceptionThrown 2769 2770 2771/* ------------------------------ */ 2772 .balign 64 2773.L_OP_IPUT_CHAR: /* 0x5e */ 2774/* File: armv5te/OP_IPUT_CHAR.S */ 2775@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2776/* File: armv5te/OP_IPUT.S */ 2777 /* 2778 * General 32-bit instance field put. 2779 * 2780 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2781 */ 2782 /* op vA, vB, field@CCCC */ 2783 mov r0, rINST, lsr #12 @ r0<- B 2784 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2785 FETCH(r1, 1) @ r1<- field ref CCCC 2786 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2787 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2788 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2789 cmp r0, #0 @ is resolved entry null? 2790 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27918: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2792 EXPORT_PC() @ resolve() could throw 2793 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2794 bl dvmResolveInstField @ r0<- resolved InstField ptr 2795 cmp r0, #0 @ success? 2796 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2797 b common_exceptionThrown 2798 2799 2800/* ------------------------------ */ 2801 .balign 64 2802.L_OP_IPUT_SHORT: /* 0x5f */ 2803/* File: armv5te/OP_IPUT_SHORT.S */ 2804@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2805/* File: armv5te/OP_IPUT.S */ 2806 /* 2807 * General 32-bit instance field put. 2808 * 2809 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2810 */ 2811 /* op vA, vB, field@CCCC */ 2812 mov r0, rINST, lsr #12 @ r0<- B 2813 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2814 FETCH(r1, 1) @ r1<- field ref CCCC 2815 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2816 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2817 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2818 cmp r0, #0 @ is resolved entry null? 2819 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2821 EXPORT_PC() @ resolve() could throw 2822 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2823 bl dvmResolveInstField @ r0<- resolved InstField ptr 2824 cmp r0, #0 @ success? 2825 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2826 b common_exceptionThrown 2827 2828 2829/* ------------------------------ */ 2830 .balign 64 2831.L_OP_SGET: /* 0x60 */ 2832/* File: armv5te/OP_SGET.S */ 2833 /* 2834 * General 32-bit SGET handler. 2835 * 2836 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2837 */ 2838 /* op vAA, field@BBBB */ 2839 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2840 FETCH(r1, 1) @ r1<- field ref BBBB 2841 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2842 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2843 cmp r0, #0 @ is resolved entry null? 2844 beq .LOP_SGET_resolve @ yes, do resolve 2845.LOP_SGET_finish: @ field ptr in r0 2846 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2847 mov r2, rINST, lsr #8 @ r2<- AA 2848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2849 SET_VREG(r1, r2) @ fp[AA]<- r1 2850 GET_INST_OPCODE(ip) @ extract opcode from rINST 2851 GOTO_OPCODE(ip) @ jump to next instruction 2852 2853/* ------------------------------ */ 2854 .balign 64 2855.L_OP_SGET_WIDE: /* 0x61 */ 2856/* File: armv5te/OP_SGET_WIDE.S */ 2857 /* 2858 * 64-bit SGET handler. 2859 */ 2860 /* sget-wide vAA, field@BBBB */ 2861 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2862 FETCH(r1, 1) @ r1<- field ref BBBB 2863 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2864 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2865 cmp r0, #0 @ is resolved entry null? 2866 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2867.LOP_SGET_WIDE_finish: 2868 mov r1, rINST, lsr #8 @ r1<- AA 2869 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2870 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2871 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2872 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2873 GET_INST_OPCODE(ip) @ extract opcode from rINST 2874 GOTO_OPCODE(ip) @ jump to next instruction 2875 2876/* ------------------------------ */ 2877 .balign 64 2878.L_OP_SGET_OBJECT: /* 0x62 */ 2879/* File: armv5te/OP_SGET_OBJECT.S */ 2880/* File: armv5te/OP_SGET.S */ 2881 /* 2882 * General 32-bit SGET handler. 2883 * 2884 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2885 */ 2886 /* op vAA, field@BBBB */ 2887 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2888 FETCH(r1, 1) @ r1<- field ref BBBB 2889 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2890 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2891 cmp r0, #0 @ is resolved entry null? 2892 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2893.LOP_SGET_OBJECT_finish: @ field ptr in r0 2894 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2895 mov r2, rINST, lsr #8 @ r2<- AA 2896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2897 SET_VREG(r1, r2) @ fp[AA]<- r1 2898 GET_INST_OPCODE(ip) @ extract opcode from rINST 2899 GOTO_OPCODE(ip) @ jump to next instruction 2900 2901 2902/* ------------------------------ */ 2903 .balign 64 2904.L_OP_SGET_BOOLEAN: /* 0x63 */ 2905/* File: armv5te/OP_SGET_BOOLEAN.S */ 2906/* File: armv5te/OP_SGET.S */ 2907 /* 2908 * General 32-bit SGET handler. 2909 * 2910 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2911 */ 2912 /* op vAA, field@BBBB */ 2913 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2914 FETCH(r1, 1) @ r1<- field ref BBBB 2915 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2916 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2917 cmp r0, #0 @ is resolved entry null? 2918 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2919.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2920 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2921 mov r2, rINST, lsr #8 @ r2<- AA 2922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2923 SET_VREG(r1, r2) @ fp[AA]<- r1 2924 GET_INST_OPCODE(ip) @ extract opcode from rINST 2925 GOTO_OPCODE(ip) @ jump to next instruction 2926 2927 2928/* ------------------------------ */ 2929 .balign 64 2930.L_OP_SGET_BYTE: /* 0x64 */ 2931/* File: armv5te/OP_SGET_BYTE.S */ 2932/* File: armv5te/OP_SGET.S */ 2933 /* 2934 * General 32-bit SGET handler. 2935 * 2936 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2937 */ 2938 /* op vAA, field@BBBB */ 2939 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2940 FETCH(r1, 1) @ r1<- field ref BBBB 2941 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2942 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2943 cmp r0, #0 @ is resolved entry null? 2944 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2945.LOP_SGET_BYTE_finish: @ field ptr in r0 2946 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2947 mov r2, rINST, lsr #8 @ r2<- AA 2948 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2949 SET_VREG(r1, r2) @ fp[AA]<- r1 2950 GET_INST_OPCODE(ip) @ extract opcode from rINST 2951 GOTO_OPCODE(ip) @ jump to next instruction 2952 2953 2954/* ------------------------------ */ 2955 .balign 64 2956.L_OP_SGET_CHAR: /* 0x65 */ 2957/* File: armv5te/OP_SGET_CHAR.S */ 2958/* File: armv5te/OP_SGET.S */ 2959 /* 2960 * General 32-bit SGET handler. 2961 * 2962 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2963 */ 2964 /* op vAA, field@BBBB */ 2965 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2966 FETCH(r1, 1) @ r1<- field ref BBBB 2967 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2968 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2969 cmp r0, #0 @ is resolved entry null? 2970 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2971.LOP_SGET_CHAR_finish: @ field ptr in r0 2972 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2973 mov r2, rINST, lsr #8 @ r2<- AA 2974 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2975 SET_VREG(r1, r2) @ fp[AA]<- r1 2976 GET_INST_OPCODE(ip) @ extract opcode from rINST 2977 GOTO_OPCODE(ip) @ jump to next instruction 2978 2979 2980/* ------------------------------ */ 2981 .balign 64 2982.L_OP_SGET_SHORT: /* 0x66 */ 2983/* File: armv5te/OP_SGET_SHORT.S */ 2984/* File: armv5te/OP_SGET.S */ 2985 /* 2986 * General 32-bit SGET handler. 2987 * 2988 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2989 */ 2990 /* op vAA, field@BBBB */ 2991 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2992 FETCH(r1, 1) @ r1<- field ref BBBB 2993 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2994 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2995 cmp r0, #0 @ is resolved entry null? 2996 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2997.LOP_SGET_SHORT_finish: @ field ptr in r0 2998 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2999 mov r2, rINST, lsr #8 @ r2<- AA 3000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3001 SET_VREG(r1, r2) @ fp[AA]<- r1 3002 GET_INST_OPCODE(ip) @ extract opcode from rINST 3003 GOTO_OPCODE(ip) @ jump to next instruction 3004 3005 3006/* ------------------------------ */ 3007 .balign 64 3008.L_OP_SPUT: /* 0x67 */ 3009/* File: armv5te/OP_SPUT.S */ 3010 /* 3011 * General 32-bit SPUT handler. 3012 * 3013 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3014 */ 3015 /* op vAA, field@BBBB */ 3016 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3017 FETCH(r1, 1) @ r1<- field ref BBBB 3018 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3019 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3020 cmp r0, #0 @ is resolved entry null? 3021 beq .LOP_SPUT_resolve @ yes, do resolve 3022.LOP_SPUT_finish: @ field ptr in r0 3023 mov r2, rINST, lsr #8 @ r2<- AA 3024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3025 GET_VREG(r1, r2) @ r1<- fp[AA] 3026 GET_INST_OPCODE(ip) @ extract opcode from rINST 3027 str r1, [r0, #offStaticField_value] @ field<- vAA 3028 GOTO_OPCODE(ip) @ jump to next instruction 3029 3030/* ------------------------------ */ 3031 .balign 64 3032.L_OP_SPUT_WIDE: /* 0x68 */ 3033/* File: armv5te/OP_SPUT_WIDE.S */ 3034 /* 3035 * 64-bit SPUT handler. 3036 */ 3037 /* sput-wide vAA, field@BBBB */ 3038 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3039 FETCH(r1, 1) @ r1<- field ref BBBB 3040 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3041 mov r9, rINST, lsr #8 @ r9<- AA 3042 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3043 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3044 cmp r0, #0 @ is resolved entry null? 3045 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3046.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3048 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3049 GET_INST_OPCODE(ip) @ extract opcode from rINST 3050 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3051 GOTO_OPCODE(ip) @ jump to next instruction 3052 3053/* ------------------------------ */ 3054 .balign 64 3055.L_OP_SPUT_OBJECT: /* 0x69 */ 3056/* File: armv5te/OP_SPUT_OBJECT.S */ 3057/* File: armv5te/OP_SPUT.S */ 3058 /* 3059 * General 32-bit SPUT handler. 3060 * 3061 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3062 */ 3063 /* op vAA, field@BBBB */ 3064 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3065 FETCH(r1, 1) @ r1<- field ref BBBB 3066 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3067 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3068 cmp r0, #0 @ is resolved entry null? 3069 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3070.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3071 mov r2, rINST, lsr #8 @ r2<- AA 3072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3073 GET_VREG(r1, r2) @ r1<- fp[AA] 3074 GET_INST_OPCODE(ip) @ extract opcode from rINST 3075 str r1, [r0, #offStaticField_value] @ field<- vAA 3076 GOTO_OPCODE(ip) @ jump to next instruction 3077 3078 3079/* ------------------------------ */ 3080 .balign 64 3081.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3082/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3083/* File: armv5te/OP_SPUT.S */ 3084 /* 3085 * General 32-bit SPUT handler. 3086 * 3087 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3088 */ 3089 /* op vAA, field@BBBB */ 3090 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3091 FETCH(r1, 1) @ r1<- field ref BBBB 3092 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3093 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3094 cmp r0, #0 @ is resolved entry null? 3095 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3096.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3097 mov r2, rINST, lsr #8 @ r2<- AA 3098 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3099 GET_VREG(r1, r2) @ r1<- fp[AA] 3100 GET_INST_OPCODE(ip) @ extract opcode from rINST 3101 str r1, [r0, #offStaticField_value] @ field<- vAA 3102 GOTO_OPCODE(ip) @ jump to next instruction 3103 3104 3105/* ------------------------------ */ 3106 .balign 64 3107.L_OP_SPUT_BYTE: /* 0x6b */ 3108/* File: armv5te/OP_SPUT_BYTE.S */ 3109/* File: armv5te/OP_SPUT.S */ 3110 /* 3111 * General 32-bit SPUT handler. 3112 * 3113 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3114 */ 3115 /* op vAA, field@BBBB */ 3116 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3117 FETCH(r1, 1) @ r1<- field ref BBBB 3118 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3119 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3120 cmp r0, #0 @ is resolved entry null? 3121 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3122.LOP_SPUT_BYTE_finish: @ field ptr in r0 3123 mov r2, rINST, lsr #8 @ r2<- AA 3124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3125 GET_VREG(r1, r2) @ r1<- fp[AA] 3126 GET_INST_OPCODE(ip) @ extract opcode from rINST 3127 str r1, [r0, #offStaticField_value] @ field<- vAA 3128 GOTO_OPCODE(ip) @ jump to next instruction 3129 3130 3131/* ------------------------------ */ 3132 .balign 64 3133.L_OP_SPUT_CHAR: /* 0x6c */ 3134/* File: armv5te/OP_SPUT_CHAR.S */ 3135/* File: armv5te/OP_SPUT.S */ 3136 /* 3137 * General 32-bit SPUT handler. 3138 * 3139 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3140 */ 3141 /* op vAA, field@BBBB */ 3142 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3143 FETCH(r1, 1) @ r1<- field ref BBBB 3144 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3145 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3146 cmp r0, #0 @ is resolved entry null? 3147 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3148.LOP_SPUT_CHAR_finish: @ field ptr in r0 3149 mov r2, rINST, lsr #8 @ r2<- AA 3150 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3151 GET_VREG(r1, r2) @ r1<- fp[AA] 3152 GET_INST_OPCODE(ip) @ extract opcode from rINST 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-object, 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 str r1, [r0, #offStaticField_value] @ field<- vAA 3180 GOTO_OPCODE(ip) @ jump to next instruction 3181 3182 3183/* ------------------------------ */ 3184 .balign 64 3185.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3186/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3187 /* 3188 * Handle a virtual method call. 3189 * 3190 * for: invoke-virtual, invoke-virtual/range 3191 */ 3192 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3193 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3194 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3195 FETCH(r1, 1) @ r1<- BBBB 3196 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3197 FETCH(r10, 2) @ r10<- GFED or CCCC 3198 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3199 .if (!0) 3200 and r10, r10, #15 @ r10<- D (or stays CCCC) 3201 .endif 3202 cmp r0, #0 @ already resolved? 3203 EXPORT_PC() @ must export for invoke 3204 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3205 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3206 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3207 mov r2, #METHOD_VIRTUAL @ resolver method type 3208 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3209 cmp r0, #0 @ got null? 3210 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3211 b common_exceptionThrown @ yes, handle exception 3212 3213/* ------------------------------ */ 3214 .balign 64 3215.L_OP_INVOKE_SUPER: /* 0x6f */ 3216/* File: armv5te/OP_INVOKE_SUPER.S */ 3217 /* 3218 * Handle a "super" method call. 3219 * 3220 * for: invoke-super, invoke-super/range 3221 */ 3222 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3223 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3224 FETCH(r10, 2) @ r10<- GFED or CCCC 3225 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3226 .if (!0) 3227 and r10, r10, #15 @ r10<- D (or stays CCCC) 3228 .endif 3229 FETCH(r1, 1) @ r1<- BBBB 3230 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3231 GET_VREG(r2, r10) @ r2<- "this" ptr 3232 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3233 cmp r2, #0 @ null "this"? 3234 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3235 beq common_errNullObject @ null "this", throw exception 3236 cmp r0, #0 @ already resolved? 3237 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3238 EXPORT_PC() @ must export for invoke 3239 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3240 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3241 3242/* ------------------------------ */ 3243 .balign 64 3244.L_OP_INVOKE_DIRECT: /* 0x70 */ 3245/* File: armv5te/OP_INVOKE_DIRECT.S */ 3246 /* 3247 * Handle a direct method call. 3248 * 3249 * (We could defer the "is 'this' pointer null" test to the common 3250 * method invocation code, and use a flag to indicate that static 3251 * calls don't count. If we do this as part of copying the arguments 3252 * out we could avoiding loading the first arg twice.) 3253 * 3254 * for: invoke-direct, invoke-direct/range 3255 */ 3256 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3257 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3258 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3259 FETCH(r1, 1) @ r1<- BBBB 3260 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3261 FETCH(r10, 2) @ r10<- GFED or CCCC 3262 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3263 .if (!0) 3264 and r10, r10, #15 @ r10<- D (or stays CCCC) 3265 .endif 3266 cmp r0, #0 @ already resolved? 3267 EXPORT_PC() @ must export for invoke 3268 GET_VREG(r2, r10) @ r2<- "this" ptr 3269 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3270.LOP_INVOKE_DIRECT_finish: 3271 cmp r2, #0 @ null "this" ref? 3272 bne common_invokeMethodNoRange @ no, continue on 3273 b common_errNullObject @ yes, throw exception 3274 3275/* ------------------------------ */ 3276 .balign 64 3277.L_OP_INVOKE_STATIC: /* 0x71 */ 3278/* File: armv5te/OP_INVOKE_STATIC.S */ 3279 /* 3280 * Handle a static method call. 3281 * 3282 * for: invoke-static, invoke-static/range 3283 */ 3284 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3285 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3286 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3287 FETCH(r1, 1) @ r1<- BBBB 3288 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3289 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3290 cmp r0, #0 @ already resolved? 3291 EXPORT_PC() @ must export for invoke 3292 bne common_invokeMethodNoRange @ yes, continue on 32930: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3294 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3295 mov r2, #METHOD_STATIC @ resolver method type 3296 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3297 cmp r0, #0 @ got null? 3298 bne common_invokeMethodNoRange @ no, continue 3299 b common_exceptionThrown @ yes, handle exception 3300 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/* ------------------------------ */ 3332 .balign 64 3333.L_OP_UNUSED_73: /* 0x73 */ 3334/* File: armv5te/OP_UNUSED_73.S */ 3335/* File: armv5te/unused.S */ 3336 bl common_abort 3337 3338 3339 3340/* ------------------------------ */ 3341 .balign 64 3342.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3343/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3344/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3345 /* 3346 * Handle a virtual method call. 3347 * 3348 * for: invoke-virtual, invoke-virtual/range 3349 */ 3350 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3351 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3352 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3353 FETCH(r1, 1) @ r1<- BBBB 3354 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3355 FETCH(r10, 2) @ r10<- GFED or CCCC 3356 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3357 .if (!1) 3358 and r10, r10, #15 @ r10<- D (or stays CCCC) 3359 .endif 3360 cmp r0, #0 @ already resolved? 3361 EXPORT_PC() @ must export for invoke 3362 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3363 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3364 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3365 mov r2, #METHOD_VIRTUAL @ resolver method type 3366 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3367 cmp r0, #0 @ got null? 3368 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3369 b common_exceptionThrown @ yes, handle exception 3370 3371 3372/* ------------------------------ */ 3373 .balign 64 3374.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3375/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3376/* File: armv5te/OP_INVOKE_SUPER.S */ 3377 /* 3378 * Handle a "super" method call. 3379 * 3380 * for: invoke-super, invoke-super/range 3381 */ 3382 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3383 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3384 FETCH(r10, 2) @ r10<- GFED or CCCC 3385 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3386 .if (!1) 3387 and r10, r10, #15 @ r10<- D (or stays CCCC) 3388 .endif 3389 FETCH(r1, 1) @ r1<- BBBB 3390 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3391 GET_VREG(r2, r10) @ r2<- "this" ptr 3392 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3393 cmp r2, #0 @ null "this"? 3394 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3395 beq common_errNullObject @ null "this", throw exception 3396 cmp r0, #0 @ already resolved? 3397 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3398 EXPORT_PC() @ must export for invoke 3399 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3400 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3401 3402 3403/* ------------------------------ */ 3404 .balign 64 3405.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3406/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3407/* File: armv5te/OP_INVOKE_DIRECT.S */ 3408 /* 3409 * Handle a direct method call. 3410 * 3411 * (We could defer the "is 'this' pointer null" test to the common 3412 * method invocation code, and use a flag to indicate that static 3413 * calls don't count. If we do this as part of copying the arguments 3414 * out we could avoiding loading the first arg twice.) 3415 * 3416 * for: invoke-direct, invoke-direct/range 3417 */ 3418 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3419 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3420 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3421 FETCH(r1, 1) @ r1<- BBBB 3422 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3423 FETCH(r10, 2) @ r10<- GFED or CCCC 3424 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3425 .if (!1) 3426 and r10, r10, #15 @ r10<- D (or stays CCCC) 3427 .endif 3428 cmp r0, #0 @ already resolved? 3429 EXPORT_PC() @ must export for invoke 3430 GET_VREG(r2, r10) @ r2<- "this" ptr 3431 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3432.LOP_INVOKE_DIRECT_RANGE_finish: 3433 cmp r2, #0 @ null "this" ref? 3434 bne common_invokeMethodRange @ no, continue on 3435 b common_errNullObject @ yes, throw exception 3436 3437 3438/* ------------------------------ */ 3439 .balign 64 3440.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3441/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3442/* File: armv5te/OP_INVOKE_STATIC.S */ 3443 /* 3444 * Handle a static method call. 3445 * 3446 * for: invoke-static, invoke-static/range 3447 */ 3448 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3449 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3450 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3451 FETCH(r1, 1) @ r1<- BBBB 3452 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3453 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3454 cmp r0, #0 @ already resolved? 3455 EXPORT_PC() @ must export for invoke 3456 bne common_invokeMethodRange @ yes, continue on 34570: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3458 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3459 mov r2, #METHOD_STATIC @ resolver method type 3460 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3461 cmp r0, #0 @ got null? 3462 bne common_invokeMethodRange @ no, continue 3463 b common_exceptionThrown @ yes, handle exception 3464 3465 3466 3467/* ------------------------------ */ 3468 .balign 64 3469.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3470/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3471/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3472 /* 3473 * Handle an interface method call. 3474 * 3475 * for: invoke-interface, invoke-interface/range 3476 */ 3477 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3478 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3479 FETCH(r2, 2) @ r2<- FEDC or CCCC 3480 FETCH(r1, 1) @ r1<- BBBB 3481 .if (!1) 3482 and r2, r2, #15 @ r2<- C (or stays CCCC) 3483 .endif 3484 EXPORT_PC() @ must export for invoke 3485 GET_VREG(r0, r2) @ r0<- first arg ("this") 3486 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3487 cmp r0, #0 @ null obj? 3488 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3489 beq common_errNullObject @ yes, fail 3490 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3491 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3492 cmp r0, #0 @ failed? 3493 beq common_exceptionThrown @ yes, handle exception 3494 b common_invokeMethodRange @ jump to common handler 3495 3496 3497 3498/* ------------------------------ */ 3499 .balign 64 3500.L_OP_UNUSED_79: /* 0x79 */ 3501/* File: armv5te/OP_UNUSED_79.S */ 3502/* File: armv5te/unused.S */ 3503 bl common_abort 3504 3505 3506 3507/* ------------------------------ */ 3508 .balign 64 3509.L_OP_UNUSED_7A: /* 0x7a */ 3510/* File: armv5te/OP_UNUSED_7A.S */ 3511/* File: armv5te/unused.S */ 3512 bl common_abort 3513 3514 3515 3516/* ------------------------------ */ 3517 .balign 64 3518.L_OP_NEG_INT: /* 0x7b */ 3519/* File: armv5te/OP_NEG_INT.S */ 3520/* File: armv5te/unop.S */ 3521 /* 3522 * Generic 32-bit unary operation. Provide an "instr" line that 3523 * specifies an instruction that performs "result = op r0". 3524 * This could be an ARM instruction or a function call. 3525 * 3526 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3527 * int-to-byte, int-to-char, int-to-short 3528 */ 3529 /* unop vA, vB */ 3530 mov r3, rINST, lsr #12 @ r3<- B 3531 mov r9, rINST, lsr #8 @ r9<- A+ 3532 GET_VREG(r0, r3) @ r0<- vB 3533 and r9, r9, #15 3534 @ optional op; may set condition codes 3535 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3536 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3537 GET_INST_OPCODE(ip) @ extract opcode from rINST 3538 SET_VREG(r0, r9) @ vAA<- r0 3539 GOTO_OPCODE(ip) @ jump to next instruction 3540 /* 9-10 instructions */ 3541 3542 3543/* ------------------------------ */ 3544 .balign 64 3545.L_OP_NOT_INT: /* 0x7c */ 3546/* File: armv5te/OP_NOT_INT.S */ 3547/* File: armv5te/unop.S */ 3548 /* 3549 * Generic 32-bit unary operation. Provide an "instr" line that 3550 * specifies an instruction that performs "result = op r0". 3551 * This could be an ARM instruction or a function call. 3552 * 3553 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3554 * int-to-byte, int-to-char, int-to-short 3555 */ 3556 /* unop vA, vB */ 3557 mov r3, rINST, lsr #12 @ r3<- B 3558 mov r9, rINST, lsr #8 @ r9<- A+ 3559 GET_VREG(r0, r3) @ r0<- vB 3560 and r9, r9, #15 3561 @ optional op; may set condition codes 3562 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3563 mvn r0, r0 @ r0<- op, r0-r3 changed 3564 GET_INST_OPCODE(ip) @ extract opcode from rINST 3565 SET_VREG(r0, r9) @ vAA<- r0 3566 GOTO_OPCODE(ip) @ jump to next instruction 3567 /* 9-10 instructions */ 3568 3569 3570/* ------------------------------ */ 3571 .balign 64 3572.L_OP_NEG_LONG: /* 0x7d */ 3573/* File: armv5te/OP_NEG_LONG.S */ 3574/* File: armv5te/unopWide.S */ 3575 /* 3576 * Generic 64-bit unary operation. Provide an "instr" line that 3577 * specifies an instruction that performs "result = op r0/r1". 3578 * This could be an ARM instruction or a function call. 3579 * 3580 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3581 */ 3582 /* unop vA, vB */ 3583 mov r9, rINST, lsr #8 @ r9<- A+ 3584 mov r3, rINST, lsr #12 @ r3<- B 3585 and r9, r9, #15 3586 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3587 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3588 ldmia r3, {r0-r1} @ r0/r1<- vAA 3589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3590 rsbs r0, r0, #0 @ optional op; may set condition codes 3591 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3592 GET_INST_OPCODE(ip) @ extract opcode from rINST 3593 stmia r9, {r0-r1} @ vAA<- r0/r1 3594 GOTO_OPCODE(ip) @ jump to next instruction 3595 /* 12-13 instructions */ 3596 3597 3598 3599/* ------------------------------ */ 3600 .balign 64 3601.L_OP_NOT_LONG: /* 0x7e */ 3602/* File: armv5te/OP_NOT_LONG.S */ 3603/* File: armv5te/unopWide.S */ 3604 /* 3605 * Generic 64-bit unary operation. Provide an "instr" line that 3606 * specifies an instruction that performs "result = op r0/r1". 3607 * This could be an ARM instruction or a function call. 3608 * 3609 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3610 */ 3611 /* unop vA, vB */ 3612 mov r9, rINST, lsr #8 @ r9<- A+ 3613 mov r3, rINST, lsr #12 @ r3<- B 3614 and r9, r9, #15 3615 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3616 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3617 ldmia r3, {r0-r1} @ r0/r1<- vAA 3618 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3619 mvn r0, r0 @ optional op; may set condition codes 3620 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3621 GET_INST_OPCODE(ip) @ extract opcode from rINST 3622 stmia r9, {r0-r1} @ vAA<- r0/r1 3623 GOTO_OPCODE(ip) @ jump to next instruction 3624 /* 12-13 instructions */ 3625 3626 3627 3628/* ------------------------------ */ 3629 .balign 64 3630.L_OP_NEG_FLOAT: /* 0x7f */ 3631/* File: armv5te/OP_NEG_FLOAT.S */ 3632/* File: armv5te/unop.S */ 3633 /* 3634 * Generic 32-bit unary operation. Provide an "instr" line that 3635 * specifies an instruction that performs "result = op r0". 3636 * This could be an ARM instruction or a function call. 3637 * 3638 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3639 * int-to-byte, int-to-char, int-to-short 3640 */ 3641 /* unop vA, vB */ 3642 mov r3, rINST, lsr #12 @ r3<- B 3643 mov r9, rINST, lsr #8 @ r9<- A+ 3644 GET_VREG(r0, r3) @ r0<- vB 3645 and r9, r9, #15 3646 @ optional op; may set condition codes 3647 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3648 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3649 GET_INST_OPCODE(ip) @ extract opcode from rINST 3650 SET_VREG(r0, r9) @ vAA<- r0 3651 GOTO_OPCODE(ip) @ jump to next instruction 3652 /* 9-10 instructions */ 3653 3654 3655/* ------------------------------ */ 3656 .balign 64 3657.L_OP_NEG_DOUBLE: /* 0x80 */ 3658/* File: armv5te/OP_NEG_DOUBLE.S */ 3659/* File: armv5te/unopWide.S */ 3660 /* 3661 * Generic 64-bit unary operation. Provide an "instr" line that 3662 * specifies an instruction that performs "result = op r0/r1". 3663 * This could be an ARM instruction or a function call. 3664 * 3665 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3666 */ 3667 /* unop vA, vB */ 3668 mov r9, rINST, lsr #8 @ r9<- A+ 3669 mov r3, rINST, lsr #12 @ r3<- B 3670 and r9, r9, #15 3671 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3672 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3673 ldmia r3, {r0-r1} @ r0/r1<- vAA 3674 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3675 @ optional op; may set condition codes 3676 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3677 GET_INST_OPCODE(ip) @ extract opcode from rINST 3678 stmia r9, {r0-r1} @ vAA<- r0/r1 3679 GOTO_OPCODE(ip) @ jump to next instruction 3680 /* 12-13 instructions */ 3681 3682 3683 3684/* ------------------------------ */ 3685 .balign 64 3686.L_OP_INT_TO_LONG: /* 0x81 */ 3687/* File: armv5te/OP_INT_TO_LONG.S */ 3688/* File: armv5te/unopWider.S */ 3689 /* 3690 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3691 * that specifies an instruction that performs "result = op r0", where 3692 * "result" is a 64-bit quantity in r0/r1. 3693 * 3694 * For: int-to-long, int-to-double, float-to-long, float-to-double 3695 */ 3696 /* unop vA, vB */ 3697 mov r9, rINST, lsr #8 @ r9<- A+ 3698 mov r3, rINST, lsr #12 @ r3<- B 3699 and r9, r9, #15 3700 GET_VREG(r0, r3) @ r0<- vB 3701 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3702 @ optional op; may set condition codes 3703 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3704 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3705 GET_INST_OPCODE(ip) @ extract opcode from rINST 3706 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3707 GOTO_OPCODE(ip) @ jump to next instruction 3708 /* 10-11 instructions */ 3709 3710 3711/* ------------------------------ */ 3712 .balign 64 3713.L_OP_INT_TO_FLOAT: /* 0x82 */ 3714/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3715/* File: arm-vfp/funop.S */ 3716 /* 3717 * Generic 32-bit unary floating-point operation. Provide an "instr" 3718 * line that specifies an instruction that performs "s1 = op s0". 3719 * 3720 * for: int-to-float, float-to-int 3721 */ 3722 /* unop vA, vB */ 3723 mov r3, rINST, lsr #12 @ r3<- B 3724 mov r9, rINST, lsr #8 @ r9<- A+ 3725 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3726 flds s0, [r3] @ s0<- vB 3727 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3728 and r9, r9, #15 @ r9<- A 3729 fsitos s1, s0 @ s1<- op 3730 GET_INST_OPCODE(ip) @ extract opcode from rINST 3731 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3732 fsts s1, [r9] @ vA<- s1 3733 GOTO_OPCODE(ip) @ jump to next instruction 3734 3735 3736/* ------------------------------ */ 3737 .balign 64 3738.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3739/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3740/* File: arm-vfp/funopWider.S */ 3741 /* 3742 * Generic 32bit-to-64bit floating point unary operation. Provide an 3743 * "instr" line that specifies an instruction that performs "d0 = op s0". 3744 * 3745 * For: int-to-double, float-to-double 3746 */ 3747 /* unop vA, vB */ 3748 mov r3, rINST, lsr #12 @ r3<- B 3749 mov r9, rINST, lsr #8 @ r9<- A+ 3750 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3751 flds s0, [r3] @ s0<- vB 3752 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3753 and r9, r9, #15 @ r9<- A 3754 fsitod d0, s0 @ d0<- op 3755 GET_INST_OPCODE(ip) @ extract opcode from rINST 3756 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3757 fstd d0, [r9] @ vA<- d0 3758 GOTO_OPCODE(ip) @ jump to next instruction 3759 3760 3761/* ------------------------------ */ 3762 .balign 64 3763.L_OP_LONG_TO_INT: /* 0x84 */ 3764/* File: armv5te/OP_LONG_TO_INT.S */ 3765/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3766/* File: armv5te/OP_MOVE.S */ 3767 /* for move, move-object, long-to-int */ 3768 /* op vA, vB */ 3769 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3770 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3771 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3772 GET_VREG(r2, r1) @ r2<- fp[B] 3773 and r0, r0, #15 3774 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3775 SET_VREG(r2, r0) @ fp[A]<- r2 3776 GOTO_OPCODE(ip) @ execute next instruction 3777 3778 3779 3780/* ------------------------------ */ 3781 .balign 64 3782.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3783/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3784/* File: armv5te/unopNarrower.S */ 3785 /* 3786 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3787 * that specifies an instruction that performs "result = op r0/r1", where 3788 * "result" is a 32-bit quantity in r0. 3789 * 3790 * For: long-to-float, double-to-int, double-to-float 3791 * 3792 * (This would work for long-to-int, but that instruction is actually 3793 * an exact match for OP_MOVE.) 3794 */ 3795 /* unop vA, vB */ 3796 mov r3, rINST, lsr #12 @ r3<- B 3797 mov r9, rINST, lsr #8 @ r9<- A+ 3798 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3799 and r9, r9, #15 3800 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3801 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3802 @ optional op; may set condition codes 3803 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3804 GET_INST_OPCODE(ip) @ extract opcode from rINST 3805 SET_VREG(r0, r9) @ vA<- r0 3806 GOTO_OPCODE(ip) @ jump to next instruction 3807 /* 10-11 instructions */ 3808 3809 3810/* ------------------------------ */ 3811 .balign 64 3812.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3813/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3814/* File: armv5te/unopWide.S */ 3815 /* 3816 * Generic 64-bit unary operation. Provide an "instr" line that 3817 * specifies an instruction that performs "result = op r0/r1". 3818 * This could be an ARM instruction or a function call. 3819 * 3820 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3821 */ 3822 /* unop vA, vB */ 3823 mov r9, rINST, lsr #8 @ r9<- A+ 3824 mov r3, rINST, lsr #12 @ r3<- B 3825 and r9, r9, #15 3826 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3827 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3828 ldmia r3, {r0-r1} @ r0/r1<- vAA 3829 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3830 @ optional op; may set condition codes 3831 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3832 GET_INST_OPCODE(ip) @ extract opcode from rINST 3833 stmia r9, {r0-r1} @ vAA<- r0/r1 3834 GOTO_OPCODE(ip) @ jump to next instruction 3835 /* 12-13 instructions */ 3836 3837 3838 3839/* ------------------------------ */ 3840 .balign 64 3841.L_OP_FLOAT_TO_INT: /* 0x87 */ 3842/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3843/* File: arm-vfp/funop.S */ 3844 /* 3845 * Generic 32-bit unary floating-point operation. Provide an "instr" 3846 * line that specifies an instruction that performs "s1 = op s0". 3847 * 3848 * for: int-to-float, float-to-int 3849 */ 3850 /* unop vA, vB */ 3851 mov r3, rINST, lsr #12 @ r3<- B 3852 mov r9, rINST, lsr #8 @ r9<- A+ 3853 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3854 flds s0, [r3] @ s0<- vB 3855 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3856 and r9, r9, #15 @ r9<- A 3857 ftosizs s1, s0 @ s1<- op 3858 GET_INST_OPCODE(ip) @ extract opcode from rINST 3859 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3860 fsts s1, [r9] @ vA<- s1 3861 GOTO_OPCODE(ip) @ jump to next instruction 3862 3863 3864/* ------------------------------ */ 3865 .balign 64 3866.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3867/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3868@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3869/* File: armv5te/unopWider.S */ 3870 /* 3871 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3872 * that specifies an instruction that performs "result = op r0", where 3873 * "result" is a 64-bit quantity in r0/r1. 3874 * 3875 * For: int-to-long, int-to-double, float-to-long, float-to-double 3876 */ 3877 /* unop vA, vB */ 3878 mov r9, rINST, lsr #8 @ r9<- A+ 3879 mov r3, rINST, lsr #12 @ r3<- B 3880 and r9, r9, #15 3881 GET_VREG(r0, r3) @ r0<- vB 3882 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3883 @ optional op; may set condition codes 3884 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3885 bl f2l_doconv @ r0<- op, r0-r3 changed 3886 GET_INST_OPCODE(ip) @ extract opcode from rINST 3887 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3888 GOTO_OPCODE(ip) @ jump to next instruction 3889 /* 10-11 instructions */ 3890 3891 3892 3893/* ------------------------------ */ 3894 .balign 64 3895.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3896/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3897/* File: arm-vfp/funopWider.S */ 3898 /* 3899 * Generic 32bit-to-64bit floating point unary operation. Provide an 3900 * "instr" line that specifies an instruction that performs "d0 = op s0". 3901 * 3902 * For: int-to-double, float-to-double 3903 */ 3904 /* unop vA, vB */ 3905 mov r3, rINST, lsr #12 @ r3<- B 3906 mov r9, rINST, lsr #8 @ r9<- A+ 3907 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3908 flds s0, [r3] @ s0<- vB 3909 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3910 and r9, r9, #15 @ r9<- A 3911 fcvtds d0, s0 @ d0<- op 3912 GET_INST_OPCODE(ip) @ extract opcode from rINST 3913 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3914 fstd d0, [r9] @ vA<- d0 3915 GOTO_OPCODE(ip) @ jump to next instruction 3916 3917 3918/* ------------------------------ */ 3919 .balign 64 3920.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3921/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3922/* File: arm-vfp/funopNarrower.S */ 3923 /* 3924 * Generic 64bit-to-32bit unary floating point operation. Provide an 3925 * "instr" line that specifies an instruction that performs "s0 = op d0". 3926 * 3927 * For: double-to-int, double-to-float 3928 */ 3929 /* unop vA, vB */ 3930 mov r3, rINST, lsr #12 @ r3<- B 3931 mov r9, rINST, lsr #8 @ r9<- A+ 3932 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3933 fldd d0, [r3] @ d0<- vB 3934 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3935 and r9, r9, #15 @ r9<- A 3936 ftosizd s0, d0 @ s0<- op 3937 GET_INST_OPCODE(ip) @ extract opcode from rINST 3938 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3939 fsts s0, [r9] @ vA<- s0 3940 GOTO_OPCODE(ip) @ jump to next instruction 3941 3942 3943/* ------------------------------ */ 3944 .balign 64 3945.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3946/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3947@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3948/* File: armv5te/unopWide.S */ 3949 /* 3950 * Generic 64-bit unary operation. Provide an "instr" line that 3951 * specifies an instruction that performs "result = op r0/r1". 3952 * This could be an ARM instruction or a function call. 3953 * 3954 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3955 */ 3956 /* unop vA, vB */ 3957 mov r9, rINST, lsr #8 @ r9<- A+ 3958 mov r3, rINST, lsr #12 @ r3<- B 3959 and r9, r9, #15 3960 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3961 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3962 ldmia r3, {r0-r1} @ r0/r1<- vAA 3963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3964 @ optional op; may set condition codes 3965 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3966 GET_INST_OPCODE(ip) @ extract opcode from rINST 3967 stmia r9, {r0-r1} @ vAA<- r0/r1 3968 GOTO_OPCODE(ip) @ jump to next instruction 3969 /* 12-13 instructions */ 3970 3971 3972 3973 3974/* ------------------------------ */ 3975 .balign 64 3976.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3977/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3978/* File: arm-vfp/funopNarrower.S */ 3979 /* 3980 * Generic 64bit-to-32bit unary floating point operation. Provide an 3981 * "instr" line that specifies an instruction that performs "s0 = op d0". 3982 * 3983 * For: double-to-int, double-to-float 3984 */ 3985 /* unop vA, vB */ 3986 mov r3, rINST, lsr #12 @ r3<- B 3987 mov r9, rINST, lsr #8 @ r9<- A+ 3988 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3989 fldd d0, [r3] @ d0<- vB 3990 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3991 and r9, r9, #15 @ r9<- A 3992 fcvtsd s0, d0 @ s0<- op 3993 GET_INST_OPCODE(ip) @ extract opcode from rINST 3994 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3995 fsts s0, [r9] @ vA<- s0 3996 GOTO_OPCODE(ip) @ jump to next instruction 3997 3998 3999/* ------------------------------ */ 4000 .balign 64 4001.L_OP_INT_TO_BYTE: /* 0x8d */ 4002/* File: armv5te/OP_INT_TO_BYTE.S */ 4003/* File: armv5te/unop.S */ 4004 /* 4005 * Generic 32-bit unary operation. Provide an "instr" line that 4006 * specifies an instruction that performs "result = op r0". 4007 * This could be an ARM instruction or a function call. 4008 * 4009 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4010 * int-to-byte, int-to-char, int-to-short 4011 */ 4012 /* unop vA, vB */ 4013 mov r3, rINST, lsr #12 @ r3<- B 4014 mov r9, rINST, lsr #8 @ r9<- A+ 4015 GET_VREG(r0, r3) @ r0<- vB 4016 and r9, r9, #15 4017 mov r0, r0, asl #24 @ optional op; may set condition codes 4018 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4019 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4020 GET_INST_OPCODE(ip) @ extract opcode from rINST 4021 SET_VREG(r0, r9) @ vAA<- r0 4022 GOTO_OPCODE(ip) @ jump to next instruction 4023 /* 9-10 instructions */ 4024 4025 4026/* ------------------------------ */ 4027 .balign 64 4028.L_OP_INT_TO_CHAR: /* 0x8e */ 4029/* File: armv5te/OP_INT_TO_CHAR.S */ 4030/* File: armv5te/unop.S */ 4031 /* 4032 * Generic 32-bit unary operation. Provide an "instr" line that 4033 * specifies an instruction that performs "result = op r0". 4034 * This could be an ARM instruction or a function call. 4035 * 4036 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4037 * int-to-byte, int-to-char, int-to-short 4038 */ 4039 /* unop vA, vB */ 4040 mov r3, rINST, lsr #12 @ r3<- B 4041 mov r9, rINST, lsr #8 @ r9<- A+ 4042 GET_VREG(r0, r3) @ r0<- vB 4043 and r9, r9, #15 4044 mov r0, r0, asl #16 @ optional op; may set condition codes 4045 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4046 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4047 GET_INST_OPCODE(ip) @ extract opcode from rINST 4048 SET_VREG(r0, r9) @ vAA<- r0 4049 GOTO_OPCODE(ip) @ jump to next instruction 4050 /* 9-10 instructions */ 4051 4052 4053/* ------------------------------ */ 4054 .balign 64 4055.L_OP_INT_TO_SHORT: /* 0x8f */ 4056/* File: armv5te/OP_INT_TO_SHORT.S */ 4057/* File: armv5te/unop.S */ 4058 /* 4059 * Generic 32-bit unary operation. Provide an "instr" line that 4060 * specifies an instruction that performs "result = op r0". 4061 * This could be an ARM instruction or a function call. 4062 * 4063 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4064 * int-to-byte, int-to-char, int-to-short 4065 */ 4066 /* unop vA, vB */ 4067 mov r3, rINST, lsr #12 @ r3<- B 4068 mov r9, rINST, lsr #8 @ r9<- A+ 4069 GET_VREG(r0, r3) @ r0<- vB 4070 and r9, r9, #15 4071 mov r0, r0, asl #16 @ optional op; may set condition codes 4072 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4073 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4074 GET_INST_OPCODE(ip) @ extract opcode from rINST 4075 SET_VREG(r0, r9) @ vAA<- r0 4076 GOTO_OPCODE(ip) @ jump to next instruction 4077 /* 9-10 instructions */ 4078 4079 4080/* ------------------------------ */ 4081 .balign 64 4082.L_OP_ADD_INT: /* 0x90 */ 4083/* File: armv5te/OP_ADD_INT.S */ 4084/* File: armv5te/binop.S */ 4085 /* 4086 * Generic 32-bit binary operation. Provide an "instr" line that 4087 * specifies an instruction that performs "result = r0 op r1". 4088 * This could be an ARM instruction or a function call. (If the result 4089 * comes back in a register other than r0, you can override "result".) 4090 * 4091 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4092 * vCC (r1). Useful for integer division and modulus. Note that we 4093 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4094 * handles it correctly. 4095 * 4096 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4097 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4098 * mul-float, div-float, rem-float 4099 */ 4100 /* binop vAA, vBB, vCC */ 4101 FETCH(r0, 1) @ r0<- CCBB 4102 mov r9, rINST, lsr #8 @ r9<- AA 4103 mov r3, r0, lsr #8 @ r3<- CC 4104 and r2, r0, #255 @ r2<- BB 4105 GET_VREG(r1, r3) @ r1<- vCC 4106 GET_VREG(r0, r2) @ r0<- vBB 4107 .if 0 4108 cmp r1, #0 @ is second operand zero? 4109 beq common_errDivideByZero 4110 .endif 4111 4112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4113 @ optional op; may set condition codes 4114 add r0, r0, r1 @ r0<- op, r0-r3 changed 4115 GET_INST_OPCODE(ip) @ extract opcode from rINST 4116 SET_VREG(r0, r9) @ vAA<- r0 4117 GOTO_OPCODE(ip) @ jump to next instruction 4118 /* 11-14 instructions */ 4119 4120 4121 4122/* ------------------------------ */ 4123 .balign 64 4124.L_OP_SUB_INT: /* 0x91 */ 4125/* File: armv5te/OP_SUB_INT.S */ 4126/* File: armv5te/binop.S */ 4127 /* 4128 * Generic 32-bit binary operation. Provide an "instr" line that 4129 * specifies an instruction that performs "result = r0 op r1". 4130 * This could be an ARM instruction or a function call. (If the result 4131 * comes back in a register other than r0, you can override "result".) 4132 * 4133 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4134 * vCC (r1). Useful for integer division and modulus. Note that we 4135 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4136 * handles it correctly. 4137 * 4138 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4139 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4140 * mul-float, div-float, rem-float 4141 */ 4142 /* binop vAA, vBB, vCC */ 4143 FETCH(r0, 1) @ r0<- CCBB 4144 mov r9, rINST, lsr #8 @ r9<- AA 4145 mov r3, r0, lsr #8 @ r3<- CC 4146 and r2, r0, #255 @ r2<- BB 4147 GET_VREG(r1, r3) @ r1<- vCC 4148 GET_VREG(r0, r2) @ r0<- vBB 4149 .if 0 4150 cmp r1, #0 @ is second operand zero? 4151 beq common_errDivideByZero 4152 .endif 4153 4154 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4155 @ optional op; may set condition codes 4156 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4157 GET_INST_OPCODE(ip) @ extract opcode from rINST 4158 SET_VREG(r0, r9) @ vAA<- r0 4159 GOTO_OPCODE(ip) @ jump to next instruction 4160 /* 11-14 instructions */ 4161 4162 4163 4164/* ------------------------------ */ 4165 .balign 64 4166.L_OP_MUL_INT: /* 0x92 */ 4167/* File: armv5te/OP_MUL_INT.S */ 4168/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4169/* File: armv5te/binop.S */ 4170 /* 4171 * Generic 32-bit binary operation. Provide an "instr" line that 4172 * specifies an instruction that performs "result = r0 op r1". 4173 * This could be an ARM instruction or a function call. (If the result 4174 * comes back in a register other than r0, you can override "result".) 4175 * 4176 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4177 * vCC (r1). Useful for integer division and modulus. Note that we 4178 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4179 * handles it correctly. 4180 * 4181 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4182 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4183 * mul-float, div-float, rem-float 4184 */ 4185 /* binop vAA, vBB, vCC */ 4186 FETCH(r0, 1) @ r0<- CCBB 4187 mov r9, rINST, lsr #8 @ r9<- AA 4188 mov r3, r0, lsr #8 @ r3<- CC 4189 and r2, r0, #255 @ r2<- BB 4190 GET_VREG(r1, r3) @ r1<- vCC 4191 GET_VREG(r0, r2) @ r0<- vBB 4192 .if 0 4193 cmp r1, #0 @ is second operand zero? 4194 beq common_errDivideByZero 4195 .endif 4196 4197 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4198 @ optional op; may set condition codes 4199 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4200 GET_INST_OPCODE(ip) @ extract opcode from rINST 4201 SET_VREG(r0, r9) @ vAA<- r0 4202 GOTO_OPCODE(ip) @ jump to next instruction 4203 /* 11-14 instructions */ 4204 4205 4206 4207/* ------------------------------ */ 4208 .balign 64 4209.L_OP_DIV_INT: /* 0x93 */ 4210/* File: armv5te/OP_DIV_INT.S */ 4211/* File: armv5te/binop.S */ 4212 /* 4213 * Generic 32-bit binary operation. Provide an "instr" line that 4214 * specifies an instruction that performs "result = r0 op r1". 4215 * This could be an ARM instruction or a function call. (If the result 4216 * comes back in a register other than r0, you can override "result".) 4217 * 4218 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4219 * vCC (r1). Useful for integer division and modulus. Note that we 4220 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4221 * handles it correctly. 4222 * 4223 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4224 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4225 * mul-float, div-float, rem-float 4226 */ 4227 /* binop vAA, vBB, vCC */ 4228 FETCH(r0, 1) @ r0<- CCBB 4229 mov r9, rINST, lsr #8 @ r9<- AA 4230 mov r3, r0, lsr #8 @ r3<- CC 4231 and r2, r0, #255 @ r2<- BB 4232 GET_VREG(r1, r3) @ r1<- vCC 4233 GET_VREG(r0, r2) @ r0<- vBB 4234 .if 1 4235 cmp r1, #0 @ is second operand zero? 4236 beq common_errDivideByZero 4237 .endif 4238 4239 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4240 @ optional op; may set condition codes 4241 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4242 GET_INST_OPCODE(ip) @ extract opcode from rINST 4243 SET_VREG(r0, r9) @ vAA<- r0 4244 GOTO_OPCODE(ip) @ jump to next instruction 4245 /* 11-14 instructions */ 4246 4247 4248 4249/* ------------------------------ */ 4250 .balign 64 4251.L_OP_REM_INT: /* 0x94 */ 4252/* File: armv5te/OP_REM_INT.S */ 4253/* idivmod returns quotient in r0 and remainder in r1 */ 4254/* File: armv5te/binop.S */ 4255 /* 4256 * Generic 32-bit binary operation. Provide an "instr" line that 4257 * specifies an instruction that performs "result = r0 op r1". 4258 * This could be an ARM instruction or a function call. (If the result 4259 * comes back in a register other than r0, you can override "result".) 4260 * 4261 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4262 * vCC (r1). Useful for integer division and modulus. Note that we 4263 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4264 * handles it correctly. 4265 * 4266 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4267 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4268 * mul-float, div-float, rem-float 4269 */ 4270 /* binop vAA, vBB, vCC */ 4271 FETCH(r0, 1) @ r0<- CCBB 4272 mov r9, rINST, lsr #8 @ r9<- AA 4273 mov r3, r0, lsr #8 @ r3<- CC 4274 and r2, r0, #255 @ r2<- BB 4275 GET_VREG(r1, r3) @ r1<- vCC 4276 GET_VREG(r0, r2) @ r0<- vBB 4277 .if 1 4278 cmp r1, #0 @ is second operand zero? 4279 beq common_errDivideByZero 4280 .endif 4281 4282 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4283 @ optional op; may set condition codes 4284 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4285 GET_INST_OPCODE(ip) @ extract opcode from rINST 4286 SET_VREG(r1, r9) @ vAA<- r1 4287 GOTO_OPCODE(ip) @ jump to next instruction 4288 /* 11-14 instructions */ 4289 4290 4291 4292/* ------------------------------ */ 4293 .balign 64 4294.L_OP_AND_INT: /* 0x95 */ 4295/* File: armv5te/OP_AND_INT.S */ 4296/* File: armv5te/binop.S */ 4297 /* 4298 * Generic 32-bit binary operation. Provide an "instr" line that 4299 * specifies an instruction that performs "result = r0 op r1". 4300 * This could be an ARM instruction or a function call. (If the result 4301 * comes back in a register other than r0, you can override "result".) 4302 * 4303 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4304 * vCC (r1). Useful for integer division and modulus. Note that we 4305 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4306 * handles it correctly. 4307 * 4308 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4309 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4310 * mul-float, div-float, rem-float 4311 */ 4312 /* binop vAA, vBB, vCC */ 4313 FETCH(r0, 1) @ r0<- CCBB 4314 mov r9, rINST, lsr #8 @ r9<- AA 4315 mov r3, r0, lsr #8 @ r3<- CC 4316 and r2, r0, #255 @ r2<- BB 4317 GET_VREG(r1, r3) @ r1<- vCC 4318 GET_VREG(r0, r2) @ r0<- vBB 4319 .if 0 4320 cmp r1, #0 @ is second operand zero? 4321 beq common_errDivideByZero 4322 .endif 4323 4324 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4325 @ optional op; may set condition codes 4326 and r0, r0, r1 @ r0<- op, r0-r3 changed 4327 GET_INST_OPCODE(ip) @ extract opcode from rINST 4328 SET_VREG(r0, r9) @ vAA<- r0 4329 GOTO_OPCODE(ip) @ jump to next instruction 4330 /* 11-14 instructions */ 4331 4332 4333 4334/* ------------------------------ */ 4335 .balign 64 4336.L_OP_OR_INT: /* 0x96 */ 4337/* File: armv5te/OP_OR_INT.S */ 4338/* File: armv5te/binop.S */ 4339 /* 4340 * Generic 32-bit binary operation. Provide an "instr" line that 4341 * specifies an instruction that performs "result = r0 op r1". 4342 * This could be an ARM instruction or a function call. (If the result 4343 * comes back in a register other than r0, you can override "result".) 4344 * 4345 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4346 * vCC (r1). Useful for integer division and modulus. Note that we 4347 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4348 * handles it correctly. 4349 * 4350 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4351 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4352 * mul-float, div-float, rem-float 4353 */ 4354 /* binop vAA, vBB, vCC */ 4355 FETCH(r0, 1) @ r0<- CCBB 4356 mov r9, rINST, lsr #8 @ r9<- AA 4357 mov r3, r0, lsr #8 @ r3<- CC 4358 and r2, r0, #255 @ r2<- BB 4359 GET_VREG(r1, r3) @ r1<- vCC 4360 GET_VREG(r0, r2) @ r0<- vBB 4361 .if 0 4362 cmp r1, #0 @ is second operand zero? 4363 beq common_errDivideByZero 4364 .endif 4365 4366 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4367 @ optional op; may set condition codes 4368 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4369 GET_INST_OPCODE(ip) @ extract opcode from rINST 4370 SET_VREG(r0, r9) @ vAA<- r0 4371 GOTO_OPCODE(ip) @ jump to next instruction 4372 /* 11-14 instructions */ 4373 4374 4375 4376/* ------------------------------ */ 4377 .balign 64 4378.L_OP_XOR_INT: /* 0x97 */ 4379/* File: armv5te/OP_XOR_INT.S */ 4380/* File: armv5te/binop.S */ 4381 /* 4382 * Generic 32-bit binary operation. Provide an "instr" line that 4383 * specifies an instruction that performs "result = r0 op r1". 4384 * This could be an ARM instruction or a function call. (If the result 4385 * comes back in a register other than r0, you can override "result".) 4386 * 4387 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4388 * vCC (r1). Useful for integer division and modulus. Note that we 4389 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4390 * handles it correctly. 4391 * 4392 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4393 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4394 * mul-float, div-float, rem-float 4395 */ 4396 /* binop vAA, vBB, vCC */ 4397 FETCH(r0, 1) @ r0<- CCBB 4398 mov r9, rINST, lsr #8 @ r9<- AA 4399 mov r3, r0, lsr #8 @ r3<- CC 4400 and r2, r0, #255 @ r2<- BB 4401 GET_VREG(r1, r3) @ r1<- vCC 4402 GET_VREG(r0, r2) @ r0<- vBB 4403 .if 0 4404 cmp r1, #0 @ is second operand zero? 4405 beq common_errDivideByZero 4406 .endif 4407 4408 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4409 @ optional op; may set condition codes 4410 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4411 GET_INST_OPCODE(ip) @ extract opcode from rINST 4412 SET_VREG(r0, r9) @ vAA<- r0 4413 GOTO_OPCODE(ip) @ jump to next instruction 4414 /* 11-14 instructions */ 4415 4416 4417 4418/* ------------------------------ */ 4419 .balign 64 4420.L_OP_SHL_INT: /* 0x98 */ 4421/* File: armv5te/OP_SHL_INT.S */ 4422/* File: armv5te/binop.S */ 4423 /* 4424 * Generic 32-bit binary operation. Provide an "instr" line that 4425 * specifies an instruction that performs "result = r0 op r1". 4426 * This could be an ARM instruction or a function call. (If the result 4427 * comes back in a register other than r0, you can override "result".) 4428 * 4429 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4430 * vCC (r1). Useful for integer division and modulus. Note that we 4431 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4432 * handles it correctly. 4433 * 4434 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4435 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4436 * mul-float, div-float, rem-float 4437 */ 4438 /* binop vAA, vBB, vCC */ 4439 FETCH(r0, 1) @ r0<- CCBB 4440 mov r9, rINST, lsr #8 @ r9<- AA 4441 mov r3, r0, lsr #8 @ r3<- CC 4442 and r2, r0, #255 @ r2<- BB 4443 GET_VREG(r1, r3) @ r1<- vCC 4444 GET_VREG(r0, r2) @ r0<- vBB 4445 .if 0 4446 cmp r1, #0 @ is second operand zero? 4447 beq common_errDivideByZero 4448 .endif 4449 4450 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4451 and r1, r1, #31 @ optional op; may set condition codes 4452 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4453 GET_INST_OPCODE(ip) @ extract opcode from rINST 4454 SET_VREG(r0, r9) @ vAA<- r0 4455 GOTO_OPCODE(ip) @ jump to next instruction 4456 /* 11-14 instructions */ 4457 4458 4459 4460/* ------------------------------ */ 4461 .balign 64 4462.L_OP_SHR_INT: /* 0x99 */ 4463/* File: armv5te/OP_SHR_INT.S */ 4464/* File: armv5te/binop.S */ 4465 /* 4466 * Generic 32-bit binary operation. Provide an "instr" line that 4467 * specifies an instruction that performs "result = r0 op r1". 4468 * This could be an ARM instruction or a function call. (If the result 4469 * comes back in a register other than r0, you can override "result".) 4470 * 4471 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4472 * vCC (r1). Useful for integer division and modulus. Note that we 4473 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4474 * handles it correctly. 4475 * 4476 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4477 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4478 * mul-float, div-float, rem-float 4479 */ 4480 /* binop vAA, vBB, vCC */ 4481 FETCH(r0, 1) @ r0<- CCBB 4482 mov r9, rINST, lsr #8 @ r9<- AA 4483 mov r3, r0, lsr #8 @ r3<- CC 4484 and r2, r0, #255 @ r2<- BB 4485 GET_VREG(r1, r3) @ r1<- vCC 4486 GET_VREG(r0, r2) @ r0<- vBB 4487 .if 0 4488 cmp r1, #0 @ is second operand zero? 4489 beq common_errDivideByZero 4490 .endif 4491 4492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4493 and r1, r1, #31 @ optional op; may set condition codes 4494 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4495 GET_INST_OPCODE(ip) @ extract opcode from rINST 4496 SET_VREG(r0, r9) @ vAA<- r0 4497 GOTO_OPCODE(ip) @ jump to next instruction 4498 /* 11-14 instructions */ 4499 4500 4501 4502/* ------------------------------ */ 4503 .balign 64 4504.L_OP_USHR_INT: /* 0x9a */ 4505/* File: armv5te/OP_USHR_INT.S */ 4506/* File: armv5te/binop.S */ 4507 /* 4508 * Generic 32-bit binary operation. Provide an "instr" line that 4509 * specifies an instruction that performs "result = r0 op r1". 4510 * This could be an ARM instruction or a function call. (If the result 4511 * comes back in a register other than r0, you can override "result".) 4512 * 4513 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4514 * vCC (r1). Useful for integer division and modulus. Note that we 4515 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4516 * handles it correctly. 4517 * 4518 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4519 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4520 * mul-float, div-float, rem-float 4521 */ 4522 /* binop vAA, vBB, vCC */ 4523 FETCH(r0, 1) @ r0<- CCBB 4524 mov r9, rINST, lsr #8 @ r9<- AA 4525 mov r3, r0, lsr #8 @ r3<- CC 4526 and r2, r0, #255 @ r2<- BB 4527 GET_VREG(r1, r3) @ r1<- vCC 4528 GET_VREG(r0, r2) @ r0<- vBB 4529 .if 0 4530 cmp r1, #0 @ is second operand zero? 4531 beq common_errDivideByZero 4532 .endif 4533 4534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4535 and r1, r1, #31 @ optional op; may set condition codes 4536 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4537 GET_INST_OPCODE(ip) @ extract opcode from rINST 4538 SET_VREG(r0, r9) @ vAA<- r0 4539 GOTO_OPCODE(ip) @ jump to next instruction 4540 /* 11-14 instructions */ 4541 4542 4543 4544/* ------------------------------ */ 4545 .balign 64 4546.L_OP_ADD_LONG: /* 0x9b */ 4547/* File: armv5te/OP_ADD_LONG.S */ 4548/* File: armv5te/binopWide.S */ 4549 /* 4550 * Generic 64-bit binary operation. Provide an "instr" line that 4551 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4552 * This could be an ARM instruction or a function call. (If the result 4553 * comes back in a register other than r0, you can override "result".) 4554 * 4555 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4556 * vCC (r1). Useful for integer division and modulus. 4557 * 4558 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4559 * xor-long, add-double, sub-double, mul-double, div-double, 4560 * rem-double 4561 * 4562 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4563 */ 4564 /* binop vAA, vBB, vCC */ 4565 FETCH(r0, 1) @ r0<- CCBB 4566 mov r9, rINST, lsr #8 @ r9<- AA 4567 and r2, r0, #255 @ r2<- BB 4568 mov r3, r0, lsr #8 @ r3<- CC 4569 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4570 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4571 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4572 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4573 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4574 .if 0 4575 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4576 beq common_errDivideByZero 4577 .endif 4578 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4579 4580 adds r0, r0, r2 @ optional op; may set condition codes 4581 adc r1, r1, r3 @ result<- op, r0-r3 changed 4582 GET_INST_OPCODE(ip) @ extract opcode from rINST 4583 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4584 GOTO_OPCODE(ip) @ jump to next instruction 4585 /* 14-17 instructions */ 4586 4587 4588 4589/* ------------------------------ */ 4590 .balign 64 4591.L_OP_SUB_LONG: /* 0x9c */ 4592/* File: armv5te/OP_SUB_LONG.S */ 4593/* File: armv5te/binopWide.S */ 4594 /* 4595 * Generic 64-bit binary operation. Provide an "instr" line that 4596 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4597 * This could be an ARM instruction or a function call. (If the result 4598 * comes back in a register other than r0, you can override "result".) 4599 * 4600 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4601 * vCC (r1). Useful for integer division and modulus. 4602 * 4603 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4604 * xor-long, add-double, sub-double, mul-double, div-double, 4605 * rem-double 4606 * 4607 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4608 */ 4609 /* binop vAA, vBB, vCC */ 4610 FETCH(r0, 1) @ r0<- CCBB 4611 mov r9, rINST, lsr #8 @ r9<- AA 4612 and r2, r0, #255 @ r2<- BB 4613 mov r3, r0, lsr #8 @ r3<- CC 4614 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4615 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4616 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4617 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4618 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4619 .if 0 4620 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4621 beq common_errDivideByZero 4622 .endif 4623 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4624 4625 subs r0, r0, r2 @ optional op; may set condition codes 4626 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4627 GET_INST_OPCODE(ip) @ extract opcode from rINST 4628 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4629 GOTO_OPCODE(ip) @ jump to next instruction 4630 /* 14-17 instructions */ 4631 4632 4633 4634/* ------------------------------ */ 4635 .balign 64 4636.L_OP_MUL_LONG: /* 0x9d */ 4637/* File: armv5te/OP_MUL_LONG.S */ 4638 /* 4639 * Signed 64-bit integer multiply. 4640 * 4641 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4642 * WX 4643 * x YZ 4644 * -------- 4645 * ZW ZX 4646 * YW YX 4647 * 4648 * The low word of the result holds ZX, the high word holds 4649 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4650 * it doesn't fit in the low 64 bits. 4651 * 4652 * Unlike most ARM math operations, multiply instructions have 4653 * restrictions on using the same register more than once (Rd and Rm 4654 * cannot be the same). 4655 */ 4656 /* mul-long vAA, vBB, vCC */ 4657 FETCH(r0, 1) @ r0<- CCBB 4658 and r2, r0, #255 @ r2<- BB 4659 mov r3, r0, lsr #8 @ r3<- CC 4660 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4661 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4662 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4663 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4664 mul ip, r2, r1 @ ip<- ZxW 4665 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4666 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4667 mov r0, rINST, lsr #8 @ r0<- AA 4668 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4669 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4670 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4671 b .LOP_MUL_LONG_finish 4672 4673/* ------------------------------ */ 4674 .balign 64 4675.L_OP_DIV_LONG: /* 0x9e */ 4676/* File: armv5te/OP_DIV_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 1 4704 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4705 beq common_errDivideByZero 4706 .endif 4707 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4708 4709 @ optional op; may set condition codes 4710 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4711 GET_INST_OPCODE(ip) @ extract opcode from rINST 4712 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4713 GOTO_OPCODE(ip) @ jump to next instruction 4714 /* 14-17 instructions */ 4715 4716 4717 4718/* ------------------------------ */ 4719 .balign 64 4720.L_OP_REM_LONG: /* 0x9f */ 4721/* File: armv5te/OP_REM_LONG.S */ 4722/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4723/* File: armv5te/binopWide.S */ 4724 /* 4725 * Generic 64-bit binary operation. Provide an "instr" line that 4726 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4727 * This could be an ARM instruction or a function call. (If the result 4728 * comes back in a register other than r0, you can override "result".) 4729 * 4730 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4731 * vCC (r1). Useful for integer division and modulus. 4732 * 4733 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4734 * xor-long, add-double, sub-double, mul-double, div-double, 4735 * rem-double 4736 * 4737 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4738 */ 4739 /* binop vAA, vBB, vCC */ 4740 FETCH(r0, 1) @ r0<- CCBB 4741 mov r9, rINST, lsr #8 @ r9<- AA 4742 and r2, r0, #255 @ r2<- BB 4743 mov r3, r0, lsr #8 @ r3<- CC 4744 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4745 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4746 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4747 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4748 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4749 .if 1 4750 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4751 beq common_errDivideByZero 4752 .endif 4753 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4754 4755 @ optional op; may set condition codes 4756 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4757 GET_INST_OPCODE(ip) @ extract opcode from rINST 4758 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4759 GOTO_OPCODE(ip) @ jump to next instruction 4760 /* 14-17 instructions */ 4761 4762 4763 4764/* ------------------------------ */ 4765 .balign 64 4766.L_OP_AND_LONG: /* 0xa0 */ 4767/* File: armv5te/OP_AND_LONG.S */ 4768/* File: armv5te/binopWide.S */ 4769 /* 4770 * Generic 64-bit binary operation. Provide an "instr" line that 4771 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4772 * This could be an ARM instruction or a function call. (If the result 4773 * comes back in a register other than r0, you can override "result".) 4774 * 4775 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4776 * vCC (r1). Useful for integer division and modulus. 4777 * 4778 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4779 * xor-long, add-double, sub-double, mul-double, div-double, 4780 * rem-double 4781 * 4782 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4783 */ 4784 /* binop vAA, vBB, vCC */ 4785 FETCH(r0, 1) @ r0<- CCBB 4786 mov r9, rINST, lsr #8 @ r9<- AA 4787 and r2, r0, #255 @ r2<- BB 4788 mov r3, r0, lsr #8 @ r3<- CC 4789 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4790 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4791 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4792 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4793 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4794 .if 0 4795 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4796 beq common_errDivideByZero 4797 .endif 4798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4799 4800 and r0, r0, r2 @ optional op; may set condition codes 4801 and r1, r1, r3 @ result<- op, r0-r3 changed 4802 GET_INST_OPCODE(ip) @ extract opcode from rINST 4803 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4804 GOTO_OPCODE(ip) @ jump to next instruction 4805 /* 14-17 instructions */ 4806 4807 4808 4809/* ------------------------------ */ 4810 .balign 64 4811.L_OP_OR_LONG: /* 0xa1 */ 4812/* File: armv5te/OP_OR_LONG.S */ 4813/* File: armv5te/binopWide.S */ 4814 /* 4815 * Generic 64-bit binary operation. Provide an "instr" line that 4816 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4817 * This could be an ARM instruction or a function call. (If the result 4818 * comes back in a register other than r0, you can override "result".) 4819 * 4820 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4821 * vCC (r1). Useful for integer division and modulus. 4822 * 4823 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4824 * xor-long, add-double, sub-double, mul-double, div-double, 4825 * rem-double 4826 * 4827 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4828 */ 4829 /* binop vAA, vBB, vCC */ 4830 FETCH(r0, 1) @ r0<- CCBB 4831 mov r9, rINST, lsr #8 @ r9<- AA 4832 and r2, r0, #255 @ r2<- BB 4833 mov r3, r0, lsr #8 @ r3<- CC 4834 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4835 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4836 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4837 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4838 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4839 .if 0 4840 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4841 beq common_errDivideByZero 4842 .endif 4843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4844 4845 orr r0, r0, r2 @ optional op; may set condition codes 4846 orr r1, r1, r3 @ result<- op, r0-r3 changed 4847 GET_INST_OPCODE(ip) @ extract opcode from rINST 4848 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4849 GOTO_OPCODE(ip) @ jump to next instruction 4850 /* 14-17 instructions */ 4851 4852 4853 4854/* ------------------------------ */ 4855 .balign 64 4856.L_OP_XOR_LONG: /* 0xa2 */ 4857/* File: armv5te/OP_XOR_LONG.S */ 4858/* File: armv5te/binopWide.S */ 4859 /* 4860 * Generic 64-bit binary operation. Provide an "instr" line that 4861 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4862 * This could be an ARM instruction or a function call. (If the result 4863 * comes back in a register other than r0, you can override "result".) 4864 * 4865 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4866 * vCC (r1). Useful for integer division and modulus. 4867 * 4868 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4869 * xor-long, add-double, sub-double, mul-double, div-double, 4870 * rem-double 4871 * 4872 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4873 */ 4874 /* binop vAA, vBB, vCC */ 4875 FETCH(r0, 1) @ r0<- CCBB 4876 mov r9, rINST, lsr #8 @ r9<- AA 4877 and r2, r0, #255 @ r2<- BB 4878 mov r3, r0, lsr #8 @ r3<- CC 4879 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4880 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4881 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4882 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4883 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4884 .if 0 4885 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4886 beq common_errDivideByZero 4887 .endif 4888 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4889 4890 eor r0, r0, r2 @ optional op; may set condition codes 4891 eor r1, r1, r3 @ result<- op, r0-r3 changed 4892 GET_INST_OPCODE(ip) @ extract opcode from rINST 4893 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4894 GOTO_OPCODE(ip) @ jump to next instruction 4895 /* 14-17 instructions */ 4896 4897 4898 4899/* ------------------------------ */ 4900 .balign 64 4901.L_OP_SHL_LONG: /* 0xa3 */ 4902/* File: armv5te/OP_SHL_LONG.S */ 4903 /* 4904 * Long integer shift. This is different from the generic 32/64-bit 4905 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4906 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4907 * 6 bits of the shift distance. 4908 */ 4909 /* shl-long vAA, vBB, vCC */ 4910 FETCH(r0, 1) @ r0<- CCBB 4911 mov r9, rINST, lsr #8 @ r9<- AA 4912 and r3, r0, #255 @ r3<- BB 4913 mov r0, r0, lsr #8 @ r0<- CC 4914 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4915 GET_VREG(r2, r0) @ r2<- vCC 4916 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4917 and r2, r2, #63 @ r2<- r2 & 0x3f 4918 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4919 4920 mov r1, r1, asl r2 @ r1<- r1 << r2 4921 rsb r3, r2, #32 @ r3<- 32 - r2 4922 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4923 subs ip, r2, #32 @ ip<- r2 - 32 4924 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4925 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4926 b .LOP_SHL_LONG_finish 4927 4928/* ------------------------------ */ 4929 .balign 64 4930.L_OP_SHR_LONG: /* 0xa4 */ 4931/* File: armv5te/OP_SHR_LONG.S */ 4932 /* 4933 * Long integer shift. This is different from the generic 32/64-bit 4934 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4935 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4936 * 6 bits of the shift distance. 4937 */ 4938 /* shr-long vAA, vBB, vCC */ 4939 FETCH(r0, 1) @ r0<- CCBB 4940 mov r9, rINST, lsr #8 @ r9<- AA 4941 and r3, r0, #255 @ r3<- BB 4942 mov r0, r0, lsr #8 @ r0<- CC 4943 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4944 GET_VREG(r2, r0) @ r2<- vCC 4945 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4946 and r2, r2, #63 @ r0<- r0 & 0x3f 4947 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4948 4949 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4950 rsb r3, r2, #32 @ r3<- 32 - r2 4951 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4952 subs ip, r2, #32 @ ip<- r2 - 32 4953 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4954 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4955 b .LOP_SHR_LONG_finish 4956 4957/* ------------------------------ */ 4958 .balign 64 4959.L_OP_USHR_LONG: /* 0xa5 */ 4960/* File: armv5te/OP_USHR_LONG.S */ 4961 /* 4962 * Long integer shift. This is different from the generic 32/64-bit 4963 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4964 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4965 * 6 bits of the shift distance. 4966 */ 4967 /* ushr-long vAA, vBB, vCC */ 4968 FETCH(r0, 1) @ r0<- CCBB 4969 mov r9, rINST, lsr #8 @ r9<- AA 4970 and r3, r0, #255 @ r3<- BB 4971 mov r0, r0, lsr #8 @ r0<- CC 4972 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4973 GET_VREG(r2, r0) @ r2<- vCC 4974 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4975 and r2, r2, #63 @ r0<- r0 & 0x3f 4976 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4977 4978 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4979 rsb r3, r2, #32 @ r3<- 32 - r2 4980 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4981 subs ip, r2, #32 @ ip<- r2 - 32 4982 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4983 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4984 b .LOP_USHR_LONG_finish 4985 4986/* ------------------------------ */ 4987 .balign 64 4988.L_OP_ADD_FLOAT: /* 0xa6 */ 4989/* File: arm-vfp/OP_ADD_FLOAT.S */ 4990/* File: arm-vfp/fbinop.S */ 4991 /* 4992 * Generic 32-bit floating-point operation. Provide an "instr" line that 4993 * specifies an instruction that performs "s2 = s0 op s1". Because we 4994 * use the "softfp" ABI, this must be an instruction, not a function call. 4995 * 4996 * For: add-float, sub-float, mul-float, div-float 4997 */ 4998 /* floatop vAA, vBB, vCC */ 4999 FETCH(r0, 1) @ r0<- CCBB 5000 mov r9, rINST, lsr #8 @ r9<- AA 5001 mov r3, r0, lsr #8 @ r3<- CC 5002 and r2, r0, #255 @ r2<- BB 5003 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5004 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5005 flds s1, [r3] @ s1<- vCC 5006 flds s0, [r2] @ s0<- vBB 5007 5008 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5009 fadds s2, s0, s1 @ s2<- op 5010 GET_INST_OPCODE(ip) @ extract opcode from rINST 5011 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5012 fsts s2, [r9] @ vAA<- s2 5013 GOTO_OPCODE(ip) @ jump to next instruction 5014 5015 5016/* ------------------------------ */ 5017 .balign 64 5018.L_OP_SUB_FLOAT: /* 0xa7 */ 5019/* File: arm-vfp/OP_SUB_FLOAT.S */ 5020/* File: arm-vfp/fbinop.S */ 5021 /* 5022 * Generic 32-bit floating-point operation. Provide an "instr" line that 5023 * specifies an instruction that performs "s2 = s0 op s1". Because we 5024 * use the "softfp" ABI, this must be an instruction, not a function call. 5025 * 5026 * For: add-float, sub-float, mul-float, div-float 5027 */ 5028 /* floatop vAA, vBB, vCC */ 5029 FETCH(r0, 1) @ r0<- CCBB 5030 mov r9, rINST, lsr #8 @ r9<- AA 5031 mov r3, r0, lsr #8 @ r3<- CC 5032 and r2, r0, #255 @ r2<- BB 5033 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5034 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5035 flds s1, [r3] @ s1<- vCC 5036 flds s0, [r2] @ s0<- vBB 5037 5038 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5039 fsubs s2, s0, s1 @ s2<- op 5040 GET_INST_OPCODE(ip) @ extract opcode from rINST 5041 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5042 fsts s2, [r9] @ vAA<- s2 5043 GOTO_OPCODE(ip) @ jump to next instruction 5044 5045 5046/* ------------------------------ */ 5047 .balign 64 5048.L_OP_MUL_FLOAT: /* 0xa8 */ 5049/* File: arm-vfp/OP_MUL_FLOAT.S */ 5050/* File: arm-vfp/fbinop.S */ 5051 /* 5052 * Generic 32-bit floating-point operation. Provide an "instr" line that 5053 * specifies an instruction that performs "s2 = s0 op s1". Because we 5054 * use the "softfp" ABI, this must be an instruction, not a function call. 5055 * 5056 * For: add-float, sub-float, mul-float, div-float 5057 */ 5058 /* floatop vAA, vBB, vCC */ 5059 FETCH(r0, 1) @ r0<- CCBB 5060 mov r9, rINST, lsr #8 @ r9<- AA 5061 mov r3, r0, lsr #8 @ r3<- CC 5062 and r2, r0, #255 @ r2<- BB 5063 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5064 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5065 flds s1, [r3] @ s1<- vCC 5066 flds s0, [r2] @ s0<- vBB 5067 5068 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5069 fmuls s2, s0, s1 @ s2<- op 5070 GET_INST_OPCODE(ip) @ extract opcode from rINST 5071 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5072 fsts s2, [r9] @ vAA<- s2 5073 GOTO_OPCODE(ip) @ jump to next instruction 5074 5075 5076/* ------------------------------ */ 5077 .balign 64 5078.L_OP_DIV_FLOAT: /* 0xa9 */ 5079/* File: arm-vfp/OP_DIV_FLOAT.S */ 5080/* File: arm-vfp/fbinop.S */ 5081 /* 5082 * Generic 32-bit floating-point operation. Provide an "instr" line that 5083 * specifies an instruction that performs "s2 = s0 op s1". Because we 5084 * use the "softfp" ABI, this must be an instruction, not a function call. 5085 * 5086 * For: add-float, sub-float, mul-float, div-float 5087 */ 5088 /* floatop vAA, vBB, vCC */ 5089 FETCH(r0, 1) @ r0<- CCBB 5090 mov r9, rINST, lsr #8 @ r9<- AA 5091 mov r3, r0, lsr #8 @ r3<- CC 5092 and r2, r0, #255 @ r2<- BB 5093 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5094 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5095 flds s1, [r3] @ s1<- vCC 5096 flds s0, [r2] @ s0<- vBB 5097 5098 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5099 fdivs s2, s0, s1 @ s2<- op 5100 GET_INST_OPCODE(ip) @ extract opcode from rINST 5101 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5102 fsts s2, [r9] @ vAA<- s2 5103 GOTO_OPCODE(ip) @ jump to next instruction 5104 5105 5106/* ------------------------------ */ 5107 .balign 64 5108.L_OP_REM_FLOAT: /* 0xaa */ 5109/* File: armv5te/OP_REM_FLOAT.S */ 5110/* EABI doesn't define a float remainder function, but libm does */ 5111/* File: armv5te/binop.S */ 5112 /* 5113 * Generic 32-bit binary operation. Provide an "instr" line that 5114 * specifies an instruction that performs "result = r0 op r1". 5115 * This could be an ARM instruction or a function call. (If the result 5116 * comes back in a register other than r0, you can override "result".) 5117 * 5118 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5119 * vCC (r1). Useful for integer division and modulus. Note that we 5120 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5121 * handles it correctly. 5122 * 5123 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5124 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5125 * mul-float, div-float, rem-float 5126 */ 5127 /* binop vAA, vBB, vCC */ 5128 FETCH(r0, 1) @ r0<- CCBB 5129 mov r9, rINST, lsr #8 @ r9<- AA 5130 mov r3, r0, lsr #8 @ r3<- CC 5131 and r2, r0, #255 @ r2<- BB 5132 GET_VREG(r1, r3) @ r1<- vCC 5133 GET_VREG(r0, r2) @ r0<- vBB 5134 .if 0 5135 cmp r1, #0 @ is second operand zero? 5136 beq common_errDivideByZero 5137 .endif 5138 5139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5140 @ optional op; may set condition codes 5141 bl fmodf @ r0<- op, r0-r3 changed 5142 GET_INST_OPCODE(ip) @ extract opcode from rINST 5143 SET_VREG(r0, r9) @ vAA<- r0 5144 GOTO_OPCODE(ip) @ jump to next instruction 5145 /* 11-14 instructions */ 5146 5147 5148 5149/* ------------------------------ */ 5150 .balign 64 5151.L_OP_ADD_DOUBLE: /* 0xab */ 5152/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5153/* File: arm-vfp/fbinopWide.S */ 5154 /* 5155 * Generic 64-bit double-precision floating point binary operation. 5156 * Provide an "instr" line that specifies an instruction that performs 5157 * "d2 = d0 op d1". 5158 * 5159 * for: add-double, sub-double, mul-double, div-double 5160 */ 5161 /* doubleop vAA, vBB, vCC */ 5162 FETCH(r0, 1) @ r0<- CCBB 5163 mov r9, rINST, lsr #8 @ r9<- AA 5164 mov r3, r0, lsr #8 @ r3<- CC 5165 and r2, r0, #255 @ r2<- BB 5166 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5167 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5168 fldd d1, [r3] @ d1<- vCC 5169 fldd d0, [r2] @ d0<- vBB 5170 5171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5172 faddd d2, d0, d1 @ s2<- op 5173 GET_INST_OPCODE(ip) @ extract opcode from rINST 5174 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5175 fstd d2, [r9] @ vAA<- d2 5176 GOTO_OPCODE(ip) @ jump to next instruction 5177 5178 5179/* ------------------------------ */ 5180 .balign 64 5181.L_OP_SUB_DOUBLE: /* 0xac */ 5182/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5183/* File: arm-vfp/fbinopWide.S */ 5184 /* 5185 * Generic 64-bit double-precision floating point binary operation. 5186 * Provide an "instr" line that specifies an instruction that performs 5187 * "d2 = d0 op d1". 5188 * 5189 * for: add-double, sub-double, mul-double, div-double 5190 */ 5191 /* doubleop vAA, vBB, vCC */ 5192 FETCH(r0, 1) @ r0<- CCBB 5193 mov r9, rINST, lsr #8 @ r9<- AA 5194 mov r3, r0, lsr #8 @ r3<- CC 5195 and r2, r0, #255 @ r2<- BB 5196 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5197 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5198 fldd d1, [r3] @ d1<- vCC 5199 fldd d0, [r2] @ d0<- vBB 5200 5201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5202 fsubd d2, d0, d1 @ s2<- op 5203 GET_INST_OPCODE(ip) @ extract opcode from rINST 5204 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5205 fstd d2, [r9] @ vAA<- d2 5206 GOTO_OPCODE(ip) @ jump to next instruction 5207 5208 5209/* ------------------------------ */ 5210 .balign 64 5211.L_OP_MUL_DOUBLE: /* 0xad */ 5212/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5213/* File: arm-vfp/fbinopWide.S */ 5214 /* 5215 * Generic 64-bit double-precision floating point binary operation. 5216 * Provide an "instr" line that specifies an instruction that performs 5217 * "d2 = d0 op d1". 5218 * 5219 * for: add-double, sub-double, mul-double, div-double 5220 */ 5221 /* doubleop vAA, vBB, vCC */ 5222 FETCH(r0, 1) @ r0<- CCBB 5223 mov r9, rINST, lsr #8 @ r9<- AA 5224 mov r3, r0, lsr #8 @ r3<- CC 5225 and r2, r0, #255 @ r2<- BB 5226 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5227 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5228 fldd d1, [r3] @ d1<- vCC 5229 fldd d0, [r2] @ d0<- vBB 5230 5231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5232 fmuld d2, d0, d1 @ s2<- op 5233 GET_INST_OPCODE(ip) @ extract opcode from rINST 5234 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5235 fstd d2, [r9] @ vAA<- d2 5236 GOTO_OPCODE(ip) @ jump to next instruction 5237 5238 5239/* ------------------------------ */ 5240 .balign 64 5241.L_OP_DIV_DOUBLE: /* 0xae */ 5242/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5243/* File: arm-vfp/fbinopWide.S */ 5244 /* 5245 * Generic 64-bit double-precision floating point binary operation. 5246 * Provide an "instr" line that specifies an instruction that performs 5247 * "d2 = d0 op d1". 5248 * 5249 * for: add-double, sub-double, mul-double, div-double 5250 */ 5251 /* doubleop vAA, vBB, vCC */ 5252 FETCH(r0, 1) @ r0<- CCBB 5253 mov r9, rINST, lsr #8 @ r9<- AA 5254 mov r3, r0, lsr #8 @ r3<- CC 5255 and r2, r0, #255 @ r2<- BB 5256 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5257 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5258 fldd d1, [r3] @ d1<- vCC 5259 fldd d0, [r2] @ d0<- vBB 5260 5261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5262 fdivd d2, d0, d1 @ s2<- op 5263 GET_INST_OPCODE(ip) @ extract opcode from rINST 5264 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5265 fstd d2, [r9] @ vAA<- d2 5266 GOTO_OPCODE(ip) @ jump to next instruction 5267 5268 5269/* ------------------------------ */ 5270 .balign 64 5271.L_OP_REM_DOUBLE: /* 0xaf */ 5272/* File: armv5te/OP_REM_DOUBLE.S */ 5273/* EABI doesn't define a double remainder function, but libm does */ 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 fmod @ 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/* ------------------------------ */ 5316 .balign 64 5317.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5318/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5319/* File: armv5te/binop2addr.S */ 5320 /* 5321 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5322 * that specifies an instruction that performs "result = r0 op r1". 5323 * This could be an ARM instruction or a function call. (If the result 5324 * comes back in a register other than r0, you can override "result".) 5325 * 5326 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5327 * vCC (r1). Useful for integer division and modulus. 5328 * 5329 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5330 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5331 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5332 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5333 */ 5334 /* binop/2addr vA, vB */ 5335 mov r9, rINST, lsr #8 @ r9<- A+ 5336 mov r3, rINST, lsr #12 @ r3<- B 5337 and r9, r9, #15 5338 GET_VREG(r1, r3) @ r1<- vB 5339 GET_VREG(r0, r9) @ r0<- vA 5340 .if 0 5341 cmp r1, #0 @ is second operand zero? 5342 beq common_errDivideByZero 5343 .endif 5344 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5345 5346 @ optional op; may set condition codes 5347 add r0, r0, r1 @ r0<- op, r0-r3 changed 5348 GET_INST_OPCODE(ip) @ extract opcode from rINST 5349 SET_VREG(r0, r9) @ vAA<- r0 5350 GOTO_OPCODE(ip) @ jump to next instruction 5351 /* 10-13 instructions */ 5352 5353 5354 5355/* ------------------------------ */ 5356 .balign 64 5357.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5358/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5359/* File: armv5te/binop2addr.S */ 5360 /* 5361 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5362 * that specifies an instruction that performs "result = r0 op r1". 5363 * This could be an ARM instruction or a function call. (If the result 5364 * comes back in a register other than r0, you can override "result".) 5365 * 5366 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5367 * vCC (r1). Useful for integer division and modulus. 5368 * 5369 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5370 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5371 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5372 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5373 */ 5374 /* binop/2addr vA, vB */ 5375 mov r9, rINST, lsr #8 @ r9<- A+ 5376 mov r3, rINST, lsr #12 @ r3<- B 5377 and r9, r9, #15 5378 GET_VREG(r1, r3) @ r1<- vB 5379 GET_VREG(r0, r9) @ r0<- vA 5380 .if 0 5381 cmp r1, #0 @ is second operand zero? 5382 beq common_errDivideByZero 5383 .endif 5384 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5385 5386 @ optional op; may set condition codes 5387 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5388 GET_INST_OPCODE(ip) @ extract opcode from rINST 5389 SET_VREG(r0, r9) @ vAA<- r0 5390 GOTO_OPCODE(ip) @ jump to next instruction 5391 /* 10-13 instructions */ 5392 5393 5394 5395/* ------------------------------ */ 5396 .balign 64 5397.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5398/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5399/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5400/* File: armv5te/binop2addr.S */ 5401 /* 5402 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5403 * that specifies an instruction that performs "result = r0 op r1". 5404 * This could be an ARM instruction or a function call. (If the result 5405 * comes back in a register other than r0, you can override "result".) 5406 * 5407 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5408 * vCC (r1). Useful for integer division and modulus. 5409 * 5410 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5411 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5412 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5413 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5414 */ 5415 /* binop/2addr vA, vB */ 5416 mov r9, rINST, lsr #8 @ r9<- A+ 5417 mov r3, rINST, lsr #12 @ r3<- B 5418 and r9, r9, #15 5419 GET_VREG(r1, r3) @ r1<- vB 5420 GET_VREG(r0, r9) @ r0<- vA 5421 .if 0 5422 cmp r1, #0 @ is second operand zero? 5423 beq common_errDivideByZero 5424 .endif 5425 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5426 5427 @ optional op; may set condition codes 5428 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5429 GET_INST_OPCODE(ip) @ extract opcode from rINST 5430 SET_VREG(r0, r9) @ vAA<- r0 5431 GOTO_OPCODE(ip) @ jump to next instruction 5432 /* 10-13 instructions */ 5433 5434 5435 5436/* ------------------------------ */ 5437 .balign 64 5438.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5439/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5440/* File: armv5te/binop2addr.S */ 5441 /* 5442 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5443 * that specifies an instruction that performs "result = r0 op r1". 5444 * This could be an ARM instruction or a function call. (If the result 5445 * comes back in a register other than r0, you can override "result".) 5446 * 5447 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5448 * vCC (r1). Useful for integer division and modulus. 5449 * 5450 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5451 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5452 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5453 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5454 */ 5455 /* binop/2addr vA, vB */ 5456 mov r9, rINST, lsr #8 @ r9<- A+ 5457 mov r3, rINST, lsr #12 @ r3<- B 5458 and r9, r9, #15 5459 GET_VREG(r1, r3) @ r1<- vB 5460 GET_VREG(r0, r9) @ r0<- vA 5461 .if 1 5462 cmp r1, #0 @ is second operand zero? 5463 beq common_errDivideByZero 5464 .endif 5465 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5466 5467 @ optional op; may set condition codes 5468 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5469 GET_INST_OPCODE(ip) @ extract opcode from rINST 5470 SET_VREG(r0, r9) @ vAA<- r0 5471 GOTO_OPCODE(ip) @ jump to next instruction 5472 /* 10-13 instructions */ 5473 5474 5475 5476/* ------------------------------ */ 5477 .balign 64 5478.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5479/* File: armv5te/OP_REM_INT_2ADDR.S */ 5480/* idivmod returns quotient in r0 and remainder in r1 */ 5481/* File: armv5te/binop2addr.S */ 5482 /* 5483 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5484 * that specifies an instruction that performs "result = r0 op r1". 5485 * This could be an ARM instruction or a function call. (If the result 5486 * comes back in a register other than r0, you can override "result".) 5487 * 5488 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5489 * vCC (r1). Useful for integer division and modulus. 5490 * 5491 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5492 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5493 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5494 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5495 */ 5496 /* binop/2addr vA, vB */ 5497 mov r9, rINST, lsr #8 @ r9<- A+ 5498 mov r3, rINST, lsr #12 @ r3<- B 5499 and r9, r9, #15 5500 GET_VREG(r1, r3) @ r1<- vB 5501 GET_VREG(r0, r9) @ r0<- vA 5502 .if 1 5503 cmp r1, #0 @ is second operand zero? 5504 beq common_errDivideByZero 5505 .endif 5506 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5507 5508 @ optional op; may set condition codes 5509 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5510 GET_INST_OPCODE(ip) @ extract opcode from rINST 5511 SET_VREG(r1, r9) @ vAA<- r1 5512 GOTO_OPCODE(ip) @ jump to next instruction 5513 /* 10-13 instructions */ 5514 5515 5516 5517/* ------------------------------ */ 5518 .balign 64 5519.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5520/* File: armv5te/OP_AND_INT_2ADDR.S */ 5521/* File: armv5te/binop2addr.S */ 5522 /* 5523 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5524 * that specifies an instruction that performs "result = r0 op r1". 5525 * This could be an ARM instruction or a function call. (If the result 5526 * comes back in a register other than r0, you can override "result".) 5527 * 5528 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5529 * vCC (r1). Useful for integer division and modulus. 5530 * 5531 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5532 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5533 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5534 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5535 */ 5536 /* binop/2addr vA, vB */ 5537 mov r9, rINST, lsr #8 @ r9<- A+ 5538 mov r3, rINST, lsr #12 @ r3<- B 5539 and r9, r9, #15 5540 GET_VREG(r1, r3) @ r1<- vB 5541 GET_VREG(r0, r9) @ r0<- vA 5542 .if 0 5543 cmp r1, #0 @ is second operand zero? 5544 beq common_errDivideByZero 5545 .endif 5546 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5547 5548 @ optional op; may set condition codes 5549 and r0, r0, r1 @ r0<- op, r0-r3 changed 5550 GET_INST_OPCODE(ip) @ extract opcode from rINST 5551 SET_VREG(r0, r9) @ vAA<- r0 5552 GOTO_OPCODE(ip) @ jump to next instruction 5553 /* 10-13 instructions */ 5554 5555 5556 5557/* ------------------------------ */ 5558 .balign 64 5559.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5560/* File: armv5te/OP_OR_INT_2ADDR.S */ 5561/* File: armv5te/binop2addr.S */ 5562 /* 5563 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5564 * that specifies an instruction that performs "result = r0 op r1". 5565 * This could be an ARM instruction or a function call. (If the result 5566 * comes back in a register other than r0, you can override "result".) 5567 * 5568 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5569 * vCC (r1). Useful for integer division and modulus. 5570 * 5571 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5572 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5573 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5574 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5575 */ 5576 /* binop/2addr vA, vB */ 5577 mov r9, rINST, lsr #8 @ r9<- A+ 5578 mov r3, rINST, lsr #12 @ r3<- B 5579 and r9, r9, #15 5580 GET_VREG(r1, r3) @ r1<- vB 5581 GET_VREG(r0, r9) @ r0<- vA 5582 .if 0 5583 cmp r1, #0 @ is second operand zero? 5584 beq common_errDivideByZero 5585 .endif 5586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5587 5588 @ optional op; may set condition codes 5589 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5590 GET_INST_OPCODE(ip) @ extract opcode from rINST 5591 SET_VREG(r0, r9) @ vAA<- r0 5592 GOTO_OPCODE(ip) @ jump to next instruction 5593 /* 10-13 instructions */ 5594 5595 5596 5597/* ------------------------------ */ 5598 .balign 64 5599.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5600/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5601/* File: armv5te/binop2addr.S */ 5602 /* 5603 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5604 * that specifies an instruction that performs "result = r0 op r1". 5605 * This could be an ARM instruction or a function call. (If the result 5606 * comes back in a register other than r0, you can override "result".) 5607 * 5608 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5609 * vCC (r1). Useful for integer division and modulus. 5610 * 5611 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5612 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5613 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5614 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5615 */ 5616 /* binop/2addr vA, vB */ 5617 mov r9, rINST, lsr #8 @ r9<- A+ 5618 mov r3, rINST, lsr #12 @ r3<- B 5619 and r9, r9, #15 5620 GET_VREG(r1, r3) @ r1<- vB 5621 GET_VREG(r0, r9) @ r0<- vA 5622 .if 0 5623 cmp r1, #0 @ is second operand zero? 5624 beq common_errDivideByZero 5625 .endif 5626 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5627 5628 @ optional op; may set condition codes 5629 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5630 GET_INST_OPCODE(ip) @ extract opcode from rINST 5631 SET_VREG(r0, r9) @ vAA<- r0 5632 GOTO_OPCODE(ip) @ jump to next instruction 5633 /* 10-13 instructions */ 5634 5635 5636 5637/* ------------------------------ */ 5638 .balign 64 5639.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5640/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5641/* File: armv5te/binop2addr.S */ 5642 /* 5643 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5644 * that specifies an instruction that performs "result = r0 op r1". 5645 * This could be an ARM instruction or a function call. (If the result 5646 * comes back in a register other than r0, you can override "result".) 5647 * 5648 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5649 * vCC (r1). Useful for integer division and modulus. 5650 * 5651 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5652 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5653 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5654 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5655 */ 5656 /* binop/2addr vA, vB */ 5657 mov r9, rINST, lsr #8 @ r9<- A+ 5658 mov r3, rINST, lsr #12 @ r3<- B 5659 and r9, r9, #15 5660 GET_VREG(r1, r3) @ r1<- vB 5661 GET_VREG(r0, r9) @ r0<- vA 5662 .if 0 5663 cmp r1, #0 @ is second operand zero? 5664 beq common_errDivideByZero 5665 .endif 5666 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5667 5668 and r1, r1, #31 @ optional op; may set condition codes 5669 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5670 GET_INST_OPCODE(ip) @ extract opcode from rINST 5671 SET_VREG(r0, r9) @ vAA<- r0 5672 GOTO_OPCODE(ip) @ jump to next instruction 5673 /* 10-13 instructions */ 5674 5675 5676 5677/* ------------------------------ */ 5678 .balign 64 5679.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5680/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5681/* File: armv5te/binop2addr.S */ 5682 /* 5683 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5684 * that specifies an instruction that performs "result = r0 op r1". 5685 * This could be an ARM instruction or a function call. (If the result 5686 * comes back in a register other than r0, you can override "result".) 5687 * 5688 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5689 * vCC (r1). Useful for integer division and modulus. 5690 * 5691 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5692 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5693 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5694 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5695 */ 5696 /* binop/2addr vA, vB */ 5697 mov r9, rINST, lsr #8 @ r9<- A+ 5698 mov r3, rINST, lsr #12 @ r3<- B 5699 and r9, r9, #15 5700 GET_VREG(r1, r3) @ r1<- vB 5701 GET_VREG(r0, r9) @ r0<- vA 5702 .if 0 5703 cmp r1, #0 @ is second operand zero? 5704 beq common_errDivideByZero 5705 .endif 5706 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5707 5708 and r1, r1, #31 @ optional op; may set condition codes 5709 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5710 GET_INST_OPCODE(ip) @ extract opcode from rINST 5711 SET_VREG(r0, r9) @ vAA<- r0 5712 GOTO_OPCODE(ip) @ jump to next instruction 5713 /* 10-13 instructions */ 5714 5715 5716 5717/* ------------------------------ */ 5718 .balign 64 5719.L_OP_USHR_INT_2ADDR: /* 0xba */ 5720/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5721/* File: armv5te/binop2addr.S */ 5722 /* 5723 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5724 * that specifies an instruction that performs "result = r0 op r1". 5725 * This could be an ARM instruction or a function call. (If the result 5726 * comes back in a register other than r0, you can override "result".) 5727 * 5728 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5729 * vCC (r1). Useful for integer division and modulus. 5730 * 5731 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5732 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5733 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5734 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5735 */ 5736 /* binop/2addr vA, vB */ 5737 mov r9, rINST, lsr #8 @ r9<- A+ 5738 mov r3, rINST, lsr #12 @ r3<- B 5739 and r9, r9, #15 5740 GET_VREG(r1, r3) @ r1<- vB 5741 GET_VREG(r0, r9) @ r0<- vA 5742 .if 0 5743 cmp r1, #0 @ is second operand zero? 5744 beq common_errDivideByZero 5745 .endif 5746 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5747 5748 and r1, r1, #31 @ optional op; may set condition codes 5749 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5750 GET_INST_OPCODE(ip) @ extract opcode from rINST 5751 SET_VREG(r0, r9) @ vAA<- r0 5752 GOTO_OPCODE(ip) @ jump to next instruction 5753 /* 10-13 instructions */ 5754 5755 5756 5757/* ------------------------------ */ 5758 .balign 64 5759.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5760/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5761/* File: armv5te/binopWide2addr.S */ 5762 /* 5763 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5764 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5765 * This could be an ARM instruction or a function call. (If the result 5766 * comes back in a register other than r0, you can override "result".) 5767 * 5768 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5769 * vCC (r1). Useful for integer division and modulus. 5770 * 5771 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5772 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5773 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5774 * rem-double/2addr 5775 */ 5776 /* binop/2addr vA, vB */ 5777 mov r9, rINST, lsr #8 @ r9<- A+ 5778 mov r1, rINST, lsr #12 @ r1<- B 5779 and r9, r9, #15 5780 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5781 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5782 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5783 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5784 .if 0 5785 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5786 beq common_errDivideByZero 5787 .endif 5788 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5789 5790 adds r0, r0, r2 @ optional op; may set condition codes 5791 adc r1, r1, r3 @ result<- op, r0-r3 changed 5792 GET_INST_OPCODE(ip) @ extract opcode from rINST 5793 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5794 GOTO_OPCODE(ip) @ jump to next instruction 5795 /* 12-15 instructions */ 5796 5797 5798 5799/* ------------------------------ */ 5800 .balign 64 5801.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5802/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5803/* File: armv5te/binopWide2addr.S */ 5804 /* 5805 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5806 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5807 * This could be an ARM instruction or a function call. (If the result 5808 * comes back in a register other than r0, you can override "result".) 5809 * 5810 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5811 * vCC (r1). Useful for integer division and modulus. 5812 * 5813 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5814 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5815 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5816 * rem-double/2addr 5817 */ 5818 /* binop/2addr vA, vB */ 5819 mov r9, rINST, lsr #8 @ r9<- A+ 5820 mov r1, rINST, lsr #12 @ r1<- B 5821 and r9, r9, #15 5822 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5823 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5824 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5825 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5826 .if 0 5827 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5828 beq common_errDivideByZero 5829 .endif 5830 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5831 5832 subs r0, r0, r2 @ optional op; may set condition codes 5833 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5834 GET_INST_OPCODE(ip) @ extract opcode from rINST 5835 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5836 GOTO_OPCODE(ip) @ jump to next instruction 5837 /* 12-15 instructions */ 5838 5839 5840 5841/* ------------------------------ */ 5842 .balign 64 5843.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5844/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5845 /* 5846 * Signed 64-bit integer multiply, "/2addr" version. 5847 * 5848 * See OP_MUL_LONG for an explanation. 5849 * 5850 * We get a little tight on registers, so to avoid looking up &fp[A] 5851 * again we stuff it into rINST. 5852 */ 5853 /* mul-long/2addr vA, vB */ 5854 mov r9, rINST, lsr #8 @ r9<- A+ 5855 mov r1, rINST, lsr #12 @ r1<- B 5856 and r9, r9, #15 5857 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5858 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5859 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5860 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5861 mul ip, r2, r1 @ ip<- ZxW 5862 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5863 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5864 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5865 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5866 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5867 GET_INST_OPCODE(ip) @ extract opcode from rINST 5868 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5869 GOTO_OPCODE(ip) @ jump to next instruction 5870 5871 5872/* ------------------------------ */ 5873 .balign 64 5874.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5875/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5876/* File: armv5te/binopWide2addr.S */ 5877 /* 5878 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5879 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5880 * This could be an ARM instruction or a function call. (If the result 5881 * comes back in a register other than r0, you can override "result".) 5882 * 5883 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5884 * vCC (r1). Useful for integer division and modulus. 5885 * 5886 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5887 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5888 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5889 * rem-double/2addr 5890 */ 5891 /* binop/2addr vA, vB */ 5892 mov r9, rINST, lsr #8 @ r9<- A+ 5893 mov r1, rINST, lsr #12 @ r1<- B 5894 and r9, r9, #15 5895 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5896 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5897 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5898 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5899 .if 1 5900 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5901 beq common_errDivideByZero 5902 .endif 5903 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5904 5905 @ optional op; may set condition codes 5906 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5907 GET_INST_OPCODE(ip) @ extract opcode from rINST 5908 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5909 GOTO_OPCODE(ip) @ jump to next instruction 5910 /* 12-15 instructions */ 5911 5912 5913 5914/* ------------------------------ */ 5915 .balign 64 5916.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5917/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5918/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5919/* File: armv5te/binopWide2addr.S */ 5920 /* 5921 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5922 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5923 * This could be an ARM instruction or a function call. (If the result 5924 * comes back in a register other than r0, you can override "result".) 5925 * 5926 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5927 * vCC (r1). Useful for integer division and modulus. 5928 * 5929 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5930 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5931 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5932 * rem-double/2addr 5933 */ 5934 /* binop/2addr vA, vB */ 5935 mov r9, rINST, lsr #8 @ r9<- A+ 5936 mov r1, rINST, lsr #12 @ r1<- B 5937 and r9, r9, #15 5938 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5939 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5940 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5941 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5942 .if 1 5943 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5944 beq common_errDivideByZero 5945 .endif 5946 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5947 5948 @ optional op; may set condition codes 5949 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5950 GET_INST_OPCODE(ip) @ extract opcode from rINST 5951 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5952 GOTO_OPCODE(ip) @ jump to next instruction 5953 /* 12-15 instructions */ 5954 5955 5956 5957/* ------------------------------ */ 5958 .balign 64 5959.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5960/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5961/* File: armv5te/binopWide2addr.S */ 5962 /* 5963 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5964 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5965 * This could be an ARM instruction or a function call. (If the result 5966 * comes back in a register other than r0, you can override "result".) 5967 * 5968 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5969 * vCC (r1). Useful for integer division and modulus. 5970 * 5971 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5972 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5973 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5974 * rem-double/2addr 5975 */ 5976 /* binop/2addr vA, vB */ 5977 mov r9, rINST, lsr #8 @ r9<- A+ 5978 mov r1, rINST, lsr #12 @ r1<- B 5979 and r9, r9, #15 5980 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5981 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5982 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5983 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5984 .if 0 5985 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5986 beq common_errDivideByZero 5987 .endif 5988 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5989 5990 and r0, r0, r2 @ optional op; may set condition codes 5991 and r1, r1, r3 @ result<- op, r0-r3 changed 5992 GET_INST_OPCODE(ip) @ extract opcode from rINST 5993 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5994 GOTO_OPCODE(ip) @ jump to next instruction 5995 /* 12-15 instructions */ 5996 5997 5998 5999/* ------------------------------ */ 6000 .balign 64 6001.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6002/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6003/* File: armv5te/binopWide2addr.S */ 6004 /* 6005 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6006 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6007 * This could be an ARM instruction or a function call. (If the result 6008 * comes back in a register other than r0, you can override "result".) 6009 * 6010 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6011 * vCC (r1). Useful for integer division and modulus. 6012 * 6013 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6014 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6015 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6016 * rem-double/2addr 6017 */ 6018 /* binop/2addr vA, vB */ 6019 mov r9, rINST, lsr #8 @ r9<- A+ 6020 mov r1, rINST, lsr #12 @ r1<- B 6021 and r9, r9, #15 6022 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6023 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6024 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6025 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6026 .if 0 6027 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6028 beq common_errDivideByZero 6029 .endif 6030 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6031 6032 orr r0, r0, r2 @ optional op; may set condition codes 6033 orr r1, r1, r3 @ result<- op, r0-r3 changed 6034 GET_INST_OPCODE(ip) @ extract opcode from rINST 6035 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6036 GOTO_OPCODE(ip) @ jump to next instruction 6037 /* 12-15 instructions */ 6038 6039 6040 6041/* ------------------------------ */ 6042 .balign 64 6043.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6044/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6045/* File: armv5te/binopWide2addr.S */ 6046 /* 6047 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6048 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6049 * This could be an ARM instruction or a function call. (If the result 6050 * comes back in a register other than r0, you can override "result".) 6051 * 6052 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6053 * vCC (r1). Useful for integer division and modulus. 6054 * 6055 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6056 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6057 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6058 * rem-double/2addr 6059 */ 6060 /* binop/2addr vA, vB */ 6061 mov r9, rINST, lsr #8 @ r9<- A+ 6062 mov r1, rINST, lsr #12 @ r1<- B 6063 and r9, r9, #15 6064 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6065 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6066 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6067 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6068 .if 0 6069 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6070 beq common_errDivideByZero 6071 .endif 6072 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6073 6074 eor r0, r0, r2 @ optional op; may set condition codes 6075 eor r1, r1, r3 @ result<- op, r0-r3 changed 6076 GET_INST_OPCODE(ip) @ extract opcode from rINST 6077 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6078 GOTO_OPCODE(ip) @ jump to next instruction 6079 /* 12-15 instructions */ 6080 6081 6082 6083/* ------------------------------ */ 6084 .balign 64 6085.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6086/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6087 /* 6088 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6089 * 32-bit shift distance. 6090 */ 6091 /* shl-long/2addr vA, vB */ 6092 mov r9, rINST, lsr #8 @ r9<- A+ 6093 mov r3, rINST, lsr #12 @ r3<- B 6094 and r9, r9, #15 6095 GET_VREG(r2, r3) @ r2<- vB 6096 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6097 and r2, r2, #63 @ r2<- r2 & 0x3f 6098 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6099 6100 mov r1, r1, asl r2 @ r1<- r1 << r2 6101 rsb r3, r2, #32 @ r3<- 32 - r2 6102 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6103 subs ip, r2, #32 @ ip<- r2 - 32 6104 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6105 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6106 mov r0, r0, asl r2 @ r0<- r0 << r2 6107 b .LOP_SHL_LONG_2ADDR_finish 6108 6109/* ------------------------------ */ 6110 .balign 64 6111.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6112/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6113 /* 6114 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6115 * 32-bit shift distance. 6116 */ 6117 /* shr-long/2addr vA, vB */ 6118 mov r9, rINST, lsr #8 @ r9<- A+ 6119 mov r3, rINST, lsr #12 @ r3<- B 6120 and r9, r9, #15 6121 GET_VREG(r2, r3) @ r2<- vB 6122 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6123 and r2, r2, #63 @ r2<- r2 & 0x3f 6124 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6125 6126 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6127 rsb r3, r2, #32 @ r3<- 32 - r2 6128 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6129 subs ip, r2, #32 @ ip<- r2 - 32 6130 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6131 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6132 mov r1, r1, asr r2 @ r1<- r1 >> r2 6133 b .LOP_SHR_LONG_2ADDR_finish 6134 6135/* ------------------------------ */ 6136 .balign 64 6137.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6138/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6139 /* 6140 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6141 * 32-bit shift distance. 6142 */ 6143 /* ushr-long/2addr vA, vB */ 6144 mov r9, rINST, lsr #8 @ r9<- A+ 6145 mov r3, rINST, lsr #12 @ r3<- B 6146 and r9, r9, #15 6147 GET_VREG(r2, r3) @ r2<- vB 6148 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6149 and r2, r2, #63 @ r2<- r2 & 0x3f 6150 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6151 6152 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6153 rsb r3, r2, #32 @ r3<- 32 - r2 6154 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6155 subs ip, r2, #32 @ ip<- r2 - 32 6156 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6157 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6158 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6159 b .LOP_USHR_LONG_2ADDR_finish 6160 6161/* ------------------------------ */ 6162 .balign 64 6163.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6164/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6165/* File: arm-vfp/fbinop2addr.S */ 6166 /* 6167 * Generic 32-bit floating point "/2addr" binary operation. Provide 6168 * an "instr" line that specifies an instruction that performs 6169 * "s2 = s0 op s1". 6170 * 6171 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6172 */ 6173 /* binop/2addr vA, vB */ 6174 mov r3, rINST, lsr #12 @ r3<- B 6175 mov r9, rINST, lsr #8 @ r9<- A+ 6176 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6177 and r9, r9, #15 @ r9<- A 6178 flds s1, [r3] @ s1<- vB 6179 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6180 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6181 flds s0, [r9] @ s0<- vA 6182 6183 fadds s2, s0, s1 @ s2<- op 6184 GET_INST_OPCODE(ip) @ extract opcode from rINST 6185 fsts s2, [r9] @ vAA<- s2 6186 GOTO_OPCODE(ip) @ jump to next instruction 6187 6188 6189/* ------------------------------ */ 6190 .balign 64 6191.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6192/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6193/* File: arm-vfp/fbinop2addr.S */ 6194 /* 6195 * Generic 32-bit floating point "/2addr" binary operation. Provide 6196 * an "instr" line that specifies an instruction that performs 6197 * "s2 = s0 op s1". 6198 * 6199 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6200 */ 6201 /* binop/2addr vA, vB */ 6202 mov r3, rINST, lsr #12 @ r3<- B 6203 mov r9, rINST, lsr #8 @ r9<- A+ 6204 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6205 and r9, r9, #15 @ r9<- A 6206 flds s1, [r3] @ s1<- vB 6207 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6208 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6209 flds s0, [r9] @ s0<- vA 6210 6211 fsubs s2, s0, s1 @ s2<- op 6212 GET_INST_OPCODE(ip) @ extract opcode from rINST 6213 fsts s2, [r9] @ vAA<- s2 6214 GOTO_OPCODE(ip) @ jump to next instruction 6215 6216 6217/* ------------------------------ */ 6218 .balign 64 6219.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6220/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6221/* File: arm-vfp/fbinop2addr.S */ 6222 /* 6223 * Generic 32-bit floating point "/2addr" binary operation. Provide 6224 * an "instr" line that specifies an instruction that performs 6225 * "s2 = s0 op s1". 6226 * 6227 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6228 */ 6229 /* binop/2addr vA, vB */ 6230 mov r3, rINST, lsr #12 @ r3<- B 6231 mov r9, rINST, lsr #8 @ r9<- A+ 6232 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6233 and r9, r9, #15 @ r9<- A 6234 flds s1, [r3] @ s1<- vB 6235 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6236 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6237 flds s0, [r9] @ s0<- vA 6238 6239 fmuls s2, s0, s1 @ s2<- op 6240 GET_INST_OPCODE(ip) @ extract opcode from rINST 6241 fsts s2, [r9] @ vAA<- s2 6242 GOTO_OPCODE(ip) @ jump to next instruction 6243 6244 6245/* ------------------------------ */ 6246 .balign 64 6247.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6248/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6249/* File: arm-vfp/fbinop2addr.S */ 6250 /* 6251 * Generic 32-bit floating point "/2addr" binary operation. Provide 6252 * an "instr" line that specifies an instruction that performs 6253 * "s2 = s0 op s1". 6254 * 6255 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6256 */ 6257 /* binop/2addr vA, vB */ 6258 mov r3, rINST, lsr #12 @ r3<- B 6259 mov r9, rINST, lsr #8 @ r9<- A+ 6260 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6261 and r9, r9, #15 @ r9<- A 6262 flds s1, [r3] @ s1<- vB 6263 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6264 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6265 flds s0, [r9] @ s0<- vA 6266 6267 fdivs s2, s0, s1 @ s2<- op 6268 GET_INST_OPCODE(ip) @ extract opcode from rINST 6269 fsts s2, [r9] @ vAA<- s2 6270 GOTO_OPCODE(ip) @ jump to next instruction 6271 6272 6273/* ------------------------------ */ 6274 .balign 64 6275.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6276/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6277/* EABI doesn't define a float remainder function, but libm does */ 6278/* File: armv5te/binop2addr.S */ 6279 /* 6280 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6281 * that specifies an instruction that performs "result = r0 op r1". 6282 * This could be an ARM instruction or a function call. (If the result 6283 * comes back in a register other than r0, you can override "result".) 6284 * 6285 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6286 * vCC (r1). Useful for integer division and modulus. 6287 * 6288 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6289 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6290 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6291 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6292 */ 6293 /* binop/2addr vA, vB */ 6294 mov r9, rINST, lsr #8 @ r9<- A+ 6295 mov r3, rINST, lsr #12 @ r3<- B 6296 and r9, r9, #15 6297 GET_VREG(r1, r3) @ r1<- vB 6298 GET_VREG(r0, r9) @ r0<- vA 6299 .if 0 6300 cmp r1, #0 @ is second operand zero? 6301 beq common_errDivideByZero 6302 .endif 6303 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6304 6305 @ optional op; may set condition codes 6306 bl fmodf @ r0<- op, r0-r3 changed 6307 GET_INST_OPCODE(ip) @ extract opcode from rINST 6308 SET_VREG(r0, r9) @ vAA<- r0 6309 GOTO_OPCODE(ip) @ jump to next instruction 6310 /* 10-13 instructions */ 6311 6312 6313 6314/* ------------------------------ */ 6315 .balign 64 6316.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6317/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6318/* File: arm-vfp/fbinopWide2addr.S */ 6319 /* 6320 * Generic 64-bit floating point "/2addr" binary operation. Provide 6321 * an "instr" line that specifies an instruction that performs 6322 * "d2 = d0 op d1". 6323 * 6324 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6325 * div-double/2addr 6326 */ 6327 /* binop/2addr vA, vB */ 6328 mov r3, rINST, lsr #12 @ r3<- B 6329 mov r9, rINST, lsr #8 @ r9<- A+ 6330 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6331 and r9, r9, #15 @ r9<- A 6332 fldd d1, [r3] @ d1<- vB 6333 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6334 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6335 fldd d0, [r9] @ d0<- vA 6336 6337 faddd d2, d0, d1 @ d2<- op 6338 GET_INST_OPCODE(ip) @ extract opcode from rINST 6339 fstd d2, [r9] @ vAA<- d2 6340 GOTO_OPCODE(ip) @ jump to next instruction 6341 6342 6343/* ------------------------------ */ 6344 .balign 64 6345.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6346/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6347/* File: arm-vfp/fbinopWide2addr.S */ 6348 /* 6349 * Generic 64-bit floating point "/2addr" binary operation. Provide 6350 * an "instr" line that specifies an instruction that performs 6351 * "d2 = d0 op d1". 6352 * 6353 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6354 * div-double/2addr 6355 */ 6356 /* binop/2addr vA, vB */ 6357 mov r3, rINST, lsr #12 @ r3<- B 6358 mov r9, rINST, lsr #8 @ r9<- A+ 6359 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6360 and r9, r9, #15 @ r9<- A 6361 fldd d1, [r3] @ d1<- vB 6362 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6363 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6364 fldd d0, [r9] @ d0<- vA 6365 6366 fsubd d2, d0, d1 @ d2<- op 6367 GET_INST_OPCODE(ip) @ extract opcode from rINST 6368 fstd d2, [r9] @ vAA<- d2 6369 GOTO_OPCODE(ip) @ jump to next instruction 6370 6371 6372/* ------------------------------ */ 6373 .balign 64 6374.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6375/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6376/* File: arm-vfp/fbinopWide2addr.S */ 6377 /* 6378 * Generic 64-bit floating point "/2addr" binary operation. Provide 6379 * an "instr" line that specifies an instruction that performs 6380 * "d2 = d0 op d1". 6381 * 6382 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6383 * div-double/2addr 6384 */ 6385 /* binop/2addr vA, vB */ 6386 mov r3, rINST, lsr #12 @ r3<- B 6387 mov r9, rINST, lsr #8 @ r9<- A+ 6388 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6389 and r9, r9, #15 @ r9<- A 6390 fldd d1, [r3] @ d1<- vB 6391 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6392 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6393 fldd d0, [r9] @ d0<- vA 6394 6395 fmuld d2, d0, d1 @ d2<- op 6396 GET_INST_OPCODE(ip) @ extract opcode from rINST 6397 fstd d2, [r9] @ vAA<- d2 6398 GOTO_OPCODE(ip) @ jump to next instruction 6399 6400 6401/* ------------------------------ */ 6402 .balign 64 6403.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6404/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6405/* File: arm-vfp/fbinopWide2addr.S */ 6406 /* 6407 * Generic 64-bit floating point "/2addr" binary operation. Provide 6408 * an "instr" line that specifies an instruction that performs 6409 * "d2 = d0 op d1". 6410 * 6411 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6412 * div-double/2addr 6413 */ 6414 /* binop/2addr vA, vB */ 6415 mov r3, rINST, lsr #12 @ r3<- B 6416 mov r9, rINST, lsr #8 @ r9<- A+ 6417 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6418 and r9, r9, #15 @ r9<- A 6419 fldd d1, [r3] @ d1<- vB 6420 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6421 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6422 fldd d0, [r9] @ d0<- vA 6423 6424 fdivd d2, d0, d1 @ d2<- op 6425 GET_INST_OPCODE(ip) @ extract opcode from rINST 6426 fstd d2, [r9] @ vAA<- d2 6427 GOTO_OPCODE(ip) @ jump to next instruction 6428 6429 6430/* ------------------------------ */ 6431 .balign 64 6432.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6433/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6434/* EABI doesn't define a double remainder function, but libm does */ 6435/* File: armv5te/binopWide2addr.S */ 6436 /* 6437 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6438 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6439 * This could be an ARM instruction or a function call. (If the result 6440 * comes back in a register other than r0, you can override "result".) 6441 * 6442 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6443 * vCC (r1). Useful for integer division and modulus. 6444 * 6445 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6446 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6447 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6448 * rem-double/2addr 6449 */ 6450 /* binop/2addr vA, vB */ 6451 mov r9, rINST, lsr #8 @ r9<- A+ 6452 mov r1, rINST, lsr #12 @ r1<- B 6453 and r9, r9, #15 6454 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6455 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6456 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6457 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6458 .if 0 6459 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6460 beq common_errDivideByZero 6461 .endif 6462 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6463 6464 @ optional op; may set condition codes 6465 bl fmod @ result<- op, r0-r3 changed 6466 GET_INST_OPCODE(ip) @ extract opcode from rINST 6467 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6468 GOTO_OPCODE(ip) @ jump to next instruction 6469 /* 12-15 instructions */ 6470 6471 6472 6473/* ------------------------------ */ 6474 .balign 64 6475.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6476/* File: armv5te/OP_ADD_INT_LIT16.S */ 6477/* File: armv5te/binopLit16.S */ 6478 /* 6479 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6480 * that specifies an instruction that performs "result = r0 op r1". 6481 * This could be an ARM instruction or a function call. (If the result 6482 * comes back in a register other than r0, you can override "result".) 6483 * 6484 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6485 * vCC (r1). Useful for integer division and modulus. 6486 * 6487 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6488 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6489 */ 6490 /* binop/lit16 vA, vB, #+CCCC */ 6491 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6492 mov r2, rINST, lsr #12 @ r2<- B 6493 mov r9, rINST, lsr #8 @ r9<- A+ 6494 GET_VREG(r0, r2) @ r0<- vB 6495 and r9, r9, #15 6496 .if 0 6497 cmp r1, #0 @ is second operand zero? 6498 beq common_errDivideByZero 6499 .endif 6500 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6501 6502 add r0, r0, r1 @ r0<- op, r0-r3 changed 6503 GET_INST_OPCODE(ip) @ extract opcode from rINST 6504 SET_VREG(r0, r9) @ vAA<- r0 6505 GOTO_OPCODE(ip) @ jump to next instruction 6506 /* 10-13 instructions */ 6507 6508 6509 6510/* ------------------------------ */ 6511 .balign 64 6512.L_OP_RSUB_INT: /* 0xd1 */ 6513/* File: armv5te/OP_RSUB_INT.S */ 6514/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6515/* File: armv5te/binopLit16.S */ 6516 /* 6517 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6518 * that specifies an instruction that performs "result = r0 op r1". 6519 * This could be an ARM instruction or a function call. (If the result 6520 * comes back in a register other than r0, you can override "result".) 6521 * 6522 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6523 * vCC (r1). Useful for integer division and modulus. 6524 * 6525 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6526 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6527 */ 6528 /* binop/lit16 vA, vB, #+CCCC */ 6529 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6530 mov r2, rINST, lsr #12 @ r2<- B 6531 mov r9, rINST, lsr #8 @ r9<- A+ 6532 GET_VREG(r0, r2) @ r0<- vB 6533 and r9, r9, #15 6534 .if 0 6535 cmp r1, #0 @ is second operand zero? 6536 beq common_errDivideByZero 6537 .endif 6538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6539 6540 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6541 GET_INST_OPCODE(ip) @ extract opcode from rINST 6542 SET_VREG(r0, r9) @ vAA<- r0 6543 GOTO_OPCODE(ip) @ jump to next instruction 6544 /* 10-13 instructions */ 6545 6546 6547 6548/* ------------------------------ */ 6549 .balign 64 6550.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6551/* File: armv5te/OP_MUL_INT_LIT16.S */ 6552/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6553/* File: armv5te/binopLit16.S */ 6554 /* 6555 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6556 * that specifies an instruction that performs "result = r0 op r1". 6557 * This could be an ARM instruction or a function call. (If the result 6558 * comes back in a register other than r0, you can override "result".) 6559 * 6560 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6561 * vCC (r1). Useful for integer division and modulus. 6562 * 6563 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6564 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6565 */ 6566 /* binop/lit16 vA, vB, #+CCCC */ 6567 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6568 mov r2, rINST, lsr #12 @ r2<- B 6569 mov r9, rINST, lsr #8 @ r9<- A+ 6570 GET_VREG(r0, r2) @ r0<- vB 6571 and r9, r9, #15 6572 .if 0 6573 cmp r1, #0 @ is second operand zero? 6574 beq common_errDivideByZero 6575 .endif 6576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6577 6578 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6579 GET_INST_OPCODE(ip) @ extract opcode from rINST 6580 SET_VREG(r0, r9) @ vAA<- r0 6581 GOTO_OPCODE(ip) @ jump to next instruction 6582 /* 10-13 instructions */ 6583 6584 6585 6586/* ------------------------------ */ 6587 .balign 64 6588.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6589/* File: armv5te/OP_DIV_INT_LIT16.S */ 6590/* File: armv5te/binopLit16.S */ 6591 /* 6592 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6593 * that specifies an instruction that performs "result = r0 op r1". 6594 * This could be an ARM instruction or a function call. (If the result 6595 * comes back in a register other than r0, you can override "result".) 6596 * 6597 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6598 * vCC (r1). Useful for integer division and modulus. 6599 * 6600 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6601 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6602 */ 6603 /* binop/lit16 vA, vB, #+CCCC */ 6604 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6605 mov r2, rINST, lsr #12 @ r2<- B 6606 mov r9, rINST, lsr #8 @ r9<- A+ 6607 GET_VREG(r0, r2) @ r0<- vB 6608 and r9, r9, #15 6609 .if 1 6610 cmp r1, #0 @ is second operand zero? 6611 beq common_errDivideByZero 6612 .endif 6613 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6614 6615 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6616 GET_INST_OPCODE(ip) @ extract opcode from rINST 6617 SET_VREG(r0, r9) @ vAA<- r0 6618 GOTO_OPCODE(ip) @ jump to next instruction 6619 /* 10-13 instructions */ 6620 6621 6622 6623/* ------------------------------ */ 6624 .balign 64 6625.L_OP_REM_INT_LIT16: /* 0xd4 */ 6626/* File: armv5te/OP_REM_INT_LIT16.S */ 6627/* idivmod returns quotient in r0 and remainder in r1 */ 6628/* File: armv5te/binopLit16.S */ 6629 /* 6630 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6631 * that specifies an instruction that performs "result = r0 op r1". 6632 * This could be an ARM instruction or a function call. (If the result 6633 * comes back in a register other than r0, you can override "result".) 6634 * 6635 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6636 * vCC (r1). Useful for integer division and modulus. 6637 * 6638 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6639 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6640 */ 6641 /* binop/lit16 vA, vB, #+CCCC */ 6642 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6643 mov r2, rINST, lsr #12 @ r2<- B 6644 mov r9, rINST, lsr #8 @ r9<- A+ 6645 GET_VREG(r0, r2) @ r0<- vB 6646 and r9, r9, #15 6647 .if 1 6648 cmp r1, #0 @ is second operand zero? 6649 beq common_errDivideByZero 6650 .endif 6651 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6652 6653 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6654 GET_INST_OPCODE(ip) @ extract opcode from rINST 6655 SET_VREG(r1, r9) @ vAA<- r1 6656 GOTO_OPCODE(ip) @ jump to next instruction 6657 /* 10-13 instructions */ 6658 6659 6660 6661/* ------------------------------ */ 6662 .balign 64 6663.L_OP_AND_INT_LIT16: /* 0xd5 */ 6664/* File: armv5te/OP_AND_INT_LIT16.S */ 6665/* File: armv5te/binopLit16.S */ 6666 /* 6667 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6668 * that specifies an instruction that performs "result = r0 op r1". 6669 * This could be an ARM instruction or a function call. (If the result 6670 * comes back in a register other than r0, you can override "result".) 6671 * 6672 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6673 * vCC (r1). Useful for integer division and modulus. 6674 * 6675 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6676 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6677 */ 6678 /* binop/lit16 vA, vB, #+CCCC */ 6679 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6680 mov r2, rINST, lsr #12 @ r2<- B 6681 mov r9, rINST, lsr #8 @ r9<- A+ 6682 GET_VREG(r0, r2) @ r0<- vB 6683 and r9, r9, #15 6684 .if 0 6685 cmp r1, #0 @ is second operand zero? 6686 beq common_errDivideByZero 6687 .endif 6688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6689 6690 and r0, r0, r1 @ r0<- op, r0-r3 changed 6691 GET_INST_OPCODE(ip) @ extract opcode from rINST 6692 SET_VREG(r0, r9) @ vAA<- r0 6693 GOTO_OPCODE(ip) @ jump to next instruction 6694 /* 10-13 instructions */ 6695 6696 6697 6698/* ------------------------------ */ 6699 .balign 64 6700.L_OP_OR_INT_LIT16: /* 0xd6 */ 6701/* File: armv5te/OP_OR_INT_LIT16.S */ 6702/* File: armv5te/binopLit16.S */ 6703 /* 6704 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6705 * that specifies an instruction that performs "result = r0 op r1". 6706 * This could be an ARM instruction or a function call. (If the result 6707 * comes back in a register other than r0, you can override "result".) 6708 * 6709 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6710 * vCC (r1). Useful for integer division and modulus. 6711 * 6712 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6713 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6714 */ 6715 /* binop/lit16 vA, vB, #+CCCC */ 6716 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6717 mov r2, rINST, lsr #12 @ r2<- B 6718 mov r9, rINST, lsr #8 @ r9<- A+ 6719 GET_VREG(r0, r2) @ r0<- vB 6720 and r9, r9, #15 6721 .if 0 6722 cmp r1, #0 @ is second operand zero? 6723 beq common_errDivideByZero 6724 .endif 6725 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6726 6727 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6728 GET_INST_OPCODE(ip) @ extract opcode from rINST 6729 SET_VREG(r0, r9) @ vAA<- r0 6730 GOTO_OPCODE(ip) @ jump to next instruction 6731 /* 10-13 instructions */ 6732 6733 6734 6735/* ------------------------------ */ 6736 .balign 64 6737.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6738/* File: armv5te/OP_XOR_INT_LIT16.S */ 6739/* File: armv5te/binopLit16.S */ 6740 /* 6741 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6742 * that specifies an instruction that performs "result = r0 op r1". 6743 * This could be an ARM instruction or a function call. (If the result 6744 * comes back in a register other than r0, you can override "result".) 6745 * 6746 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6747 * vCC (r1). Useful for integer division and modulus. 6748 * 6749 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6750 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6751 */ 6752 /* binop/lit16 vA, vB, #+CCCC */ 6753 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6754 mov r2, rINST, lsr #12 @ r2<- B 6755 mov r9, rINST, lsr #8 @ r9<- A+ 6756 GET_VREG(r0, r2) @ r0<- vB 6757 and r9, r9, #15 6758 .if 0 6759 cmp r1, #0 @ is second operand zero? 6760 beq common_errDivideByZero 6761 .endif 6762 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6763 6764 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6765 GET_INST_OPCODE(ip) @ extract opcode from rINST 6766 SET_VREG(r0, r9) @ vAA<- r0 6767 GOTO_OPCODE(ip) @ jump to next instruction 6768 /* 10-13 instructions */ 6769 6770 6771 6772/* ------------------------------ */ 6773 .balign 64 6774.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6775/* File: armv5te/OP_ADD_INT_LIT8.S */ 6776/* File: armv5te/binopLit8.S */ 6777 /* 6778 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6779 * that specifies an instruction that performs "result = r0 op r1". 6780 * This could be an ARM instruction or a function call. (If the result 6781 * comes back in a register other than r0, you can override "result".) 6782 * 6783 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6784 * vCC (r1). Useful for integer division and modulus. 6785 * 6786 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6787 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6788 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6789 */ 6790 /* binop/lit8 vAA, vBB, #+CC */ 6791 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6792 mov r9, rINST, lsr #8 @ r9<- AA 6793 and r2, r3, #255 @ r2<- BB 6794 GET_VREG(r0, r2) @ r0<- vBB 6795 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6796 .if 0 6797 @cmp r1, #0 @ is second operand zero? 6798 beq common_errDivideByZero 6799 .endif 6800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6801 6802 @ optional op; may set condition codes 6803 add r0, r0, r1 @ r0<- op, r0-r3 changed 6804 GET_INST_OPCODE(ip) @ extract opcode from rINST 6805 SET_VREG(r0, r9) @ vAA<- r0 6806 GOTO_OPCODE(ip) @ jump to next instruction 6807 /* 10-12 instructions */ 6808 6809 6810 6811/* ------------------------------ */ 6812 .balign 64 6813.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6814/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6815/* File: armv5te/binopLit8.S */ 6816 /* 6817 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6818 * that specifies an instruction that performs "result = r0 op r1". 6819 * This could be an ARM instruction or a function call. (If the result 6820 * comes back in a register other than r0, you can override "result".) 6821 * 6822 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6823 * vCC (r1). Useful for integer division and modulus. 6824 * 6825 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6826 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6827 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6828 */ 6829 /* binop/lit8 vAA, vBB, #+CC */ 6830 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6831 mov r9, rINST, lsr #8 @ r9<- AA 6832 and r2, r3, #255 @ r2<- BB 6833 GET_VREG(r0, r2) @ r0<- vBB 6834 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6835 .if 0 6836 @cmp r1, #0 @ is second operand zero? 6837 beq common_errDivideByZero 6838 .endif 6839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6840 6841 @ optional op; may set condition codes 6842 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6843 GET_INST_OPCODE(ip) @ extract opcode from rINST 6844 SET_VREG(r0, r9) @ vAA<- r0 6845 GOTO_OPCODE(ip) @ jump to next instruction 6846 /* 10-12 instructions */ 6847 6848 6849 6850/* ------------------------------ */ 6851 .balign 64 6852.L_OP_MUL_INT_LIT8: /* 0xda */ 6853/* File: armv5te/OP_MUL_INT_LIT8.S */ 6854/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6855/* File: armv5te/binopLit8.S */ 6856 /* 6857 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6858 * that specifies an instruction that performs "result = r0 op r1". 6859 * This could be an ARM instruction or a function call. (If the result 6860 * comes back in a register other than r0, you can override "result".) 6861 * 6862 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6863 * vCC (r1). Useful for integer division and modulus. 6864 * 6865 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6866 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6867 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6868 */ 6869 /* binop/lit8 vAA, vBB, #+CC */ 6870 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6871 mov r9, rINST, lsr #8 @ r9<- AA 6872 and r2, r3, #255 @ r2<- BB 6873 GET_VREG(r0, r2) @ r0<- vBB 6874 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6875 .if 0 6876 @cmp r1, #0 @ is second operand zero? 6877 beq common_errDivideByZero 6878 .endif 6879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6880 6881 @ optional op; may set condition codes 6882 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6883 GET_INST_OPCODE(ip) @ extract opcode from rINST 6884 SET_VREG(r0, r9) @ vAA<- r0 6885 GOTO_OPCODE(ip) @ jump to next instruction 6886 /* 10-12 instructions */ 6887 6888 6889 6890/* ------------------------------ */ 6891 .balign 64 6892.L_OP_DIV_INT_LIT8: /* 0xdb */ 6893/* File: armv5te/OP_DIV_INT_LIT8.S */ 6894/* File: armv5te/binopLit8.S */ 6895 /* 6896 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6897 * that specifies an instruction that performs "result = r0 op r1". 6898 * This could be an ARM instruction or a function call. (If the result 6899 * comes back in a register other than r0, you can override "result".) 6900 * 6901 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6902 * vCC (r1). Useful for integer division and modulus. 6903 * 6904 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6905 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6906 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6907 */ 6908 /* binop/lit8 vAA, vBB, #+CC */ 6909 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6910 mov r9, rINST, lsr #8 @ r9<- AA 6911 and r2, r3, #255 @ r2<- BB 6912 GET_VREG(r0, r2) @ r0<- vBB 6913 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6914 .if 1 6915 @cmp r1, #0 @ is second operand zero? 6916 beq common_errDivideByZero 6917 .endif 6918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6919 6920 @ optional op; may set condition codes 6921 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6922 GET_INST_OPCODE(ip) @ extract opcode from rINST 6923 SET_VREG(r0, r9) @ vAA<- r0 6924 GOTO_OPCODE(ip) @ jump to next instruction 6925 /* 10-12 instructions */ 6926 6927 6928 6929/* ------------------------------ */ 6930 .balign 64 6931.L_OP_REM_INT_LIT8: /* 0xdc */ 6932/* File: armv5te/OP_REM_INT_LIT8.S */ 6933/* idivmod returns quotient in r0 and remainder in r1 */ 6934/* File: armv5te/binopLit8.S */ 6935 /* 6936 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6937 * that specifies an instruction that performs "result = r0 op r1". 6938 * This could be an ARM instruction or a function call. (If the result 6939 * comes back in a register other than r0, you can override "result".) 6940 * 6941 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6942 * vCC (r1). Useful for integer division and modulus. 6943 * 6944 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6945 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6946 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6947 */ 6948 /* binop/lit8 vAA, vBB, #+CC */ 6949 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6950 mov r9, rINST, lsr #8 @ r9<- AA 6951 and r2, r3, #255 @ r2<- BB 6952 GET_VREG(r0, r2) @ r0<- vBB 6953 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6954 .if 1 6955 @cmp r1, #0 @ is second operand zero? 6956 beq common_errDivideByZero 6957 .endif 6958 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6959 6960 @ optional op; may set condition codes 6961 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6962 GET_INST_OPCODE(ip) @ extract opcode from rINST 6963 SET_VREG(r1, r9) @ vAA<- r1 6964 GOTO_OPCODE(ip) @ jump to next instruction 6965 /* 10-12 instructions */ 6966 6967 6968 6969/* ------------------------------ */ 6970 .balign 64 6971.L_OP_AND_INT_LIT8: /* 0xdd */ 6972/* File: armv5te/OP_AND_INT_LIT8.S */ 6973/* File: armv5te/binopLit8.S */ 6974 /* 6975 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6976 * that specifies an instruction that performs "result = r0 op r1". 6977 * This could be an ARM instruction or a function call. (If the result 6978 * comes back in a register other than r0, you can override "result".) 6979 * 6980 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6981 * vCC (r1). Useful for integer division and modulus. 6982 * 6983 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6984 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6985 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6986 */ 6987 /* binop/lit8 vAA, vBB, #+CC */ 6988 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6989 mov r9, rINST, lsr #8 @ r9<- AA 6990 and r2, r3, #255 @ r2<- BB 6991 GET_VREG(r0, r2) @ r0<- vBB 6992 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6993 .if 0 6994 @cmp r1, #0 @ is second operand zero? 6995 beq common_errDivideByZero 6996 .endif 6997 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6998 6999 @ optional op; may set condition codes 7000 and r0, r0, r1 @ r0<- op, r0-r3 changed 7001 GET_INST_OPCODE(ip) @ extract opcode from rINST 7002 SET_VREG(r0, r9) @ vAA<- r0 7003 GOTO_OPCODE(ip) @ jump to next instruction 7004 /* 10-12 instructions */ 7005 7006 7007 7008/* ------------------------------ */ 7009 .balign 64 7010.L_OP_OR_INT_LIT8: /* 0xde */ 7011/* File: armv5te/OP_OR_INT_LIT8.S */ 7012/* File: armv5te/binopLit8.S */ 7013 /* 7014 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7015 * that specifies an instruction that performs "result = r0 op r1". 7016 * This could be an ARM instruction or a function call. (If the result 7017 * comes back in a register other than r0, you can override "result".) 7018 * 7019 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7020 * vCC (r1). Useful for integer division and modulus. 7021 * 7022 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7023 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7024 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7025 */ 7026 /* binop/lit8 vAA, vBB, #+CC */ 7027 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7028 mov r9, rINST, lsr #8 @ r9<- AA 7029 and r2, r3, #255 @ r2<- BB 7030 GET_VREG(r0, r2) @ r0<- vBB 7031 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7032 .if 0 7033 @cmp r1, #0 @ is second operand zero? 7034 beq common_errDivideByZero 7035 .endif 7036 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7037 7038 @ optional op; may set condition codes 7039 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7040 GET_INST_OPCODE(ip) @ extract opcode from rINST 7041 SET_VREG(r0, r9) @ vAA<- r0 7042 GOTO_OPCODE(ip) @ jump to next instruction 7043 /* 10-12 instructions */ 7044 7045 7046 7047/* ------------------------------ */ 7048 .balign 64 7049.L_OP_XOR_INT_LIT8: /* 0xdf */ 7050/* File: armv5te/OP_XOR_INT_LIT8.S */ 7051/* File: armv5te/binopLit8.S */ 7052 /* 7053 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7054 * that specifies an instruction that performs "result = r0 op r1". 7055 * This could be an ARM instruction or a function call. (If the result 7056 * comes back in a register other than r0, you can override "result".) 7057 * 7058 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7059 * vCC (r1). Useful for integer division and modulus. 7060 * 7061 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7062 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7063 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7064 */ 7065 /* binop/lit8 vAA, vBB, #+CC */ 7066 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7067 mov r9, rINST, lsr #8 @ r9<- AA 7068 and r2, r3, #255 @ r2<- BB 7069 GET_VREG(r0, r2) @ r0<- vBB 7070 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7071 .if 0 7072 @cmp r1, #0 @ is second operand zero? 7073 beq common_errDivideByZero 7074 .endif 7075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7076 7077 @ optional op; may set condition codes 7078 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7079 GET_INST_OPCODE(ip) @ extract opcode from rINST 7080 SET_VREG(r0, r9) @ vAA<- r0 7081 GOTO_OPCODE(ip) @ jump to next instruction 7082 /* 10-12 instructions */ 7083 7084 7085 7086/* ------------------------------ */ 7087 .balign 64 7088.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7089/* File: armv5te/OP_SHL_INT_LIT8.S */ 7090/* File: armv5te/binopLit8.S */ 7091 /* 7092 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7093 * that specifies an instruction that performs "result = r0 op r1". 7094 * This could be an ARM instruction or a function call. (If the result 7095 * comes back in a register other than r0, you can override "result".) 7096 * 7097 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7098 * vCC (r1). Useful for integer division and modulus. 7099 * 7100 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7101 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7102 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7103 */ 7104 /* binop/lit8 vAA, vBB, #+CC */ 7105 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7106 mov r9, rINST, lsr #8 @ r9<- AA 7107 and r2, r3, #255 @ r2<- BB 7108 GET_VREG(r0, r2) @ r0<- vBB 7109 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7110 .if 0 7111 @cmp r1, #0 @ is second operand zero? 7112 beq common_errDivideByZero 7113 .endif 7114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7115 7116 and r1, r1, #31 @ optional op; may set condition codes 7117 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7118 GET_INST_OPCODE(ip) @ extract opcode from rINST 7119 SET_VREG(r0, r9) @ vAA<- r0 7120 GOTO_OPCODE(ip) @ jump to next instruction 7121 /* 10-12 instructions */ 7122 7123 7124 7125/* ------------------------------ */ 7126 .balign 64 7127.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7128/* File: armv5te/OP_SHR_INT_LIT8.S */ 7129/* File: armv5te/binopLit8.S */ 7130 /* 7131 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7132 * that specifies an instruction that performs "result = r0 op r1". 7133 * This could be an ARM instruction or a function call. (If the result 7134 * comes back in a register other than r0, you can override "result".) 7135 * 7136 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7137 * vCC (r1). Useful for integer division and modulus. 7138 * 7139 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7140 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7141 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7142 */ 7143 /* binop/lit8 vAA, vBB, #+CC */ 7144 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7145 mov r9, rINST, lsr #8 @ r9<- AA 7146 and r2, r3, #255 @ r2<- BB 7147 GET_VREG(r0, r2) @ r0<- vBB 7148 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7149 .if 0 7150 @cmp r1, #0 @ is second operand zero? 7151 beq common_errDivideByZero 7152 .endif 7153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7154 7155 and r1, r1, #31 @ optional op; may set condition codes 7156 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7157 GET_INST_OPCODE(ip) @ extract opcode from rINST 7158 SET_VREG(r0, r9) @ vAA<- r0 7159 GOTO_OPCODE(ip) @ jump to next instruction 7160 /* 10-12 instructions */ 7161 7162 7163 7164/* ------------------------------ */ 7165 .balign 64 7166.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7167/* File: armv5te/OP_USHR_INT_LIT8.S */ 7168/* File: armv5te/binopLit8.S */ 7169 /* 7170 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7171 * that specifies an instruction that performs "result = r0 op r1". 7172 * This could be an ARM instruction or a function call. (If the result 7173 * comes back in a register other than r0, you can override "result".) 7174 * 7175 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7176 * vCC (r1). Useful for integer division and modulus. 7177 * 7178 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7179 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7180 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7181 */ 7182 /* binop/lit8 vAA, vBB, #+CC */ 7183 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7184 mov r9, rINST, lsr #8 @ r9<- AA 7185 and r2, r3, #255 @ r2<- BB 7186 GET_VREG(r0, r2) @ r0<- vBB 7187 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7188 .if 0 7189 @cmp r1, #0 @ is second operand zero? 7190 beq common_errDivideByZero 7191 .endif 7192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7193 7194 and r1, r1, #31 @ optional op; may set condition codes 7195 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7196 GET_INST_OPCODE(ip) @ extract opcode from rINST 7197 SET_VREG(r0, r9) @ vAA<- r0 7198 GOTO_OPCODE(ip) @ jump to next instruction 7199 /* 10-12 instructions */ 7200 7201 7202 7203/* ------------------------------ */ 7204 .balign 64 7205.L_OP_UNUSED_E3: /* 0xe3 */ 7206/* File: armv5te/OP_UNUSED_E3.S */ 7207/* File: armv5te/unused.S */ 7208 bl common_abort 7209 7210 7211 7212/* ------------------------------ */ 7213 .balign 64 7214.L_OP_UNUSED_E4: /* 0xe4 */ 7215/* File: armv5te/OP_UNUSED_E4.S */ 7216/* File: armv5te/unused.S */ 7217 bl common_abort 7218 7219 7220 7221/* ------------------------------ */ 7222 .balign 64 7223.L_OP_UNUSED_E5: /* 0xe5 */ 7224/* File: armv5te/OP_UNUSED_E5.S */ 7225/* File: armv5te/unused.S */ 7226 bl common_abort 7227 7228 7229 7230/* ------------------------------ */ 7231 .balign 64 7232.L_OP_UNUSED_E6: /* 0xe6 */ 7233/* File: armv5te/OP_UNUSED_E6.S */ 7234/* File: armv5te/unused.S */ 7235 bl common_abort 7236 7237 7238 7239/* ------------------------------ */ 7240 .balign 64 7241.L_OP_UNUSED_E7: /* 0xe7 */ 7242/* File: armv5te/OP_UNUSED_E7.S */ 7243/* File: armv5te/unused.S */ 7244 bl common_abort 7245 7246 7247 7248/* ------------------------------ */ 7249 .balign 64 7250.L_OP_UNUSED_E8: /* 0xe8 */ 7251/* File: armv5te/OP_UNUSED_E8.S */ 7252/* File: armv5te/unused.S */ 7253 bl common_abort 7254 7255 7256 7257/* ------------------------------ */ 7258 .balign 64 7259.L_OP_UNUSED_E9: /* 0xe9 */ 7260/* File: armv5te/OP_UNUSED_E9.S */ 7261/* File: armv5te/unused.S */ 7262 bl common_abort 7263 7264 7265 7266/* ------------------------------ */ 7267 .balign 64 7268.L_OP_UNUSED_EA: /* 0xea */ 7269/* File: armv5te/OP_UNUSED_EA.S */ 7270/* File: armv5te/unused.S */ 7271 bl common_abort 7272 7273 7274 7275/* ------------------------------ */ 7276 .balign 64 7277.L_OP_UNUSED_EB: /* 0xeb */ 7278/* File: armv5te/OP_UNUSED_EB.S */ 7279/* File: armv5te/unused.S */ 7280 bl common_abort 7281 7282 7283 7284/* ------------------------------ */ 7285 .balign 64 7286.L_OP_BREAKPOINT: /* 0xec */ 7287/* File: armv5te/OP_BREAKPOINT.S */ 7288/* File: armv5te/unused.S */ 7289 bl common_abort 7290 7291 7292 7293/* ------------------------------ */ 7294 .balign 64 7295.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7296/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7297 /* 7298 * Handle a throw-verification-error instruction. This throws an 7299 * exception for an error discovered during verification. The 7300 * exception is indicated by AA, with some detail provided by BBBB. 7301 */ 7302 /* op AA, ref@BBBB */ 7303 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7304 FETCH(r2, 1) @ r2<- BBBB 7305 EXPORT_PC() @ export the PC 7306 mov r1, rINST, lsr #8 @ r1<- AA 7307 bl dvmThrowVerificationError @ always throws 7308 b common_exceptionThrown @ handle exception 7309 7310 7311/* ------------------------------ */ 7312 .balign 64 7313.L_OP_EXECUTE_INLINE: /* 0xee */ 7314/* File: armv5te/OP_EXECUTE_INLINE.S */ 7315 /* 7316 * Execute a "native inline" instruction. 7317 * 7318 * We need to call an InlineOp4Func: 7319 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7320 * 7321 * The first four args are in r0-r3, pointer to return value storage 7322 * is on the stack. The function's return value is a flag that tells 7323 * us if an exception was thrown. 7324 */ 7325 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7326 FETCH(r10, 1) @ r10<- BBBB 7327 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7328 EXPORT_PC() @ can throw 7329 sub sp, sp, #8 @ make room for arg, +64 bit align 7330 mov r0, rINST, lsr #12 @ r0<- B 7331 str r1, [sp] @ push &glue->retval 7332 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7333 add sp, sp, #8 @ pop stack 7334 cmp r0, #0 @ test boolean result of inline 7335 beq common_exceptionThrown @ returned false, handle exception 7336 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7337 GET_INST_OPCODE(ip) @ extract opcode from rINST 7338 GOTO_OPCODE(ip) @ jump to next instruction 7339 7340/* ------------------------------ */ 7341 .balign 64 7342.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7343/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7344 /* 7345 * Execute a "native inline" instruction, using "/range" semantics. 7346 * Same idea as execute-inline, but we get the args differently. 7347 * 7348 * We need to call an InlineOp4Func: 7349 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7350 * 7351 * The first four args are in r0-r3, pointer to return value storage 7352 * is on the stack. The function's return value is a flag that tells 7353 * us if an exception was thrown. 7354 */ 7355 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7356 FETCH(r10, 1) @ r10<- BBBB 7357 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7358 EXPORT_PC() @ can throw 7359 sub sp, sp, #8 @ make room for arg, +64 bit align 7360 mov r0, rINST, lsr #8 @ r0<- AA 7361 str r1, [sp] @ push &glue->retval 7362 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7363 add sp, sp, #8 @ pop stack 7364 cmp r0, #0 @ test boolean result of inline 7365 beq common_exceptionThrown @ returned false, handle exception 7366 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7367 GET_INST_OPCODE(ip) @ extract opcode from rINST 7368 GOTO_OPCODE(ip) @ jump to next instruction 7369 7370/* ------------------------------ */ 7371 .balign 64 7372.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7373/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7374 /* 7375 * invoke-direct-empty is a no-op in a "standard" interpreter. 7376 */ 7377 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7378 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7379 GOTO_OPCODE(ip) @ execute it 7380 7381/* ------------------------------ */ 7382 .balign 64 7383.L_OP_UNUSED_F1: /* 0xf1 */ 7384/* File: armv5te/OP_UNUSED_F1.S */ 7385/* File: armv5te/unused.S */ 7386 bl common_abort 7387 7388 7389 7390/* ------------------------------ */ 7391 .balign 64 7392.L_OP_IGET_QUICK: /* 0xf2 */ 7393/* File: armv5te/OP_IGET_QUICK.S */ 7394 /* For: iget-quick, iget-object-quick */ 7395 /* op vA, vB, offset@CCCC */ 7396 mov r2, rINST, lsr #12 @ r2<- B 7397 GET_VREG(r3, r2) @ r3<- object we're operating on 7398 FETCH(r1, 1) @ r1<- field byte offset 7399 cmp r3, #0 @ check object for null 7400 mov r2, rINST, lsr #8 @ r2<- A(+) 7401 beq common_errNullObject @ object was null 7402 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7403 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7404 and r2, r2, #15 7405 GET_INST_OPCODE(ip) @ extract opcode from rINST 7406 SET_VREG(r0, r2) @ fp[A]<- r0 7407 GOTO_OPCODE(ip) @ jump to next instruction 7408 7409 7410/* ------------------------------ */ 7411 .balign 64 7412.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7413/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7414 /* iget-wide-quick vA, vB, offset@CCCC */ 7415 mov r2, rINST, lsr #12 @ r2<- B 7416 GET_VREG(r3, r2) @ r3<- object we're operating on 7417 FETCH(r1, 1) @ r1<- field byte offset 7418 cmp r3, #0 @ check object for null 7419 mov r2, rINST, lsr #8 @ r2<- A(+) 7420 beq common_errNullObject @ object was null 7421 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7422 and r2, r2, #15 7423 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7424 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7425 GET_INST_OPCODE(ip) @ extract opcode from rINST 7426 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7427 GOTO_OPCODE(ip) @ jump to next instruction 7428 7429 7430/* ------------------------------ */ 7431 .balign 64 7432.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7433/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7434/* File: armv5te/OP_IGET_QUICK.S */ 7435 /* For: iget-quick, iget-object-quick */ 7436 /* op vA, vB, offset@CCCC */ 7437 mov r2, rINST, lsr #12 @ r2<- B 7438 GET_VREG(r3, r2) @ r3<- object we're operating on 7439 FETCH(r1, 1) @ r1<- field byte offset 7440 cmp r3, #0 @ check object for null 7441 mov r2, rINST, lsr #8 @ r2<- A(+) 7442 beq common_errNullObject @ object was null 7443 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7444 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7445 and r2, r2, #15 7446 GET_INST_OPCODE(ip) @ extract opcode from rINST 7447 SET_VREG(r0, r2) @ fp[A]<- r0 7448 GOTO_OPCODE(ip) @ jump to next instruction 7449 7450 7451 7452/* ------------------------------ */ 7453 .balign 64 7454.L_OP_IPUT_QUICK: /* 0xf5 */ 7455/* File: armv5te/OP_IPUT_QUICK.S */ 7456 /* For: iput-quick, iput-object-quick */ 7457 /* op vA, vB, offset@CCCC */ 7458 mov r2, rINST, lsr #12 @ r2<- B 7459 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7460 FETCH(r1, 1) @ r1<- field byte offset 7461 cmp r3, #0 @ check object for null 7462 mov r2, rINST, lsr #8 @ r2<- A(+) 7463 beq common_errNullObject @ object was null 7464 and r2, r2, #15 7465 GET_VREG(r0, r2) @ r0<- fp[A] 7466 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7467 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7468 GET_INST_OPCODE(ip) @ extract opcode from rINST 7469 GOTO_OPCODE(ip) @ jump to next instruction 7470 7471 7472/* ------------------------------ */ 7473 .balign 64 7474.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7475/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7476 /* iput-wide-quick vA, vB, offset@CCCC */ 7477 mov r0, rINST, lsr #8 @ r0<- A(+) 7478 mov r1, rINST, lsr #12 @ r1<- B 7479 and r0, r0, #15 7480 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7481 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7482 cmp r2, #0 @ check object for null 7483 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7484 beq common_errNullObject @ object was null 7485 FETCH(r3, 1) @ r3<- field byte offset 7486 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7487 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7488 GET_INST_OPCODE(ip) @ extract opcode from rINST 7489 GOTO_OPCODE(ip) @ jump to next instruction 7490 7491 7492/* ------------------------------ */ 7493 .balign 64 7494.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7495/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7496/* File: armv5te/OP_IPUT_QUICK.S */ 7497 /* For: iput-quick, iput-object-quick */ 7498 /* op vA, vB, offset@CCCC */ 7499 mov r2, rINST, lsr #12 @ r2<- B 7500 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7501 FETCH(r1, 1) @ r1<- field byte offset 7502 cmp r3, #0 @ check object for null 7503 mov r2, rINST, lsr #8 @ r2<- A(+) 7504 beq common_errNullObject @ object was null 7505 and r2, r2, #15 7506 GET_VREG(r0, r2) @ r0<- fp[A] 7507 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7508 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7509 GET_INST_OPCODE(ip) @ extract opcode from rINST 7510 GOTO_OPCODE(ip) @ jump to next instruction 7511 7512 7513 7514/* ------------------------------ */ 7515 .balign 64 7516.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7517/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7518 /* 7519 * Handle an optimized virtual method call. 7520 * 7521 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7522 */ 7523 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7524 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7525 FETCH(r3, 2) @ r3<- FEDC or CCCC 7526 FETCH(r1, 1) @ r1<- BBBB 7527 .if (!0) 7528 and r3, r3, #15 @ r3<- C (or stays CCCC) 7529 .endif 7530 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7531 cmp r2, #0 @ is "this" null? 7532 beq common_errNullObject @ null "this", throw exception 7533 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7534 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7535 EXPORT_PC() @ invoke must export 7536 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7537 bl common_invokeMethodNoRange @ continue on 7538 7539/* ------------------------------ */ 7540 .balign 64 7541.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7542/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7543/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7544 /* 7545 * Handle an optimized virtual method call. 7546 * 7547 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7548 */ 7549 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7550 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7551 FETCH(r3, 2) @ r3<- FEDC or CCCC 7552 FETCH(r1, 1) @ r1<- BBBB 7553 .if (!1) 7554 and r3, r3, #15 @ r3<- C (or stays CCCC) 7555 .endif 7556 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7557 cmp r2, #0 @ is "this" null? 7558 beq common_errNullObject @ null "this", throw exception 7559 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7560 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7561 EXPORT_PC() @ invoke must export 7562 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7563 bl common_invokeMethodRange @ continue on 7564 7565 7566/* ------------------------------ */ 7567 .balign 64 7568.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7569/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7570 /* 7571 * Handle an optimized "super" method call. 7572 * 7573 * for: [opt] invoke-super-quick, invoke-super-quick/range 7574 */ 7575 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7576 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7577 FETCH(r10, 2) @ r10<- GFED or CCCC 7578 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7579 .if (!0) 7580 and r10, r10, #15 @ r10<- D (or stays CCCC) 7581 .endif 7582 FETCH(r1, 1) @ r1<- BBBB 7583 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7584 EXPORT_PC() @ must export for invoke 7585 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7586 GET_VREG(r3, r10) @ r3<- "this" 7587 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7588 cmp r3, #0 @ null "this" ref? 7589 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7590 beq common_errNullObject @ "this" is null, throw exception 7591 bl common_invokeMethodNoRange @ continue on 7592 7593 7594/* ------------------------------ */ 7595 .balign 64 7596.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7597/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7598/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7599 /* 7600 * Handle an optimized "super" method call. 7601 * 7602 * for: [opt] invoke-super-quick, invoke-super-quick/range 7603 */ 7604 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7605 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7606 FETCH(r10, 2) @ r10<- GFED or CCCC 7607 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7608 .if (!1) 7609 and r10, r10, #15 @ r10<- D (or stays CCCC) 7610 .endif 7611 FETCH(r1, 1) @ r1<- BBBB 7612 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7613 EXPORT_PC() @ must export for invoke 7614 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7615 GET_VREG(r3, r10) @ r3<- "this" 7616 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7617 cmp r3, #0 @ null "this" ref? 7618 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7619 beq common_errNullObject @ "this" is null, throw exception 7620 bl common_invokeMethodRange @ continue on 7621 7622 7623 7624/* ------------------------------ */ 7625 .balign 64 7626.L_OP_UNUSED_FC: /* 0xfc */ 7627/* File: armv5te/OP_UNUSED_FC.S */ 7628/* File: armv5te/unused.S */ 7629 bl common_abort 7630 7631 7632 7633/* ------------------------------ */ 7634 .balign 64 7635.L_OP_UNUSED_FD: /* 0xfd */ 7636/* File: armv5te/OP_UNUSED_FD.S */ 7637/* File: armv5te/unused.S */ 7638 bl common_abort 7639 7640 7641 7642/* ------------------------------ */ 7643 .balign 64 7644.L_OP_UNUSED_FE: /* 0xfe */ 7645/* File: armv5te/OP_UNUSED_FE.S */ 7646/* File: armv5te/unused.S */ 7647 bl common_abort 7648 7649 7650 7651/* ------------------------------ */ 7652 .balign 64 7653.L_OP_UNUSED_FF: /* 0xff */ 7654/* File: armv5te/OP_UNUSED_FF.S */ 7655/* File: armv5te/unused.S */ 7656 bl common_abort 7657 7658 7659 7660 7661 .balign 64 7662 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7663 .global dvmAsmInstructionEnd 7664dvmAsmInstructionEnd: 7665 7666/* 7667 * =========================================================================== 7668 * Sister implementations 7669 * =========================================================================== 7670 */ 7671 .global dvmAsmSisterStart 7672 .type dvmAsmSisterStart, %function 7673 .text 7674 .balign 4 7675dvmAsmSisterStart: 7676 7677/* continuation for OP_CONST_STRING */ 7678 7679 /* 7680 * Continuation if the String has not yet been resolved. 7681 * r1: BBBB (String ref) 7682 * r9: target register 7683 */ 7684.LOP_CONST_STRING_resolve: 7685 EXPORT_PC() 7686 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7687 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7688 bl dvmResolveString @ r0<- String reference 7689 cmp r0, #0 @ failed? 7690 beq common_exceptionThrown @ yup, handle the exception 7691 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7692 GET_INST_OPCODE(ip) @ extract opcode from rINST 7693 SET_VREG(r0, r9) @ vAA<- r0 7694 GOTO_OPCODE(ip) @ jump to next instruction 7695 7696 7697/* continuation for OP_CONST_STRING_JUMBO */ 7698 7699 /* 7700 * Continuation if the String has not yet been resolved. 7701 * r1: BBBBBBBB (String ref) 7702 * r9: target register 7703 */ 7704.LOP_CONST_STRING_JUMBO_resolve: 7705 EXPORT_PC() 7706 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7707 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7708 bl dvmResolveString @ r0<- String reference 7709 cmp r0, #0 @ failed? 7710 beq common_exceptionThrown @ yup, handle the exception 7711 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7712 GET_INST_OPCODE(ip) @ extract opcode from rINST 7713 SET_VREG(r0, r9) @ vAA<- r0 7714 GOTO_OPCODE(ip) @ jump to next instruction 7715 7716 7717/* continuation for OP_CONST_CLASS */ 7718 7719 /* 7720 * Continuation if the Class has not yet been resolved. 7721 * r1: BBBB (Class ref) 7722 * r9: target register 7723 */ 7724.LOP_CONST_CLASS_resolve: 7725 EXPORT_PC() 7726 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7727 mov r2, #1 @ r2<- true 7728 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7729 bl dvmResolveClass @ r0<- Class reference 7730 cmp r0, #0 @ failed? 7731 beq common_exceptionThrown @ yup, handle the exception 7732 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7733 GET_INST_OPCODE(ip) @ extract opcode from rINST 7734 SET_VREG(r0, r9) @ vAA<- r0 7735 GOTO_OPCODE(ip) @ jump to next instruction 7736 7737 7738/* continuation for OP_CHECK_CAST */ 7739 7740 /* 7741 * Trivial test failed, need to perform full check. This is common. 7742 * r0 holds obj->clazz 7743 * r1 holds class resolved from BBBB 7744 * r9 holds object 7745 */ 7746.LOP_CHECK_CAST_fullcheck: 7747 bl dvmInstanceofNonTrivial @ r0<- boolean result 7748 cmp r0, #0 @ failed? 7749 bne .LOP_CHECK_CAST_okay @ no, success 7750 7751 @ A cast has failed. We need to throw a ClassCastException with the 7752 @ class of the object that failed to be cast. 7753 EXPORT_PC() @ about to throw 7754 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7755 ldr r0, .LstrClassCastExceptionPtr 7756 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7757 bl dvmThrowExceptionWithClassMessage 7758 b common_exceptionThrown 7759 7760 /* 7761 * Resolution required. This is the least-likely path. 7762 * 7763 * r2 holds BBBB 7764 * r9 holds object 7765 */ 7766.LOP_CHECK_CAST_resolve: 7767 EXPORT_PC() @ resolve() could throw 7768 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7769 mov r1, r2 @ r1<- BBBB 7770 mov r2, #0 @ r2<- false 7771 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7772 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7773 cmp r0, #0 @ got null? 7774 beq common_exceptionThrown @ yes, handle exception 7775 mov r1, r0 @ r1<- class resolved from BBB 7776 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7777 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7778 7779.LstrClassCastExceptionPtr: 7780 .word .LstrClassCastException 7781 7782 7783/* continuation for OP_INSTANCE_OF */ 7784 7785 /* 7786 * Trivial test failed, need to perform full check. This is common. 7787 * r0 holds obj->clazz 7788 * r1 holds class resolved from BBBB 7789 * r9 holds A 7790 */ 7791.LOP_INSTANCE_OF_fullcheck: 7792 bl dvmInstanceofNonTrivial @ r0<- boolean result 7793 @ fall through to OP_INSTANCE_OF_store 7794 7795 /* 7796 * r0 holds boolean result 7797 * r9 holds A 7798 */ 7799.LOP_INSTANCE_OF_store: 7800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7801 SET_VREG(r0, r9) @ vA<- r0 7802 GET_INST_OPCODE(ip) @ extract opcode from rINST 7803 GOTO_OPCODE(ip) @ jump to next instruction 7804 7805 /* 7806 * Trivial test succeeded, save and bail. 7807 * r9 holds A 7808 */ 7809.LOP_INSTANCE_OF_trivial: 7810 mov r0, #1 @ indicate success 7811 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7813 SET_VREG(r0, r9) @ vA<- r0 7814 GET_INST_OPCODE(ip) @ extract opcode from rINST 7815 GOTO_OPCODE(ip) @ jump to next instruction 7816 7817 /* 7818 * Resolution required. This is the least-likely path. 7819 * 7820 * r3 holds BBBB 7821 * r9 holds A 7822 */ 7823.LOP_INSTANCE_OF_resolve: 7824 EXPORT_PC() @ resolve() could throw 7825 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7826 mov r1, r3 @ r1<- BBBB 7827 mov r2, #1 @ r2<- true 7828 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7829 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7830 cmp r0, #0 @ got null? 7831 beq common_exceptionThrown @ yes, handle exception 7832 mov r1, r0 @ r1<- class resolved from BBB 7833 mov r3, rINST, lsr #12 @ r3<- B 7834 GET_VREG(r0, r3) @ r0<- vB (object) 7835 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7836 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7837 7838 7839/* continuation for OP_NEW_INSTANCE */ 7840 7841 .balign 32 @ minimize cache lines 7842.LOP_NEW_INSTANCE_finish: @ r0=new object 7843 mov r3, rINST, lsr #8 @ r3<- AA 7844 cmp r0, #0 @ failed? 7845 beq common_exceptionThrown @ yes, handle the exception 7846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7847 GET_INST_OPCODE(ip) @ extract opcode from rINST 7848 SET_VREG(r0, r3) @ vAA<- r0 7849 GOTO_OPCODE(ip) @ jump to next instruction 7850 7851 /* 7852 * Class initialization required. 7853 * 7854 * r0 holds class object 7855 */ 7856.LOP_NEW_INSTANCE_needinit: 7857 mov r9, r0 @ save r0 7858 bl dvmInitClass @ initialize class 7859 cmp r0, #0 @ check boolean result 7860 mov r0, r9 @ restore r0 7861 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7862 b common_exceptionThrown @ failed, deal with init exception 7863 7864 /* 7865 * Resolution required. This is the least-likely path. 7866 * 7867 * r1 holds BBBB 7868 */ 7869.LOP_NEW_INSTANCE_resolve: 7870 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7871 mov r2, #0 @ r2<- false 7872 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7873 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7874 cmp r0, #0 @ got null? 7875 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7876 b common_exceptionThrown @ yes, handle exception 7877 7878.LstrInstantiationErrorPtr: 7879 .word .LstrInstantiationError 7880 7881 7882/* continuation for OP_NEW_ARRAY */ 7883 7884 7885 /* 7886 * Resolve class. (This is an uncommon case.) 7887 * 7888 * r1 holds array length 7889 * r2 holds class ref CCCC 7890 */ 7891.LOP_NEW_ARRAY_resolve: 7892 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7893 mov r9, r1 @ r9<- length (save) 7894 mov r1, r2 @ r1<- CCCC 7895 mov r2, #0 @ r2<- false 7896 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7897 bl dvmResolveClass @ r0<- call(clazz, ref) 7898 cmp r0, #0 @ got null? 7899 mov r1, r9 @ r1<- length (restore) 7900 beq common_exceptionThrown @ yes, handle exception 7901 @ fall through to OP_NEW_ARRAY_finish 7902 7903 /* 7904 * Finish allocation. 7905 * 7906 * r0 holds class 7907 * r1 holds array length 7908 */ 7909.LOP_NEW_ARRAY_finish: 7910 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7911 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7912 cmp r0, #0 @ failed? 7913 mov r2, rINST, lsr #8 @ r2<- A+ 7914 beq common_exceptionThrown @ yes, handle the exception 7915 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7916 and r2, r2, #15 @ r2<- A 7917 GET_INST_OPCODE(ip) @ extract opcode from rINST 7918 SET_VREG(r0, r2) @ vA<- r0 7919 GOTO_OPCODE(ip) @ jump to next instruction 7920 7921 7922/* continuation for OP_FILLED_NEW_ARRAY */ 7923 7924 /* 7925 * On entry: 7926 * r0 holds array class 7927 * r10 holds AA or BA 7928 */ 7929.LOP_FILLED_NEW_ARRAY_continue: 7930 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7931 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7932 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7933 .if 0 7934 mov r1, r10 @ r1<- AA (length) 7935 .else 7936 mov r1, r10, lsr #4 @ r1<- B (length) 7937 .endif 7938 cmp r3, #'I' @ array of ints? 7939 cmpne r3, #'L' @ array of objects? 7940 cmpne r3, #'[' @ array of arrays? 7941 mov r9, r1 @ save length in r9 7942 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7943 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7944 cmp r0, #0 @ null return? 7945 beq common_exceptionThrown @ alloc failed, handle exception 7946 7947 FETCH(r1, 2) @ r1<- FEDC or CCCC 7948 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7949 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7950 subs r9, r9, #1 @ length--, check for neg 7951 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7952 bmi 2f @ was zero, bail 7953 7954 @ copy values from registers into the array 7955 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7956 .if 0 7957 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79581: ldr r3, [r2], #4 @ r3<- *r2++ 7959 subs r9, r9, #1 @ count-- 7960 str r3, [r0], #4 @ *contents++ = vX 7961 bpl 1b 7962 @ continue at 2 7963 .else 7964 cmp r9, #4 @ length was initially 5? 7965 and r2, r10, #15 @ r2<- A 7966 bne 1f @ <= 4 args, branch 7967 GET_VREG(r3, r2) @ r3<- vA 7968 sub r9, r9, #1 @ count-- 7969 str r3, [r0, #16] @ contents[4] = vA 79701: and r2, r1, #15 @ r2<- F/E/D/C 7971 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7972 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7973 subs r9, r9, #1 @ count-- 7974 str r3, [r0], #4 @ *contents++ = vX 7975 bpl 1b 7976 @ continue at 2 7977 .endif 7978 79792: 7980 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7981 GOTO_OPCODE(ip) @ execute it 7982 7983 /* 7984 * Throw an exception indicating that we have not implemented this 7985 * mode of filled-new-array. 7986 */ 7987.LOP_FILLED_NEW_ARRAY_notimpl: 7988 ldr r0, .L_strInternalError 7989 ldr r1, .L_strFilledNewArrayNotImpl 7990 bl dvmThrowException 7991 b common_exceptionThrown 7992 7993 .if (!0) @ define in one or the other, not both 7994.L_strFilledNewArrayNotImpl: 7995 .word .LstrFilledNewArrayNotImpl 7996.L_strInternalError: 7997 .word .LstrInternalError 7998 .endif 7999 8000 8001/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8002 8003 /* 8004 * On entry: 8005 * r0 holds array class 8006 * r10 holds AA or BA 8007 */ 8008.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8009 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8010 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8011 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8012 .if 1 8013 mov r1, r10 @ r1<- AA (length) 8014 .else 8015 mov r1, r10, lsr #4 @ r1<- B (length) 8016 .endif 8017 cmp r3, #'I' @ array of ints? 8018 cmpne r3, #'L' @ array of objects? 8019 cmpne r3, #'[' @ array of arrays? 8020 mov r9, r1 @ save length in r9 8021 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8022 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8023 cmp r0, #0 @ null return? 8024 beq common_exceptionThrown @ alloc failed, handle exception 8025 8026 FETCH(r1, 2) @ r1<- FEDC or CCCC 8027 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8028 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8029 subs r9, r9, #1 @ length--, check for neg 8030 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8031 bmi 2f @ was zero, bail 8032 8033 @ copy values from registers into the array 8034 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8035 .if 1 8036 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80371: ldr r3, [r2], #4 @ r3<- *r2++ 8038 subs r9, r9, #1 @ count-- 8039 str r3, [r0], #4 @ *contents++ = vX 8040 bpl 1b 8041 @ continue at 2 8042 .else 8043 cmp r9, #4 @ length was initially 5? 8044 and r2, r10, #15 @ r2<- A 8045 bne 1f @ <= 4 args, branch 8046 GET_VREG(r3, r2) @ r3<- vA 8047 sub r9, r9, #1 @ count-- 8048 str r3, [r0, #16] @ contents[4] = vA 80491: and r2, r1, #15 @ r2<- F/E/D/C 8050 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8051 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8052 subs r9, r9, #1 @ count-- 8053 str r3, [r0], #4 @ *contents++ = vX 8054 bpl 1b 8055 @ continue at 2 8056 .endif 8057 80582: 8059 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8060 GOTO_OPCODE(ip) @ execute it 8061 8062 /* 8063 * Throw an exception indicating that we have not implemented this 8064 * mode of filled-new-array. 8065 */ 8066.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8067 ldr r0, .L_strInternalError 8068 ldr r1, .L_strFilledNewArrayNotImpl 8069 bl dvmThrowException 8070 b common_exceptionThrown 8071 8072 .if (!1) @ define in one or the other, not both 8073.L_strFilledNewArrayNotImpl: 8074 .word .LstrFilledNewArrayNotImpl 8075.L_strInternalError: 8076 .word .LstrInternalError 8077 .endif 8078 8079 8080/* continuation for OP_CMPL_FLOAT */ 8081.LOP_CMPL_FLOAT_finish: 8082 SET_VREG(r0, r9) @ vAA<- r0 8083 GOTO_OPCODE(ip) @ jump to next instruction 8084 8085 8086/* continuation for OP_CMPG_FLOAT */ 8087.LOP_CMPG_FLOAT_finish: 8088 SET_VREG(r0, r9) @ vAA<- r0 8089 GOTO_OPCODE(ip) @ jump to next instruction 8090 8091 8092/* continuation for OP_CMPL_DOUBLE */ 8093.LOP_CMPL_DOUBLE_finish: 8094 SET_VREG(r0, r9) @ vAA<- r0 8095 GOTO_OPCODE(ip) @ jump to next instruction 8096 8097 8098/* continuation for OP_CMPG_DOUBLE */ 8099.LOP_CMPG_DOUBLE_finish: 8100 SET_VREG(r0, r9) @ vAA<- r0 8101 GOTO_OPCODE(ip) @ jump to next instruction 8102 8103 8104/* continuation for OP_CMP_LONG */ 8105 8106.LOP_CMP_LONG_less: 8107 mvn r1, #0 @ r1<- -1 8108 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8109 @ instead, we just replicate the tail end. 8110 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8111 SET_VREG(r1, r9) @ vAA<- r1 8112 GET_INST_OPCODE(ip) @ extract opcode from rINST 8113 GOTO_OPCODE(ip) @ jump to next instruction 8114 8115.LOP_CMP_LONG_greater: 8116 mov r1, #1 @ r1<- 1 8117 @ fall through to _finish 8118 8119.LOP_CMP_LONG_finish: 8120 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8121 SET_VREG(r1, r9) @ vAA<- r1 8122 GET_INST_OPCODE(ip) @ extract opcode from rINST 8123 GOTO_OPCODE(ip) @ jump to next instruction 8124 8125 8126/* continuation for OP_AGET_WIDE */ 8127 8128.LOP_AGET_WIDE_finish: 8129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8130 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8131 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8132 GET_INST_OPCODE(ip) @ extract opcode from rINST 8133 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8134 GOTO_OPCODE(ip) @ jump to next instruction 8135 8136 8137/* continuation for OP_APUT_WIDE */ 8138 8139.LOP_APUT_WIDE_finish: 8140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8141 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8142 GET_INST_OPCODE(ip) @ extract opcode from rINST 8143 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8144 GOTO_OPCODE(ip) @ jump to next instruction 8145 8146 8147/* continuation for OP_APUT_OBJECT */ 8148 /* 8149 * On entry: 8150 * r1 = vBB (arrayObj) 8151 * r9 = vAA (obj) 8152 * r10 = offset into array (vBB + vCC * width) 8153 */ 8154.LOP_APUT_OBJECT_finish: 8155 cmp r9, #0 @ storing null reference? 8156 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8157 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8158 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8159 bl dvmCanPutArrayElement @ test object type vs. array type 8160 cmp r0, #0 @ okay? 8161 beq common_errArrayStore @ no 8162.LOP_APUT_OBJECT_skip_check: 8163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8164 GET_INST_OPCODE(ip) @ extract opcode from rINST 8165 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8166 GOTO_OPCODE(ip) @ jump to next instruction 8167 8168 8169/* continuation for OP_IGET */ 8170 8171 /* 8172 * Currently: 8173 * r0 holds resolved field 8174 * r9 holds object 8175 */ 8176.LOP_IGET_finish: 8177 @bl common_squeak0 8178 cmp r9, #0 @ check object for null 8179 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8180 beq common_errNullObject @ object was null 8181 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8182 mov r2, rINST, lsr #8 @ r2<- A+ 8183 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8184 and r2, r2, #15 @ r2<- A 8185 GET_INST_OPCODE(ip) @ extract opcode from rINST 8186 SET_VREG(r0, r2) @ fp[A]<- r0 8187 GOTO_OPCODE(ip) @ jump to next instruction 8188 8189 8190/* continuation for OP_IGET_WIDE */ 8191 8192 /* 8193 * Currently: 8194 * r0 holds resolved field 8195 * r9 holds object 8196 */ 8197.LOP_IGET_WIDE_finish: 8198 cmp r9, #0 @ check object for null 8199 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8200 beq common_errNullObject @ object was null 8201 mov r2, rINST, lsr #8 @ r2<- A+ 8202 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8203 and r2, r2, #15 @ r2<- A 8204 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8205 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8206 GET_INST_OPCODE(ip) @ extract opcode from rINST 8207 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8208 GOTO_OPCODE(ip) @ jump to next instruction 8209 8210 8211/* continuation for OP_IGET_OBJECT */ 8212 8213 /* 8214 * Currently: 8215 * r0 holds resolved field 8216 * r9 holds object 8217 */ 8218.LOP_IGET_OBJECT_finish: 8219 @bl common_squeak0 8220 cmp r9, #0 @ check object for null 8221 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8222 beq common_errNullObject @ object was null 8223 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8224 mov r2, rINST, lsr #8 @ r2<- A+ 8225 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8226 and r2, r2, #15 @ r2<- A 8227 GET_INST_OPCODE(ip) @ extract opcode from rINST 8228 SET_VREG(r0, r2) @ fp[A]<- r0 8229 GOTO_OPCODE(ip) @ jump to next instruction 8230 8231 8232/* continuation for OP_IGET_BOOLEAN */ 8233 8234 /* 8235 * Currently: 8236 * r0 holds resolved field 8237 * r9 holds object 8238 */ 8239.LOP_IGET_BOOLEAN_finish: 8240 @bl common_squeak1 8241 cmp r9, #0 @ check object for null 8242 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8243 beq common_errNullObject @ object was null 8244 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8245 mov r2, rINST, lsr #8 @ r2<- A+ 8246 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8247 and r2, r2, #15 @ r2<- A 8248 GET_INST_OPCODE(ip) @ extract opcode from rINST 8249 SET_VREG(r0, r2) @ fp[A]<- r0 8250 GOTO_OPCODE(ip) @ jump to next instruction 8251 8252 8253/* continuation for OP_IGET_BYTE */ 8254 8255 /* 8256 * Currently: 8257 * r0 holds resolved field 8258 * r9 holds object 8259 */ 8260.LOP_IGET_BYTE_finish: 8261 @bl common_squeak2 8262 cmp r9, #0 @ check object for null 8263 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8264 beq common_errNullObject @ object was null 8265 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8266 mov r2, rINST, lsr #8 @ r2<- A+ 8267 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8268 and r2, r2, #15 @ r2<- A 8269 GET_INST_OPCODE(ip) @ extract opcode from rINST 8270 SET_VREG(r0, r2) @ fp[A]<- r0 8271 GOTO_OPCODE(ip) @ jump to next instruction 8272 8273 8274/* continuation for OP_IGET_CHAR */ 8275 8276 /* 8277 * Currently: 8278 * r0 holds resolved field 8279 * r9 holds object 8280 */ 8281.LOP_IGET_CHAR_finish: 8282 @bl common_squeak3 8283 cmp r9, #0 @ check object for null 8284 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8285 beq common_errNullObject @ object was null 8286 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8287 mov r2, rINST, lsr #8 @ r2<- A+ 8288 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8289 and r2, r2, #15 @ r2<- A 8290 GET_INST_OPCODE(ip) @ extract opcode from rINST 8291 SET_VREG(r0, r2) @ fp[A]<- r0 8292 GOTO_OPCODE(ip) @ jump to next instruction 8293 8294 8295/* continuation for OP_IGET_SHORT */ 8296 8297 /* 8298 * Currently: 8299 * r0 holds resolved field 8300 * r9 holds object 8301 */ 8302.LOP_IGET_SHORT_finish: 8303 @bl common_squeak4 8304 cmp r9, #0 @ check object for null 8305 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8306 beq common_errNullObject @ object was null 8307 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8308 mov r2, rINST, lsr #8 @ r2<- A+ 8309 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8310 and r2, r2, #15 @ r2<- A 8311 GET_INST_OPCODE(ip) @ extract opcode from rINST 8312 SET_VREG(r0, r2) @ fp[A]<- r0 8313 GOTO_OPCODE(ip) @ jump to next instruction 8314 8315 8316/* continuation for OP_IPUT */ 8317 8318 /* 8319 * Currently: 8320 * r0 holds resolved field 8321 * r9 holds object 8322 */ 8323.LOP_IPUT_finish: 8324 @bl common_squeak0 8325 mov r1, rINST, lsr #8 @ r1<- A+ 8326 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8327 and r1, r1, #15 @ r1<- A 8328 cmp r9, #0 @ check object for null 8329 GET_VREG(r0, r1) @ r0<- fp[A] 8330 beq common_errNullObject @ object was null 8331 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8332 GET_INST_OPCODE(ip) @ extract opcode from rINST 8333 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8334 GOTO_OPCODE(ip) @ jump to next instruction 8335 8336 8337/* continuation for OP_IPUT_WIDE */ 8338 8339 /* 8340 * Currently: 8341 * r0 holds resolved field 8342 * r9 holds object 8343 */ 8344.LOP_IPUT_WIDE_finish: 8345 mov r2, rINST, lsr #8 @ r2<- A+ 8346 cmp r9, #0 @ check object for null 8347 and r2, r2, #15 @ r2<- A 8348 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8349 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8350 beq common_errNullObject @ object was null 8351 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8352 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8353 GET_INST_OPCODE(ip) @ extract opcode from rINST 8354 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8355 GOTO_OPCODE(ip) @ jump to next instruction 8356 8357 8358/* continuation for OP_IPUT_OBJECT */ 8359 8360 /* 8361 * Currently: 8362 * r0 holds resolved field 8363 * r9 holds object 8364 */ 8365.LOP_IPUT_OBJECT_finish: 8366 @bl common_squeak0 8367 mov r1, rINST, lsr #8 @ r1<- A+ 8368 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8369 and r1, r1, #15 @ r1<- A 8370 cmp r9, #0 @ check object for null 8371 GET_VREG(r0, r1) @ r0<- fp[A] 8372 beq common_errNullObject @ object was null 8373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8374 GET_INST_OPCODE(ip) @ extract opcode from rINST 8375 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8376 GOTO_OPCODE(ip) @ jump to next instruction 8377 8378 8379/* continuation for OP_IPUT_BOOLEAN */ 8380 8381 /* 8382 * Currently: 8383 * r0 holds resolved field 8384 * r9 holds object 8385 */ 8386.LOP_IPUT_BOOLEAN_finish: 8387 @bl common_squeak1 8388 mov r1, rINST, lsr #8 @ r1<- A+ 8389 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8390 and r1, r1, #15 @ r1<- A 8391 cmp r9, #0 @ check object for null 8392 GET_VREG(r0, r1) @ r0<- fp[A] 8393 beq common_errNullObject @ object was null 8394 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8395 GET_INST_OPCODE(ip) @ extract opcode from rINST 8396 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8397 GOTO_OPCODE(ip) @ jump to next instruction 8398 8399 8400/* continuation for OP_IPUT_BYTE */ 8401 8402 /* 8403 * Currently: 8404 * r0 holds resolved field 8405 * r9 holds object 8406 */ 8407.LOP_IPUT_BYTE_finish: 8408 @bl common_squeak2 8409 mov r1, rINST, lsr #8 @ r1<- A+ 8410 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8411 and r1, r1, #15 @ r1<- A 8412 cmp r9, #0 @ check object for null 8413 GET_VREG(r0, r1) @ r0<- fp[A] 8414 beq common_errNullObject @ object was null 8415 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8416 GET_INST_OPCODE(ip) @ extract opcode from rINST 8417 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8418 GOTO_OPCODE(ip) @ jump to next instruction 8419 8420 8421/* continuation for OP_IPUT_CHAR */ 8422 8423 /* 8424 * Currently: 8425 * r0 holds resolved field 8426 * r9 holds object 8427 */ 8428.LOP_IPUT_CHAR_finish: 8429 @bl common_squeak3 8430 mov r1, rINST, lsr #8 @ r1<- A+ 8431 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8432 and r1, r1, #15 @ r1<- A 8433 cmp r9, #0 @ check object for null 8434 GET_VREG(r0, r1) @ r0<- fp[A] 8435 beq common_errNullObject @ object was null 8436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8437 GET_INST_OPCODE(ip) @ extract opcode from rINST 8438 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8439 GOTO_OPCODE(ip) @ jump to next instruction 8440 8441 8442/* continuation for OP_IPUT_SHORT */ 8443 8444 /* 8445 * Currently: 8446 * r0 holds resolved field 8447 * r9 holds object 8448 */ 8449.LOP_IPUT_SHORT_finish: 8450 @bl common_squeak4 8451 mov r1, rINST, lsr #8 @ r1<- A+ 8452 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8453 and r1, r1, #15 @ r1<- A 8454 cmp r9, #0 @ check object for null 8455 GET_VREG(r0, r1) @ r0<- fp[A] 8456 beq common_errNullObject @ object was null 8457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8458 GET_INST_OPCODE(ip) @ extract opcode from rINST 8459 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8460 GOTO_OPCODE(ip) @ jump to next instruction 8461 8462 8463/* continuation for OP_SGET */ 8464 8465 /* 8466 * Continuation if the field has not yet been resolved. 8467 * r1: BBBB field ref 8468 */ 8469.LOP_SGET_resolve: 8470 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8471 EXPORT_PC() @ resolve() could throw, so export now 8472 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8473 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8474 cmp r0, #0 @ success? 8475 bne .LOP_SGET_finish @ yes, finish 8476 b common_exceptionThrown @ no, handle exception 8477 8478 8479/* continuation for OP_SGET_WIDE */ 8480 8481 /* 8482 * Continuation if the field has not yet been resolved. 8483 * r1: BBBB field ref 8484 */ 8485.LOP_SGET_WIDE_resolve: 8486 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8487 EXPORT_PC() @ resolve() could throw, so export now 8488 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8489 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8490 cmp r0, #0 @ success? 8491 bne .LOP_SGET_WIDE_finish @ yes, finish 8492 b common_exceptionThrown @ no, handle exception 8493 8494 8495/* continuation for OP_SGET_OBJECT */ 8496 8497 /* 8498 * Continuation if the field has not yet been resolved. 8499 * r1: BBBB field ref 8500 */ 8501.LOP_SGET_OBJECT_resolve: 8502 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8503 EXPORT_PC() @ resolve() could throw, so export now 8504 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8505 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8506 cmp r0, #0 @ success? 8507 bne .LOP_SGET_OBJECT_finish @ yes, finish 8508 b common_exceptionThrown @ no, handle exception 8509 8510 8511/* continuation for OP_SGET_BOOLEAN */ 8512 8513 /* 8514 * Continuation if the field has not yet been resolved. 8515 * r1: BBBB field ref 8516 */ 8517.LOP_SGET_BOOLEAN_resolve: 8518 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8519 EXPORT_PC() @ resolve() could throw, so export now 8520 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8521 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8522 cmp r0, #0 @ success? 8523 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8524 b common_exceptionThrown @ no, handle exception 8525 8526 8527/* continuation for OP_SGET_BYTE */ 8528 8529 /* 8530 * Continuation if the field has not yet been resolved. 8531 * r1: BBBB field ref 8532 */ 8533.LOP_SGET_BYTE_resolve: 8534 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8535 EXPORT_PC() @ resolve() could throw, so export now 8536 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8537 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8538 cmp r0, #0 @ success? 8539 bne .LOP_SGET_BYTE_finish @ yes, finish 8540 b common_exceptionThrown @ no, handle exception 8541 8542 8543/* continuation for OP_SGET_CHAR */ 8544 8545 /* 8546 * Continuation if the field has not yet been resolved. 8547 * r1: BBBB field ref 8548 */ 8549.LOP_SGET_CHAR_resolve: 8550 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8551 EXPORT_PC() @ resolve() could throw, so export now 8552 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8553 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8554 cmp r0, #0 @ success? 8555 bne .LOP_SGET_CHAR_finish @ yes, finish 8556 b common_exceptionThrown @ no, handle exception 8557 8558 8559/* continuation for OP_SGET_SHORT */ 8560 8561 /* 8562 * Continuation if the field has not yet been resolved. 8563 * r1: BBBB field ref 8564 */ 8565.LOP_SGET_SHORT_resolve: 8566 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8567 EXPORT_PC() @ resolve() could throw, so export now 8568 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8569 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8570 cmp r0, #0 @ success? 8571 bne .LOP_SGET_SHORT_finish @ yes, finish 8572 b common_exceptionThrown @ no, handle exception 8573 8574 8575/* continuation for OP_SPUT */ 8576 8577 /* 8578 * Continuation if the field has not yet been resolved. 8579 * r1: BBBB field ref 8580 */ 8581.LOP_SPUT_resolve: 8582 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8583 EXPORT_PC() @ resolve() could throw, so export now 8584 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8585 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8586 cmp r0, #0 @ success? 8587 bne .LOP_SPUT_finish @ yes, finish 8588 b common_exceptionThrown @ no, handle exception 8589 8590 8591/* continuation for OP_SPUT_WIDE */ 8592 8593 /* 8594 * Continuation if the field has not yet been resolved. 8595 * r1: BBBB field ref 8596 * r9: &fp[AA] 8597 */ 8598.LOP_SPUT_WIDE_resolve: 8599 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8600 EXPORT_PC() @ resolve() could throw, so export now 8601 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8602 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8603 cmp r0, #0 @ success? 8604 bne .LOP_SPUT_WIDE_finish @ yes, finish 8605 b common_exceptionThrown @ no, handle exception 8606 8607 8608/* continuation for OP_SPUT_OBJECT */ 8609 8610 /* 8611 * Continuation if the field has not yet been resolved. 8612 * r1: BBBB field ref 8613 */ 8614.LOP_SPUT_OBJECT_resolve: 8615 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8616 EXPORT_PC() @ resolve() could throw, so export now 8617 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8618 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8619 cmp r0, #0 @ success? 8620 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8621 b common_exceptionThrown @ no, handle exception 8622 8623 8624/* continuation for OP_SPUT_BOOLEAN */ 8625 8626 /* 8627 * Continuation if the field has not yet been resolved. 8628 * r1: BBBB field ref 8629 */ 8630.LOP_SPUT_BOOLEAN_resolve: 8631 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8632 EXPORT_PC() @ resolve() could throw, so export now 8633 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8634 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8635 cmp r0, #0 @ success? 8636 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8637 b common_exceptionThrown @ no, handle exception 8638 8639 8640/* continuation for OP_SPUT_BYTE */ 8641 8642 /* 8643 * Continuation if the field has not yet been resolved. 8644 * r1: BBBB field ref 8645 */ 8646.LOP_SPUT_BYTE_resolve: 8647 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8648 EXPORT_PC() @ resolve() could throw, so export now 8649 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8650 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8651 cmp r0, #0 @ success? 8652 bne .LOP_SPUT_BYTE_finish @ yes, finish 8653 b common_exceptionThrown @ no, handle exception 8654 8655 8656/* continuation for OP_SPUT_CHAR */ 8657 8658 /* 8659 * Continuation if the field has not yet been resolved. 8660 * r1: BBBB field ref 8661 */ 8662.LOP_SPUT_CHAR_resolve: 8663 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8664 EXPORT_PC() @ resolve() could throw, so export now 8665 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8666 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8667 cmp r0, #0 @ success? 8668 bne .LOP_SPUT_CHAR_finish @ yes, finish 8669 b common_exceptionThrown @ no, handle exception 8670 8671 8672/* continuation for OP_SPUT_SHORT */ 8673 8674 /* 8675 * Continuation if the field has not yet been resolved. 8676 * r1: BBBB field ref 8677 */ 8678.LOP_SPUT_SHORT_resolve: 8679 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8680 EXPORT_PC() @ resolve() could throw, so export now 8681 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8682 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8683 cmp r0, #0 @ success? 8684 bne .LOP_SPUT_SHORT_finish @ yes, finish 8685 b common_exceptionThrown @ no, handle exception 8686 8687 8688/* continuation for OP_INVOKE_VIRTUAL */ 8689 8690 /* 8691 * At this point: 8692 * r0 = resolved base method 8693 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8694 */ 8695.LOP_INVOKE_VIRTUAL_continue: 8696 GET_VREG(r1, r10) @ r1<- "this" ptr 8697 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8698 cmp r1, #0 @ is "this" null? 8699 beq common_errNullObject @ null "this", throw exception 8700 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8701 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8702 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8703 bl common_invokeMethodNoRange @ continue on 8704 8705 8706/* continuation for OP_INVOKE_SUPER */ 8707 8708 /* 8709 * At this point: 8710 * r0 = resolved base method 8711 * r9 = method->clazz 8712 */ 8713.LOP_INVOKE_SUPER_continue: 8714 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8715 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8716 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8717 EXPORT_PC() @ must export for invoke 8718 cmp r2, r3 @ compare (methodIndex, vtableCount) 8719 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8720 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8721 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8722 bl common_invokeMethodNoRange @ continue on 8723 8724.LOP_INVOKE_SUPER_resolve: 8725 mov r0, r9 @ r0<- method->clazz 8726 mov r2, #METHOD_VIRTUAL @ resolver method type 8727 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8728 cmp r0, #0 @ got null? 8729 bne .LOP_INVOKE_SUPER_continue @ no, continue 8730 b common_exceptionThrown @ yes, handle exception 8731 8732 /* 8733 * Throw a NoSuchMethodError with the method name as the message. 8734 * r0 = resolved base method 8735 */ 8736.LOP_INVOKE_SUPER_nsm: 8737 ldr r1, [r0, #offMethod_name] @ r1<- method name 8738 b common_errNoSuchMethod 8739 8740 8741/* continuation for OP_INVOKE_DIRECT */ 8742 8743 /* 8744 * On entry: 8745 * r1 = reference (BBBB or CCCC) 8746 * r10 = "this" register 8747 */ 8748.LOP_INVOKE_DIRECT_resolve: 8749 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8750 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8751 mov r2, #METHOD_DIRECT @ resolver method type 8752 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8753 cmp r0, #0 @ got null? 8754 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8755 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8756 b common_exceptionThrown @ yes, handle exception 8757 8758 8759/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8760 8761 /* 8762 * At this point: 8763 * r0 = resolved base method 8764 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8765 */ 8766.LOP_INVOKE_VIRTUAL_RANGE_continue: 8767 GET_VREG(r1, r10) @ r1<- "this" ptr 8768 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8769 cmp r1, #0 @ is "this" null? 8770 beq common_errNullObject @ null "this", throw exception 8771 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8772 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8773 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8774 bl common_invokeMethodRange @ continue on 8775 8776 8777/* continuation for OP_INVOKE_SUPER_RANGE */ 8778 8779 /* 8780 * At this point: 8781 * r0 = resolved base method 8782 * r9 = method->clazz 8783 */ 8784.LOP_INVOKE_SUPER_RANGE_continue: 8785 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8786 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8787 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8788 EXPORT_PC() @ must export for invoke 8789 cmp r2, r3 @ compare (methodIndex, vtableCount) 8790 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8791 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8792 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8793 bl common_invokeMethodRange @ continue on 8794 8795.LOP_INVOKE_SUPER_RANGE_resolve: 8796 mov r0, r9 @ r0<- method->clazz 8797 mov r2, #METHOD_VIRTUAL @ resolver method type 8798 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8799 cmp r0, #0 @ got null? 8800 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8801 b common_exceptionThrown @ yes, handle exception 8802 8803 /* 8804 * Throw a NoSuchMethodError with the method name as the message. 8805 * r0 = resolved base method 8806 */ 8807.LOP_INVOKE_SUPER_RANGE_nsm: 8808 ldr r1, [r0, #offMethod_name] @ r1<- method name 8809 b common_errNoSuchMethod 8810 8811 8812/* continuation for OP_INVOKE_DIRECT_RANGE */ 8813 8814 /* 8815 * On entry: 8816 * r1 = reference (BBBB or CCCC) 8817 * r10 = "this" register 8818 */ 8819.LOP_INVOKE_DIRECT_RANGE_resolve: 8820 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8821 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8822 mov r2, #METHOD_DIRECT @ resolver method type 8823 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8824 cmp r0, #0 @ got null? 8825 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8826 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8827 b common_exceptionThrown @ yes, handle exception 8828 8829 8830/* continuation for OP_FLOAT_TO_LONG */ 8831/* 8832 * Convert the float in r0 to a long in r0/r1. 8833 * 8834 * We have to clip values to long min/max per the specification. The 8835 * expected common case is a "reasonable" value that converts directly 8836 * to modest integer. The EABI convert function isn't doing this for us. 8837 */ 8838f2l_doconv: 8839 stmfd sp!, {r4, lr} 8840 mov r1, #0x5f000000 @ (float)maxlong 8841 mov r4, r0 8842 bl __aeabi_fcmpge @ is arg >= maxlong? 8843 cmp r0, #0 @ nonzero == yes 8844 mvnne r0, #0 @ return maxlong (7fffffff) 8845 mvnne r1, #0x80000000 8846 ldmnefd sp!, {r4, pc} 8847 8848 mov r0, r4 @ recover arg 8849 mov r1, #0xdf000000 @ (float)minlong 8850 bl __aeabi_fcmple @ is arg <= minlong? 8851 cmp r0, #0 @ nonzero == yes 8852 movne r0, #0 @ return minlong (80000000) 8853 movne r1, #0x80000000 8854 ldmnefd sp!, {r4, pc} 8855 8856 mov r0, r4 @ recover arg 8857 mov r1, r4 8858 bl __aeabi_fcmpeq @ is arg == self? 8859 cmp r0, #0 @ zero == no 8860 moveq r1, #0 @ return zero for NaN 8861 ldmeqfd sp!, {r4, pc} 8862 8863 mov r0, r4 @ recover arg 8864 bl __aeabi_f2lz @ convert float to long 8865 ldmfd sp!, {r4, pc} 8866 8867 8868/* continuation for OP_DOUBLE_TO_LONG */ 8869/* 8870 * Convert the double in r0/r1 to a long in r0/r1. 8871 * 8872 * We have to clip values to long min/max per the specification. The 8873 * expected common case is a "reasonable" value that converts directly 8874 * to modest integer. The EABI convert function isn't doing this for us. 8875 */ 8876d2l_doconv: 8877 stmfd sp!, {r4, r5, lr} @ save regs 8878 mov r3, #0x43000000 @ maxlong, as a double (high word) 8879 add r3, #0x00e00000 @ 0x43e00000 8880 mov r2, #0 @ maxlong, as a double (low word) 8881 sub sp, sp, #4 @ align for EABI 8882 mov r4, r0 @ save a copy of r0 8883 mov r5, r1 @ and r1 8884 bl __aeabi_dcmpge @ is arg >= maxlong? 8885 cmp r0, #0 @ nonzero == yes 8886 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8887 mvnne r1, #0x80000000 8888 bne 1f 8889 8890 mov r0, r4 @ recover arg 8891 mov r1, r5 8892 mov r3, #0xc3000000 @ minlong, as a double (high word) 8893 add r3, #0x00e00000 @ 0xc3e00000 8894 mov r2, #0 @ minlong, as a double (low word) 8895 bl __aeabi_dcmple @ is arg <= minlong? 8896 cmp r0, #0 @ nonzero == yes 8897 movne r0, #0 @ return minlong (8000000000000000) 8898 movne r1, #0x80000000 8899 bne 1f 8900 8901 mov r0, r4 @ recover arg 8902 mov r1, r5 8903 mov r2, r4 @ compare against self 8904 mov r3, r5 8905 bl __aeabi_dcmpeq @ is arg == self? 8906 cmp r0, #0 @ zero == no 8907 moveq r1, #0 @ return zero for NaN 8908 beq 1f 8909 8910 mov r0, r4 @ recover arg 8911 mov r1, r5 8912 bl __aeabi_d2lz @ convert double to long 8913 89141: 8915 add sp, sp, #4 8916 ldmfd sp!, {r4, r5, pc} 8917 8918 8919/* continuation for OP_MUL_LONG */ 8920 8921.LOP_MUL_LONG_finish: 8922 GET_INST_OPCODE(ip) @ extract opcode from rINST 8923 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8924 GOTO_OPCODE(ip) @ jump to next instruction 8925 8926 8927/* continuation for OP_SHL_LONG */ 8928 8929.LOP_SHL_LONG_finish: 8930 mov r0, r0, asl r2 @ r0<- r0 << r2 8931 GET_INST_OPCODE(ip) @ extract opcode from rINST 8932 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8933 GOTO_OPCODE(ip) @ jump to next instruction 8934 8935 8936/* continuation for OP_SHR_LONG */ 8937 8938.LOP_SHR_LONG_finish: 8939 mov r1, r1, asr r2 @ r1<- r1 >> r2 8940 GET_INST_OPCODE(ip) @ extract opcode from rINST 8941 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8942 GOTO_OPCODE(ip) @ jump to next instruction 8943 8944 8945/* continuation for OP_USHR_LONG */ 8946 8947.LOP_USHR_LONG_finish: 8948 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8949 GET_INST_OPCODE(ip) @ extract opcode from rINST 8950 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8951 GOTO_OPCODE(ip) @ jump to next instruction 8952 8953 8954/* continuation for OP_SHL_LONG_2ADDR */ 8955 8956.LOP_SHL_LONG_2ADDR_finish: 8957 GET_INST_OPCODE(ip) @ extract opcode from rINST 8958 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8959 GOTO_OPCODE(ip) @ jump to next instruction 8960 8961 8962/* continuation for OP_SHR_LONG_2ADDR */ 8963 8964.LOP_SHR_LONG_2ADDR_finish: 8965 GET_INST_OPCODE(ip) @ extract opcode from rINST 8966 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8967 GOTO_OPCODE(ip) @ jump to next instruction 8968 8969 8970/* continuation for OP_USHR_LONG_2ADDR */ 8971 8972.LOP_USHR_LONG_2ADDR_finish: 8973 GET_INST_OPCODE(ip) @ extract opcode from rINST 8974 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8975 GOTO_OPCODE(ip) @ jump to next instruction 8976 8977 8978/* continuation for OP_EXECUTE_INLINE */ 8979 8980 /* 8981 * Extract args, call function. 8982 * r0 = #of args (0-4) 8983 * r10 = call index 8984 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8985 * 8986 * Other ideas: 8987 * - Use a jump table from the main piece to jump directly into the 8988 * AND/LDR pairs. Costs a data load, saves a branch. 8989 * - Have five separate pieces that do the loading, so we can work the 8990 * interleave a little better. Increases code size. 8991 */ 8992.LOP_EXECUTE_INLINE_continue: 8993 rsb r0, r0, #4 @ r0<- 4-r0 8994 FETCH(r9, 2) @ r9<- FEDC 8995 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8996 bl common_abort @ (skipped due to ARM prefetch) 89974: and ip, r9, #0xf000 @ isolate F 8998 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89993: and ip, r9, #0x0f00 @ isolate E 9000 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 90012: and ip, r9, #0x00f0 @ isolate D 9002 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 90031: and ip, r9, #0x000f @ isolate C 9004 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 90050: 9006 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9007 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9008 @ (not reached) 9009 9010.LOP_EXECUTE_INLINE_table: 9011 .word gDvmInlineOpsTable 9012 9013 9014/* continuation for OP_EXECUTE_INLINE_RANGE */ 9015 9016 /* 9017 * Extract args, call function. 9018 * r0 = #of args (0-4) 9019 * r10 = call index 9020 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9021 */ 9022.LOP_EXECUTE_INLINE_RANGE_continue: 9023 rsb r0, r0, #4 @ r0<- 4-r0 9024 FETCH(r9, 2) @ r9<- CCCC 9025 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9026 bl common_abort @ (skipped due to ARM prefetch) 90274: add ip, r9, #3 @ base+3 9028 GET_VREG(r3, ip) @ r3<- vBase[3] 90293: add ip, r9, #2 @ base+2 9030 GET_VREG(r2, ip) @ r2<- vBase[2] 90312: add ip, r9, #1 @ base+1 9032 GET_VREG(r1, ip) @ r1<- vBase[1] 90331: add ip, r9, #0 @ (nop) 9034 GET_VREG(r0, ip) @ r0<- vBase[0] 90350: 9036 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9037 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9038 @ (not reached) 9039 9040.LOP_EXECUTE_INLINE_RANGE_table: 9041 .word gDvmInlineOpsTable 9042 9043 9044 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9045 .global dvmAsmSisterEnd 9046dvmAsmSisterEnd: 9047 9048/* File: armv5te/footer.S */ 9049 9050/* 9051 * =========================================================================== 9052 * Common subroutines and data 9053 * =========================================================================== 9054 */ 9055 9056 9057 9058 .text 9059 .align 2 9060 9061#if defined(WITH_JIT) 9062#if defined(WITH_SELF_VERIFICATION) 9063 .global dvmJitToInterpPunt 9064dvmJitToInterpPunt: 9065 mov r2,#kSVSPunt @ r2<- interpreter entry point 9066 b dvmJitSelfVerificationEnd @ doesn't return 9067 9068 .global dvmJitToInterpSingleStep 9069dvmJitToInterpSingleStep: 9070 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9071 b dvmJitSelfVerificationEnd @ doesn't return 9072 9073 .global dvmJitToTraceSelect 9074dvmJitToTraceSelect: 9075 ldr r0,[lr, #-1] @ pass our target PC 9076 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9077 b dvmJitSelfVerificationEnd @ doesn't return 9078 9079 .global dvmJitToBackwardBranch 9080dvmJitToBackwardBranch: 9081 ldr r0,[lr, #-1] @ pass our target PC 9082 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9083 b dvmJitSelfVerificationEnd @ doesn't return 9084 9085 .global dvmJitToInterpNormal 9086dvmJitToInterpNormal: 9087 ldr r0,[lr, #-1] @ pass our target PC 9088 mov r2,#kSVSNormal @ r2<- interpreter entry point 9089 b dvmJitSelfVerificationEnd @ doesn't return 9090 9091 .global dvmJitToInterpNoChain 9092dvmJitToInterpNoChain: 9093 mov r0,rPC @ pass our target PC 9094 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9095 b dvmJitSelfVerificationEnd @ doesn't return 9096#else 9097/* 9098 * Return from the translation cache to the interpreter when the compiler is 9099 * having issues translating/executing a Dalvik instruction. We have to skip 9100 * the code cache lookup otherwise it is possible to indefinitely bouce 9101 * between the interpreter and the code cache if the instruction that fails 9102 * to be compiled happens to be at a trace start. 9103 */ 9104 .global dvmJitToInterpPunt 9105dvmJitToInterpPunt: 9106 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9107 mov rPC, r0 9108#ifdef EXIT_STATS 9109 mov r0,lr 9110 bl dvmBumpPunt; 9111#endif 9112 EXPORT_PC() 9113 mov r0, #0 9114 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9115 adrl rIBASE, dvmAsmInstructionStart 9116 FETCH_INST() 9117 GET_INST_OPCODE(ip) 9118 GOTO_OPCODE(ip) 9119 9120/* 9121 * Return to the interpreter to handle a single instruction. 9122 * On entry: 9123 * r0 <= PC 9124 * r1 <= PC of resume instruction 9125 * lr <= resume point in translation 9126 */ 9127 .global dvmJitToInterpSingleStep 9128dvmJitToInterpSingleStep: 9129 str lr,[rGLUE,#offGlue_jitResume] 9130 str r1,[rGLUE,#offGlue_jitResumePC] 9131 mov r1,#kInterpEntryInstr 9132 @ enum is 4 byte in aapcs-EABI 9133 str r1, [rGLUE, #offGlue_entryPoint] 9134 mov rPC,r0 9135 EXPORT_PC() 9136 9137 adrl rIBASE, dvmAsmInstructionStart 9138 mov r2,#kJitSingleStep @ Ask for single step and then revert 9139 str r2,[rGLUE,#offGlue_jitState] 9140 mov r1,#1 @ set changeInterp to bail to debug interp 9141 b common_gotoBail 9142 9143 9144/* 9145 * Return from the translation cache and immediately request 9146 * a translation for the exit target. Commonly used following 9147 * invokes. 9148 */ 9149 .global dvmJitToTraceSelect 9150dvmJitToTraceSelect: 9151 ldr rPC,[lr, #-1] @ get our target PC 9152 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9153 add rINST,lr,#-5 @ save start of chain branch 9154 mov r0,rPC 9155 bl dvmJitGetCodeAddr @ Is there a translation? 9156 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9157 cmp r0,#0 9158 beq 2f 9159 mov r1,rINST 9160 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9161 mov r1, rPC @ arg1 of translation may need this 9162 mov lr, #0 @ in case target is HANDLER_INTERPRET 9163 cmp r0,#0 @ successful chain? 9164 bxne r0 @ continue native execution 9165 b toInterpreter @ didn't chain - resume with interpreter 9166 9167/* No translation, so request one if profiling isn't disabled*/ 91682: 9169 adrl rIBASE, dvmAsmInstructionStart 9170 GET_JIT_PROF_TABLE(r0) 9171 FETCH_INST() 9172 cmp r0, #0 9173 bne common_selectTrace 9174 GET_INST_OPCODE(ip) 9175 GOTO_OPCODE(ip) 9176 9177/* 9178 * Return from the translation cache to the interpreter. 9179 * The return was done with a BLX from thumb mode, and 9180 * the following 32-bit word contains the target rPC value. 9181 * Note that lr (r14) will have its low-order bit set to denote 9182 * its thumb-mode origin. 9183 * 9184 * We'll need to stash our lr origin away, recover the new 9185 * target and then check to see if there is a translation available 9186 * for our new target. If so, we do a translation chain and 9187 * go back to native execution. Otherwise, it's back to the 9188 * interpreter (after treating this entry as a potential 9189 * trace start). 9190 */ 9191 .global dvmJitToInterpNormal 9192dvmJitToInterpNormal: 9193 ldr rPC,[lr, #-1] @ get our target PC 9194 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9195 add rINST,lr,#-5 @ save start of chain branch 9196#ifdef EXIT_STATS 9197 bl dvmBumpNormal 9198#endif 9199 mov r0,rPC 9200 bl dvmJitGetCodeAddr @ Is there a translation? 9201 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9202 cmp r0,#0 9203 beq toInterpreter @ go if not, otherwise do chain 9204 mov r1,rINST 9205 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9206 mov r1, rPC @ arg1 of translation may need this 9207 mov lr, #0 @ in case target is HANDLER_INTERPRET 9208 cmp r0,#0 @ successful chain? 9209 bxne r0 @ continue native execution 9210 b toInterpreter @ didn't chain - resume with interpreter 9211 9212/* 9213 * Return from the translation cache to the interpreter to do method invocation. 9214 * Check if translation exists for the callee, but don't chain to it. 9215 */ 9216 .global dvmJitToInterpNoChain 9217dvmJitToInterpNoChain: 9218#ifdef EXIT_STATS 9219 bl dvmBumpNoChain 9220#endif 9221 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9222 mov r0,rPC 9223 bl dvmJitGetCodeAddr @ Is there a translation? 9224 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9225 mov r1, rPC @ arg1 of translation may need this 9226 mov lr, #0 @ in case target is HANDLER_INTERPRET 9227 cmp r0,#0 9228 bxne r0 @ continue native execution if so 9229#endif 9230 9231/* 9232 * No translation, restore interpreter regs and start interpreting. 9233 * rGLUE & rFP were preserved in the translated code, and rPC has 9234 * already been restored by the time we get here. We'll need to set 9235 * up rIBASE & rINST, and load the address of the JitTable into r0. 9236 */ 9237toInterpreter: 9238 EXPORT_PC() 9239 adrl rIBASE, dvmAsmInstructionStart 9240 FETCH_INST() 9241 GET_JIT_PROF_TABLE(r0) 9242 @ NOTE: intended fallthrough 9243/* 9244 * Common code to update potential trace start counter, and initiate 9245 * a trace-build if appropriate. On entry, rPC should point to the 9246 * next instruction to execute, and rINST should be already loaded with 9247 * the next opcode word, and r0 holds a pointer to the jit profile 9248 * table (pJitProfTable). 9249 */ 9250common_testUpdateProfile: 9251 cmp r0,#0 9252 GET_INST_OPCODE(ip) 9253 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9254 9255common_updateProfile: 9256 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9257 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9258 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9259 GET_INST_OPCODE(ip) 9260 subs r1,r1,#1 @ decrement counter 9261 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9262 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9263 9264/* 9265 * Here, we switch to the debug interpreter to request 9266 * trace selection. First, though, check to see if there 9267 * is already a native translation in place (and, if so, 9268 * jump to it now). 9269 */ 9270 GET_JIT_THRESHOLD(r1) 9271 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9272 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9273 EXPORT_PC() 9274 mov r0,rPC 9275 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9276 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9277 mov r1, rPC @ arg1 of translation may need this 9278 mov lr, #0 @ in case target is HANDLER_INTERPRET 9279 cmp r0,#0 9280#if !defined(WITH_SELF_VERIFICATION) 9281 bxne r0 @ jump to the translation 9282#else 9283 beq common_selectTrace 9284 /* 9285 * At this point, we have a target translation. However, if 9286 * that translation is actually the interpret-only pseudo-translation 9287 * we want to treat it the same as no translation. 9288 */ 9289 mov r10, r0 @ save target 9290 bl dvmCompilerGetInterpretTemplate 9291 cmp r0, r10 @ special case? 9292 bne dvmJitSelfVerificationStart @ set up self verification 9293 GET_INST_OPCODE(ip) 9294 GOTO_OPCODE(ip) 9295 /* no return */ 9296#endif 9297 9298common_selectTrace: 9299 mov r2,#kJitTSelectRequest @ ask for trace selection 9300 str r2,[rGLUE,#offGlue_jitState] 9301 mov r2,#kInterpEntryInstr @ normal entry reason 9302 str r2,[rGLUE,#offGlue_entryPoint] 9303 mov r1,#1 @ set changeInterp 9304 b common_gotoBail 9305 9306#if defined(WITH_SELF_VERIFICATION) 9307/* 9308 * Save PC and registers to shadow memory for self verification mode 9309 * before jumping to native translation. 9310 * On entry, r10 contains the address of the target translation. 9311 */ 9312dvmJitSelfVerificationStart: 9313 mov r0,rPC @ r0<- program counter 9314 mov r1,rFP @ r1<- frame pointer 9315 mov r2,rGLUE @ r2<- InterpState pointer 9316 mov r3,r10 @ r3<- target translation 9317 bl dvmSelfVerificationSaveState @ save registers to shadow space 9318 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9319 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9320 bx r10 @ jump to the translation 9321 9322/* 9323 * Restore PC, registers, and interpState to original values 9324 * before jumping back to the interpreter. 9325 */ 9326dvmJitSelfVerificationEnd: 9327 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9328 mov r1, #0 9329 str r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9330 mov r1,rFP @ pass ending fp 9331 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9332 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9333 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9334 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9335 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9336 cmp r1,#0 @ check for punt condition 9337 beq 1f 9338 mov r2,#kJitSelfVerification @ ask for self verification 9339 str r2,[rGLUE,#offGlue_jitState] 9340 mov r2,#kInterpEntryInstr @ normal entry reason 9341 str r2,[rGLUE,#offGlue_entryPoint] 9342 mov r1,#1 @ set changeInterp 9343 b common_gotoBail 9344 93451: @ exit to interpreter without check 9346 EXPORT_PC() 9347 adrl rIBASE, dvmAsmInstructionStart 9348 FETCH_INST() 9349 GET_INST_OPCODE(ip) 9350 GOTO_OPCODE(ip) 9351#endif 9352 9353#endif 9354 9355/* 9356 * Common code when a backward branch is taken. 9357 * 9358 * On entry: 9359 * r9 is PC adjustment *in bytes* 9360 */ 9361common_backwardBranch: 9362 mov r0, #kInterpEntryInstr 9363 bl common_periodicChecks 9364#if defined(WITH_JIT) 9365 GET_JIT_PROF_TABLE(r0) 9366 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9367 cmp r0,#0 9368 bne common_updateProfile 9369 GET_INST_OPCODE(ip) 9370 GOTO_OPCODE(ip) 9371#else 9372 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9373 GET_INST_OPCODE(ip) @ extract opcode from rINST 9374 GOTO_OPCODE(ip) @ jump to next instruction 9375#endif 9376 9377 9378/* 9379 * Need to see if the thread needs to be suspended or debugger/profiler 9380 * activity has begun. 9381 * 9382 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9383 * have to do the second ldr. 9384 * 9385 * TODO: reduce this so we're just checking a single location. 9386 * 9387 * On entry: 9388 * r0 is reentry type, e.g. kInterpEntryInstr 9389 * r9 is trampoline PC adjustment *in bytes* 9390 */ 9391common_periodicChecks: 9392 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9393 9394 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9395 str r0, [rGLUE, #offGlue_entryPoint] 9396 9397#if defined(WITH_DEBUGGER) 9398 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9399#endif 9400#if defined(WITH_PROFILER) 9401 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9402#endif 9403 9404 ldr r3, [r3] @ r3<- suspendCount (int) 9405 9406#if defined(WITH_DEBUGGER) 9407 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9408#endif 9409#if defined (WITH_PROFILER) 9410 ldr r2, [r2] @ r2<- activeProfilers (int) 9411#endif 9412 9413 cmp r3, #0 @ suspend pending? 9414 bne 2f @ yes, do full suspension check 9415 9416#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9417# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9418 orrs r1, r1, r2 @ r1<- r1 | r2 9419 cmp r1, #0 @ debugger attached or profiler started? 9420# elif defined(WITH_DEBUGGER) 9421 cmp r1, #0 @ debugger attached? 9422# elif defined(WITH_PROFILER) 9423 cmp r2, #0 @ profiler started? 9424# endif 9425 bne 3f @ debugger/profiler, switch interp 9426#endif 9427 9428 bx lr @ nothing to do, return 9429 94302: @ check suspend 9431#if defined(WITH_JIT) 9432 /* 9433 * Refresh the Jit's cached copy of profile table pointer. This pointer 9434 * doubles as the Jit's on/off switch. 9435 */ 9436 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable 9437 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9438 ldr r3, [r3] @ r10 <- pJitProfTable 9439 EXPORT_PC() @ need for precise GC 9440 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9441#else 9442 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9443 EXPORT_PC() @ need for precise GC 9444#endif 9445 b dvmCheckSuspendPending @ suspend if necessary, then return 9446 94473: @ debugger/profiler enabled, bail out 9448 add rPC, rPC, r9 @ update rPC 9449 mov r1, #1 @ "want switch" = true 9450 b common_gotoBail 9451 9452 9453/* 9454 * The equivalent of "goto bail", this calls through the "bail handler". 9455 * 9456 * State registers will be saved to the "glue" area before bailing. 9457 * 9458 * On entry: 9459 * r1 is "bool changeInterp", indicating if we want to switch to the 9460 * other interpreter or just bail all the way out 9461 */ 9462common_gotoBail: 9463 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9464 mov r0, rGLUE @ r0<- glue ptr 9465 b dvmMterpStdBail @ call(glue, changeInterp) 9466 9467 @add r1, r1, #1 @ using (boolean+1) 9468 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9469 @bl _longjmp @ does not return 9470 @bl common_abort 9471 9472 9473/* 9474 * Common code for method invocation with range. 9475 * 9476 * On entry: 9477 * r0 is "Method* methodToCall", the method we're trying to call 9478 */ 9479common_invokeMethodRange: 9480.LinvokeNewRange: 9481 @ prepare to copy args to "outs" area of current frame 9482 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9483 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9484 beq .LinvokeArgsDone @ if no args, skip the rest 9485 FETCH(r1, 2) @ r1<- CCCC 9486 9487 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9488 @ (very few methods have > 10 args; could unroll for common cases) 9489 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9490 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9491 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94921: ldr r1, [r3], #4 @ val = *fp++ 9493 subs r2, r2, #1 @ count-- 9494 str r1, [r10], #4 @ *outs++ = val 9495 bne 1b @ ...while count != 0 9496 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9497 b .LinvokeArgsDone 9498 9499/* 9500 * Common code for method invocation without range. 9501 * 9502 * On entry: 9503 * r0 is "Method* methodToCall", the method we're trying to call 9504 */ 9505common_invokeMethodNoRange: 9506.LinvokeNewNoRange: 9507 @ prepare to copy args to "outs" area of current frame 9508 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9509 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9510 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9511 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9512 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9513 beq .LinvokeArgsDone 9514 9515 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9516.LinvokeNonRange: 9517 rsb r2, r2, #5 @ r2<- 5-r2 9518 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9519 bl common_abort @ (skipped due to ARM prefetch) 95205: and ip, rINST, #0x0f00 @ isolate A 9521 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9522 mov r0, r0 @ nop 9523 str r2, [r10, #-4]! @ *--outs = vA 95244: and ip, r1, #0xf000 @ isolate G 9525 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9526 mov r0, r0 @ nop 9527 str r2, [r10, #-4]! @ *--outs = vG 95283: and ip, r1, #0x0f00 @ isolate F 9529 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9530 mov r0, r0 @ nop 9531 str r2, [r10, #-4]! @ *--outs = vF 95322: and ip, r1, #0x00f0 @ isolate E 9533 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9534 mov r0, r0 @ nop 9535 str r2, [r10, #-4]! @ *--outs = vE 95361: and ip, r1, #0x000f @ isolate D 9537 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9538 mov r0, r0 @ nop 9539 str r2, [r10, #-4]! @ *--outs = vD 95400: @ fall through to .LinvokeArgsDone 9541 9542.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9543 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9544 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9545 @ find space for the new stack frame, check for overflow 9546 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9547 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9548 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9549@ bl common_dumpRegs 9550 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9551 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9552 cmp r3, r9 @ bottom < interpStackEnd? 9553 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9554 blt .LstackOverflow @ yes, this frame will overflow stack 9555 9556 @ set up newSaveArea 9557#ifdef EASY_GDB 9558 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9559 str ip, [r10, #offStackSaveArea_prevSave] 9560#endif 9561 str rFP, [r10, #offStackSaveArea_prevFrame] 9562 str rPC, [r10, #offStackSaveArea_savedPc] 9563#if defined(WITH_JIT) 9564 mov r9, #0 9565 str r9, [r10, #offStackSaveArea_returnAddr] 9566#endif 9567 str r0, [r10, #offStackSaveArea_method] 9568 tst r3, #ACC_NATIVE 9569 bne .LinvokeNative 9570 9571 /* 9572 stmfd sp!, {r0-r3} 9573 bl common_printNewline 9574 mov r0, rFP 9575 mov r1, #0 9576 bl dvmDumpFp 9577 ldmfd sp!, {r0-r3} 9578 stmfd sp!, {r0-r3} 9579 mov r0, r1 9580 mov r1, r10 9581 bl dvmDumpFp 9582 bl common_printNewline 9583 ldmfd sp!, {r0-r3} 9584 */ 9585 9586 ldrh r9, [r2] @ r9 <- load INST from new PC 9587 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9588 mov rPC, r2 @ publish new rPC 9589 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9590 9591 @ Update "glue" values for the new method 9592 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9593 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9594 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9595#if defined(WITH_JIT) 9596 GET_JIT_PROF_TABLE(r0) 9597 mov rFP, r1 @ fp = newFp 9598 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9599 mov rINST, r9 @ publish new rINST 9600 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9601 cmp r0,#0 9602 bne common_updateProfile 9603 GOTO_OPCODE(ip) @ jump to next instruction 9604#else 9605 mov rFP, r1 @ fp = newFp 9606 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9607 mov rINST, r9 @ publish new rINST 9608 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9609 GOTO_OPCODE(ip) @ jump to next instruction 9610#endif 9611 9612.LinvokeNative: 9613 @ Prep for the native call 9614 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9615 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9616 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9617 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9618 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9619 mov r9, r3 @ r9<- glue->self (preserve) 9620 9621 mov r2, r0 @ r2<- methodToCall 9622 mov r0, r1 @ r0<- newFp (points to args) 9623 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9624 9625#ifdef ASSIST_DEBUGGER 9626 /* insert fake function header to help gdb find the stack frame */ 9627 b .Lskip 9628 .type dalvik_mterp, %function 9629dalvik_mterp: 9630 .fnstart 9631 MTERP_ENTRY1 9632 MTERP_ENTRY2 9633.Lskip: 9634#endif 9635 9636 @mov lr, pc @ set return addr 9637 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9638 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9639 9640#if defined(WITH_JIT) 9641 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9642#endif 9643 9644 @ native return; r9=self, r10=newSaveArea 9645 @ equivalent to dvmPopJniLocals 9646 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9647 ldr r1, [r9, #offThread_exception] @ check for exception 9648#if defined(WITH_JIT) 9649 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9650#endif 9651 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9652 cmp r1, #0 @ null? 9653 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9654#if defined(WITH_JIT) 9655 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9656#endif 9657 bne common_exceptionThrown @ no, handle exception 9658 9659 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9660 GET_INST_OPCODE(ip) @ extract opcode from rINST 9661 GOTO_OPCODE(ip) @ jump to next instruction 9662 9663.LstackOverflow: @ r0=methodToCall 9664 mov r1, r0 @ r1<- methodToCall 9665 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9666 bl dvmHandleStackOverflow 9667 b common_exceptionThrown 9668#ifdef ASSIST_DEBUGGER 9669 .fnend 9670#endif 9671 9672 9673 /* 9674 * Common code for method invocation, calling through "glue code". 9675 * 9676 * TODO: now that we have range and non-range invoke handlers, this 9677 * needs to be split into two. Maybe just create entry points 9678 * that set r9 and jump here? 9679 * 9680 * On entry: 9681 * r0 is "Method* methodToCall", the method we're trying to call 9682 * r9 is "bool methodCallRange", indicating if this is a /range variant 9683 */ 9684 .if 0 9685.LinvokeOld: 9686 sub sp, sp, #8 @ space for args + pad 9687 FETCH(ip, 2) @ ip<- FEDC or CCCC 9688 mov r2, r0 @ A2<- methodToCall 9689 mov r0, rGLUE @ A0<- glue 9690 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9691 mov r1, r9 @ A1<- methodCallRange 9692 mov r3, rINST, lsr #8 @ A3<- AA 9693 str ip, [sp, #0] @ A4<- ip 9694 bl dvmMterp_invokeMethod @ call the C invokeMethod 9695 add sp, sp, #8 @ remove arg area 9696 b common_resumeAfterGlueCall @ continue to next instruction 9697 .endif 9698 9699 9700 9701/* 9702 * Common code for handling a return instruction. 9703 * 9704 * This does not return. 9705 */ 9706common_returnFromMethod: 9707.LreturnNew: 9708 mov r0, #kInterpEntryReturn 9709 mov r9, #0 9710 bl common_periodicChecks 9711 9712 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9713 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9714 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9715 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9716 @ r2<- method we're returning to 9717 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9718 cmp r2, #0 @ is this a break frame? 9719 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9720 mov r1, #0 @ "want switch" = false 9721 beq common_gotoBail @ break frame, bail out completely 9722 9723 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9724 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9725 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9726 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9727#if defined(WITH_JIT) 9728 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 9729 GET_JIT_PROF_TABLE(r0) 9730 mov rPC, r9 @ publish new rPC 9731 str r1, [rGLUE, #offGlue_methodClassDex] 9732 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 9733 cmp r10, #0 @ caller is compiled code 9734 blxne r10 9735 GET_INST_OPCODE(ip) @ extract opcode from rINST 9736 cmp r0,#0 9737 bne common_updateProfile 9738 GOTO_OPCODE(ip) @ jump to next instruction 9739#else 9740 GET_INST_OPCODE(ip) @ extract opcode from rINST 9741 mov rPC, r9 @ publish new rPC 9742 str r1, [rGLUE, #offGlue_methodClassDex] 9743 GOTO_OPCODE(ip) @ jump to next instruction 9744#endif 9745 9746 /* 9747 * Return handling, calls through "glue code". 9748 */ 9749 .if 0 9750.LreturnOld: 9751 SAVE_PC_FP_TO_GLUE() @ export state 9752 mov r0, rGLUE @ arg to function 9753 bl dvmMterp_returnFromMethod 9754 b common_resumeAfterGlueCall 9755 .endif 9756 9757 9758/* 9759 * Somebody has thrown an exception. Handle it. 9760 * 9761 * If the exception processing code returns to us (instead of falling 9762 * out of the interpreter), continue with whatever the next instruction 9763 * now happens to be. 9764 * 9765 * This does not return. 9766 */ 9767 .global dvmMterpCommonExceptionThrown 9768dvmMterpCommonExceptionThrown: 9769common_exceptionThrown: 9770.LexceptionNew: 9771 mov r0, #kInterpEntryThrow 9772 mov r9, #0 9773 bl common_periodicChecks 9774 9775#if defined(WITH_JIT) 9776 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9777 str r2,[rGLUE,#offGlue_jitState] 9778#endif 9779 9780 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9781 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9782 mov r1, r10 @ r1<- self 9783 mov r0, r9 @ r0<- exception 9784 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9785 mov r3, #0 @ r3<- NULL 9786 str r3, [r10, #offThread_exception] @ self->exception = NULL 9787 9788 /* set up args and a local for "&fp" */ 9789 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9790 str rFP, [sp, #-4]! @ *--sp = fp 9791 mov ip, sp @ ip<- &fp 9792 mov r3, #0 @ r3<- false 9793 str ip, [sp, #-4]! @ *--sp = &fp 9794 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9795 mov r0, r10 @ r0<- self 9796 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9797 mov r2, r9 @ r2<- exception 9798 sub r1, rPC, r1 @ r1<- pc - method->insns 9799 mov r1, r1, asr #1 @ r1<- offset in code units 9800 9801 /* call, r0 gets catchRelPc (a code-unit offset) */ 9802 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9803 9804 /* fix earlier stack overflow if necessary; may trash rFP */ 9805 ldrb r1, [r10, #offThread_stackOverflowed] 9806 cmp r1, #0 @ did we overflow earlier? 9807 beq 1f @ no, skip ahead 9808 mov rFP, r0 @ save relPc result in rFP 9809 mov r0, r10 @ r0<- self 9810 mov r1, r9 @ r1<- exception 9811 bl dvmCleanupStackOverflow @ call(self) 9812 mov r0, rFP @ restore result 98131: 9814 9815 /* update frame pointer and check result from dvmFindCatchBlock */ 9816 ldr rFP, [sp, #4] @ retrieve the updated rFP 9817 cmp r0, #0 @ is catchRelPc < 0? 9818 add sp, sp, #8 @ restore stack 9819 bmi .LnotCaughtLocally 9820 9821 /* adjust locals to match self->curFrame and updated PC */ 9822 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9823 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9824 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9825 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9826 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9827 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9828 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9829 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9830 9831 /* release the tracked alloc on the exception */ 9832 mov r0, r9 @ r0<- exception 9833 mov r1, r10 @ r1<- self 9834 bl dvmReleaseTrackedAlloc @ release the exception 9835 9836 /* restore the exception if the handler wants it */ 9837 FETCH_INST() @ load rINST from rPC 9838 GET_INST_OPCODE(ip) @ extract opcode from rINST 9839 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9840 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9841 GOTO_OPCODE(ip) @ jump to next instruction 9842 9843.LnotCaughtLocally: @ r9=exception, r10=self 9844 /* fix stack overflow if necessary */ 9845 ldrb r1, [r10, #offThread_stackOverflowed] 9846 cmp r1, #0 @ did we overflow earlier? 9847 movne r0, r10 @ if yes: r0<- self 9848 movne r1, r9 @ if yes: r1<- exception 9849 blne dvmCleanupStackOverflow @ if yes: call(self) 9850 9851 @ may want to show "not caught locally" debug messages here 9852#if DVM_SHOW_EXCEPTION >= 2 9853 /* call __android_log_print(prio, tag, format, ...) */ 9854 /* "Exception %s from %s:%d not caught locally" */ 9855 @ dvmLineNumFromPC(method, pc - method->insns) 9856 ldr r0, [rGLUE, #offGlue_method] 9857 ldr r1, [r0, #offMethod_insns] 9858 sub r1, rPC, r1 9859 asr r1, r1, #1 9860 bl dvmLineNumFromPC 9861 str r0, [sp, #-4]! 9862 @ dvmGetMethodSourceFile(method) 9863 ldr r0, [rGLUE, #offGlue_method] 9864 bl dvmGetMethodSourceFile 9865 str r0, [sp, #-4]! 9866 @ exception->clazz->descriptor 9867 ldr r3, [r9, #offObject_clazz] 9868 ldr r3, [r3, #offClassObject_descriptor] 9869 @ 9870 ldr r2, strExceptionNotCaughtLocally 9871 ldr r1, strLogTag 9872 mov r0, #3 @ LOG_DEBUG 9873 bl __android_log_print 9874#endif 9875 str r9, [r10, #offThread_exception] @ restore exception 9876 mov r0, r9 @ r0<- exception 9877 mov r1, r10 @ r1<- self 9878 bl dvmReleaseTrackedAlloc @ release the exception 9879 mov r1, #0 @ "want switch" = false 9880 b common_gotoBail @ bail out 9881 9882 9883 /* 9884 * Exception handling, calls through "glue code". 9885 */ 9886 .if 0 9887.LexceptionOld: 9888 SAVE_PC_FP_TO_GLUE() @ export state 9889 mov r0, rGLUE @ arg to function 9890 bl dvmMterp_exceptionThrown 9891 b common_resumeAfterGlueCall 9892 .endif 9893 9894 9895/* 9896 * After returning from a "glued" function, pull out the updated 9897 * values and start executing at the next instruction. 9898 */ 9899common_resumeAfterGlueCall: 9900 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9901 FETCH_INST() @ load rINST from rPC 9902 GET_INST_OPCODE(ip) @ extract opcode from rINST 9903 GOTO_OPCODE(ip) @ jump to next instruction 9904 9905/* 9906 * Invalid array index. 9907 */ 9908common_errArrayIndex: 9909 EXPORT_PC() 9910 ldr r0, strArrayIndexException 9911 mov r1, #0 9912 bl dvmThrowException 9913 b common_exceptionThrown 9914 9915/* 9916 * Invalid array value. 9917 */ 9918common_errArrayStore: 9919 EXPORT_PC() 9920 ldr r0, strArrayStoreException 9921 mov r1, #0 9922 bl dvmThrowException 9923 b common_exceptionThrown 9924 9925/* 9926 * Integer divide or mod by zero. 9927 */ 9928common_errDivideByZero: 9929 EXPORT_PC() 9930 ldr r0, strArithmeticException 9931 ldr r1, strDivideByZero 9932 bl dvmThrowException 9933 b common_exceptionThrown 9934 9935/* 9936 * Attempt to allocate an array with a negative size. 9937 */ 9938common_errNegativeArraySize: 9939 EXPORT_PC() 9940 ldr r0, strNegativeArraySizeException 9941 mov r1, #0 9942 bl dvmThrowException 9943 b common_exceptionThrown 9944 9945/* 9946 * Invocation of a non-existent method. 9947 */ 9948common_errNoSuchMethod: 9949 EXPORT_PC() 9950 ldr r0, strNoSuchMethodError 9951 mov r1, #0 9952 bl dvmThrowException 9953 b common_exceptionThrown 9954 9955/* 9956 * We encountered a null object when we weren't expecting one. We 9957 * export the PC, throw a NullPointerException, and goto the exception 9958 * processing code. 9959 */ 9960common_errNullObject: 9961 EXPORT_PC() 9962 ldr r0, strNullPointerException 9963 mov r1, #0 9964 bl dvmThrowException 9965 b common_exceptionThrown 9966 9967/* 9968 * For debugging, cause an immediate fault. The source address will 9969 * be in lr (use a bl instruction to jump here). 9970 */ 9971common_abort: 9972 ldr pc, .LdeadFood 9973.LdeadFood: 9974 .word 0xdeadf00d 9975 9976/* 9977 * Spit out a "we were here", preserving all registers. (The attempt 9978 * to save ip won't work, but we need to save an even number of 9979 * registers for EABI 64-bit stack alignment.) 9980 */ 9981 .macro SQUEAK num 9982common_squeak\num: 9983 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9984 ldr r0, strSqueak 9985 mov r1, #\num 9986 bl printf 9987 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9988 bx lr 9989 .endm 9990 9991 SQUEAK 0 9992 SQUEAK 1 9993 SQUEAK 2 9994 SQUEAK 3 9995 SQUEAK 4 9996 SQUEAK 5 9997 9998/* 9999 * Spit out the number in r0, preserving registers. 10000 */ 10001common_printNum: 10002 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10003 mov r1, r0 10004 ldr r0, strSqueak 10005 bl printf 10006 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10007 bx lr 10008 10009/* 10010 * Print a newline, preserving registers. 10011 */ 10012common_printNewline: 10013 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10014 ldr r0, strNewline 10015 bl printf 10016 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10017 bx lr 10018 10019 /* 10020 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10021 */ 10022common_printHex: 10023 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10024 mov r1, r0 10025 ldr r0, strPrintHex 10026 bl printf 10027 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10028 bx lr 10029 10030/* 10031 * Print the 64-bit quantity in r0-r1, preserving registers. 10032 */ 10033common_printLong: 10034 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10035 mov r3, r1 10036 mov r2, r0 10037 ldr r0, strPrintLong 10038 bl printf 10039 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10040 bx lr 10041 10042/* 10043 * Print full method info. Pass the Method* in r0. Preserves regs. 10044 */ 10045common_printMethod: 10046 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10047 bl dvmMterpPrintMethod 10048 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10049 bx lr 10050 10051/* 10052 * Call a C helper function that dumps regs and possibly some 10053 * additional info. Requires the C function to be compiled in. 10054 */ 10055 .if 0 10056common_dumpRegs: 10057 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10058 bl dvmMterpDumpArmRegs 10059 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10060 bx lr 10061 .endif 10062 10063#if 0 10064/* 10065 * Experiment on VFP mode. 10066 * 10067 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10068 * 10069 * Updates the bits specified by "mask", setting them to the values in "val". 10070 */ 10071setFPSCR: 10072 and r0, r0, r1 @ make sure no stray bits are set 10073 fmrx r2, fpscr @ get VFP reg 10074 mvn r1, r1 @ bit-invert mask 10075 and r2, r2, r1 @ clear masked bits 10076 orr r2, r2, r0 @ set specified bits 10077 fmxr fpscr, r2 @ set VFP reg 10078 mov r0, r2 @ return new value 10079 bx lr 10080 10081 .align 2 10082 .global dvmConfigureFP 10083 .type dvmConfigureFP, %function 10084dvmConfigureFP: 10085 stmfd sp!, {ip, lr} 10086 /* 0x03000000 sets DN/FZ */ 10087 /* 0x00009f00 clears the six exception enable flags */ 10088 bl common_squeak0 10089 mov r0, #0x03000000 @ r0<- 0x03000000 10090 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10091 bl setFPSCR 10092 ldmfd sp!, {ip, pc} 10093#endif 10094 10095 10096/* 10097 * String references, must be close to the code that uses them. 10098 */ 10099 .align 2 10100strArithmeticException: 10101 .word .LstrArithmeticException 10102strArrayIndexException: 10103 .word .LstrArrayIndexException 10104strArrayStoreException: 10105 .word .LstrArrayStoreException 10106strDivideByZero: 10107 .word .LstrDivideByZero 10108strNegativeArraySizeException: 10109 .word .LstrNegativeArraySizeException 10110strNoSuchMethodError: 10111 .word .LstrNoSuchMethodError 10112strNullPointerException: 10113 .word .LstrNullPointerException 10114 10115strLogTag: 10116 .word .LstrLogTag 10117strExceptionNotCaughtLocally: 10118 .word .LstrExceptionNotCaughtLocally 10119 10120strNewline: 10121 .word .LstrNewline 10122strSqueak: 10123 .word .LstrSqueak 10124strPrintHex: 10125 .word .LstrPrintHex 10126strPrintLong: 10127 .word .LstrPrintLong 10128 10129/* 10130 * Zero-terminated ASCII string data. 10131 * 10132 * On ARM we have two choices: do like gcc does, and LDR from a .word 10133 * with the address, or use an ADR pseudo-op to get the address 10134 * directly. ADR saves 4 bytes and an indirection, but it's using a 10135 * PC-relative addressing mode and hence has a limited range, which 10136 * makes it not work well with mergeable string sections. 10137 */ 10138 .section .rodata.str1.4,"aMS",%progbits,1 10139 10140.LstrBadEntryPoint: 10141 .asciz "Bad entry point %d\n" 10142.LstrArithmeticException: 10143 .asciz "Ljava/lang/ArithmeticException;" 10144.LstrArrayIndexException: 10145 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10146.LstrArrayStoreException: 10147 .asciz "Ljava/lang/ArrayStoreException;" 10148.LstrClassCastException: 10149 .asciz "Ljava/lang/ClassCastException;" 10150.LstrDivideByZero: 10151 .asciz "divide by zero" 10152.LstrFilledNewArrayNotImpl: 10153 .asciz "filled-new-array only implemented for objects and 'int'" 10154.LstrInternalError: 10155 .asciz "Ljava/lang/InternalError;" 10156.LstrInstantiationError: 10157 .asciz "Ljava/lang/InstantiationError;" 10158.LstrNegativeArraySizeException: 10159 .asciz "Ljava/lang/NegativeArraySizeException;" 10160.LstrNoSuchMethodError: 10161 .asciz "Ljava/lang/NoSuchMethodError;" 10162.LstrNullPointerException: 10163 .asciz "Ljava/lang/NullPointerException;" 10164 10165.LstrLogTag: 10166 .asciz "mterp" 10167.LstrExceptionNotCaughtLocally: 10168 .asciz "Exception %s from %s:%d not caught locally\n" 10169 10170.LstrNewline: 10171 .asciz "\n" 10172.LstrSqueak: 10173 .asciz "<%d>" 10174.LstrPrintHex: 10175 .asciz "<0x%x>" 10176.LstrPrintLong: 10177 .asciz "<%lld>" 10178 10179 10180