InterpAsm-armv5te-vfp.S revision 6bbdd6b005ec5cb567ec9576190a7cd784248c5c
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 1f @ 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 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 916 beq common_exceptionThrown @ yes, exception is pending 917 GET_INST_OPCODE(ip) @ extract opcode from rINST 918 GOTO_OPCODE(ip) @ jump to next instruction 9191: 920 FETCH_ADVANCE_INST(1) @ advance before throw 921 b common_errNullObject 922 923 924/* ------------------------------ */ 925 .balign 64 926.L_OP_CHECK_CAST: /* 0x1f */ 927/* File: armv5te/OP_CHECK_CAST.S */ 928 /* 929 * Check to see if a cast from one class to another is allowed. 930 */ 931 /* check-cast vAA, class@BBBB */ 932 mov r3, rINST, lsr #8 @ r3<- AA 933 FETCH(r2, 1) @ r2<- BBBB 934 GET_VREG(r9, r3) @ r9<- object 935 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 936 cmp r9, #0 @ is object null? 937 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 938 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 939 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 940 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 941 cmp r1, #0 @ have we resolved this before? 942 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 943.LOP_CHECK_CAST_resolved: 944 cmp r0, r1 @ same class (trivial success)? 945 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 946.LOP_CHECK_CAST_okay: 947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 948 GET_INST_OPCODE(ip) @ extract opcode from rINST 949 GOTO_OPCODE(ip) @ jump to next instruction 950 951/* ------------------------------ */ 952 .balign 64 953.L_OP_INSTANCE_OF: /* 0x20 */ 954/* File: armv5te/OP_INSTANCE_OF.S */ 955 /* 956 * Check to see if an object reference is an instance of a class. 957 * 958 * Most common situation is a non-null object, being compared against 959 * an already-resolved class. 960 */ 961 /* instance-of vA, vB, class@CCCC */ 962 mov r3, rINST, lsr #12 @ r3<- B 963 mov r9, rINST, lsr #8 @ r9<- A+ 964 GET_VREG(r0, r3) @ r0<- vB (object) 965 and r9, r9, #15 @ r9<- A 966 cmp r0, #0 @ is object null? 967 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 968 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 969 FETCH(r3, 1) @ r3<- CCCC 970 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 971 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 972 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 973 cmp r1, #0 @ have we resolved this before? 974 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 975.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 976 cmp r0, r1 @ same class (trivial success)? 977 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 978 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 979 980/* ------------------------------ */ 981 .balign 64 982.L_OP_ARRAY_LENGTH: /* 0x21 */ 983/* File: armv5te/OP_ARRAY_LENGTH.S */ 984 /* 985 * Return the length of an array. 986 */ 987 mov r1, rINST, lsr #12 @ r1<- B 988 mov r2, rINST, lsr #8 @ r2<- A+ 989 GET_VREG(r0, r1) @ r0<- vB (object ref) 990 and r2, r2, #15 @ r2<- A 991 cmp r0, #0 @ is object null? 992 beq common_errNullObject @ yup, fail 993 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 994 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 995 GET_INST_OPCODE(ip) @ extract opcode from rINST 996 SET_VREG(r3, r2) @ vB<- length 997 GOTO_OPCODE(ip) @ jump to next instruction 998 999 1000/* ------------------------------ */ 1001 .balign 64 1002.L_OP_NEW_INSTANCE: /* 0x22 */ 1003/* File: armv5te/OP_NEW_INSTANCE.S */ 1004 /* 1005 * Create a new instance of a class. 1006 */ 1007 /* new-instance vAA, class@BBBB */ 1008 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1009 FETCH(r1, 1) @ r1<- BBBB 1010 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1011 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1012 EXPORT_PC() @ req'd for init, resolve, alloc 1013 cmp r0, #0 @ already resolved? 1014 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1015.LOP_NEW_INSTANCE_resolved: @ r0=class 1016 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1017 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1018 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1019.LOP_NEW_INSTANCE_initialized: @ r0=class 1020 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1021 bl dvmAllocObject @ r0<- new object 1022 b .LOP_NEW_INSTANCE_finish @ continue 1023 1024/* ------------------------------ */ 1025 .balign 64 1026.L_OP_NEW_ARRAY: /* 0x23 */ 1027/* File: armv5te/OP_NEW_ARRAY.S */ 1028 /* 1029 * Allocate an array of objects, specified with the array class 1030 * and a count. 1031 * 1032 * The verifier guarantees that this is an array class, so we don't 1033 * check for it here. 1034 */ 1035 /* new-array vA, vB, class@CCCC */ 1036 mov r0, rINST, lsr #12 @ r0<- B 1037 FETCH(r2, 1) @ r2<- CCCC 1038 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1039 GET_VREG(r1, r0) @ r1<- vB (array length) 1040 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1041 cmp r1, #0 @ check length 1042 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1043 bmi common_errNegativeArraySize @ negative length, bail 1044 cmp r0, #0 @ already resolved? 1045 EXPORT_PC() @ req'd for resolve, alloc 1046 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1047 b .LOP_NEW_ARRAY_resolve @ do resolve now 1048 1049/* ------------------------------ */ 1050 .balign 64 1051.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1052/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1053 /* 1054 * Create a new array with elements filled from registers. 1055 * 1056 * for: filled-new-array, filled-new-array/range 1057 */ 1058 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1059 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1060 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1061 FETCH(r1, 1) @ r1<- BBBB 1062 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1063 EXPORT_PC() @ need for resolve and alloc 1064 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1065 mov r10, rINST, lsr #8 @ r10<- AA or BA 1066 cmp r0, #0 @ already resolved? 1067 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10688: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1069 mov r2, #0 @ r2<- false 1070 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1071 bl dvmResolveClass @ r0<- call(clazz, ref) 1072 cmp r0, #0 @ got null? 1073 beq common_exceptionThrown @ yes, handle exception 1074 b .LOP_FILLED_NEW_ARRAY_continue 1075 1076/* ------------------------------ */ 1077 .balign 64 1078.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1079/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1080/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1081 /* 1082 * Create a new array with elements filled from registers. 1083 * 1084 * for: filled-new-array, filled-new-array/range 1085 */ 1086 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1087 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1088 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1089 FETCH(r1, 1) @ r1<- BBBB 1090 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1091 EXPORT_PC() @ need for resolve and alloc 1092 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1093 mov r10, rINST, lsr #8 @ r10<- AA or BA 1094 cmp r0, #0 @ already resolved? 1095 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10968: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1097 mov r2, #0 @ r2<- false 1098 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1099 bl dvmResolveClass @ r0<- call(clazz, ref) 1100 cmp r0, #0 @ got null? 1101 beq common_exceptionThrown @ yes, handle exception 1102 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1103 1104 1105/* ------------------------------ */ 1106 .balign 64 1107.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1108/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1109 /* fill-array-data vAA, +BBBBBBBB */ 1110 FETCH(r0, 1) @ r0<- bbbb (lo) 1111 FETCH(r1, 2) @ r1<- BBBB (hi) 1112 mov r3, rINST, lsr #8 @ r3<- AA 1113 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1114 GET_VREG(r0, r3) @ r0<- vAA (array object) 1115 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1116 EXPORT_PC(); 1117 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1118 cmp r0, #0 @ 0 means an exception is thrown 1119 beq common_exceptionThrown @ has exception 1120 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1121 GET_INST_OPCODE(ip) @ extract opcode from rINST 1122 GOTO_OPCODE(ip) @ jump to next instruction 1123 1124/* ------------------------------ */ 1125 .balign 64 1126.L_OP_THROW: /* 0x27 */ 1127/* File: armv5te/OP_THROW.S */ 1128 /* 1129 * Throw an exception object in the current thread. 1130 */ 1131 /* throw vAA */ 1132 mov r2, rINST, lsr #8 @ r2<- AA 1133 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1134 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1135 cmp r1, #0 @ null object? 1136 beq common_errNullObject @ yes, throw an NPE instead 1137 @ bypass dvmSetException, just store it 1138 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1139 b common_exceptionThrown 1140 1141 1142/* ------------------------------ */ 1143 .balign 64 1144.L_OP_GOTO: /* 0x28 */ 1145/* File: armv5te/OP_GOTO.S */ 1146 /* 1147 * Unconditional branch, 8-bit offset. 1148 * 1149 * The branch distance is a signed code-unit offset, which we need to 1150 * double to get a byte offset. 1151 */ 1152 /* goto +AA */ 1153 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1154 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1155 mov r9, r9, lsl #1 @ r9<- byte offset 1156 bmi common_backwardBranch @ backward branch, do periodic checks 1157#if defined(WITH_JIT) 1158 GET_JIT_PROF_TABLE(r0) 1159 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1160 cmp r0,#0 1161 bne common_updateProfile 1162 GET_INST_OPCODE(ip) @ extract opcode from rINST 1163 GOTO_OPCODE(ip) @ jump to next instruction 1164#else 1165 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1166 GET_INST_OPCODE(ip) @ extract opcode from rINST 1167 GOTO_OPCODE(ip) @ jump to next instruction 1168#endif 1169 1170/* ------------------------------ */ 1171 .balign 64 1172.L_OP_GOTO_16: /* 0x29 */ 1173/* File: armv5te/OP_GOTO_16.S */ 1174 /* 1175 * Unconditional branch, 16-bit offset. 1176 * 1177 * The branch distance is a signed code-unit offset, which we need to 1178 * double to get a byte offset. 1179 */ 1180 /* goto/16 +AAAA */ 1181 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1182 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1183 bmi common_backwardBranch @ backward branch, do periodic checks 1184#if defined(WITH_JIT) 1185 GET_JIT_PROF_TABLE(r0) 1186 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1187 cmp r0,#0 1188 bne common_updateProfile 1189 GET_INST_OPCODE(ip) @ extract opcode from rINST 1190 GOTO_OPCODE(ip) @ jump to next instruction 1191#else 1192 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1193 GET_INST_OPCODE(ip) @ extract opcode from rINST 1194 GOTO_OPCODE(ip) @ jump to next instruction 1195#endif 1196 1197 1198/* ------------------------------ */ 1199 .balign 64 1200.L_OP_GOTO_32: /* 0x2a */ 1201/* File: armv5te/OP_GOTO_32.S */ 1202 /* 1203 * Unconditional branch, 32-bit offset. 1204 * 1205 * The branch distance is a signed code-unit offset, which we need to 1206 * double to get a byte offset. 1207 * 1208 * Unlike most opcodes, this one is allowed to branch to itself, so 1209 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1210 * instruction doesn't affect the V flag, so we need to clear it 1211 * explicitly. 1212 */ 1213 /* goto/32 +AAAAAAAA */ 1214 FETCH(r0, 1) @ r0<- aaaa (lo) 1215 FETCH(r1, 2) @ r1<- AAAA (hi) 1216 cmp ip, ip @ (clear V flag during stall) 1217 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1218 mov r9, r0, asl #1 @ r9<- byte offset 1219 ble common_backwardBranch @ backward branch, do periodic checks 1220#if defined(WITH_JIT) 1221 GET_JIT_PROF_TABLE(r0) 1222 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1223 cmp r0,#0 1224 bne common_updateProfile 1225 GET_INST_OPCODE(ip) @ extract opcode from rINST 1226 GOTO_OPCODE(ip) @ jump to next instruction 1227#else 1228 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1229 GET_INST_OPCODE(ip) @ extract opcode from rINST 1230 GOTO_OPCODE(ip) @ jump to next instruction 1231#endif 1232 1233/* ------------------------------ */ 1234 .balign 64 1235.L_OP_PACKED_SWITCH: /* 0x2b */ 1236/* File: armv5te/OP_PACKED_SWITCH.S */ 1237 /* 1238 * Handle a packed-switch or sparse-switch instruction. In both cases 1239 * we decode it and hand it off to a helper function. 1240 * 1241 * We don't really expect backward branches in a switch statement, but 1242 * they're perfectly legal, so we check for them here. 1243 * 1244 * for: packed-switch, sparse-switch 1245 */ 1246 /* op vAA, +BBBB */ 1247 FETCH(r0, 1) @ r0<- bbbb (lo) 1248 FETCH(r1, 2) @ r1<- BBBB (hi) 1249 mov r3, rINST, lsr #8 @ r3<- AA 1250 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1251 GET_VREG(r1, r3) @ r1<- vAA 1252 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1253 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1254 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1255 bmi common_backwardBranch @ backward branch, do periodic checks 1256 beq common_backwardBranch @ (want to use BLE but V is unknown) 1257#if defined(WITH_JIT) 1258 GET_JIT_PROF_TABLE(r0) 1259 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1260 cmp r0,#0 1261 bne common_updateProfile 1262 GET_INST_OPCODE(ip) @ extract opcode from rINST 1263 GOTO_OPCODE(ip) @ jump to next instruction 1264#else 1265 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1266 GET_INST_OPCODE(ip) @ extract opcode from rINST 1267 GOTO_OPCODE(ip) @ jump to next instruction 1268#endif 1269 1270 1271/* ------------------------------ */ 1272 .balign 64 1273.L_OP_SPARSE_SWITCH: /* 0x2c */ 1274/* File: armv5te/OP_SPARSE_SWITCH.S */ 1275/* File: armv5te/OP_PACKED_SWITCH.S */ 1276 /* 1277 * Handle a packed-switch or sparse-switch instruction. In both cases 1278 * we decode it and hand it off to a helper function. 1279 * 1280 * We don't really expect backward branches in a switch statement, but 1281 * they're perfectly legal, so we check for them here. 1282 * 1283 * for: packed-switch, sparse-switch 1284 */ 1285 /* op vAA, +BBBB */ 1286 FETCH(r0, 1) @ r0<- bbbb (lo) 1287 FETCH(r1, 2) @ r1<- BBBB (hi) 1288 mov r3, rINST, lsr #8 @ r3<- AA 1289 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1290 GET_VREG(r1, r3) @ r1<- vAA 1291 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1292 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1293 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1294 bmi common_backwardBranch @ backward branch, do periodic checks 1295 beq common_backwardBranch @ (want to use BLE but V is unknown) 1296#if defined(WITH_JIT) 1297 GET_JIT_PROF_TABLE(r0) 1298 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1299 cmp r0,#0 1300 bne common_updateProfile 1301 GET_INST_OPCODE(ip) @ extract opcode from rINST 1302 GOTO_OPCODE(ip) @ jump to next instruction 1303#else 1304 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1305 GET_INST_OPCODE(ip) @ extract opcode from rINST 1306 GOTO_OPCODE(ip) @ jump to next instruction 1307#endif 1308 1309 1310 1311/* ------------------------------ */ 1312 .balign 64 1313.L_OP_CMPL_FLOAT: /* 0x2d */ 1314/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1315 /* 1316 * Compare two floating-point values. Puts 0, 1, or -1 into the 1317 * destination register based on the results of the comparison. 1318 * 1319 * int compare(x, y) { 1320 * if (x == y) { 1321 * return 0; 1322 * } else if (x > y) { 1323 * return 1; 1324 * } else if (x < y) { 1325 * return -1; 1326 * } else { 1327 * return -1; 1328 * } 1329 * } 1330 */ 1331 /* op vAA, vBB, vCC */ 1332 FETCH(r0, 1) @ r0<- CCBB 1333 mov r9, rINST, lsr #8 @ r9<- AA 1334 and r2, r0, #255 @ r2<- BB 1335 mov r3, r0, lsr #8 @ r3<- CC 1336 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1337 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1338 flds s0, [r2] @ s0<- vBB 1339 flds s1, [r3] @ s1<- vCC 1340 fcmpes s0, s1 @ compare (vBB, vCC) 1341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1342 mvn r0, #0 @ r0<- -1 (default) 1343 GET_INST_OPCODE(ip) @ extract opcode from rINST 1344 fmstat @ export status flags 1345 movgt r0, #1 @ (greater than) r1<- 1 1346 moveq r0, #0 @ (equal) r1<- 0 1347 b .LOP_CMPL_FLOAT_finish @ argh 1348 1349 1350/* ------------------------------ */ 1351 .balign 64 1352.L_OP_CMPG_FLOAT: /* 0x2e */ 1353/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1354 /* 1355 * Compare two floating-point values. Puts 0, 1, or -1 into the 1356 * destination register based on the results of the comparison. 1357 * 1358 * int compare(x, y) { 1359 * if (x == y) { 1360 * return 0; 1361 * } else if (x < y) { 1362 * return -1; 1363 * } else if (x > y) { 1364 * return 1; 1365 * } else { 1366 * return 1; 1367 * } 1368 * } 1369 */ 1370 /* op vAA, vBB, vCC */ 1371 FETCH(r0, 1) @ r0<- CCBB 1372 mov r9, rINST, lsr #8 @ r9<- AA 1373 and r2, r0, #255 @ r2<- BB 1374 mov r3, r0, lsr #8 @ r3<- CC 1375 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1376 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1377 flds s0, [r2] @ s0<- vBB 1378 flds s1, [r3] @ s1<- vCC 1379 fcmpes s0, s1 @ compare (vBB, vCC) 1380 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1381 mov r0, #1 @ r0<- 1 (default) 1382 GET_INST_OPCODE(ip) @ extract opcode from rINST 1383 fmstat @ export status flags 1384 mvnmi r0, #0 @ (less than) r1<- -1 1385 moveq r0, #0 @ (equal) r1<- 0 1386 b .LOP_CMPG_FLOAT_finish @ argh 1387 1388 1389/* ------------------------------ */ 1390 .balign 64 1391.L_OP_CMPL_DOUBLE: /* 0x2f */ 1392/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1393 /* 1394 * Compare two floating-point values. Puts 0, 1, or -1 into the 1395 * destination register based on the results of the comparison. 1396 * 1397 * int compare(x, y) { 1398 * if (x == y) { 1399 * return 0; 1400 * } else if (x > y) { 1401 * return 1; 1402 * } else if (x < y) { 1403 * return -1; 1404 * } else { 1405 * return -1; 1406 * } 1407 * } 1408 */ 1409 /* op vAA, vBB, vCC */ 1410 FETCH(r0, 1) @ r0<- CCBB 1411 mov r9, rINST, lsr #8 @ r9<- AA 1412 and r2, r0, #255 @ r2<- BB 1413 mov r3, r0, lsr #8 @ r3<- CC 1414 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1415 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1416 fldd d0, [r2] @ d0<- vBB 1417 fldd d1, [r3] @ d1<- vCC 1418 fcmped d0, d1 @ compare (vBB, vCC) 1419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1420 mvn r0, #0 @ r0<- -1 (default) 1421 GET_INST_OPCODE(ip) @ extract opcode from rINST 1422 fmstat @ export status flags 1423 movgt r0, #1 @ (greater than) r1<- 1 1424 moveq r0, #0 @ (equal) r1<- 0 1425 b .LOP_CMPL_DOUBLE_finish @ argh 1426 1427 1428/* ------------------------------ */ 1429 .balign 64 1430.L_OP_CMPG_DOUBLE: /* 0x30 */ 1431/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1432 /* 1433 * Compare two floating-point values. Puts 0, 1, or -1 into the 1434 * destination register based on the results of the comparison. 1435 * 1436 * int compare(x, y) { 1437 * if (x == y) { 1438 * return 0; 1439 * } else if (x < y) { 1440 * return -1; 1441 * } else if (x > y) { 1442 * return 1; 1443 * } else { 1444 * return 1; 1445 * } 1446 * } 1447 */ 1448 /* op vAA, vBB, vCC */ 1449 FETCH(r0, 1) @ r0<- CCBB 1450 mov r9, rINST, lsr #8 @ r9<- AA 1451 and r2, r0, #255 @ r2<- BB 1452 mov r3, r0, lsr #8 @ r3<- CC 1453 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1454 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1455 fldd d0, [r2] @ d0<- vBB 1456 fldd d1, [r3] @ d1<- vCC 1457 fcmped d0, d1 @ compare (vBB, vCC) 1458 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1459 mov r0, #1 @ r0<- 1 (default) 1460 GET_INST_OPCODE(ip) @ extract opcode from rINST 1461 fmstat @ export status flags 1462 mvnmi r0, #0 @ (less than) r1<- -1 1463 moveq r0, #0 @ (equal) r1<- 0 1464 b .LOP_CMPG_DOUBLE_finish @ argh 1465 1466 1467/* ------------------------------ */ 1468 .balign 64 1469.L_OP_CMP_LONG: /* 0x31 */ 1470/* File: armv5te/OP_CMP_LONG.S */ 1471 /* 1472 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1473 * register based on the results of the comparison. 1474 * 1475 * We load the full values with LDM, but in practice many values could 1476 * be resolved by only looking at the high word. This could be made 1477 * faster or slower by splitting the LDM into a pair of LDRs. 1478 * 1479 * If we just wanted to set condition flags, we could do this: 1480 * subs ip, r0, r2 1481 * sbcs ip, r1, r3 1482 * subeqs ip, r0, r2 1483 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1484 * integer value, which we can do with 2 conditional mov/mvn instructions 1485 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1486 * us a constant 5-cycle path plus a branch at the end to the 1487 * instruction epilogue code. The multi-compare approach below needs 1488 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1489 * in the worst case (the 64-bit values are equal). 1490 */ 1491 /* cmp-long vAA, vBB, vCC */ 1492 FETCH(r0, 1) @ r0<- CCBB 1493 mov r9, rINST, lsr #8 @ r9<- AA 1494 and r2, r0, #255 @ r2<- BB 1495 mov r3, r0, lsr #8 @ r3<- CC 1496 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1497 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1498 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1499 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1500 cmp r1, r3 @ compare (vBB+1, vCC+1) 1501 blt .LOP_CMP_LONG_less @ signed compare on high part 1502 bgt .LOP_CMP_LONG_greater 1503 subs r1, r0, r2 @ r1<- r0 - r2 1504 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1505 bne .LOP_CMP_LONG_less 1506 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1507 1508/* ------------------------------ */ 1509 .balign 64 1510.L_OP_IF_EQ: /* 0x32 */ 1511/* File: armv5te/OP_IF_EQ.S */ 1512/* File: armv5te/bincmp.S */ 1513 /* 1514 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1515 * fragment that specifies the *reverse* comparison to perform, e.g. 1516 * for "if-le" you would use "gt". 1517 * 1518 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1519 */ 1520 /* if-cmp vA, vB, +CCCC */ 1521 mov r0, rINST, lsr #8 @ r0<- A+ 1522 mov r1, rINST, lsr #12 @ r1<- B 1523 and r0, r0, #15 1524 GET_VREG(r3, r1) @ r3<- vB 1525 GET_VREG(r2, r0) @ r2<- vA 1526 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1527 cmp r2, r3 @ compare (vA, vB) 1528 bne 1f @ branch to 1 if comparison failed 1529 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1530 movs r9, r9, asl #1 @ convert to bytes, check sign 1531 bmi common_backwardBranch @ yes, do periodic checks 15321: 1533#if defined(WITH_JIT) 1534 GET_JIT_PROF_TABLE(r0) 1535 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1536 b common_testUpdateProfile 1537#else 1538 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1539 GET_INST_OPCODE(ip) @ extract opcode from rINST 1540 GOTO_OPCODE(ip) @ jump to next instruction 1541#endif 1542 1543 1544 1545/* ------------------------------ */ 1546 .balign 64 1547.L_OP_IF_NE: /* 0x33 */ 1548/* File: armv5te/OP_IF_NE.S */ 1549/* File: armv5te/bincmp.S */ 1550 /* 1551 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1552 * fragment that specifies the *reverse* comparison to perform, e.g. 1553 * for "if-le" you would use "gt". 1554 * 1555 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1556 */ 1557 /* if-cmp vA, vB, +CCCC */ 1558 mov r0, rINST, lsr #8 @ r0<- A+ 1559 mov r1, rINST, lsr #12 @ r1<- B 1560 and r0, r0, #15 1561 GET_VREG(r3, r1) @ r3<- vB 1562 GET_VREG(r2, r0) @ r2<- vA 1563 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1564 cmp r2, r3 @ compare (vA, vB) 1565 beq 1f @ branch to 1 if comparison failed 1566 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1567 movs r9, r9, asl #1 @ convert to bytes, check sign 1568 bmi common_backwardBranch @ yes, do periodic checks 15691: 1570#if defined(WITH_JIT) 1571 GET_JIT_PROF_TABLE(r0) 1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1573 b common_testUpdateProfile 1574#else 1575 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1576 GET_INST_OPCODE(ip) @ extract opcode from rINST 1577 GOTO_OPCODE(ip) @ jump to next instruction 1578#endif 1579 1580 1581 1582/* ------------------------------ */ 1583 .balign 64 1584.L_OP_IF_LT: /* 0x34 */ 1585/* File: armv5te/OP_IF_LT.S */ 1586/* File: armv5te/bincmp.S */ 1587 /* 1588 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1589 * fragment that specifies the *reverse* comparison to perform, e.g. 1590 * for "if-le" you would use "gt". 1591 * 1592 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1593 */ 1594 /* if-cmp vA, vB, +CCCC */ 1595 mov r0, rINST, lsr #8 @ r0<- A+ 1596 mov r1, rINST, lsr #12 @ r1<- B 1597 and r0, r0, #15 1598 GET_VREG(r3, r1) @ r3<- vB 1599 GET_VREG(r2, r0) @ r2<- vA 1600 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1601 cmp r2, r3 @ compare (vA, vB) 1602 bge 1f @ branch to 1 if comparison failed 1603 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1604 movs r9, r9, asl #1 @ convert to bytes, check sign 1605 bmi common_backwardBranch @ yes, do periodic checks 16061: 1607#if defined(WITH_JIT) 1608 GET_JIT_PROF_TABLE(r0) 1609 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1610 b common_testUpdateProfile 1611#else 1612 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1613 GET_INST_OPCODE(ip) @ extract opcode from rINST 1614 GOTO_OPCODE(ip) @ jump to next instruction 1615#endif 1616 1617 1618 1619/* ------------------------------ */ 1620 .balign 64 1621.L_OP_IF_GE: /* 0x35 */ 1622/* File: armv5te/OP_IF_GE.S */ 1623/* File: armv5te/bincmp.S */ 1624 /* 1625 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1626 * fragment that specifies the *reverse* comparison to perform, e.g. 1627 * for "if-le" you would use "gt". 1628 * 1629 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1630 */ 1631 /* if-cmp vA, vB, +CCCC */ 1632 mov r0, rINST, lsr #8 @ r0<- A+ 1633 mov r1, rINST, lsr #12 @ r1<- B 1634 and r0, r0, #15 1635 GET_VREG(r3, r1) @ r3<- vB 1636 GET_VREG(r2, r0) @ r2<- vA 1637 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1638 cmp r2, r3 @ compare (vA, vB) 1639 blt 1f @ branch to 1 if comparison failed 1640 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1641 movs r9, r9, asl #1 @ convert to bytes, check sign 1642 bmi common_backwardBranch @ yes, do periodic checks 16431: 1644#if defined(WITH_JIT) 1645 GET_JIT_PROF_TABLE(r0) 1646 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1647 b common_testUpdateProfile 1648#else 1649 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1650 GET_INST_OPCODE(ip) @ extract opcode from rINST 1651 GOTO_OPCODE(ip) @ jump to next instruction 1652#endif 1653 1654 1655 1656/* ------------------------------ */ 1657 .balign 64 1658.L_OP_IF_GT: /* 0x36 */ 1659/* File: armv5te/OP_IF_GT.S */ 1660/* File: armv5te/bincmp.S */ 1661 /* 1662 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1663 * fragment that specifies the *reverse* comparison to perform, e.g. 1664 * for "if-le" you would use "gt". 1665 * 1666 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1667 */ 1668 /* if-cmp vA, vB, +CCCC */ 1669 mov r0, rINST, lsr #8 @ r0<- A+ 1670 mov r1, rINST, lsr #12 @ r1<- B 1671 and r0, r0, #15 1672 GET_VREG(r3, r1) @ r3<- vB 1673 GET_VREG(r2, r0) @ r2<- vA 1674 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1675 cmp r2, r3 @ compare (vA, vB) 1676 ble 1f @ branch to 1 if comparison failed 1677 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1678 movs r9, r9, asl #1 @ convert to bytes, check sign 1679 bmi common_backwardBranch @ yes, do periodic checks 16801: 1681#if defined(WITH_JIT) 1682 GET_JIT_PROF_TABLE(r0) 1683 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1684 b common_testUpdateProfile 1685#else 1686 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1687 GET_INST_OPCODE(ip) @ extract opcode from rINST 1688 GOTO_OPCODE(ip) @ jump to next instruction 1689#endif 1690 1691 1692 1693/* ------------------------------ */ 1694 .balign 64 1695.L_OP_IF_LE: /* 0x37 */ 1696/* File: armv5te/OP_IF_LE.S */ 1697/* File: armv5te/bincmp.S */ 1698 /* 1699 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1700 * fragment that specifies the *reverse* comparison to perform, e.g. 1701 * for "if-le" you would use "gt". 1702 * 1703 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1704 */ 1705 /* if-cmp vA, vB, +CCCC */ 1706 mov r0, rINST, lsr #8 @ r0<- A+ 1707 mov r1, rINST, lsr #12 @ r1<- B 1708 and r0, r0, #15 1709 GET_VREG(r3, r1) @ r3<- vB 1710 GET_VREG(r2, r0) @ r2<- vA 1711 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1712 cmp r2, r3 @ compare (vA, vB) 1713 bgt 1f @ branch to 1 if comparison failed 1714 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1715 movs r9, r9, asl #1 @ convert to bytes, check sign 1716 bmi common_backwardBranch @ yes, do periodic checks 17171: 1718#if defined(WITH_JIT) 1719 GET_JIT_PROF_TABLE(r0) 1720 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1721 b common_testUpdateProfile 1722#else 1723 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1724 GET_INST_OPCODE(ip) @ extract opcode from rINST 1725 GOTO_OPCODE(ip) @ jump to next instruction 1726#endif 1727 1728 1729 1730/* ------------------------------ */ 1731 .balign 64 1732.L_OP_IF_EQZ: /* 0x38 */ 1733/* File: armv5te/OP_IF_EQZ.S */ 1734/* File: armv5te/zcmp.S */ 1735 /* 1736 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1737 * fragment that specifies the *reverse* comparison to perform, e.g. 1738 * for "if-le" you would use "gt". 1739 * 1740 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1741 */ 1742 /* if-cmp vAA, +BBBB */ 1743 mov r0, rINST, lsr #8 @ r0<- AA 1744 GET_VREG(r2, r0) @ r2<- vAA 1745 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1746 cmp r2, #0 @ compare (vA, 0) 1747 bne 1f @ branch to 1 if comparison failed 1748 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1749 movs r9, r9, asl #1 @ convert to bytes, check sign 1750 bmi common_backwardBranch @ backward branch, do periodic checks 17511: 1752#if defined(WITH_JIT) 1753 GET_JIT_PROF_TABLE(r0) 1754 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1755 cmp r0,#0 1756 bne common_updateProfile 1757 GET_INST_OPCODE(ip) @ extract opcode from rINST 1758 GOTO_OPCODE(ip) @ jump to next instruction 1759#else 1760 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1761 GET_INST_OPCODE(ip) @ extract opcode from rINST 1762 GOTO_OPCODE(ip) @ jump to next instruction 1763#endif 1764 1765 1766 1767/* ------------------------------ */ 1768 .balign 64 1769.L_OP_IF_NEZ: /* 0x39 */ 1770/* File: armv5te/OP_IF_NEZ.S */ 1771/* File: armv5te/zcmp.S */ 1772 /* 1773 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1774 * fragment that specifies the *reverse* comparison to perform, e.g. 1775 * for "if-le" you would use "gt". 1776 * 1777 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1778 */ 1779 /* if-cmp vAA, +BBBB */ 1780 mov r0, rINST, lsr #8 @ r0<- AA 1781 GET_VREG(r2, r0) @ r2<- vAA 1782 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1783 cmp r2, #0 @ compare (vA, 0) 1784 beq 1f @ branch to 1 if comparison failed 1785 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1786 movs r9, r9, asl #1 @ convert to bytes, check sign 1787 bmi common_backwardBranch @ backward branch, do periodic checks 17881: 1789#if defined(WITH_JIT) 1790 GET_JIT_PROF_TABLE(r0) 1791 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1792 cmp r0,#0 1793 bne common_updateProfile 1794 GET_INST_OPCODE(ip) @ extract opcode from rINST 1795 GOTO_OPCODE(ip) @ jump to next instruction 1796#else 1797 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1798 GET_INST_OPCODE(ip) @ extract opcode from rINST 1799 GOTO_OPCODE(ip) @ jump to next instruction 1800#endif 1801 1802 1803 1804/* ------------------------------ */ 1805 .balign 64 1806.L_OP_IF_LTZ: /* 0x3a */ 1807/* File: armv5te/OP_IF_LTZ.S */ 1808/* File: armv5te/zcmp.S */ 1809 /* 1810 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1811 * fragment that specifies the *reverse* comparison to perform, e.g. 1812 * for "if-le" you would use "gt". 1813 * 1814 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1815 */ 1816 /* if-cmp vAA, +BBBB */ 1817 mov r0, rINST, lsr #8 @ r0<- AA 1818 GET_VREG(r2, r0) @ r2<- vAA 1819 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1820 cmp r2, #0 @ compare (vA, 0) 1821 bge 1f @ branch to 1 if comparison failed 1822 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1823 movs r9, r9, asl #1 @ convert to bytes, check sign 1824 bmi common_backwardBranch @ backward branch, do periodic checks 18251: 1826#if defined(WITH_JIT) 1827 GET_JIT_PROF_TABLE(r0) 1828 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1829 cmp r0,#0 1830 bne common_updateProfile 1831 GET_INST_OPCODE(ip) @ extract opcode from rINST 1832 GOTO_OPCODE(ip) @ jump to next instruction 1833#else 1834 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1835 GET_INST_OPCODE(ip) @ extract opcode from rINST 1836 GOTO_OPCODE(ip) @ jump to next instruction 1837#endif 1838 1839 1840 1841/* ------------------------------ */ 1842 .balign 64 1843.L_OP_IF_GEZ: /* 0x3b */ 1844/* File: armv5te/OP_IF_GEZ.S */ 1845/* File: armv5te/zcmp.S */ 1846 /* 1847 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1848 * fragment that specifies the *reverse* comparison to perform, e.g. 1849 * for "if-le" you would use "gt". 1850 * 1851 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1852 */ 1853 /* if-cmp vAA, +BBBB */ 1854 mov r0, rINST, lsr #8 @ r0<- AA 1855 GET_VREG(r2, r0) @ r2<- vAA 1856 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1857 cmp r2, #0 @ compare (vA, 0) 1858 blt 1f @ branch to 1 if comparison failed 1859 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1860 movs r9, r9, asl #1 @ convert to bytes, check sign 1861 bmi common_backwardBranch @ backward branch, do periodic checks 18621: 1863#if defined(WITH_JIT) 1864 GET_JIT_PROF_TABLE(r0) 1865 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1866 cmp r0,#0 1867 bne common_updateProfile 1868 GET_INST_OPCODE(ip) @ extract opcode from rINST 1869 GOTO_OPCODE(ip) @ jump to next instruction 1870#else 1871 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1872 GET_INST_OPCODE(ip) @ extract opcode from rINST 1873 GOTO_OPCODE(ip) @ jump to next instruction 1874#endif 1875 1876 1877 1878/* ------------------------------ */ 1879 .balign 64 1880.L_OP_IF_GTZ: /* 0x3c */ 1881/* File: armv5te/OP_IF_GTZ.S */ 1882/* File: armv5te/zcmp.S */ 1883 /* 1884 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1885 * fragment that specifies the *reverse* comparison to perform, e.g. 1886 * for "if-le" you would use "gt". 1887 * 1888 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1889 */ 1890 /* if-cmp vAA, +BBBB */ 1891 mov r0, rINST, lsr #8 @ r0<- AA 1892 GET_VREG(r2, r0) @ r2<- vAA 1893 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1894 cmp r2, #0 @ compare (vA, 0) 1895 ble 1f @ branch to 1 if comparison failed 1896 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1897 movs r9, r9, asl #1 @ convert to bytes, check sign 1898 bmi common_backwardBranch @ backward branch, do periodic checks 18991: 1900#if defined(WITH_JIT) 1901 GET_JIT_PROF_TABLE(r0) 1902 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1903 cmp r0,#0 1904 bne common_updateProfile 1905 GET_INST_OPCODE(ip) @ extract opcode from rINST 1906 GOTO_OPCODE(ip) @ jump to next instruction 1907#else 1908 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1909 GET_INST_OPCODE(ip) @ extract opcode from rINST 1910 GOTO_OPCODE(ip) @ jump to next instruction 1911#endif 1912 1913 1914 1915/* ------------------------------ */ 1916 .balign 64 1917.L_OP_IF_LEZ: /* 0x3d */ 1918/* File: armv5te/OP_IF_LEZ.S */ 1919/* File: armv5te/zcmp.S */ 1920 /* 1921 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1922 * fragment that specifies the *reverse* comparison to perform, e.g. 1923 * for "if-le" you would use "gt". 1924 * 1925 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1926 */ 1927 /* if-cmp vAA, +BBBB */ 1928 mov r0, rINST, lsr #8 @ r0<- AA 1929 GET_VREG(r2, r0) @ r2<- vAA 1930 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1931 cmp r2, #0 @ compare (vA, 0) 1932 bgt 1f @ branch to 1 if comparison failed 1933 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1934 movs r9, r9, asl #1 @ convert to bytes, check sign 1935 bmi common_backwardBranch @ backward branch, do periodic checks 19361: 1937#if defined(WITH_JIT) 1938 GET_JIT_PROF_TABLE(r0) 1939 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1940 cmp r0,#0 1941 bne common_updateProfile 1942 GET_INST_OPCODE(ip) @ extract opcode from rINST 1943 GOTO_OPCODE(ip) @ jump to next instruction 1944#else 1945 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1946 GET_INST_OPCODE(ip) @ extract opcode from rINST 1947 GOTO_OPCODE(ip) @ jump to next instruction 1948#endif 1949 1950 1951 1952/* ------------------------------ */ 1953 .balign 64 1954.L_OP_UNUSED_3E: /* 0x3e */ 1955/* File: armv5te/OP_UNUSED_3E.S */ 1956/* File: armv5te/unused.S */ 1957 bl common_abort 1958 1959 1960 1961/* ------------------------------ */ 1962 .balign 64 1963.L_OP_UNUSED_3F: /* 0x3f */ 1964/* File: armv5te/OP_UNUSED_3F.S */ 1965/* File: armv5te/unused.S */ 1966 bl common_abort 1967 1968 1969 1970/* ------------------------------ */ 1971 .balign 64 1972.L_OP_UNUSED_40: /* 0x40 */ 1973/* File: armv5te/OP_UNUSED_40.S */ 1974/* File: armv5te/unused.S */ 1975 bl common_abort 1976 1977 1978 1979/* ------------------------------ */ 1980 .balign 64 1981.L_OP_UNUSED_41: /* 0x41 */ 1982/* File: armv5te/OP_UNUSED_41.S */ 1983/* File: armv5te/unused.S */ 1984 bl common_abort 1985 1986 1987 1988/* ------------------------------ */ 1989 .balign 64 1990.L_OP_UNUSED_42: /* 0x42 */ 1991/* File: armv5te/OP_UNUSED_42.S */ 1992/* File: armv5te/unused.S */ 1993 bl common_abort 1994 1995 1996 1997/* ------------------------------ */ 1998 .balign 64 1999.L_OP_UNUSED_43: /* 0x43 */ 2000/* File: armv5te/OP_UNUSED_43.S */ 2001/* File: armv5te/unused.S */ 2002 bl common_abort 2003 2004 2005 2006/* ------------------------------ */ 2007 .balign 64 2008.L_OP_AGET: /* 0x44 */ 2009/* File: armv5te/OP_AGET.S */ 2010 /* 2011 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2012 * 2013 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2014 * instructions. We use a pair of FETCH_Bs instead. 2015 * 2016 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2017 */ 2018 /* op vAA, vBB, vCC */ 2019 FETCH_B(r2, 1, 0) @ r2<- BB 2020 mov r9, rINST, lsr #8 @ r9<- AA 2021 FETCH_B(r3, 1, 1) @ r3<- CC 2022 GET_VREG(r0, r2) @ r0<- vBB (array object) 2023 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2024 cmp r0, #0 @ null array object? 2025 beq common_errNullObject @ yes, bail 2026 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2027 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2028 cmp r1, r3 @ compare unsigned index, length 2029 bcs common_errArrayIndex @ index >= length, bail 2030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2031 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2032 GET_INST_OPCODE(ip) @ extract opcode from rINST 2033 SET_VREG(r2, r9) @ vAA<- r2 2034 GOTO_OPCODE(ip) @ jump to next instruction 2035 2036 2037/* ------------------------------ */ 2038 .balign 64 2039.L_OP_AGET_WIDE: /* 0x45 */ 2040/* File: armv5te/OP_AGET_WIDE.S */ 2041 /* 2042 * Array get, 64 bits. vAA <- vBB[vCC]. 2043 * 2044 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2045 */ 2046 /* aget-wide vAA, vBB, vCC */ 2047 FETCH(r0, 1) @ r0<- CCBB 2048 mov r9, rINST, lsr #8 @ r9<- AA 2049 and r2, r0, #255 @ r2<- BB 2050 mov r3, r0, lsr #8 @ r3<- CC 2051 GET_VREG(r0, r2) @ r0<- vBB (array object) 2052 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2053 cmp r0, #0 @ null array object? 2054 beq common_errNullObject @ yes, bail 2055 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2056 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2057 cmp r1, r3 @ compare unsigned index, length 2058 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2059 b common_errArrayIndex @ index >= length, bail 2060 @ May want to swap the order of these two branches depending on how the 2061 @ branch prediction (if any) handles conditional forward branches vs. 2062 @ unconditional forward branches. 2063 2064/* ------------------------------ */ 2065 .balign 64 2066.L_OP_AGET_OBJECT: /* 0x46 */ 2067/* File: armv5te/OP_AGET_OBJECT.S */ 2068/* File: armv5te/OP_AGET.S */ 2069 /* 2070 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2071 * 2072 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2073 * instructions. We use a pair of FETCH_Bs instead. 2074 * 2075 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2076 */ 2077 /* op vAA, vBB, vCC */ 2078 FETCH_B(r2, 1, 0) @ r2<- BB 2079 mov r9, rINST, lsr #8 @ r9<- AA 2080 FETCH_B(r3, 1, 1) @ r3<- CC 2081 GET_VREG(r0, r2) @ r0<- vBB (array object) 2082 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2083 cmp r0, #0 @ null array object? 2084 beq common_errNullObject @ yes, bail 2085 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2086 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2087 cmp r1, r3 @ compare unsigned index, length 2088 bcs common_errArrayIndex @ index >= length, bail 2089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2090 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2091 GET_INST_OPCODE(ip) @ extract opcode from rINST 2092 SET_VREG(r2, r9) @ vAA<- r2 2093 GOTO_OPCODE(ip) @ jump to next instruction 2094 2095 2096 2097/* ------------------------------ */ 2098 .balign 64 2099.L_OP_AGET_BOOLEAN: /* 0x47 */ 2100/* File: armv5te/OP_AGET_BOOLEAN.S */ 2101/* File: armv5te/OP_AGET.S */ 2102 /* 2103 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2104 * 2105 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2106 * instructions. We use a pair of FETCH_Bs instead. 2107 * 2108 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2109 */ 2110 /* op vAA, vBB, vCC */ 2111 FETCH_B(r2, 1, 0) @ r2<- BB 2112 mov r9, rINST, lsr #8 @ r9<- AA 2113 FETCH_B(r3, 1, 1) @ r3<- CC 2114 GET_VREG(r0, r2) @ r0<- vBB (array object) 2115 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2116 cmp r0, #0 @ null array object? 2117 beq common_errNullObject @ yes, bail 2118 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2119 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2120 cmp r1, r3 @ compare unsigned index, length 2121 bcs common_errArrayIndex @ index >= length, bail 2122 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2123 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2124 GET_INST_OPCODE(ip) @ extract opcode from rINST 2125 SET_VREG(r2, r9) @ vAA<- r2 2126 GOTO_OPCODE(ip) @ jump to next instruction 2127 2128 2129 2130/* ------------------------------ */ 2131 .balign 64 2132.L_OP_AGET_BYTE: /* 0x48 */ 2133/* File: armv5te/OP_AGET_BYTE.S */ 2134/* File: armv5te/OP_AGET.S */ 2135 /* 2136 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2137 * 2138 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2139 * instructions. We use a pair of FETCH_Bs instead. 2140 * 2141 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2142 */ 2143 /* op vAA, vBB, vCC */ 2144 FETCH_B(r2, 1, 0) @ r2<- BB 2145 mov r9, rINST, lsr #8 @ r9<- AA 2146 FETCH_B(r3, 1, 1) @ r3<- CC 2147 GET_VREG(r0, r2) @ r0<- vBB (array object) 2148 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2149 cmp r0, #0 @ null array object? 2150 beq common_errNullObject @ yes, bail 2151 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2152 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2153 cmp r1, r3 @ compare unsigned index, length 2154 bcs common_errArrayIndex @ index >= length, bail 2155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2156 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2157 GET_INST_OPCODE(ip) @ extract opcode from rINST 2158 SET_VREG(r2, r9) @ vAA<- r2 2159 GOTO_OPCODE(ip) @ jump to next instruction 2160 2161 2162 2163/* ------------------------------ */ 2164 .balign 64 2165.L_OP_AGET_CHAR: /* 0x49 */ 2166/* File: armv5te/OP_AGET_CHAR.S */ 2167/* File: armv5te/OP_AGET.S */ 2168 /* 2169 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2170 * 2171 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2172 * instructions. We use a pair of FETCH_Bs instead. 2173 * 2174 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2175 */ 2176 /* op vAA, vBB, vCC */ 2177 FETCH_B(r2, 1, 0) @ r2<- BB 2178 mov r9, rINST, lsr #8 @ r9<- AA 2179 FETCH_B(r3, 1, 1) @ r3<- CC 2180 GET_VREG(r0, r2) @ r0<- vBB (array object) 2181 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2182 cmp r0, #0 @ null array object? 2183 beq common_errNullObject @ yes, bail 2184 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2185 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2186 cmp r1, r3 @ compare unsigned index, length 2187 bcs common_errArrayIndex @ index >= length, bail 2188 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2189 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2190 GET_INST_OPCODE(ip) @ extract opcode from rINST 2191 SET_VREG(r2, r9) @ vAA<- r2 2192 GOTO_OPCODE(ip) @ jump to next instruction 2193 2194 2195 2196/* ------------------------------ */ 2197 .balign 64 2198.L_OP_AGET_SHORT: /* 0x4a */ 2199/* File: armv5te/OP_AGET_SHORT.S */ 2200/* File: armv5te/OP_AGET.S */ 2201 /* 2202 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2203 * 2204 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2205 * instructions. We use a pair of FETCH_Bs instead. 2206 * 2207 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2208 */ 2209 /* op vAA, vBB, vCC */ 2210 FETCH_B(r2, 1, 0) @ r2<- BB 2211 mov r9, rINST, lsr #8 @ r9<- AA 2212 FETCH_B(r3, 1, 1) @ r3<- CC 2213 GET_VREG(r0, r2) @ r0<- vBB (array object) 2214 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2215 cmp r0, #0 @ null array object? 2216 beq common_errNullObject @ yes, bail 2217 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2218 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2219 cmp r1, r3 @ compare unsigned index, length 2220 bcs common_errArrayIndex @ index >= length, bail 2221 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2222 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2223 GET_INST_OPCODE(ip) @ extract opcode from rINST 2224 SET_VREG(r2, r9) @ vAA<- r2 2225 GOTO_OPCODE(ip) @ jump to next instruction 2226 2227 2228 2229/* ------------------------------ */ 2230 .balign 64 2231.L_OP_APUT: /* 0x4b */ 2232/* File: armv5te/OP_APUT.S */ 2233 /* 2234 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2235 * 2236 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2237 * instructions. We use a pair of FETCH_Bs instead. 2238 * 2239 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2240 */ 2241 /* op vAA, vBB, vCC */ 2242 FETCH_B(r2, 1, 0) @ r2<- BB 2243 mov r9, rINST, lsr #8 @ r9<- AA 2244 FETCH_B(r3, 1, 1) @ r3<- CC 2245 GET_VREG(r0, r2) @ r0<- vBB (array object) 2246 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2247 cmp r0, #0 @ null array object? 2248 beq common_errNullObject @ yes, bail 2249 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2250 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2251 cmp r1, r3 @ compare unsigned index, length 2252 bcs common_errArrayIndex @ index >= length, bail 2253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2254 GET_VREG(r2, r9) @ r2<- vAA 2255 GET_INST_OPCODE(ip) @ extract opcode from rINST 2256 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2257 GOTO_OPCODE(ip) @ jump to next instruction 2258 2259 2260/* ------------------------------ */ 2261 .balign 64 2262.L_OP_APUT_WIDE: /* 0x4c */ 2263/* File: armv5te/OP_APUT_WIDE.S */ 2264 /* 2265 * Array put, 64 bits. vBB[vCC] <- vAA. 2266 * 2267 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2268 */ 2269 /* aput-wide vAA, vBB, vCC */ 2270 FETCH(r0, 1) @ r0<- CCBB 2271 mov r9, rINST, lsr #8 @ r9<- AA 2272 and r2, r0, #255 @ r2<- BB 2273 mov r3, r0, lsr #8 @ r3<- CC 2274 GET_VREG(r0, r2) @ r0<- vBB (array object) 2275 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2276 cmp r0, #0 @ null array object? 2277 beq common_errNullObject @ yes, bail 2278 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2279 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2280 cmp r1, r3 @ compare unsigned index, length 2281 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2282 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2283 b common_errArrayIndex @ index >= length, bail 2284 @ May want to swap the order of these two branches depending on how the 2285 @ branch prediction (if any) handles conditional forward branches vs. 2286 @ unconditional forward branches. 2287 2288/* ------------------------------ */ 2289 .balign 64 2290.L_OP_APUT_OBJECT: /* 0x4d */ 2291/* File: armv5te/OP_APUT_OBJECT.S */ 2292 /* 2293 * Store an object into an array. vBB[vCC] <- vAA. 2294 * 2295 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2296 * instructions. We use a pair of FETCH_Bs instead. 2297 */ 2298 /* op vAA, vBB, vCC */ 2299 FETCH(r0, 1) @ r0<- CCBB 2300 mov r9, rINST, lsr #8 @ r9<- AA 2301 and r2, r0, #255 @ r2<- BB 2302 mov r3, r0, lsr #8 @ r3<- CC 2303 GET_VREG(r1, r2) @ r1<- vBB (array object) 2304 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2305 cmp r1, #0 @ null array object? 2306 GET_VREG(r9, r9) @ r9<- vAA 2307 beq common_errNullObject @ yes, bail 2308 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2309 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2310 cmp r0, r3 @ compare unsigned index, length 2311 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2312 b common_errArrayIndex @ index >= length, bail 2313 2314 2315/* ------------------------------ */ 2316 .balign 64 2317.L_OP_APUT_BOOLEAN: /* 0x4e */ 2318/* File: armv5te/OP_APUT_BOOLEAN.S */ 2319/* File: armv5te/OP_APUT.S */ 2320 /* 2321 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2322 * 2323 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2324 * instructions. We use a pair of FETCH_Bs instead. 2325 * 2326 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2327 */ 2328 /* op vAA, vBB, vCC */ 2329 FETCH_B(r2, 1, 0) @ r2<- BB 2330 mov r9, rINST, lsr #8 @ r9<- AA 2331 FETCH_B(r3, 1, 1) @ r3<- CC 2332 GET_VREG(r0, r2) @ r0<- vBB (array object) 2333 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2334 cmp r0, #0 @ null array object? 2335 beq common_errNullObject @ yes, bail 2336 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2337 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2338 cmp r1, r3 @ compare unsigned index, length 2339 bcs common_errArrayIndex @ index >= length, bail 2340 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2341 GET_VREG(r2, r9) @ r2<- vAA 2342 GET_INST_OPCODE(ip) @ extract opcode from rINST 2343 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2344 GOTO_OPCODE(ip) @ jump to next instruction 2345 2346 2347 2348/* ------------------------------ */ 2349 .balign 64 2350.L_OP_APUT_BYTE: /* 0x4f */ 2351/* File: armv5te/OP_APUT_BYTE.S */ 2352/* File: armv5te/OP_APUT.S */ 2353 /* 2354 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2355 * 2356 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2357 * instructions. We use a pair of FETCH_Bs instead. 2358 * 2359 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2360 */ 2361 /* op vAA, vBB, vCC */ 2362 FETCH_B(r2, 1, 0) @ r2<- BB 2363 mov r9, rINST, lsr #8 @ r9<- AA 2364 FETCH_B(r3, 1, 1) @ r3<- CC 2365 GET_VREG(r0, r2) @ r0<- vBB (array object) 2366 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2367 cmp r0, #0 @ null array object? 2368 beq common_errNullObject @ yes, bail 2369 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2370 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2371 cmp r1, r3 @ compare unsigned index, length 2372 bcs common_errArrayIndex @ index >= length, bail 2373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2374 GET_VREG(r2, r9) @ r2<- vAA 2375 GET_INST_OPCODE(ip) @ extract opcode from rINST 2376 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2377 GOTO_OPCODE(ip) @ jump to next instruction 2378 2379 2380 2381/* ------------------------------ */ 2382 .balign 64 2383.L_OP_APUT_CHAR: /* 0x50 */ 2384/* File: armv5te/OP_APUT_CHAR.S */ 2385/* File: armv5te/OP_APUT.S */ 2386 /* 2387 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2388 * 2389 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2390 * instructions. We use a pair of FETCH_Bs instead. 2391 * 2392 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2393 */ 2394 /* op vAA, vBB, vCC */ 2395 FETCH_B(r2, 1, 0) @ r2<- BB 2396 mov r9, rINST, lsr #8 @ r9<- AA 2397 FETCH_B(r3, 1, 1) @ r3<- CC 2398 GET_VREG(r0, r2) @ r0<- vBB (array object) 2399 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2400 cmp r0, #0 @ null array object? 2401 beq common_errNullObject @ yes, bail 2402 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2403 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2404 cmp r1, r3 @ compare unsigned index, length 2405 bcs common_errArrayIndex @ index >= length, bail 2406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2407 GET_VREG(r2, r9) @ r2<- vAA 2408 GET_INST_OPCODE(ip) @ extract opcode from rINST 2409 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2410 GOTO_OPCODE(ip) @ jump to next instruction 2411 2412 2413 2414/* ------------------------------ */ 2415 .balign 64 2416.L_OP_APUT_SHORT: /* 0x51 */ 2417/* File: armv5te/OP_APUT_SHORT.S */ 2418/* File: armv5te/OP_APUT.S */ 2419 /* 2420 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2421 * 2422 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2423 * instructions. We use a pair of FETCH_Bs instead. 2424 * 2425 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2426 */ 2427 /* op vAA, vBB, vCC */ 2428 FETCH_B(r2, 1, 0) @ r2<- BB 2429 mov r9, rINST, lsr #8 @ r9<- AA 2430 FETCH_B(r3, 1, 1) @ r3<- CC 2431 GET_VREG(r0, r2) @ r0<- vBB (array object) 2432 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2433 cmp r0, #0 @ null array object? 2434 beq common_errNullObject @ yes, bail 2435 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2436 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2437 cmp r1, r3 @ compare unsigned index, length 2438 bcs common_errArrayIndex @ index >= length, bail 2439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2440 GET_VREG(r2, r9) @ r2<- vAA 2441 GET_INST_OPCODE(ip) @ extract opcode from rINST 2442 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2443 GOTO_OPCODE(ip) @ jump to next instruction 2444 2445 2446 2447/* ------------------------------ */ 2448 .balign 64 2449.L_OP_IGET: /* 0x52 */ 2450/* File: armv5te/OP_IGET.S */ 2451 /* 2452 * General 32-bit instance field get. 2453 * 2454 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2455 */ 2456 /* op vA, vB, field@CCCC */ 2457 mov r0, rINST, lsr #12 @ r0<- B 2458 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2459 FETCH(r1, 1) @ r1<- field ref CCCC 2460 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2461 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2462 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2463 cmp r0, #0 @ is resolved entry null? 2464 bne .LOP_IGET_finish @ no, already resolved 24658: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2466 EXPORT_PC() @ resolve() could throw 2467 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2468 bl dvmResolveInstField @ r0<- resolved InstField ptr 2469 cmp r0, #0 2470 bne .LOP_IGET_finish 2471 b common_exceptionThrown 2472 2473/* ------------------------------ */ 2474 .balign 64 2475.L_OP_IGET_WIDE: /* 0x53 */ 2476/* File: armv5te/OP_IGET_WIDE.S */ 2477 /* 2478 * Wide 32-bit instance field get. 2479 */ 2480 /* iget-wide vA, vB, field@CCCC */ 2481 mov r0, rINST, lsr #12 @ r0<- B 2482 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2483 FETCH(r1, 1) @ r1<- field ref CCCC 2484 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2485 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2486 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2487 cmp r0, #0 @ is resolved entry null? 2488 bne .LOP_IGET_WIDE_finish @ no, already resolved 24898: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2490 EXPORT_PC() @ resolve() could throw 2491 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2492 bl dvmResolveInstField @ r0<- resolved InstField ptr 2493 cmp r0, #0 2494 bne .LOP_IGET_WIDE_finish 2495 b common_exceptionThrown 2496 2497/* ------------------------------ */ 2498 .balign 64 2499.L_OP_IGET_OBJECT: /* 0x54 */ 2500/* File: armv5te/OP_IGET_OBJECT.S */ 2501/* File: armv5te/OP_IGET.S */ 2502 /* 2503 * General 32-bit instance field get. 2504 * 2505 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2506 */ 2507 /* op vA, vB, field@CCCC */ 2508 mov r0, rINST, lsr #12 @ r0<- B 2509 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2510 FETCH(r1, 1) @ r1<- field ref CCCC 2511 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2512 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2513 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2514 cmp r0, #0 @ is resolved entry null? 2515 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25168: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2517 EXPORT_PC() @ resolve() could throw 2518 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2519 bl dvmResolveInstField @ r0<- resolved InstField ptr 2520 cmp r0, #0 2521 bne .LOP_IGET_OBJECT_finish 2522 b common_exceptionThrown 2523 2524 2525/* ------------------------------ */ 2526 .balign 64 2527.L_OP_IGET_BOOLEAN: /* 0x55 */ 2528/* File: armv5te/OP_IGET_BOOLEAN.S */ 2529@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2530/* File: armv5te/OP_IGET.S */ 2531 /* 2532 * General 32-bit instance field get. 2533 * 2534 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2535 */ 2536 /* op vA, vB, field@CCCC */ 2537 mov r0, rINST, lsr #12 @ r0<- B 2538 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2539 FETCH(r1, 1) @ r1<- field ref CCCC 2540 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2541 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2542 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2543 cmp r0, #0 @ is resolved entry null? 2544 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25458: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2546 EXPORT_PC() @ resolve() could throw 2547 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2548 bl dvmResolveInstField @ r0<- resolved InstField ptr 2549 cmp r0, #0 2550 bne .LOP_IGET_BOOLEAN_finish 2551 b common_exceptionThrown 2552 2553 2554/* ------------------------------ */ 2555 .balign 64 2556.L_OP_IGET_BYTE: /* 0x56 */ 2557/* File: armv5te/OP_IGET_BYTE.S */ 2558@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2559/* File: armv5te/OP_IGET.S */ 2560 /* 2561 * General 32-bit instance field get. 2562 * 2563 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2564 */ 2565 /* op vA, vB, field@CCCC */ 2566 mov r0, rINST, lsr #12 @ r0<- B 2567 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2568 FETCH(r1, 1) @ r1<- field ref CCCC 2569 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2570 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2571 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2572 cmp r0, #0 @ is resolved entry null? 2573 bne .LOP_IGET_BYTE_finish @ no, already resolved 25748: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2575 EXPORT_PC() @ resolve() could throw 2576 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2577 bl dvmResolveInstField @ r0<- resolved InstField ptr 2578 cmp r0, #0 2579 bne .LOP_IGET_BYTE_finish 2580 b common_exceptionThrown 2581 2582 2583/* ------------------------------ */ 2584 .balign 64 2585.L_OP_IGET_CHAR: /* 0x57 */ 2586/* File: armv5te/OP_IGET_CHAR.S */ 2587@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2588/* File: armv5te/OP_IGET.S */ 2589 /* 2590 * General 32-bit instance field get. 2591 * 2592 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2593 */ 2594 /* op vA, vB, field@CCCC */ 2595 mov r0, rINST, lsr #12 @ r0<- B 2596 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2597 FETCH(r1, 1) @ r1<- field ref CCCC 2598 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2599 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2600 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2601 cmp r0, #0 @ is resolved entry null? 2602 bne .LOP_IGET_CHAR_finish @ no, already resolved 26038: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2604 EXPORT_PC() @ resolve() could throw 2605 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2606 bl dvmResolveInstField @ r0<- resolved InstField ptr 2607 cmp r0, #0 2608 bne .LOP_IGET_CHAR_finish 2609 b common_exceptionThrown 2610 2611 2612/* ------------------------------ */ 2613 .balign 64 2614.L_OP_IGET_SHORT: /* 0x58 */ 2615/* File: armv5te/OP_IGET_SHORT.S */ 2616@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2617/* File: armv5te/OP_IGET.S */ 2618 /* 2619 * General 32-bit instance field get. 2620 * 2621 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2622 */ 2623 /* op vA, vB, field@CCCC */ 2624 mov r0, rINST, lsr #12 @ r0<- B 2625 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2626 FETCH(r1, 1) @ r1<- field ref CCCC 2627 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2628 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2629 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2630 cmp r0, #0 @ is resolved entry null? 2631 bne .LOP_IGET_SHORT_finish @ no, already resolved 26328: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2633 EXPORT_PC() @ resolve() could throw 2634 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2635 bl dvmResolveInstField @ r0<- resolved InstField ptr 2636 cmp r0, #0 2637 bne .LOP_IGET_SHORT_finish 2638 b common_exceptionThrown 2639 2640 2641/* ------------------------------ */ 2642 .balign 64 2643.L_OP_IPUT: /* 0x59 */ 2644/* File: armv5te/OP_IPUT.S */ 2645 /* 2646 * General 32-bit instance field put. 2647 * 2648 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2649 */ 2650 /* op vA, vB, field@CCCC */ 2651 mov r0, rINST, lsr #12 @ r0<- B 2652 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2653 FETCH(r1, 1) @ r1<- field ref CCCC 2654 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2655 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2656 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2657 cmp r0, #0 @ is resolved entry null? 2658 bne .LOP_IPUT_finish @ no, already resolved 26598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2660 EXPORT_PC() @ resolve() could throw 2661 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2662 bl dvmResolveInstField @ r0<- resolved InstField ptr 2663 cmp r0, #0 @ success? 2664 bne .LOP_IPUT_finish @ yes, finish up 2665 b common_exceptionThrown 2666 2667/* ------------------------------ */ 2668 .balign 64 2669.L_OP_IPUT_WIDE: /* 0x5a */ 2670/* File: armv5te/OP_IPUT_WIDE.S */ 2671 /* iput-wide vA, vB, field@CCCC */ 2672 mov r0, rINST, lsr #12 @ r0<- B 2673 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2674 FETCH(r1, 1) @ r1<- field ref CCCC 2675 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2676 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2677 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2678 cmp r0, #0 @ is resolved entry null? 2679 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26808: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2681 EXPORT_PC() @ resolve() could throw 2682 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2683 bl dvmResolveInstField @ r0<- resolved InstField ptr 2684 cmp r0, #0 @ success? 2685 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2686 b common_exceptionThrown 2687 2688/* ------------------------------ */ 2689 .balign 64 2690.L_OP_IPUT_OBJECT: /* 0x5b */ 2691/* File: armv5te/OP_IPUT_OBJECT.S */ 2692/* File: armv5te/OP_IPUT.S */ 2693 /* 2694 * General 32-bit instance field put. 2695 * 2696 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2697 */ 2698 /* op vA, vB, field@CCCC */ 2699 mov r0, rINST, lsr #12 @ r0<- B 2700 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2701 FETCH(r1, 1) @ r1<- field ref CCCC 2702 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2703 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2704 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2705 cmp r0, #0 @ is resolved entry null? 2706 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2708 EXPORT_PC() @ resolve() could throw 2709 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2710 bl dvmResolveInstField @ r0<- resolved InstField ptr 2711 cmp r0, #0 @ success? 2712 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2713 b common_exceptionThrown 2714 2715 2716/* ------------------------------ */ 2717 .balign 64 2718.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2719/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2720@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2721/* File: armv5te/OP_IPUT.S */ 2722 /* 2723 * General 32-bit instance field put. 2724 * 2725 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2726 */ 2727 /* op vA, vB, field@CCCC */ 2728 mov r0, rINST, lsr #12 @ r0<- B 2729 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2730 FETCH(r1, 1) @ r1<- field ref CCCC 2731 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2732 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2733 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2734 cmp r0, #0 @ is resolved entry null? 2735 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2737 EXPORT_PC() @ resolve() could throw 2738 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2739 bl dvmResolveInstField @ r0<- resolved InstField ptr 2740 cmp r0, #0 @ success? 2741 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2742 b common_exceptionThrown 2743 2744 2745/* ------------------------------ */ 2746 .balign 64 2747.L_OP_IPUT_BYTE: /* 0x5d */ 2748/* File: armv5te/OP_IPUT_BYTE.S */ 2749@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2750/* File: armv5te/OP_IPUT.S */ 2751 /* 2752 * General 32-bit instance field put. 2753 * 2754 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2755 */ 2756 /* op vA, vB, field@CCCC */ 2757 mov r0, rINST, lsr #12 @ r0<- B 2758 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2759 FETCH(r1, 1) @ r1<- field ref CCCC 2760 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2761 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2762 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2763 cmp r0, #0 @ is resolved entry null? 2764 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27658: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2766 EXPORT_PC() @ resolve() could throw 2767 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2768 bl dvmResolveInstField @ r0<- resolved InstField ptr 2769 cmp r0, #0 @ success? 2770 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2771 b common_exceptionThrown 2772 2773 2774/* ------------------------------ */ 2775 .balign 64 2776.L_OP_IPUT_CHAR: /* 0x5e */ 2777/* File: armv5te/OP_IPUT_CHAR.S */ 2778@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2779/* File: armv5te/OP_IPUT.S */ 2780 /* 2781 * General 32-bit instance field put. 2782 * 2783 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2784 */ 2785 /* op vA, vB, field@CCCC */ 2786 mov r0, rINST, lsr #12 @ r0<- B 2787 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2788 FETCH(r1, 1) @ r1<- field ref CCCC 2789 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2790 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2791 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2792 cmp r0, #0 @ is resolved entry null? 2793 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2795 EXPORT_PC() @ resolve() could throw 2796 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2797 bl dvmResolveInstField @ r0<- resolved InstField ptr 2798 cmp r0, #0 @ success? 2799 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2800 b common_exceptionThrown 2801 2802 2803/* ------------------------------ */ 2804 .balign 64 2805.L_OP_IPUT_SHORT: /* 0x5f */ 2806/* File: armv5te/OP_IPUT_SHORT.S */ 2807@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2808/* File: armv5te/OP_IPUT.S */ 2809 /* 2810 * General 32-bit instance field put. 2811 * 2812 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2813 */ 2814 /* op vA, vB, field@CCCC */ 2815 mov r0, rINST, lsr #12 @ r0<- B 2816 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2817 FETCH(r1, 1) @ r1<- field ref CCCC 2818 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2819 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2820 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2821 cmp r0, #0 @ is resolved entry null? 2822 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2824 EXPORT_PC() @ resolve() could throw 2825 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2826 bl dvmResolveInstField @ r0<- resolved InstField ptr 2827 cmp r0, #0 @ success? 2828 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2829 b common_exceptionThrown 2830 2831 2832/* ------------------------------ */ 2833 .balign 64 2834.L_OP_SGET: /* 0x60 */ 2835/* File: armv5te/OP_SGET.S */ 2836 /* 2837 * General 32-bit SGET handler. 2838 * 2839 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2840 */ 2841 /* op vAA, field@BBBB */ 2842 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2843 FETCH(r1, 1) @ r1<- field ref BBBB 2844 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2845 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2846 cmp r0, #0 @ is resolved entry null? 2847 beq .LOP_SGET_resolve @ yes, do resolve 2848.LOP_SGET_finish: @ field ptr in r0 2849 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2850 mov r2, rINST, lsr #8 @ r2<- AA 2851 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2852 SET_VREG(r1, r2) @ fp[AA]<- r1 2853 GET_INST_OPCODE(ip) @ extract opcode from rINST 2854 GOTO_OPCODE(ip) @ jump to next instruction 2855 2856/* ------------------------------ */ 2857 .balign 64 2858.L_OP_SGET_WIDE: /* 0x61 */ 2859/* File: armv5te/OP_SGET_WIDE.S */ 2860 /* 2861 * 64-bit SGET handler. 2862 */ 2863 /* sget-wide vAA, field@BBBB */ 2864 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2865 FETCH(r1, 1) @ r1<- field ref BBBB 2866 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2867 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2868 cmp r0, #0 @ is resolved entry null? 2869 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2870.LOP_SGET_WIDE_finish: 2871 mov r1, rINST, lsr #8 @ r1<- AA 2872 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2873 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2874 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2875 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2876 GET_INST_OPCODE(ip) @ extract opcode from rINST 2877 GOTO_OPCODE(ip) @ jump to next instruction 2878 2879/* ------------------------------ */ 2880 .balign 64 2881.L_OP_SGET_OBJECT: /* 0x62 */ 2882/* File: armv5te/OP_SGET_OBJECT.S */ 2883/* File: armv5te/OP_SGET.S */ 2884 /* 2885 * General 32-bit SGET handler. 2886 * 2887 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2888 */ 2889 /* op vAA, field@BBBB */ 2890 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2891 FETCH(r1, 1) @ r1<- field ref BBBB 2892 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2893 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2894 cmp r0, #0 @ is resolved entry null? 2895 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2896.LOP_SGET_OBJECT_finish: @ field ptr in r0 2897 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2898 mov r2, rINST, lsr #8 @ r2<- AA 2899 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2900 SET_VREG(r1, r2) @ fp[AA]<- r1 2901 GET_INST_OPCODE(ip) @ extract opcode from rINST 2902 GOTO_OPCODE(ip) @ jump to next instruction 2903 2904 2905/* ------------------------------ */ 2906 .balign 64 2907.L_OP_SGET_BOOLEAN: /* 0x63 */ 2908/* File: armv5te/OP_SGET_BOOLEAN.S */ 2909/* File: armv5te/OP_SGET.S */ 2910 /* 2911 * General 32-bit SGET handler. 2912 * 2913 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2914 */ 2915 /* op vAA, field@BBBB */ 2916 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2917 FETCH(r1, 1) @ r1<- field ref BBBB 2918 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2919 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2920 cmp r0, #0 @ is resolved entry null? 2921 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2922.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2923 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2924 mov r2, rINST, lsr #8 @ r2<- AA 2925 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2926 SET_VREG(r1, r2) @ fp[AA]<- r1 2927 GET_INST_OPCODE(ip) @ extract opcode from rINST 2928 GOTO_OPCODE(ip) @ jump to next instruction 2929 2930 2931/* ------------------------------ */ 2932 .balign 64 2933.L_OP_SGET_BYTE: /* 0x64 */ 2934/* File: armv5te/OP_SGET_BYTE.S */ 2935/* File: armv5te/OP_SGET.S */ 2936 /* 2937 * General 32-bit SGET handler. 2938 * 2939 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2940 */ 2941 /* op vAA, field@BBBB */ 2942 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2943 FETCH(r1, 1) @ r1<- field ref BBBB 2944 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2945 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2946 cmp r0, #0 @ is resolved entry null? 2947 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2948.LOP_SGET_BYTE_finish: @ field ptr in r0 2949 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2950 mov r2, rINST, lsr #8 @ r2<- AA 2951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2952 SET_VREG(r1, r2) @ fp[AA]<- r1 2953 GET_INST_OPCODE(ip) @ extract opcode from rINST 2954 GOTO_OPCODE(ip) @ jump to next instruction 2955 2956 2957/* ------------------------------ */ 2958 .balign 64 2959.L_OP_SGET_CHAR: /* 0x65 */ 2960/* File: armv5te/OP_SGET_CHAR.S */ 2961/* File: armv5te/OP_SGET.S */ 2962 /* 2963 * General 32-bit SGET handler. 2964 * 2965 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2966 */ 2967 /* op vAA, field@BBBB */ 2968 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2969 FETCH(r1, 1) @ r1<- field ref BBBB 2970 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2971 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2972 cmp r0, #0 @ is resolved entry null? 2973 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2974.LOP_SGET_CHAR_finish: @ field ptr in r0 2975 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2976 mov r2, rINST, lsr #8 @ r2<- AA 2977 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2978 SET_VREG(r1, r2) @ fp[AA]<- r1 2979 GET_INST_OPCODE(ip) @ extract opcode from rINST 2980 GOTO_OPCODE(ip) @ jump to next instruction 2981 2982 2983/* ------------------------------ */ 2984 .balign 64 2985.L_OP_SGET_SHORT: /* 0x66 */ 2986/* File: armv5te/OP_SGET_SHORT.S */ 2987/* File: armv5te/OP_SGET.S */ 2988 /* 2989 * General 32-bit SGET handler. 2990 * 2991 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2992 */ 2993 /* op vAA, field@BBBB */ 2994 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2995 FETCH(r1, 1) @ r1<- field ref BBBB 2996 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2997 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2998 cmp r0, #0 @ is resolved entry null? 2999 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 3000.LOP_SGET_SHORT_finish: @ field ptr in r0 3001 ldr r1, [r0, #offStaticField_value] @ r1<- field value 3002 mov r2, rINST, lsr #8 @ r2<- AA 3003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3004 SET_VREG(r1, r2) @ fp[AA]<- r1 3005 GET_INST_OPCODE(ip) @ extract opcode from rINST 3006 GOTO_OPCODE(ip) @ jump to next instruction 3007 3008 3009/* ------------------------------ */ 3010 .balign 64 3011.L_OP_SPUT: /* 0x67 */ 3012/* File: armv5te/OP_SPUT.S */ 3013 /* 3014 * General 32-bit SPUT handler. 3015 * 3016 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3017 */ 3018 /* op vAA, field@BBBB */ 3019 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3020 FETCH(r1, 1) @ r1<- field ref BBBB 3021 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3022 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3023 cmp r0, #0 @ is resolved entry null? 3024 beq .LOP_SPUT_resolve @ yes, do resolve 3025.LOP_SPUT_finish: @ field ptr in r0 3026 mov r2, rINST, lsr #8 @ r2<- AA 3027 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3028 GET_VREG(r1, r2) @ r1<- fp[AA] 3029 GET_INST_OPCODE(ip) @ extract opcode from rINST 3030 str r1, [r0, #offStaticField_value] @ field<- vAA 3031 GOTO_OPCODE(ip) @ jump to next instruction 3032 3033/* ------------------------------ */ 3034 .balign 64 3035.L_OP_SPUT_WIDE: /* 0x68 */ 3036/* File: armv5te/OP_SPUT_WIDE.S */ 3037 /* 3038 * 64-bit SPUT handler. 3039 */ 3040 /* sput-wide vAA, field@BBBB */ 3041 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3042 FETCH(r1, 1) @ r1<- field ref BBBB 3043 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3044 mov r9, rINST, lsr #8 @ r9<- AA 3045 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3046 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3047 cmp r0, #0 @ is resolved entry null? 3048 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3049.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3050 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3051 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3052 GET_INST_OPCODE(ip) @ extract opcode from rINST 3053 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3054 GOTO_OPCODE(ip) @ jump to next instruction 3055 3056/* ------------------------------ */ 3057 .balign 64 3058.L_OP_SPUT_OBJECT: /* 0x69 */ 3059/* File: armv5te/OP_SPUT_OBJECT.S */ 3060/* File: armv5te/OP_SPUT.S */ 3061 /* 3062 * General 32-bit SPUT handler. 3063 * 3064 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3065 */ 3066 /* op vAA, field@BBBB */ 3067 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3068 FETCH(r1, 1) @ r1<- field ref BBBB 3069 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3070 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3071 cmp r0, #0 @ is resolved entry null? 3072 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3073.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3074 mov r2, rINST, lsr #8 @ r2<- AA 3075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3076 GET_VREG(r1, r2) @ r1<- fp[AA] 3077 GET_INST_OPCODE(ip) @ extract opcode from rINST 3078 str r1, [r0, #offStaticField_value] @ field<- vAA 3079 GOTO_OPCODE(ip) @ jump to next instruction 3080 3081 3082/* ------------------------------ */ 3083 .balign 64 3084.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3085/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3086/* File: armv5te/OP_SPUT.S */ 3087 /* 3088 * General 32-bit SPUT handler. 3089 * 3090 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3091 */ 3092 /* op vAA, field@BBBB */ 3093 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3094 FETCH(r1, 1) @ r1<- field ref BBBB 3095 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3096 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3097 cmp r0, #0 @ is resolved entry null? 3098 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3099.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3100 mov r2, rINST, lsr #8 @ r2<- AA 3101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3102 GET_VREG(r1, r2) @ r1<- fp[AA] 3103 GET_INST_OPCODE(ip) @ extract opcode from rINST 3104 str r1, [r0, #offStaticField_value] @ field<- vAA 3105 GOTO_OPCODE(ip) @ jump to next instruction 3106 3107 3108/* ------------------------------ */ 3109 .balign 64 3110.L_OP_SPUT_BYTE: /* 0x6b */ 3111/* File: armv5te/OP_SPUT_BYTE.S */ 3112/* File: armv5te/OP_SPUT.S */ 3113 /* 3114 * General 32-bit SPUT handler. 3115 * 3116 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3117 */ 3118 /* op vAA, field@BBBB */ 3119 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3120 FETCH(r1, 1) @ r1<- field ref BBBB 3121 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3122 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3123 cmp r0, #0 @ is resolved entry null? 3124 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3125.LOP_SPUT_BYTE_finish: @ field ptr in r0 3126 mov r2, rINST, lsr #8 @ r2<- AA 3127 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3128 GET_VREG(r1, r2) @ r1<- fp[AA] 3129 GET_INST_OPCODE(ip) @ extract opcode from rINST 3130 str r1, [r0, #offStaticField_value] @ field<- vAA 3131 GOTO_OPCODE(ip) @ jump to next instruction 3132 3133 3134/* ------------------------------ */ 3135 .balign 64 3136.L_OP_SPUT_CHAR: /* 0x6c */ 3137/* File: armv5te/OP_SPUT_CHAR.S */ 3138/* File: armv5te/OP_SPUT.S */ 3139 /* 3140 * General 32-bit SPUT handler. 3141 * 3142 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3143 */ 3144 /* op vAA, field@BBBB */ 3145 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3146 FETCH(r1, 1) @ r1<- field ref BBBB 3147 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3148 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3149 cmp r0, #0 @ is resolved entry null? 3150 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3151.LOP_SPUT_CHAR_finish: @ field ptr in r0 3152 mov r2, rINST, lsr #8 @ r2<- AA 3153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3154 GET_VREG(r1, r2) @ r1<- fp[AA] 3155 GET_INST_OPCODE(ip) @ extract opcode from rINST 3156 str r1, [r0, #offStaticField_value] @ field<- vAA 3157 GOTO_OPCODE(ip) @ jump to next instruction 3158 3159 3160/* ------------------------------ */ 3161 .balign 64 3162.L_OP_SPUT_SHORT: /* 0x6d */ 3163/* File: armv5te/OP_SPUT_SHORT.S */ 3164/* File: armv5te/OP_SPUT.S */ 3165 /* 3166 * General 32-bit SPUT handler. 3167 * 3168 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3169 */ 3170 /* op vAA, field@BBBB */ 3171 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3172 FETCH(r1, 1) @ r1<- field ref BBBB 3173 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3174 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3175 cmp r0, #0 @ is resolved entry null? 3176 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3177.LOP_SPUT_SHORT_finish: @ field ptr in r0 3178 mov r2, rINST, lsr #8 @ r2<- AA 3179 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3180 GET_VREG(r1, r2) @ r1<- fp[AA] 3181 GET_INST_OPCODE(ip) @ extract opcode from rINST 3182 str r1, [r0, #offStaticField_value] @ field<- vAA 3183 GOTO_OPCODE(ip) @ jump to next instruction 3184 3185 3186/* ------------------------------ */ 3187 .balign 64 3188.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3189/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3190 /* 3191 * Handle a virtual method call. 3192 * 3193 * for: invoke-virtual, invoke-virtual/range 3194 */ 3195 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3196 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3197 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3198 FETCH(r1, 1) @ r1<- BBBB 3199 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3200 FETCH(r10, 2) @ r10<- GFED or CCCC 3201 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3202 .if (!0) 3203 and r10, r10, #15 @ r10<- D (or stays CCCC) 3204 .endif 3205 cmp r0, #0 @ already resolved? 3206 EXPORT_PC() @ must export for invoke 3207 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3208 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3209 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3210 mov r2, #METHOD_VIRTUAL @ resolver method type 3211 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3212 cmp r0, #0 @ got null? 3213 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3214 b common_exceptionThrown @ yes, handle exception 3215 3216/* ------------------------------ */ 3217 .balign 64 3218.L_OP_INVOKE_SUPER: /* 0x6f */ 3219/* File: armv5te/OP_INVOKE_SUPER.S */ 3220 /* 3221 * Handle a "super" method call. 3222 * 3223 * for: invoke-super, invoke-super/range 3224 */ 3225 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3226 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3227 FETCH(r10, 2) @ r10<- GFED or CCCC 3228 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3229 .if (!0) 3230 and r10, r10, #15 @ r10<- D (or stays CCCC) 3231 .endif 3232 FETCH(r1, 1) @ r1<- BBBB 3233 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3234 GET_VREG(r2, r10) @ r2<- "this" ptr 3235 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3236 cmp r2, #0 @ null "this"? 3237 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3238 beq common_errNullObject @ null "this", throw exception 3239 cmp r0, #0 @ already resolved? 3240 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3241 EXPORT_PC() @ must export for invoke 3242 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3243 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3244 3245/* ------------------------------ */ 3246 .balign 64 3247.L_OP_INVOKE_DIRECT: /* 0x70 */ 3248/* File: armv5te/OP_INVOKE_DIRECT.S */ 3249 /* 3250 * Handle a direct method call. 3251 * 3252 * (We could defer the "is 'this' pointer null" test to the common 3253 * method invocation code, and use a flag to indicate that static 3254 * calls don't count. If we do this as part of copying the arguments 3255 * out we could avoiding loading the first arg twice.) 3256 * 3257 * for: invoke-direct, invoke-direct/range 3258 */ 3259 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3260 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3261 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3262 FETCH(r1, 1) @ r1<- BBBB 3263 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3264 FETCH(r10, 2) @ r10<- GFED or CCCC 3265 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3266 .if (!0) 3267 and r10, r10, #15 @ r10<- D (or stays CCCC) 3268 .endif 3269 cmp r0, #0 @ already resolved? 3270 EXPORT_PC() @ must export for invoke 3271 GET_VREG(r2, r10) @ r2<- "this" ptr 3272 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3273.LOP_INVOKE_DIRECT_finish: 3274 cmp r2, #0 @ null "this" ref? 3275 bne common_invokeMethodNoRange @ no, continue on 3276 b common_errNullObject @ yes, throw exception 3277 3278/* ------------------------------ */ 3279 .balign 64 3280.L_OP_INVOKE_STATIC: /* 0x71 */ 3281/* File: armv5te/OP_INVOKE_STATIC.S */ 3282 /* 3283 * Handle a static method call. 3284 * 3285 * for: invoke-static, invoke-static/range 3286 */ 3287 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3288 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3289 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3290 FETCH(r1, 1) @ r1<- BBBB 3291 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3292 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3293 cmp r0, #0 @ already resolved? 3294 EXPORT_PC() @ must export for invoke 3295 bne common_invokeMethodNoRange @ yes, continue on 32960: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3297 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3298 mov r2, #METHOD_STATIC @ resolver method type 3299 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3300 cmp r0, #0 @ got null? 3301 bne common_invokeMethodNoRange @ no, continue 3302 b common_exceptionThrown @ yes, handle exception 3303 3304 3305/* ------------------------------ */ 3306 .balign 64 3307.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3308/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3309 /* 3310 * Handle an interface method call. 3311 * 3312 * for: invoke-interface, invoke-interface/range 3313 */ 3314 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3315 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3316 FETCH(r2, 2) @ r2<- FEDC or CCCC 3317 FETCH(r1, 1) @ r1<- BBBB 3318 .if (!0) 3319 and r2, r2, #15 @ r2<- C (or stays CCCC) 3320 .endif 3321 EXPORT_PC() @ must export for invoke 3322 GET_VREG(r0, r2) @ r0<- first arg ("this") 3323 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3324 cmp r0, #0 @ null obj? 3325 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3326 beq common_errNullObject @ yes, fail 3327 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3328 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3329 cmp r0, #0 @ failed? 3330 beq common_exceptionThrown @ yes, handle exception 3331 b common_invokeMethodNoRange @ jump to common handler 3332 3333 3334/* ------------------------------ */ 3335 .balign 64 3336.L_OP_UNUSED_73: /* 0x73 */ 3337/* File: armv5te/OP_UNUSED_73.S */ 3338/* File: armv5te/unused.S */ 3339 bl common_abort 3340 3341 3342 3343/* ------------------------------ */ 3344 .balign 64 3345.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3346/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3347/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3348 /* 3349 * Handle a virtual method call. 3350 * 3351 * for: invoke-virtual, invoke-virtual/range 3352 */ 3353 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3354 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3355 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3356 FETCH(r1, 1) @ r1<- BBBB 3357 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3358 FETCH(r10, 2) @ r10<- GFED or CCCC 3359 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3360 .if (!1) 3361 and r10, r10, #15 @ r10<- D (or stays CCCC) 3362 .endif 3363 cmp r0, #0 @ already resolved? 3364 EXPORT_PC() @ must export for invoke 3365 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3366 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3367 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3368 mov r2, #METHOD_VIRTUAL @ resolver method type 3369 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3370 cmp r0, #0 @ got null? 3371 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3372 b common_exceptionThrown @ yes, handle exception 3373 3374 3375/* ------------------------------ */ 3376 .balign 64 3377.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3378/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3379/* File: armv5te/OP_INVOKE_SUPER.S */ 3380 /* 3381 * Handle a "super" method call. 3382 * 3383 * for: invoke-super, invoke-super/range 3384 */ 3385 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3386 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3387 FETCH(r10, 2) @ r10<- GFED or CCCC 3388 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3389 .if (!1) 3390 and r10, r10, #15 @ r10<- D (or stays CCCC) 3391 .endif 3392 FETCH(r1, 1) @ r1<- BBBB 3393 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3394 GET_VREG(r2, r10) @ r2<- "this" ptr 3395 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3396 cmp r2, #0 @ null "this"? 3397 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3398 beq common_errNullObject @ null "this", throw exception 3399 cmp r0, #0 @ already resolved? 3400 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3401 EXPORT_PC() @ must export for invoke 3402 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3403 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3404 3405 3406/* ------------------------------ */ 3407 .balign 64 3408.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3409/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3410/* File: armv5te/OP_INVOKE_DIRECT.S */ 3411 /* 3412 * Handle a direct method call. 3413 * 3414 * (We could defer the "is 'this' pointer null" test to the common 3415 * method invocation code, and use a flag to indicate that static 3416 * calls don't count. If we do this as part of copying the arguments 3417 * out we could avoiding loading the first arg twice.) 3418 * 3419 * for: invoke-direct, invoke-direct/range 3420 */ 3421 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3422 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3423 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3424 FETCH(r1, 1) @ r1<- BBBB 3425 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3426 FETCH(r10, 2) @ r10<- GFED or CCCC 3427 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3428 .if (!1) 3429 and r10, r10, #15 @ r10<- D (or stays CCCC) 3430 .endif 3431 cmp r0, #0 @ already resolved? 3432 EXPORT_PC() @ must export for invoke 3433 GET_VREG(r2, r10) @ r2<- "this" ptr 3434 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3435.LOP_INVOKE_DIRECT_RANGE_finish: 3436 cmp r2, #0 @ null "this" ref? 3437 bne common_invokeMethodRange @ no, continue on 3438 b common_errNullObject @ yes, throw exception 3439 3440 3441/* ------------------------------ */ 3442 .balign 64 3443.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3444/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3445/* File: armv5te/OP_INVOKE_STATIC.S */ 3446 /* 3447 * Handle a static method call. 3448 * 3449 * for: invoke-static, invoke-static/range 3450 */ 3451 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3452 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3453 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3454 FETCH(r1, 1) @ r1<- BBBB 3455 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3456 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3457 cmp r0, #0 @ already resolved? 3458 EXPORT_PC() @ must export for invoke 3459 bne common_invokeMethodRange @ yes, continue on 34600: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3461 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3462 mov r2, #METHOD_STATIC @ resolver method type 3463 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3464 cmp r0, #0 @ got null? 3465 bne common_invokeMethodRange @ no, continue 3466 b common_exceptionThrown @ yes, handle exception 3467 3468 3469 3470/* ------------------------------ */ 3471 .balign 64 3472.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3473/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3474/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3475 /* 3476 * Handle an interface method call. 3477 * 3478 * for: invoke-interface, invoke-interface/range 3479 */ 3480 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3481 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3482 FETCH(r2, 2) @ r2<- FEDC or CCCC 3483 FETCH(r1, 1) @ r1<- BBBB 3484 .if (!1) 3485 and r2, r2, #15 @ r2<- C (or stays CCCC) 3486 .endif 3487 EXPORT_PC() @ must export for invoke 3488 GET_VREG(r0, r2) @ r0<- first arg ("this") 3489 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3490 cmp r0, #0 @ null obj? 3491 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3492 beq common_errNullObject @ yes, fail 3493 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3494 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3495 cmp r0, #0 @ failed? 3496 beq common_exceptionThrown @ yes, handle exception 3497 b common_invokeMethodRange @ jump to common handler 3498 3499 3500 3501/* ------------------------------ */ 3502 .balign 64 3503.L_OP_UNUSED_79: /* 0x79 */ 3504/* File: armv5te/OP_UNUSED_79.S */ 3505/* File: armv5te/unused.S */ 3506 bl common_abort 3507 3508 3509 3510/* ------------------------------ */ 3511 .balign 64 3512.L_OP_UNUSED_7A: /* 0x7a */ 3513/* File: armv5te/OP_UNUSED_7A.S */ 3514/* File: armv5te/unused.S */ 3515 bl common_abort 3516 3517 3518 3519/* ------------------------------ */ 3520 .balign 64 3521.L_OP_NEG_INT: /* 0x7b */ 3522/* File: armv5te/OP_NEG_INT.S */ 3523/* File: armv5te/unop.S */ 3524 /* 3525 * Generic 32-bit unary operation. Provide an "instr" line that 3526 * specifies an instruction that performs "result = op r0". 3527 * This could be an ARM instruction or a function call. 3528 * 3529 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3530 * int-to-byte, int-to-char, int-to-short 3531 */ 3532 /* unop vA, vB */ 3533 mov r3, rINST, lsr #12 @ r3<- B 3534 mov r9, rINST, lsr #8 @ r9<- A+ 3535 GET_VREG(r0, r3) @ r0<- vB 3536 and r9, r9, #15 3537 @ optional op; may set condition codes 3538 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3539 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3540 GET_INST_OPCODE(ip) @ extract opcode from rINST 3541 SET_VREG(r0, r9) @ vAA<- r0 3542 GOTO_OPCODE(ip) @ jump to next instruction 3543 /* 9-10 instructions */ 3544 3545 3546/* ------------------------------ */ 3547 .balign 64 3548.L_OP_NOT_INT: /* 0x7c */ 3549/* File: armv5te/OP_NOT_INT.S */ 3550/* File: armv5te/unop.S */ 3551 /* 3552 * Generic 32-bit unary operation. Provide an "instr" line that 3553 * specifies an instruction that performs "result = op r0". 3554 * This could be an ARM instruction or a function call. 3555 * 3556 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3557 * int-to-byte, int-to-char, int-to-short 3558 */ 3559 /* unop vA, vB */ 3560 mov r3, rINST, lsr #12 @ r3<- B 3561 mov r9, rINST, lsr #8 @ r9<- A+ 3562 GET_VREG(r0, r3) @ r0<- vB 3563 and r9, r9, #15 3564 @ optional op; may set condition codes 3565 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3566 mvn r0, r0 @ r0<- op, r0-r3 changed 3567 GET_INST_OPCODE(ip) @ extract opcode from rINST 3568 SET_VREG(r0, r9) @ vAA<- r0 3569 GOTO_OPCODE(ip) @ jump to next instruction 3570 /* 9-10 instructions */ 3571 3572 3573/* ------------------------------ */ 3574 .balign 64 3575.L_OP_NEG_LONG: /* 0x7d */ 3576/* File: armv5te/OP_NEG_LONG.S */ 3577/* File: armv5te/unopWide.S */ 3578 /* 3579 * Generic 64-bit unary operation. Provide an "instr" line that 3580 * specifies an instruction that performs "result = op r0/r1". 3581 * This could be an ARM instruction or a function call. 3582 * 3583 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3584 */ 3585 /* unop vA, vB */ 3586 mov r9, rINST, lsr #8 @ r9<- A+ 3587 mov r3, rINST, lsr #12 @ r3<- B 3588 and r9, r9, #15 3589 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3590 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3591 ldmia r3, {r0-r1} @ r0/r1<- vAA 3592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3593 rsbs r0, r0, #0 @ optional op; may set condition codes 3594 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3595 GET_INST_OPCODE(ip) @ extract opcode from rINST 3596 stmia r9, {r0-r1} @ vAA<- r0/r1 3597 GOTO_OPCODE(ip) @ jump to next instruction 3598 /* 12-13 instructions */ 3599 3600 3601 3602/* ------------------------------ */ 3603 .balign 64 3604.L_OP_NOT_LONG: /* 0x7e */ 3605/* File: armv5te/OP_NOT_LONG.S */ 3606/* File: armv5te/unopWide.S */ 3607 /* 3608 * Generic 64-bit unary operation. Provide an "instr" line that 3609 * specifies an instruction that performs "result = op r0/r1". 3610 * This could be an ARM instruction or a function call. 3611 * 3612 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3613 */ 3614 /* unop vA, vB */ 3615 mov r9, rINST, lsr #8 @ r9<- A+ 3616 mov r3, rINST, lsr #12 @ r3<- B 3617 and r9, r9, #15 3618 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3619 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3620 ldmia r3, {r0-r1} @ r0/r1<- vAA 3621 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3622 mvn r0, r0 @ optional op; may set condition codes 3623 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3624 GET_INST_OPCODE(ip) @ extract opcode from rINST 3625 stmia r9, {r0-r1} @ vAA<- r0/r1 3626 GOTO_OPCODE(ip) @ jump to next instruction 3627 /* 12-13 instructions */ 3628 3629 3630 3631/* ------------------------------ */ 3632 .balign 64 3633.L_OP_NEG_FLOAT: /* 0x7f */ 3634/* File: armv5te/OP_NEG_FLOAT.S */ 3635/* File: armv5te/unop.S */ 3636 /* 3637 * Generic 32-bit unary operation. Provide an "instr" line that 3638 * specifies an instruction that performs "result = op r0". 3639 * This could be an ARM instruction or a function call. 3640 * 3641 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3642 * int-to-byte, int-to-char, int-to-short 3643 */ 3644 /* unop vA, vB */ 3645 mov r3, rINST, lsr #12 @ r3<- B 3646 mov r9, rINST, lsr #8 @ r9<- A+ 3647 GET_VREG(r0, r3) @ r0<- vB 3648 and r9, r9, #15 3649 @ optional op; may set condition codes 3650 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3651 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3652 GET_INST_OPCODE(ip) @ extract opcode from rINST 3653 SET_VREG(r0, r9) @ vAA<- r0 3654 GOTO_OPCODE(ip) @ jump to next instruction 3655 /* 9-10 instructions */ 3656 3657 3658/* ------------------------------ */ 3659 .balign 64 3660.L_OP_NEG_DOUBLE: /* 0x80 */ 3661/* File: armv5te/OP_NEG_DOUBLE.S */ 3662/* File: armv5te/unopWide.S */ 3663 /* 3664 * Generic 64-bit unary operation. Provide an "instr" line that 3665 * specifies an instruction that performs "result = op r0/r1". 3666 * This could be an ARM instruction or a function call. 3667 * 3668 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3669 */ 3670 /* unop vA, vB */ 3671 mov r9, rINST, lsr #8 @ r9<- A+ 3672 mov r3, rINST, lsr #12 @ r3<- B 3673 and r9, r9, #15 3674 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3675 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3676 ldmia r3, {r0-r1} @ r0/r1<- vAA 3677 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3678 @ optional op; may set condition codes 3679 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3680 GET_INST_OPCODE(ip) @ extract opcode from rINST 3681 stmia r9, {r0-r1} @ vAA<- r0/r1 3682 GOTO_OPCODE(ip) @ jump to next instruction 3683 /* 12-13 instructions */ 3684 3685 3686 3687/* ------------------------------ */ 3688 .balign 64 3689.L_OP_INT_TO_LONG: /* 0x81 */ 3690/* File: armv5te/OP_INT_TO_LONG.S */ 3691/* File: armv5te/unopWider.S */ 3692 /* 3693 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3694 * that specifies an instruction that performs "result = op r0", where 3695 * "result" is a 64-bit quantity in r0/r1. 3696 * 3697 * For: int-to-long, int-to-double, float-to-long, float-to-double 3698 */ 3699 /* unop vA, vB */ 3700 mov r9, rINST, lsr #8 @ r9<- A+ 3701 mov r3, rINST, lsr #12 @ r3<- B 3702 and r9, r9, #15 3703 GET_VREG(r0, r3) @ r0<- vB 3704 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3705 @ optional op; may set condition codes 3706 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3707 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3708 GET_INST_OPCODE(ip) @ extract opcode from rINST 3709 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3710 GOTO_OPCODE(ip) @ jump to next instruction 3711 /* 10-11 instructions */ 3712 3713 3714/* ------------------------------ */ 3715 .balign 64 3716.L_OP_INT_TO_FLOAT: /* 0x82 */ 3717/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3718/* File: arm-vfp/funop.S */ 3719 /* 3720 * Generic 32-bit unary floating-point operation. Provide an "instr" 3721 * line that specifies an instruction that performs "s1 = op s0". 3722 * 3723 * for: int-to-float, float-to-int 3724 */ 3725 /* unop vA, vB */ 3726 mov r3, rINST, lsr #12 @ r3<- B 3727 mov r9, rINST, lsr #8 @ r9<- A+ 3728 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3729 flds s0, [r3] @ s0<- vB 3730 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3731 and r9, r9, #15 @ r9<- A 3732 fsitos s1, s0 @ s1<- op 3733 GET_INST_OPCODE(ip) @ extract opcode from rINST 3734 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3735 fsts s1, [r9] @ vA<- s1 3736 GOTO_OPCODE(ip) @ jump to next instruction 3737 3738 3739/* ------------------------------ */ 3740 .balign 64 3741.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3742/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3743/* File: arm-vfp/funopWider.S */ 3744 /* 3745 * Generic 32bit-to-64bit floating point unary operation. Provide an 3746 * "instr" line that specifies an instruction that performs "d0 = op s0". 3747 * 3748 * For: int-to-double, float-to-double 3749 */ 3750 /* unop vA, vB */ 3751 mov r3, rINST, lsr #12 @ r3<- B 3752 mov r9, rINST, lsr #8 @ r9<- A+ 3753 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3754 flds s0, [r3] @ s0<- vB 3755 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3756 and r9, r9, #15 @ r9<- A 3757 fsitod d0, s0 @ d0<- op 3758 GET_INST_OPCODE(ip) @ extract opcode from rINST 3759 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3760 fstd d0, [r9] @ vA<- d0 3761 GOTO_OPCODE(ip) @ jump to next instruction 3762 3763 3764/* ------------------------------ */ 3765 .balign 64 3766.L_OP_LONG_TO_INT: /* 0x84 */ 3767/* File: armv5te/OP_LONG_TO_INT.S */ 3768/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3769/* File: armv5te/OP_MOVE.S */ 3770 /* for move, move-object, long-to-int */ 3771 /* op vA, vB */ 3772 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3773 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3774 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3775 GET_VREG(r2, r1) @ r2<- fp[B] 3776 and r0, r0, #15 3777 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3778 SET_VREG(r2, r0) @ fp[A]<- r2 3779 GOTO_OPCODE(ip) @ execute next instruction 3780 3781 3782 3783/* ------------------------------ */ 3784 .balign 64 3785.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3786/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3787/* File: armv5te/unopNarrower.S */ 3788 /* 3789 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3790 * that specifies an instruction that performs "result = op r0/r1", where 3791 * "result" is a 32-bit quantity in r0. 3792 * 3793 * For: long-to-float, double-to-int, double-to-float 3794 * 3795 * (This would work for long-to-int, but that instruction is actually 3796 * an exact match for OP_MOVE.) 3797 */ 3798 /* unop vA, vB */ 3799 mov r3, rINST, lsr #12 @ r3<- B 3800 mov r9, rINST, lsr #8 @ r9<- A+ 3801 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3802 and r9, r9, #15 3803 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3804 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3805 @ optional op; may set condition codes 3806 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3807 GET_INST_OPCODE(ip) @ extract opcode from rINST 3808 SET_VREG(r0, r9) @ vA<- r0 3809 GOTO_OPCODE(ip) @ jump to next instruction 3810 /* 10-11 instructions */ 3811 3812 3813/* ------------------------------ */ 3814 .balign 64 3815.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3816/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3817/* File: armv5te/unopWide.S */ 3818 /* 3819 * Generic 64-bit unary operation. Provide an "instr" line that 3820 * specifies an instruction that performs "result = op r0/r1". 3821 * This could be an ARM instruction or a function call. 3822 * 3823 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3824 */ 3825 /* unop vA, vB */ 3826 mov r9, rINST, lsr #8 @ r9<- A+ 3827 mov r3, rINST, lsr #12 @ r3<- B 3828 and r9, r9, #15 3829 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3830 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3831 ldmia r3, {r0-r1} @ r0/r1<- vAA 3832 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3833 @ optional op; may set condition codes 3834 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3835 GET_INST_OPCODE(ip) @ extract opcode from rINST 3836 stmia r9, {r0-r1} @ vAA<- r0/r1 3837 GOTO_OPCODE(ip) @ jump to next instruction 3838 /* 12-13 instructions */ 3839 3840 3841 3842/* ------------------------------ */ 3843 .balign 64 3844.L_OP_FLOAT_TO_INT: /* 0x87 */ 3845/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3846/* File: arm-vfp/funop.S */ 3847 /* 3848 * Generic 32-bit unary floating-point operation. Provide an "instr" 3849 * line that specifies an instruction that performs "s1 = op s0". 3850 * 3851 * for: int-to-float, float-to-int 3852 */ 3853 /* unop vA, vB */ 3854 mov r3, rINST, lsr #12 @ r3<- B 3855 mov r9, rINST, lsr #8 @ r9<- A+ 3856 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3857 flds s0, [r3] @ s0<- vB 3858 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3859 and r9, r9, #15 @ r9<- A 3860 ftosizs s1, s0 @ s1<- op 3861 GET_INST_OPCODE(ip) @ extract opcode from rINST 3862 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3863 fsts s1, [r9] @ vA<- s1 3864 GOTO_OPCODE(ip) @ jump to next instruction 3865 3866 3867/* ------------------------------ */ 3868 .balign 64 3869.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3870/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3871@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3872/* File: armv5te/unopWider.S */ 3873 /* 3874 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3875 * that specifies an instruction that performs "result = op r0", where 3876 * "result" is a 64-bit quantity in r0/r1. 3877 * 3878 * For: int-to-long, int-to-double, float-to-long, float-to-double 3879 */ 3880 /* unop vA, vB */ 3881 mov r9, rINST, lsr #8 @ r9<- A+ 3882 mov r3, rINST, lsr #12 @ r3<- B 3883 and r9, r9, #15 3884 GET_VREG(r0, r3) @ r0<- vB 3885 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3886 @ optional op; may set condition codes 3887 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3888 bl f2l_doconv @ r0<- op, r0-r3 changed 3889 GET_INST_OPCODE(ip) @ extract opcode from rINST 3890 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3891 GOTO_OPCODE(ip) @ jump to next instruction 3892 /* 10-11 instructions */ 3893 3894 3895 3896/* ------------------------------ */ 3897 .balign 64 3898.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3899/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3900/* File: arm-vfp/funopWider.S */ 3901 /* 3902 * Generic 32bit-to-64bit floating point unary operation. Provide an 3903 * "instr" line that specifies an instruction that performs "d0 = op s0". 3904 * 3905 * For: int-to-double, float-to-double 3906 */ 3907 /* unop vA, vB */ 3908 mov r3, rINST, lsr #12 @ r3<- B 3909 mov r9, rINST, lsr #8 @ r9<- A+ 3910 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3911 flds s0, [r3] @ s0<- vB 3912 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3913 and r9, r9, #15 @ r9<- A 3914 fcvtds d0, s0 @ d0<- op 3915 GET_INST_OPCODE(ip) @ extract opcode from rINST 3916 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3917 fstd d0, [r9] @ vA<- d0 3918 GOTO_OPCODE(ip) @ jump to next instruction 3919 3920 3921/* ------------------------------ */ 3922 .balign 64 3923.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3924/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3925/* File: arm-vfp/funopNarrower.S */ 3926 /* 3927 * Generic 64bit-to-32bit unary floating point operation. Provide an 3928 * "instr" line that specifies an instruction that performs "s0 = op d0". 3929 * 3930 * For: double-to-int, double-to-float 3931 */ 3932 /* unop vA, vB */ 3933 mov r3, rINST, lsr #12 @ r3<- B 3934 mov r9, rINST, lsr #8 @ r9<- A+ 3935 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3936 fldd d0, [r3] @ d0<- vB 3937 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3938 and r9, r9, #15 @ r9<- A 3939 ftosizd s0, d0 @ s0<- op 3940 GET_INST_OPCODE(ip) @ extract opcode from rINST 3941 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3942 fsts s0, [r9] @ vA<- s0 3943 GOTO_OPCODE(ip) @ jump to next instruction 3944 3945 3946/* ------------------------------ */ 3947 .balign 64 3948.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3949/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3950@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3951/* File: armv5te/unopWide.S */ 3952 /* 3953 * Generic 64-bit unary operation. Provide an "instr" line that 3954 * specifies an instruction that performs "result = op r0/r1". 3955 * This could be an ARM instruction or a function call. 3956 * 3957 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3958 */ 3959 /* unop vA, vB */ 3960 mov r9, rINST, lsr #8 @ r9<- A+ 3961 mov r3, rINST, lsr #12 @ r3<- B 3962 and r9, r9, #15 3963 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3964 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3965 ldmia r3, {r0-r1} @ r0/r1<- vAA 3966 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3967 @ optional op; may set condition codes 3968 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3969 GET_INST_OPCODE(ip) @ extract opcode from rINST 3970 stmia r9, {r0-r1} @ vAA<- r0/r1 3971 GOTO_OPCODE(ip) @ jump to next instruction 3972 /* 12-13 instructions */ 3973 3974 3975 3976 3977/* ------------------------------ */ 3978 .balign 64 3979.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3980/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3981/* File: arm-vfp/funopNarrower.S */ 3982 /* 3983 * Generic 64bit-to-32bit unary floating point operation. Provide an 3984 * "instr" line that specifies an instruction that performs "s0 = op d0". 3985 * 3986 * For: double-to-int, double-to-float 3987 */ 3988 /* unop vA, vB */ 3989 mov r3, rINST, lsr #12 @ r3<- B 3990 mov r9, rINST, lsr #8 @ r9<- A+ 3991 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3992 fldd d0, [r3] @ d0<- vB 3993 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3994 and r9, r9, #15 @ r9<- A 3995 fcvtsd s0, d0 @ s0<- op 3996 GET_INST_OPCODE(ip) @ extract opcode from rINST 3997 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3998 fsts s0, [r9] @ vA<- s0 3999 GOTO_OPCODE(ip) @ jump to next instruction 4000 4001 4002/* ------------------------------ */ 4003 .balign 64 4004.L_OP_INT_TO_BYTE: /* 0x8d */ 4005/* File: armv5te/OP_INT_TO_BYTE.S */ 4006/* File: armv5te/unop.S */ 4007 /* 4008 * Generic 32-bit unary operation. Provide an "instr" line that 4009 * specifies an instruction that performs "result = op r0". 4010 * This could be an ARM instruction or a function call. 4011 * 4012 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4013 * int-to-byte, int-to-char, int-to-short 4014 */ 4015 /* unop vA, vB */ 4016 mov r3, rINST, lsr #12 @ r3<- B 4017 mov r9, rINST, lsr #8 @ r9<- A+ 4018 GET_VREG(r0, r3) @ r0<- vB 4019 and r9, r9, #15 4020 mov r0, r0, asl #24 @ optional op; may set condition codes 4021 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4022 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4023 GET_INST_OPCODE(ip) @ extract opcode from rINST 4024 SET_VREG(r0, r9) @ vAA<- r0 4025 GOTO_OPCODE(ip) @ jump to next instruction 4026 /* 9-10 instructions */ 4027 4028 4029/* ------------------------------ */ 4030 .balign 64 4031.L_OP_INT_TO_CHAR: /* 0x8e */ 4032/* File: armv5te/OP_INT_TO_CHAR.S */ 4033/* File: armv5te/unop.S */ 4034 /* 4035 * Generic 32-bit unary operation. Provide an "instr" line that 4036 * specifies an instruction that performs "result = op r0". 4037 * This could be an ARM instruction or a function call. 4038 * 4039 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4040 * int-to-byte, int-to-char, int-to-short 4041 */ 4042 /* unop vA, vB */ 4043 mov r3, rINST, lsr #12 @ r3<- B 4044 mov r9, rINST, lsr #8 @ r9<- A+ 4045 GET_VREG(r0, r3) @ r0<- vB 4046 and r9, r9, #15 4047 mov r0, r0, asl #16 @ optional op; may set condition codes 4048 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4049 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4050 GET_INST_OPCODE(ip) @ extract opcode from rINST 4051 SET_VREG(r0, r9) @ vAA<- r0 4052 GOTO_OPCODE(ip) @ jump to next instruction 4053 /* 9-10 instructions */ 4054 4055 4056/* ------------------------------ */ 4057 .balign 64 4058.L_OP_INT_TO_SHORT: /* 0x8f */ 4059/* File: armv5te/OP_INT_TO_SHORT.S */ 4060/* File: armv5te/unop.S */ 4061 /* 4062 * Generic 32-bit unary operation. Provide an "instr" line that 4063 * specifies an instruction that performs "result = op r0". 4064 * This could be an ARM instruction or a function call. 4065 * 4066 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4067 * int-to-byte, int-to-char, int-to-short 4068 */ 4069 /* unop vA, vB */ 4070 mov r3, rINST, lsr #12 @ r3<- B 4071 mov r9, rINST, lsr #8 @ r9<- A+ 4072 GET_VREG(r0, r3) @ r0<- vB 4073 and r9, r9, #15 4074 mov r0, r0, asl #16 @ optional op; may set condition codes 4075 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4076 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4077 GET_INST_OPCODE(ip) @ extract opcode from rINST 4078 SET_VREG(r0, r9) @ vAA<- r0 4079 GOTO_OPCODE(ip) @ jump to next instruction 4080 /* 9-10 instructions */ 4081 4082 4083/* ------------------------------ */ 4084 .balign 64 4085.L_OP_ADD_INT: /* 0x90 */ 4086/* File: armv5te/OP_ADD_INT.S */ 4087/* File: armv5te/binop.S */ 4088 /* 4089 * Generic 32-bit binary operation. Provide an "instr" line that 4090 * specifies an instruction that performs "result = r0 op r1". 4091 * This could be an ARM instruction or a function call. (If the result 4092 * comes back in a register other than r0, you can override "result".) 4093 * 4094 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4095 * vCC (r1). Useful for integer division and modulus. Note that we 4096 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4097 * handles it correctly. 4098 * 4099 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4100 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4101 * mul-float, div-float, rem-float 4102 */ 4103 /* binop vAA, vBB, vCC */ 4104 FETCH(r0, 1) @ r0<- CCBB 4105 mov r9, rINST, lsr #8 @ r9<- AA 4106 mov r3, r0, lsr #8 @ r3<- CC 4107 and r2, r0, #255 @ r2<- BB 4108 GET_VREG(r1, r3) @ r1<- vCC 4109 GET_VREG(r0, r2) @ r0<- vBB 4110 .if 0 4111 cmp r1, #0 @ is second operand zero? 4112 beq common_errDivideByZero 4113 .endif 4114 4115 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4116 @ optional op; may set condition codes 4117 add r0, r0, r1 @ r0<- op, r0-r3 changed 4118 GET_INST_OPCODE(ip) @ extract opcode from rINST 4119 SET_VREG(r0, r9) @ vAA<- r0 4120 GOTO_OPCODE(ip) @ jump to next instruction 4121 /* 11-14 instructions */ 4122 4123 4124 4125/* ------------------------------ */ 4126 .balign 64 4127.L_OP_SUB_INT: /* 0x91 */ 4128/* File: armv5te/OP_SUB_INT.S */ 4129/* File: armv5te/binop.S */ 4130 /* 4131 * Generic 32-bit binary operation. Provide an "instr" line that 4132 * specifies an instruction that performs "result = r0 op r1". 4133 * This could be an ARM instruction or a function call. (If the result 4134 * comes back in a register other than r0, you can override "result".) 4135 * 4136 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4137 * vCC (r1). Useful for integer division and modulus. Note that we 4138 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4139 * handles it correctly. 4140 * 4141 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4142 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4143 * mul-float, div-float, rem-float 4144 */ 4145 /* binop vAA, vBB, vCC */ 4146 FETCH(r0, 1) @ r0<- CCBB 4147 mov r9, rINST, lsr #8 @ r9<- AA 4148 mov r3, r0, lsr #8 @ r3<- CC 4149 and r2, r0, #255 @ r2<- BB 4150 GET_VREG(r1, r3) @ r1<- vCC 4151 GET_VREG(r0, r2) @ r0<- vBB 4152 .if 0 4153 cmp r1, #0 @ is second operand zero? 4154 beq common_errDivideByZero 4155 .endif 4156 4157 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4158 @ optional op; may set condition codes 4159 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4160 GET_INST_OPCODE(ip) @ extract opcode from rINST 4161 SET_VREG(r0, r9) @ vAA<- r0 4162 GOTO_OPCODE(ip) @ jump to next instruction 4163 /* 11-14 instructions */ 4164 4165 4166 4167/* ------------------------------ */ 4168 .balign 64 4169.L_OP_MUL_INT: /* 0x92 */ 4170/* File: armv5te/OP_MUL_INT.S */ 4171/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4172/* File: armv5te/binop.S */ 4173 /* 4174 * Generic 32-bit binary operation. Provide an "instr" line that 4175 * specifies an instruction that performs "result = r0 op r1". 4176 * This could be an ARM instruction or a function call. (If the result 4177 * comes back in a register other than r0, you can override "result".) 4178 * 4179 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4180 * vCC (r1). Useful for integer division and modulus. Note that we 4181 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4182 * handles it correctly. 4183 * 4184 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4185 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4186 * mul-float, div-float, rem-float 4187 */ 4188 /* binop vAA, vBB, vCC */ 4189 FETCH(r0, 1) @ r0<- CCBB 4190 mov r9, rINST, lsr #8 @ r9<- AA 4191 mov r3, r0, lsr #8 @ r3<- CC 4192 and r2, r0, #255 @ r2<- BB 4193 GET_VREG(r1, r3) @ r1<- vCC 4194 GET_VREG(r0, r2) @ r0<- vBB 4195 .if 0 4196 cmp r1, #0 @ is second operand zero? 4197 beq common_errDivideByZero 4198 .endif 4199 4200 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4201 @ optional op; may set condition codes 4202 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4203 GET_INST_OPCODE(ip) @ extract opcode from rINST 4204 SET_VREG(r0, r9) @ vAA<- r0 4205 GOTO_OPCODE(ip) @ jump to next instruction 4206 /* 11-14 instructions */ 4207 4208 4209 4210/* ------------------------------ */ 4211 .balign 64 4212.L_OP_DIV_INT: /* 0x93 */ 4213/* File: armv5te/OP_DIV_INT.S */ 4214/* File: armv5te/binop.S */ 4215 /* 4216 * Generic 32-bit binary operation. Provide an "instr" line that 4217 * specifies an instruction that performs "result = r0 op r1". 4218 * This could be an ARM instruction or a function call. (If the result 4219 * comes back in a register other than r0, you can override "result".) 4220 * 4221 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4222 * vCC (r1). Useful for integer division and modulus. Note that we 4223 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4224 * handles it correctly. 4225 * 4226 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4227 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4228 * mul-float, div-float, rem-float 4229 */ 4230 /* binop vAA, vBB, vCC */ 4231 FETCH(r0, 1) @ r0<- CCBB 4232 mov r9, rINST, lsr #8 @ r9<- AA 4233 mov r3, r0, lsr #8 @ r3<- CC 4234 and r2, r0, #255 @ r2<- BB 4235 GET_VREG(r1, r3) @ r1<- vCC 4236 GET_VREG(r0, r2) @ r0<- vBB 4237 .if 1 4238 cmp r1, #0 @ is second operand zero? 4239 beq common_errDivideByZero 4240 .endif 4241 4242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4243 @ optional op; may set condition codes 4244 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4245 GET_INST_OPCODE(ip) @ extract opcode from rINST 4246 SET_VREG(r0, r9) @ vAA<- r0 4247 GOTO_OPCODE(ip) @ jump to next instruction 4248 /* 11-14 instructions */ 4249 4250 4251 4252/* ------------------------------ */ 4253 .balign 64 4254.L_OP_REM_INT: /* 0x94 */ 4255/* File: armv5te/OP_REM_INT.S */ 4256/* idivmod returns quotient in r0 and remainder in r1 */ 4257/* File: armv5te/binop.S */ 4258 /* 4259 * Generic 32-bit binary operation. Provide an "instr" line that 4260 * specifies an instruction that performs "result = r0 op r1". 4261 * This could be an ARM instruction or a function call. (If the result 4262 * comes back in a register other than r0, you can override "result".) 4263 * 4264 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4265 * vCC (r1). Useful for integer division and modulus. Note that we 4266 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4267 * handles it correctly. 4268 * 4269 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4270 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4271 * mul-float, div-float, rem-float 4272 */ 4273 /* binop vAA, vBB, vCC */ 4274 FETCH(r0, 1) @ r0<- CCBB 4275 mov r9, rINST, lsr #8 @ r9<- AA 4276 mov r3, r0, lsr #8 @ r3<- CC 4277 and r2, r0, #255 @ r2<- BB 4278 GET_VREG(r1, r3) @ r1<- vCC 4279 GET_VREG(r0, r2) @ r0<- vBB 4280 .if 1 4281 cmp r1, #0 @ is second operand zero? 4282 beq common_errDivideByZero 4283 .endif 4284 4285 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4286 @ optional op; may set condition codes 4287 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4288 GET_INST_OPCODE(ip) @ extract opcode from rINST 4289 SET_VREG(r1, r9) @ vAA<- r1 4290 GOTO_OPCODE(ip) @ jump to next instruction 4291 /* 11-14 instructions */ 4292 4293 4294 4295/* ------------------------------ */ 4296 .balign 64 4297.L_OP_AND_INT: /* 0x95 */ 4298/* File: armv5te/OP_AND_INT.S */ 4299/* File: armv5te/binop.S */ 4300 /* 4301 * Generic 32-bit binary operation. Provide an "instr" line that 4302 * specifies an instruction that performs "result = r0 op r1". 4303 * This could be an ARM instruction or a function call. (If the result 4304 * comes back in a register other than r0, you can override "result".) 4305 * 4306 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4307 * vCC (r1). Useful for integer division and modulus. Note that we 4308 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4309 * handles it correctly. 4310 * 4311 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4312 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4313 * mul-float, div-float, rem-float 4314 */ 4315 /* binop vAA, vBB, vCC */ 4316 FETCH(r0, 1) @ r0<- CCBB 4317 mov r9, rINST, lsr #8 @ r9<- AA 4318 mov r3, r0, lsr #8 @ r3<- CC 4319 and r2, r0, #255 @ r2<- BB 4320 GET_VREG(r1, r3) @ r1<- vCC 4321 GET_VREG(r0, r2) @ r0<- vBB 4322 .if 0 4323 cmp r1, #0 @ is second operand zero? 4324 beq common_errDivideByZero 4325 .endif 4326 4327 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4328 @ optional op; may set condition codes 4329 and r0, r0, r1 @ r0<- op, r0-r3 changed 4330 GET_INST_OPCODE(ip) @ extract opcode from rINST 4331 SET_VREG(r0, r9) @ vAA<- r0 4332 GOTO_OPCODE(ip) @ jump to next instruction 4333 /* 11-14 instructions */ 4334 4335 4336 4337/* ------------------------------ */ 4338 .balign 64 4339.L_OP_OR_INT: /* 0x96 */ 4340/* File: armv5te/OP_OR_INT.S */ 4341/* File: armv5te/binop.S */ 4342 /* 4343 * Generic 32-bit binary operation. Provide an "instr" line that 4344 * specifies an instruction that performs "result = r0 op r1". 4345 * This could be an ARM instruction or a function call. (If the result 4346 * comes back in a register other than r0, you can override "result".) 4347 * 4348 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4349 * vCC (r1). Useful for integer division and modulus. Note that we 4350 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4351 * handles it correctly. 4352 * 4353 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4354 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4355 * mul-float, div-float, rem-float 4356 */ 4357 /* binop vAA, vBB, vCC */ 4358 FETCH(r0, 1) @ r0<- CCBB 4359 mov r9, rINST, lsr #8 @ r9<- AA 4360 mov r3, r0, lsr #8 @ r3<- CC 4361 and r2, r0, #255 @ r2<- BB 4362 GET_VREG(r1, r3) @ r1<- vCC 4363 GET_VREG(r0, r2) @ r0<- vBB 4364 .if 0 4365 cmp r1, #0 @ is second operand zero? 4366 beq common_errDivideByZero 4367 .endif 4368 4369 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4370 @ optional op; may set condition codes 4371 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4372 GET_INST_OPCODE(ip) @ extract opcode from rINST 4373 SET_VREG(r0, r9) @ vAA<- r0 4374 GOTO_OPCODE(ip) @ jump to next instruction 4375 /* 11-14 instructions */ 4376 4377 4378 4379/* ------------------------------ */ 4380 .balign 64 4381.L_OP_XOR_INT: /* 0x97 */ 4382/* File: armv5te/OP_XOR_INT.S */ 4383/* File: armv5te/binop.S */ 4384 /* 4385 * Generic 32-bit binary operation. Provide an "instr" line that 4386 * specifies an instruction that performs "result = r0 op r1". 4387 * This could be an ARM instruction or a function call. (If the result 4388 * comes back in a register other than r0, you can override "result".) 4389 * 4390 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4391 * vCC (r1). Useful for integer division and modulus. Note that we 4392 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4393 * handles it correctly. 4394 * 4395 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4396 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4397 * mul-float, div-float, rem-float 4398 */ 4399 /* binop vAA, vBB, vCC */ 4400 FETCH(r0, 1) @ r0<- CCBB 4401 mov r9, rINST, lsr #8 @ r9<- AA 4402 mov r3, r0, lsr #8 @ r3<- CC 4403 and r2, r0, #255 @ r2<- BB 4404 GET_VREG(r1, r3) @ r1<- vCC 4405 GET_VREG(r0, r2) @ r0<- vBB 4406 .if 0 4407 cmp r1, #0 @ is second operand zero? 4408 beq common_errDivideByZero 4409 .endif 4410 4411 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4412 @ optional op; may set condition codes 4413 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4414 GET_INST_OPCODE(ip) @ extract opcode from rINST 4415 SET_VREG(r0, r9) @ vAA<- r0 4416 GOTO_OPCODE(ip) @ jump to next instruction 4417 /* 11-14 instructions */ 4418 4419 4420 4421/* ------------------------------ */ 4422 .balign 64 4423.L_OP_SHL_INT: /* 0x98 */ 4424/* File: armv5te/OP_SHL_INT.S */ 4425/* File: armv5te/binop.S */ 4426 /* 4427 * Generic 32-bit binary operation. Provide an "instr" line that 4428 * specifies an instruction that performs "result = r0 op r1". 4429 * This could be an ARM instruction or a function call. (If the result 4430 * comes back in a register other than r0, you can override "result".) 4431 * 4432 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4433 * vCC (r1). Useful for integer division and modulus. Note that we 4434 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4435 * handles it correctly. 4436 * 4437 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4438 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4439 * mul-float, div-float, rem-float 4440 */ 4441 /* binop vAA, vBB, vCC */ 4442 FETCH(r0, 1) @ r0<- CCBB 4443 mov r9, rINST, lsr #8 @ r9<- AA 4444 mov r3, r0, lsr #8 @ r3<- CC 4445 and r2, r0, #255 @ r2<- BB 4446 GET_VREG(r1, r3) @ r1<- vCC 4447 GET_VREG(r0, r2) @ r0<- vBB 4448 .if 0 4449 cmp r1, #0 @ is second operand zero? 4450 beq common_errDivideByZero 4451 .endif 4452 4453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4454 and r1, r1, #31 @ optional op; may set condition codes 4455 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4456 GET_INST_OPCODE(ip) @ extract opcode from rINST 4457 SET_VREG(r0, r9) @ vAA<- r0 4458 GOTO_OPCODE(ip) @ jump to next instruction 4459 /* 11-14 instructions */ 4460 4461 4462 4463/* ------------------------------ */ 4464 .balign 64 4465.L_OP_SHR_INT: /* 0x99 */ 4466/* File: armv5te/OP_SHR_INT.S */ 4467/* File: armv5te/binop.S */ 4468 /* 4469 * Generic 32-bit binary operation. Provide an "instr" line that 4470 * specifies an instruction that performs "result = r0 op r1". 4471 * This could be an ARM instruction or a function call. (If the result 4472 * comes back in a register other than r0, you can override "result".) 4473 * 4474 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4475 * vCC (r1). Useful for integer division and modulus. Note that we 4476 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4477 * handles it correctly. 4478 * 4479 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4480 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4481 * mul-float, div-float, rem-float 4482 */ 4483 /* binop vAA, vBB, vCC */ 4484 FETCH(r0, 1) @ r0<- CCBB 4485 mov r9, rINST, lsr #8 @ r9<- AA 4486 mov r3, r0, lsr #8 @ r3<- CC 4487 and r2, r0, #255 @ r2<- BB 4488 GET_VREG(r1, r3) @ r1<- vCC 4489 GET_VREG(r0, r2) @ r0<- vBB 4490 .if 0 4491 cmp r1, #0 @ is second operand zero? 4492 beq common_errDivideByZero 4493 .endif 4494 4495 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4496 and r1, r1, #31 @ optional op; may set condition codes 4497 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4498 GET_INST_OPCODE(ip) @ extract opcode from rINST 4499 SET_VREG(r0, r9) @ vAA<- r0 4500 GOTO_OPCODE(ip) @ jump to next instruction 4501 /* 11-14 instructions */ 4502 4503 4504 4505/* ------------------------------ */ 4506 .balign 64 4507.L_OP_USHR_INT: /* 0x9a */ 4508/* File: armv5te/OP_USHR_INT.S */ 4509/* File: armv5te/binop.S */ 4510 /* 4511 * Generic 32-bit binary operation. Provide an "instr" line that 4512 * specifies an instruction that performs "result = r0 op r1". 4513 * This could be an ARM instruction or a function call. (If the result 4514 * comes back in a register other than r0, you can override "result".) 4515 * 4516 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4517 * vCC (r1). Useful for integer division and modulus. Note that we 4518 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4519 * handles it correctly. 4520 * 4521 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4522 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4523 * mul-float, div-float, rem-float 4524 */ 4525 /* binop vAA, vBB, vCC */ 4526 FETCH(r0, 1) @ r0<- CCBB 4527 mov r9, rINST, lsr #8 @ r9<- AA 4528 mov r3, r0, lsr #8 @ r3<- CC 4529 and r2, r0, #255 @ r2<- BB 4530 GET_VREG(r1, r3) @ r1<- vCC 4531 GET_VREG(r0, r2) @ r0<- vBB 4532 .if 0 4533 cmp r1, #0 @ is second operand zero? 4534 beq common_errDivideByZero 4535 .endif 4536 4537 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4538 and r1, r1, #31 @ optional op; may set condition codes 4539 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4540 GET_INST_OPCODE(ip) @ extract opcode from rINST 4541 SET_VREG(r0, r9) @ vAA<- r0 4542 GOTO_OPCODE(ip) @ jump to next instruction 4543 /* 11-14 instructions */ 4544 4545 4546 4547/* ------------------------------ */ 4548 .balign 64 4549.L_OP_ADD_LONG: /* 0x9b */ 4550/* File: armv5te/OP_ADD_LONG.S */ 4551/* File: armv5te/binopWide.S */ 4552 /* 4553 * Generic 64-bit binary operation. Provide an "instr" line that 4554 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4555 * This could be an ARM instruction or a function call. (If the result 4556 * comes back in a register other than r0, you can override "result".) 4557 * 4558 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4559 * vCC (r1). Useful for integer division and modulus. 4560 * 4561 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4562 * xor-long, add-double, sub-double, mul-double, div-double, 4563 * rem-double 4564 * 4565 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4566 */ 4567 /* binop vAA, vBB, vCC */ 4568 FETCH(r0, 1) @ r0<- CCBB 4569 mov r9, rINST, lsr #8 @ r9<- AA 4570 and r2, r0, #255 @ r2<- BB 4571 mov r3, r0, lsr #8 @ r3<- CC 4572 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4573 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4574 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4575 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4576 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4577 .if 0 4578 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4579 beq common_errDivideByZero 4580 .endif 4581 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4582 4583 adds r0, r0, r2 @ optional op; may set condition codes 4584 adc r1, r1, r3 @ result<- op, r0-r3 changed 4585 GET_INST_OPCODE(ip) @ extract opcode from rINST 4586 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4587 GOTO_OPCODE(ip) @ jump to next instruction 4588 /* 14-17 instructions */ 4589 4590 4591 4592/* ------------------------------ */ 4593 .balign 64 4594.L_OP_SUB_LONG: /* 0x9c */ 4595/* File: armv5te/OP_SUB_LONG.S */ 4596/* File: armv5te/binopWide.S */ 4597 /* 4598 * Generic 64-bit binary operation. Provide an "instr" line that 4599 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4600 * This could be an ARM instruction or a function call. (If the result 4601 * comes back in a register other than r0, you can override "result".) 4602 * 4603 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4604 * vCC (r1). Useful for integer division and modulus. 4605 * 4606 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4607 * xor-long, add-double, sub-double, mul-double, div-double, 4608 * rem-double 4609 * 4610 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4611 */ 4612 /* binop vAA, vBB, vCC */ 4613 FETCH(r0, 1) @ r0<- CCBB 4614 mov r9, rINST, lsr #8 @ r9<- AA 4615 and r2, r0, #255 @ r2<- BB 4616 mov r3, r0, lsr #8 @ r3<- CC 4617 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4618 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4619 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4620 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4621 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4622 .if 0 4623 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4624 beq common_errDivideByZero 4625 .endif 4626 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4627 4628 subs r0, r0, r2 @ optional op; may set condition codes 4629 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4630 GET_INST_OPCODE(ip) @ extract opcode from rINST 4631 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4632 GOTO_OPCODE(ip) @ jump to next instruction 4633 /* 14-17 instructions */ 4634 4635 4636 4637/* ------------------------------ */ 4638 .balign 64 4639.L_OP_MUL_LONG: /* 0x9d */ 4640/* File: armv5te/OP_MUL_LONG.S */ 4641 /* 4642 * Signed 64-bit integer multiply. 4643 * 4644 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4645 * WX 4646 * x YZ 4647 * -------- 4648 * ZW ZX 4649 * YW YX 4650 * 4651 * The low word of the result holds ZX, the high word holds 4652 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4653 * it doesn't fit in the low 64 bits. 4654 * 4655 * Unlike most ARM math operations, multiply instructions have 4656 * restrictions on using the same register more than once (Rd and Rm 4657 * cannot be the same). 4658 */ 4659 /* mul-long vAA, vBB, vCC */ 4660 FETCH(r0, 1) @ r0<- CCBB 4661 and r2, r0, #255 @ r2<- BB 4662 mov r3, r0, lsr #8 @ r3<- CC 4663 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4664 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4665 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4666 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4667 mul ip, r2, r1 @ ip<- ZxW 4668 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4669 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4670 mov r0, rINST, lsr #8 @ r0<- AA 4671 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4672 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4674 b .LOP_MUL_LONG_finish 4675 4676/* ------------------------------ */ 4677 .balign 64 4678.L_OP_DIV_LONG: /* 0x9e */ 4679/* File: armv5te/OP_DIV_LONG.S */ 4680/* File: armv5te/binopWide.S */ 4681 /* 4682 * Generic 64-bit binary operation. Provide an "instr" line that 4683 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4684 * This could be an ARM instruction or a function call. (If the result 4685 * comes back in a register other than r0, you can override "result".) 4686 * 4687 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4688 * vCC (r1). Useful for integer division and modulus. 4689 * 4690 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4691 * xor-long, add-double, sub-double, mul-double, div-double, 4692 * rem-double 4693 * 4694 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4695 */ 4696 /* binop vAA, vBB, vCC */ 4697 FETCH(r0, 1) @ r0<- CCBB 4698 mov r9, rINST, lsr #8 @ r9<- AA 4699 and r2, r0, #255 @ r2<- BB 4700 mov r3, r0, lsr #8 @ r3<- CC 4701 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4702 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4703 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4704 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4705 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4706 .if 1 4707 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4708 beq common_errDivideByZero 4709 .endif 4710 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4711 4712 @ optional op; may set condition codes 4713 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4714 GET_INST_OPCODE(ip) @ extract opcode from rINST 4715 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4716 GOTO_OPCODE(ip) @ jump to next instruction 4717 /* 14-17 instructions */ 4718 4719 4720 4721/* ------------------------------ */ 4722 .balign 64 4723.L_OP_REM_LONG: /* 0x9f */ 4724/* File: armv5te/OP_REM_LONG.S */ 4725/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4726/* File: armv5te/binopWide.S */ 4727 /* 4728 * Generic 64-bit binary operation. Provide an "instr" line that 4729 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4730 * This could be an ARM instruction or a function call. (If the result 4731 * comes back in a register other than r0, you can override "result".) 4732 * 4733 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4734 * vCC (r1). Useful for integer division and modulus. 4735 * 4736 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4737 * xor-long, add-double, sub-double, mul-double, div-double, 4738 * rem-double 4739 * 4740 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4741 */ 4742 /* binop vAA, vBB, vCC */ 4743 FETCH(r0, 1) @ r0<- CCBB 4744 mov r9, rINST, lsr #8 @ r9<- AA 4745 and r2, r0, #255 @ r2<- BB 4746 mov r3, r0, lsr #8 @ r3<- CC 4747 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4748 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4749 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4750 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4751 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4752 .if 1 4753 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4754 beq common_errDivideByZero 4755 .endif 4756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4757 4758 @ optional op; may set condition codes 4759 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4760 GET_INST_OPCODE(ip) @ extract opcode from rINST 4761 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4762 GOTO_OPCODE(ip) @ jump to next instruction 4763 /* 14-17 instructions */ 4764 4765 4766 4767/* ------------------------------ */ 4768 .balign 64 4769.L_OP_AND_LONG: /* 0xa0 */ 4770/* File: armv5te/OP_AND_LONG.S */ 4771/* File: armv5te/binopWide.S */ 4772 /* 4773 * Generic 64-bit binary operation. Provide an "instr" line that 4774 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4775 * This could be an ARM instruction or a function call. (If the result 4776 * comes back in a register other than r0, you can override "result".) 4777 * 4778 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4779 * vCC (r1). Useful for integer division and modulus. 4780 * 4781 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4782 * xor-long, add-double, sub-double, mul-double, div-double, 4783 * rem-double 4784 * 4785 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4786 */ 4787 /* binop vAA, vBB, vCC */ 4788 FETCH(r0, 1) @ r0<- CCBB 4789 mov r9, rINST, lsr #8 @ r9<- AA 4790 and r2, r0, #255 @ r2<- BB 4791 mov r3, r0, lsr #8 @ r3<- CC 4792 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4793 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4794 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4795 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4796 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4797 .if 0 4798 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4799 beq common_errDivideByZero 4800 .endif 4801 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4802 4803 and r0, r0, r2 @ optional op; may set condition codes 4804 and r1, r1, r3 @ result<- op, r0-r3 changed 4805 GET_INST_OPCODE(ip) @ extract opcode from rINST 4806 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4807 GOTO_OPCODE(ip) @ jump to next instruction 4808 /* 14-17 instructions */ 4809 4810 4811 4812/* ------------------------------ */ 4813 .balign 64 4814.L_OP_OR_LONG: /* 0xa1 */ 4815/* File: armv5te/OP_OR_LONG.S */ 4816/* File: armv5te/binopWide.S */ 4817 /* 4818 * Generic 64-bit binary operation. Provide an "instr" line that 4819 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4820 * This could be an ARM instruction or a function call. (If the result 4821 * comes back in a register other than r0, you can override "result".) 4822 * 4823 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4824 * vCC (r1). Useful for integer division and modulus. 4825 * 4826 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4827 * xor-long, add-double, sub-double, mul-double, div-double, 4828 * rem-double 4829 * 4830 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4831 */ 4832 /* binop vAA, vBB, vCC */ 4833 FETCH(r0, 1) @ r0<- CCBB 4834 mov r9, rINST, lsr #8 @ r9<- AA 4835 and r2, r0, #255 @ r2<- BB 4836 mov r3, r0, lsr #8 @ r3<- CC 4837 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4838 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4839 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4840 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4841 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4842 .if 0 4843 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4844 beq common_errDivideByZero 4845 .endif 4846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4847 4848 orr r0, r0, r2 @ optional op; may set condition codes 4849 orr r1, r1, r3 @ result<- op, r0-r3 changed 4850 GET_INST_OPCODE(ip) @ extract opcode from rINST 4851 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4852 GOTO_OPCODE(ip) @ jump to next instruction 4853 /* 14-17 instructions */ 4854 4855 4856 4857/* ------------------------------ */ 4858 .balign 64 4859.L_OP_XOR_LONG: /* 0xa2 */ 4860/* File: armv5te/OP_XOR_LONG.S */ 4861/* File: armv5te/binopWide.S */ 4862 /* 4863 * Generic 64-bit binary operation. Provide an "instr" line that 4864 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4865 * This could be an ARM instruction or a function call. (If the result 4866 * comes back in a register other than r0, you can override "result".) 4867 * 4868 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4869 * vCC (r1). Useful for integer division and modulus. 4870 * 4871 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4872 * xor-long, add-double, sub-double, mul-double, div-double, 4873 * rem-double 4874 * 4875 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4876 */ 4877 /* binop vAA, vBB, vCC */ 4878 FETCH(r0, 1) @ r0<- CCBB 4879 mov r9, rINST, lsr #8 @ r9<- AA 4880 and r2, r0, #255 @ r2<- BB 4881 mov r3, r0, lsr #8 @ r3<- CC 4882 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4883 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4884 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4885 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4886 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4887 .if 0 4888 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4889 beq common_errDivideByZero 4890 .endif 4891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4892 4893 eor r0, r0, r2 @ optional op; may set condition codes 4894 eor r1, r1, r3 @ result<- op, r0-r3 changed 4895 GET_INST_OPCODE(ip) @ extract opcode from rINST 4896 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4897 GOTO_OPCODE(ip) @ jump to next instruction 4898 /* 14-17 instructions */ 4899 4900 4901 4902/* ------------------------------ */ 4903 .balign 64 4904.L_OP_SHL_LONG: /* 0xa3 */ 4905/* File: armv5te/OP_SHL_LONG.S */ 4906 /* 4907 * Long integer shift. This is different from the generic 32/64-bit 4908 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4909 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4910 * 6 bits of the shift distance. 4911 */ 4912 /* shl-long vAA, vBB, vCC */ 4913 FETCH(r0, 1) @ r0<- CCBB 4914 mov r9, rINST, lsr #8 @ r9<- AA 4915 and r3, r0, #255 @ r3<- BB 4916 mov r0, r0, lsr #8 @ r0<- CC 4917 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4918 GET_VREG(r2, r0) @ r2<- vCC 4919 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4920 and r2, r2, #63 @ r2<- r2 & 0x3f 4921 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4922 4923 mov r1, r1, asl r2 @ r1<- r1 << r2 4924 rsb r3, r2, #32 @ r3<- 32 - r2 4925 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4926 subs ip, r2, #32 @ ip<- r2 - 32 4927 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4929 b .LOP_SHL_LONG_finish 4930 4931/* ------------------------------ */ 4932 .balign 64 4933.L_OP_SHR_LONG: /* 0xa4 */ 4934/* File: armv5te/OP_SHR_LONG.S */ 4935 /* 4936 * Long integer shift. This is different from the generic 32/64-bit 4937 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4938 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4939 * 6 bits of the shift distance. 4940 */ 4941 /* shr-long vAA, vBB, vCC */ 4942 FETCH(r0, 1) @ r0<- CCBB 4943 mov r9, rINST, lsr #8 @ r9<- AA 4944 and r3, r0, #255 @ r3<- BB 4945 mov r0, r0, lsr #8 @ r0<- CC 4946 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4947 GET_VREG(r2, r0) @ r2<- vCC 4948 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4949 and r2, r2, #63 @ r0<- r0 & 0x3f 4950 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4951 4952 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4953 rsb r3, r2, #32 @ r3<- 32 - r2 4954 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4955 subs ip, r2, #32 @ ip<- r2 - 32 4956 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4957 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4958 b .LOP_SHR_LONG_finish 4959 4960/* ------------------------------ */ 4961 .balign 64 4962.L_OP_USHR_LONG: /* 0xa5 */ 4963/* File: armv5te/OP_USHR_LONG.S */ 4964 /* 4965 * Long integer shift. This is different from the generic 32/64-bit 4966 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4967 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4968 * 6 bits of the shift distance. 4969 */ 4970 /* ushr-long vAA, vBB, vCC */ 4971 FETCH(r0, 1) @ r0<- CCBB 4972 mov r9, rINST, lsr #8 @ r9<- AA 4973 and r3, r0, #255 @ r3<- BB 4974 mov r0, r0, lsr #8 @ r0<- CC 4975 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4976 GET_VREG(r2, r0) @ r2<- vCC 4977 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4978 and r2, r2, #63 @ r0<- r0 & 0x3f 4979 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4980 4981 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4982 rsb r3, r2, #32 @ r3<- 32 - r2 4983 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4984 subs ip, r2, #32 @ ip<- r2 - 32 4985 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4987 b .LOP_USHR_LONG_finish 4988 4989/* ------------------------------ */ 4990 .balign 64 4991.L_OP_ADD_FLOAT: /* 0xa6 */ 4992/* File: arm-vfp/OP_ADD_FLOAT.S */ 4993/* File: arm-vfp/fbinop.S */ 4994 /* 4995 * Generic 32-bit floating-point operation. Provide an "instr" line that 4996 * specifies an instruction that performs "s2 = s0 op s1". Because we 4997 * use the "softfp" ABI, this must be an instruction, not a function call. 4998 * 4999 * For: add-float, sub-float, mul-float, div-float 5000 */ 5001 /* floatop vAA, vBB, vCC */ 5002 FETCH(r0, 1) @ r0<- CCBB 5003 mov r9, rINST, lsr #8 @ r9<- AA 5004 mov r3, r0, lsr #8 @ r3<- CC 5005 and r2, r0, #255 @ r2<- BB 5006 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5007 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5008 flds s1, [r3] @ s1<- vCC 5009 flds s0, [r2] @ s0<- vBB 5010 5011 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5012 fadds s2, s0, s1 @ s2<- op 5013 GET_INST_OPCODE(ip) @ extract opcode from rINST 5014 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5015 fsts s2, [r9] @ vAA<- s2 5016 GOTO_OPCODE(ip) @ jump to next instruction 5017 5018 5019/* ------------------------------ */ 5020 .balign 64 5021.L_OP_SUB_FLOAT: /* 0xa7 */ 5022/* File: arm-vfp/OP_SUB_FLOAT.S */ 5023/* File: arm-vfp/fbinop.S */ 5024 /* 5025 * Generic 32-bit floating-point operation. Provide an "instr" line that 5026 * specifies an instruction that performs "s2 = s0 op s1". Because we 5027 * use the "softfp" ABI, this must be an instruction, not a function call. 5028 * 5029 * For: add-float, sub-float, mul-float, div-float 5030 */ 5031 /* floatop vAA, vBB, vCC */ 5032 FETCH(r0, 1) @ r0<- CCBB 5033 mov r9, rINST, lsr #8 @ r9<- AA 5034 mov r3, r0, lsr #8 @ r3<- CC 5035 and r2, r0, #255 @ r2<- BB 5036 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5037 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5038 flds s1, [r3] @ s1<- vCC 5039 flds s0, [r2] @ s0<- vBB 5040 5041 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5042 fsubs s2, s0, s1 @ s2<- op 5043 GET_INST_OPCODE(ip) @ extract opcode from rINST 5044 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5045 fsts s2, [r9] @ vAA<- s2 5046 GOTO_OPCODE(ip) @ jump to next instruction 5047 5048 5049/* ------------------------------ */ 5050 .balign 64 5051.L_OP_MUL_FLOAT: /* 0xa8 */ 5052/* File: arm-vfp/OP_MUL_FLOAT.S */ 5053/* File: arm-vfp/fbinop.S */ 5054 /* 5055 * Generic 32-bit floating-point operation. Provide an "instr" line that 5056 * specifies an instruction that performs "s2 = s0 op s1". Because we 5057 * use the "softfp" ABI, this must be an instruction, not a function call. 5058 * 5059 * For: add-float, sub-float, mul-float, div-float 5060 */ 5061 /* floatop vAA, vBB, vCC */ 5062 FETCH(r0, 1) @ r0<- CCBB 5063 mov r9, rINST, lsr #8 @ r9<- AA 5064 mov r3, r0, lsr #8 @ r3<- CC 5065 and r2, r0, #255 @ r2<- BB 5066 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5067 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5068 flds s1, [r3] @ s1<- vCC 5069 flds s0, [r2] @ s0<- vBB 5070 5071 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5072 fmuls s2, s0, s1 @ s2<- op 5073 GET_INST_OPCODE(ip) @ extract opcode from rINST 5074 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5075 fsts s2, [r9] @ vAA<- s2 5076 GOTO_OPCODE(ip) @ jump to next instruction 5077 5078 5079/* ------------------------------ */ 5080 .balign 64 5081.L_OP_DIV_FLOAT: /* 0xa9 */ 5082/* File: arm-vfp/OP_DIV_FLOAT.S */ 5083/* File: arm-vfp/fbinop.S */ 5084 /* 5085 * Generic 32-bit floating-point operation. Provide an "instr" line that 5086 * specifies an instruction that performs "s2 = s0 op s1". Because we 5087 * use the "softfp" ABI, this must be an instruction, not a function call. 5088 * 5089 * For: add-float, sub-float, mul-float, div-float 5090 */ 5091 /* floatop vAA, vBB, vCC */ 5092 FETCH(r0, 1) @ r0<- CCBB 5093 mov r9, rINST, lsr #8 @ r9<- AA 5094 mov r3, r0, lsr #8 @ r3<- CC 5095 and r2, r0, #255 @ r2<- BB 5096 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5097 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5098 flds s1, [r3] @ s1<- vCC 5099 flds s0, [r2] @ s0<- vBB 5100 5101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5102 fdivs s2, s0, s1 @ s2<- op 5103 GET_INST_OPCODE(ip) @ extract opcode from rINST 5104 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5105 fsts s2, [r9] @ vAA<- s2 5106 GOTO_OPCODE(ip) @ jump to next instruction 5107 5108 5109/* ------------------------------ */ 5110 .balign 64 5111.L_OP_REM_FLOAT: /* 0xaa */ 5112/* File: armv5te/OP_REM_FLOAT.S */ 5113/* EABI doesn't define a float remainder function, but libm does */ 5114/* File: armv5te/binop.S */ 5115 /* 5116 * Generic 32-bit binary operation. Provide an "instr" line that 5117 * specifies an instruction that performs "result = r0 op r1". 5118 * This could be an ARM instruction or a function call. (If the result 5119 * comes back in a register other than r0, you can override "result".) 5120 * 5121 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5122 * vCC (r1). Useful for integer division and modulus. Note that we 5123 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5124 * handles it correctly. 5125 * 5126 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5127 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5128 * mul-float, div-float, rem-float 5129 */ 5130 /* binop vAA, vBB, vCC */ 5131 FETCH(r0, 1) @ r0<- CCBB 5132 mov r9, rINST, lsr #8 @ r9<- AA 5133 mov r3, r0, lsr #8 @ r3<- CC 5134 and r2, r0, #255 @ r2<- BB 5135 GET_VREG(r1, r3) @ r1<- vCC 5136 GET_VREG(r0, r2) @ r0<- vBB 5137 .if 0 5138 cmp r1, #0 @ is second operand zero? 5139 beq common_errDivideByZero 5140 .endif 5141 5142 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5143 @ optional op; may set condition codes 5144 bl fmodf @ r0<- op, r0-r3 changed 5145 GET_INST_OPCODE(ip) @ extract opcode from rINST 5146 SET_VREG(r0, r9) @ vAA<- r0 5147 GOTO_OPCODE(ip) @ jump to next instruction 5148 /* 11-14 instructions */ 5149 5150 5151 5152/* ------------------------------ */ 5153 .balign 64 5154.L_OP_ADD_DOUBLE: /* 0xab */ 5155/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5156/* File: arm-vfp/fbinopWide.S */ 5157 /* 5158 * Generic 64-bit double-precision floating point binary operation. 5159 * Provide an "instr" line that specifies an instruction that performs 5160 * "d2 = d0 op d1". 5161 * 5162 * for: add-double, sub-double, mul-double, div-double 5163 */ 5164 /* doubleop vAA, vBB, vCC */ 5165 FETCH(r0, 1) @ r0<- CCBB 5166 mov r9, rINST, lsr #8 @ r9<- AA 5167 mov r3, r0, lsr #8 @ r3<- CC 5168 and r2, r0, #255 @ r2<- BB 5169 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5170 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5171 fldd d1, [r3] @ d1<- vCC 5172 fldd d0, [r2] @ d0<- vBB 5173 5174 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5175 faddd d2, d0, d1 @ s2<- op 5176 GET_INST_OPCODE(ip) @ extract opcode from rINST 5177 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5178 fstd d2, [r9] @ vAA<- d2 5179 GOTO_OPCODE(ip) @ jump to next instruction 5180 5181 5182/* ------------------------------ */ 5183 .balign 64 5184.L_OP_SUB_DOUBLE: /* 0xac */ 5185/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5186/* File: arm-vfp/fbinopWide.S */ 5187 /* 5188 * Generic 64-bit double-precision floating point binary operation. 5189 * Provide an "instr" line that specifies an instruction that performs 5190 * "d2 = d0 op d1". 5191 * 5192 * for: add-double, sub-double, mul-double, div-double 5193 */ 5194 /* doubleop vAA, vBB, vCC */ 5195 FETCH(r0, 1) @ r0<- CCBB 5196 mov r9, rINST, lsr #8 @ r9<- AA 5197 mov r3, r0, lsr #8 @ r3<- CC 5198 and r2, r0, #255 @ r2<- BB 5199 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5200 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5201 fldd d1, [r3] @ d1<- vCC 5202 fldd d0, [r2] @ d0<- vBB 5203 5204 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5205 fsubd d2, d0, d1 @ s2<- op 5206 GET_INST_OPCODE(ip) @ extract opcode from rINST 5207 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5208 fstd d2, [r9] @ vAA<- d2 5209 GOTO_OPCODE(ip) @ jump to next instruction 5210 5211 5212/* ------------------------------ */ 5213 .balign 64 5214.L_OP_MUL_DOUBLE: /* 0xad */ 5215/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5216/* File: arm-vfp/fbinopWide.S */ 5217 /* 5218 * Generic 64-bit double-precision floating point binary operation. 5219 * Provide an "instr" line that specifies an instruction that performs 5220 * "d2 = d0 op d1". 5221 * 5222 * for: add-double, sub-double, mul-double, div-double 5223 */ 5224 /* doubleop vAA, vBB, vCC */ 5225 FETCH(r0, 1) @ r0<- CCBB 5226 mov r9, rINST, lsr #8 @ r9<- AA 5227 mov r3, r0, lsr #8 @ r3<- CC 5228 and r2, r0, #255 @ r2<- BB 5229 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5230 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5231 fldd d1, [r3] @ d1<- vCC 5232 fldd d0, [r2] @ d0<- vBB 5233 5234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5235 fmuld d2, d0, d1 @ s2<- op 5236 GET_INST_OPCODE(ip) @ extract opcode from rINST 5237 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5238 fstd d2, [r9] @ vAA<- d2 5239 GOTO_OPCODE(ip) @ jump to next instruction 5240 5241 5242/* ------------------------------ */ 5243 .balign 64 5244.L_OP_DIV_DOUBLE: /* 0xae */ 5245/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5246/* File: arm-vfp/fbinopWide.S */ 5247 /* 5248 * Generic 64-bit double-precision floating point binary operation. 5249 * Provide an "instr" line that specifies an instruction that performs 5250 * "d2 = d0 op d1". 5251 * 5252 * for: add-double, sub-double, mul-double, div-double 5253 */ 5254 /* doubleop vAA, vBB, vCC */ 5255 FETCH(r0, 1) @ r0<- CCBB 5256 mov r9, rINST, lsr #8 @ r9<- AA 5257 mov r3, r0, lsr #8 @ r3<- CC 5258 and r2, r0, #255 @ r2<- BB 5259 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5260 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5261 fldd d1, [r3] @ d1<- vCC 5262 fldd d0, [r2] @ d0<- vBB 5263 5264 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5265 fdivd d2, d0, d1 @ s2<- op 5266 GET_INST_OPCODE(ip) @ extract opcode from rINST 5267 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5268 fstd d2, [r9] @ vAA<- d2 5269 GOTO_OPCODE(ip) @ jump to next instruction 5270 5271 5272/* ------------------------------ */ 5273 .balign 64 5274.L_OP_REM_DOUBLE: /* 0xaf */ 5275/* File: armv5te/OP_REM_DOUBLE.S */ 5276/* EABI doesn't define a double remainder function, but libm does */ 5277/* File: armv5te/binopWide.S */ 5278 /* 5279 * Generic 64-bit binary operation. Provide an "instr" line that 5280 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5281 * This could be an ARM instruction or a function call. (If the result 5282 * comes back in a register other than r0, you can override "result".) 5283 * 5284 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5285 * vCC (r1). Useful for integer division and modulus. 5286 * 5287 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5288 * xor-long, add-double, sub-double, mul-double, div-double, 5289 * rem-double 5290 * 5291 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5292 */ 5293 /* binop vAA, vBB, vCC */ 5294 FETCH(r0, 1) @ r0<- CCBB 5295 mov r9, rINST, lsr #8 @ r9<- AA 5296 and r2, r0, #255 @ r2<- BB 5297 mov r3, r0, lsr #8 @ r3<- CC 5298 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5299 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5300 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5301 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5302 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5303 .if 0 5304 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5305 beq common_errDivideByZero 5306 .endif 5307 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5308 5309 @ optional op; may set condition codes 5310 bl fmod @ result<- op, r0-r3 changed 5311 GET_INST_OPCODE(ip) @ extract opcode from rINST 5312 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5313 GOTO_OPCODE(ip) @ jump to next instruction 5314 /* 14-17 instructions */ 5315 5316 5317 5318/* ------------------------------ */ 5319 .balign 64 5320.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5321/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5322/* File: armv5te/binop2addr.S */ 5323 /* 5324 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5325 * that specifies an instruction that performs "result = r0 op r1". 5326 * This could be an ARM instruction or a function call. (If the result 5327 * comes back in a register other than r0, you can override "result".) 5328 * 5329 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5330 * vCC (r1). Useful for integer division and modulus. 5331 * 5332 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5333 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5334 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5335 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5336 */ 5337 /* binop/2addr vA, vB */ 5338 mov r9, rINST, lsr #8 @ r9<- A+ 5339 mov r3, rINST, lsr #12 @ r3<- B 5340 and r9, r9, #15 5341 GET_VREG(r1, r3) @ r1<- vB 5342 GET_VREG(r0, r9) @ r0<- vA 5343 .if 0 5344 cmp r1, #0 @ is second operand zero? 5345 beq common_errDivideByZero 5346 .endif 5347 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5348 5349 @ optional op; may set condition codes 5350 add r0, r0, r1 @ r0<- op, r0-r3 changed 5351 GET_INST_OPCODE(ip) @ extract opcode from rINST 5352 SET_VREG(r0, r9) @ vAA<- r0 5353 GOTO_OPCODE(ip) @ jump to next instruction 5354 /* 10-13 instructions */ 5355 5356 5357 5358/* ------------------------------ */ 5359 .balign 64 5360.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5361/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5362/* File: armv5te/binop2addr.S */ 5363 /* 5364 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5365 * that specifies an instruction that performs "result = r0 op r1". 5366 * This could be an ARM instruction or a function call. (If the result 5367 * comes back in a register other than r0, you can override "result".) 5368 * 5369 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5370 * vCC (r1). Useful for integer division and modulus. 5371 * 5372 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5373 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5374 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5375 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5376 */ 5377 /* binop/2addr vA, vB */ 5378 mov r9, rINST, lsr #8 @ r9<- A+ 5379 mov r3, rINST, lsr #12 @ r3<- B 5380 and r9, r9, #15 5381 GET_VREG(r1, r3) @ r1<- vB 5382 GET_VREG(r0, r9) @ r0<- vA 5383 .if 0 5384 cmp r1, #0 @ is second operand zero? 5385 beq common_errDivideByZero 5386 .endif 5387 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5388 5389 @ optional op; may set condition codes 5390 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5391 GET_INST_OPCODE(ip) @ extract opcode from rINST 5392 SET_VREG(r0, r9) @ vAA<- r0 5393 GOTO_OPCODE(ip) @ jump to next instruction 5394 /* 10-13 instructions */ 5395 5396 5397 5398/* ------------------------------ */ 5399 .balign 64 5400.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5401/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5402/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5403/* File: armv5te/binop2addr.S */ 5404 /* 5405 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5406 * that specifies an instruction that performs "result = r0 op r1". 5407 * This could be an ARM instruction or a function call. (If the result 5408 * comes back in a register other than r0, you can override "result".) 5409 * 5410 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5411 * vCC (r1). Useful for integer division and modulus. 5412 * 5413 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5414 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5415 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5416 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5417 */ 5418 /* binop/2addr vA, vB */ 5419 mov r9, rINST, lsr #8 @ r9<- A+ 5420 mov r3, rINST, lsr #12 @ r3<- B 5421 and r9, r9, #15 5422 GET_VREG(r1, r3) @ r1<- vB 5423 GET_VREG(r0, r9) @ r0<- vA 5424 .if 0 5425 cmp r1, #0 @ is second operand zero? 5426 beq common_errDivideByZero 5427 .endif 5428 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5429 5430 @ optional op; may set condition codes 5431 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5432 GET_INST_OPCODE(ip) @ extract opcode from rINST 5433 SET_VREG(r0, r9) @ vAA<- r0 5434 GOTO_OPCODE(ip) @ jump to next instruction 5435 /* 10-13 instructions */ 5436 5437 5438 5439/* ------------------------------ */ 5440 .balign 64 5441.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5442/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5443/* File: armv5te/binop2addr.S */ 5444 /* 5445 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5446 * that specifies an instruction that performs "result = r0 op r1". 5447 * This could be an ARM instruction or a function call. (If the result 5448 * comes back in a register other than r0, you can override "result".) 5449 * 5450 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5451 * vCC (r1). Useful for integer division and modulus. 5452 * 5453 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5454 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5455 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5456 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5457 */ 5458 /* binop/2addr vA, vB */ 5459 mov r9, rINST, lsr #8 @ r9<- A+ 5460 mov r3, rINST, lsr #12 @ r3<- B 5461 and r9, r9, #15 5462 GET_VREG(r1, r3) @ r1<- vB 5463 GET_VREG(r0, r9) @ r0<- vA 5464 .if 1 5465 cmp r1, #0 @ is second operand zero? 5466 beq common_errDivideByZero 5467 .endif 5468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5469 5470 @ optional op; may set condition codes 5471 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5472 GET_INST_OPCODE(ip) @ extract opcode from rINST 5473 SET_VREG(r0, r9) @ vAA<- r0 5474 GOTO_OPCODE(ip) @ jump to next instruction 5475 /* 10-13 instructions */ 5476 5477 5478 5479/* ------------------------------ */ 5480 .balign 64 5481.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5482/* File: armv5te/OP_REM_INT_2ADDR.S */ 5483/* idivmod returns quotient in r0 and remainder in r1 */ 5484/* File: armv5te/binop2addr.S */ 5485 /* 5486 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5487 * that specifies an instruction that performs "result = r0 op r1". 5488 * This could be an ARM instruction or a function call. (If the result 5489 * comes back in a register other than r0, you can override "result".) 5490 * 5491 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5492 * vCC (r1). Useful for integer division and modulus. 5493 * 5494 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5495 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5496 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5497 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5498 */ 5499 /* binop/2addr vA, vB */ 5500 mov r9, rINST, lsr #8 @ r9<- A+ 5501 mov r3, rINST, lsr #12 @ r3<- B 5502 and r9, r9, #15 5503 GET_VREG(r1, r3) @ r1<- vB 5504 GET_VREG(r0, r9) @ r0<- vA 5505 .if 1 5506 cmp r1, #0 @ is second operand zero? 5507 beq common_errDivideByZero 5508 .endif 5509 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5510 5511 @ optional op; may set condition codes 5512 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5513 GET_INST_OPCODE(ip) @ extract opcode from rINST 5514 SET_VREG(r1, r9) @ vAA<- r1 5515 GOTO_OPCODE(ip) @ jump to next instruction 5516 /* 10-13 instructions */ 5517 5518 5519 5520/* ------------------------------ */ 5521 .balign 64 5522.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5523/* File: armv5te/OP_AND_INT_2ADDR.S */ 5524/* File: armv5te/binop2addr.S */ 5525 /* 5526 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5527 * that specifies an instruction that performs "result = r0 op r1". 5528 * This could be an ARM instruction or a function call. (If the result 5529 * comes back in a register other than r0, you can override "result".) 5530 * 5531 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5532 * vCC (r1). Useful for integer division and modulus. 5533 * 5534 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5535 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5536 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5537 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5538 */ 5539 /* binop/2addr vA, vB */ 5540 mov r9, rINST, lsr #8 @ r9<- A+ 5541 mov r3, rINST, lsr #12 @ r3<- B 5542 and r9, r9, #15 5543 GET_VREG(r1, r3) @ r1<- vB 5544 GET_VREG(r0, r9) @ r0<- vA 5545 .if 0 5546 cmp r1, #0 @ is second operand zero? 5547 beq common_errDivideByZero 5548 .endif 5549 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5550 5551 @ optional op; may set condition codes 5552 and r0, r0, r1 @ r0<- op, r0-r3 changed 5553 GET_INST_OPCODE(ip) @ extract opcode from rINST 5554 SET_VREG(r0, r9) @ vAA<- r0 5555 GOTO_OPCODE(ip) @ jump to next instruction 5556 /* 10-13 instructions */ 5557 5558 5559 5560/* ------------------------------ */ 5561 .balign 64 5562.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5563/* File: armv5te/OP_OR_INT_2ADDR.S */ 5564/* File: armv5te/binop2addr.S */ 5565 /* 5566 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5567 * that specifies an instruction that performs "result = r0 op r1". 5568 * This could be an ARM instruction or a function call. (If the result 5569 * comes back in a register other than r0, you can override "result".) 5570 * 5571 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5572 * vCC (r1). Useful for integer division and modulus. 5573 * 5574 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5575 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5576 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5577 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5578 */ 5579 /* binop/2addr vA, vB */ 5580 mov r9, rINST, lsr #8 @ r9<- A+ 5581 mov r3, rINST, lsr #12 @ r3<- B 5582 and r9, r9, #15 5583 GET_VREG(r1, r3) @ r1<- vB 5584 GET_VREG(r0, r9) @ r0<- vA 5585 .if 0 5586 cmp r1, #0 @ is second operand zero? 5587 beq common_errDivideByZero 5588 .endif 5589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5590 5591 @ optional op; may set condition codes 5592 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5593 GET_INST_OPCODE(ip) @ extract opcode from rINST 5594 SET_VREG(r0, r9) @ vAA<- r0 5595 GOTO_OPCODE(ip) @ jump to next instruction 5596 /* 10-13 instructions */ 5597 5598 5599 5600/* ------------------------------ */ 5601 .balign 64 5602.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5603/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5604/* File: armv5te/binop2addr.S */ 5605 /* 5606 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5607 * that specifies an instruction that performs "result = r0 op r1". 5608 * This could be an ARM instruction or a function call. (If the result 5609 * comes back in a register other than r0, you can override "result".) 5610 * 5611 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5612 * vCC (r1). Useful for integer division and modulus. 5613 * 5614 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5615 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5616 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5617 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5618 */ 5619 /* binop/2addr vA, vB */ 5620 mov r9, rINST, lsr #8 @ r9<- A+ 5621 mov r3, rINST, lsr #12 @ r3<- B 5622 and r9, r9, #15 5623 GET_VREG(r1, r3) @ r1<- vB 5624 GET_VREG(r0, r9) @ r0<- vA 5625 .if 0 5626 cmp r1, #0 @ is second operand zero? 5627 beq common_errDivideByZero 5628 .endif 5629 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5630 5631 @ optional op; may set condition codes 5632 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5633 GET_INST_OPCODE(ip) @ extract opcode from rINST 5634 SET_VREG(r0, r9) @ vAA<- r0 5635 GOTO_OPCODE(ip) @ jump to next instruction 5636 /* 10-13 instructions */ 5637 5638 5639 5640/* ------------------------------ */ 5641 .balign 64 5642.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5643/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5644/* File: armv5te/binop2addr.S */ 5645 /* 5646 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5647 * that specifies an instruction that performs "result = r0 op r1". 5648 * This could be an ARM instruction or a function call. (If the result 5649 * comes back in a register other than r0, you can override "result".) 5650 * 5651 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5652 * vCC (r1). Useful for integer division and modulus. 5653 * 5654 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5655 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5656 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5657 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5658 */ 5659 /* binop/2addr vA, vB */ 5660 mov r9, rINST, lsr #8 @ r9<- A+ 5661 mov r3, rINST, lsr #12 @ r3<- B 5662 and r9, r9, #15 5663 GET_VREG(r1, r3) @ r1<- vB 5664 GET_VREG(r0, r9) @ r0<- vA 5665 .if 0 5666 cmp r1, #0 @ is second operand zero? 5667 beq common_errDivideByZero 5668 .endif 5669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5670 5671 and r1, r1, #31 @ optional op; may set condition codes 5672 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5673 GET_INST_OPCODE(ip) @ extract opcode from rINST 5674 SET_VREG(r0, r9) @ vAA<- r0 5675 GOTO_OPCODE(ip) @ jump to next instruction 5676 /* 10-13 instructions */ 5677 5678 5679 5680/* ------------------------------ */ 5681 .balign 64 5682.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5683/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5684/* File: armv5te/binop2addr.S */ 5685 /* 5686 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5687 * that specifies an instruction that performs "result = r0 op r1". 5688 * This could be an ARM instruction or a function call. (If the result 5689 * comes back in a register other than r0, you can override "result".) 5690 * 5691 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5692 * vCC (r1). Useful for integer division and modulus. 5693 * 5694 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5695 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5696 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5697 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5698 */ 5699 /* binop/2addr vA, vB */ 5700 mov r9, rINST, lsr #8 @ r9<- A+ 5701 mov r3, rINST, lsr #12 @ r3<- B 5702 and r9, r9, #15 5703 GET_VREG(r1, r3) @ r1<- vB 5704 GET_VREG(r0, r9) @ r0<- vA 5705 .if 0 5706 cmp r1, #0 @ is second operand zero? 5707 beq common_errDivideByZero 5708 .endif 5709 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5710 5711 and r1, r1, #31 @ optional op; may set condition codes 5712 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5713 GET_INST_OPCODE(ip) @ extract opcode from rINST 5714 SET_VREG(r0, r9) @ vAA<- r0 5715 GOTO_OPCODE(ip) @ jump to next instruction 5716 /* 10-13 instructions */ 5717 5718 5719 5720/* ------------------------------ */ 5721 .balign 64 5722.L_OP_USHR_INT_2ADDR: /* 0xba */ 5723/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5724/* File: armv5te/binop2addr.S */ 5725 /* 5726 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5727 * that specifies an instruction that performs "result = r0 op r1". 5728 * This could be an ARM instruction or a function call. (If the result 5729 * comes back in a register other than r0, you can override "result".) 5730 * 5731 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5732 * vCC (r1). Useful for integer division and modulus. 5733 * 5734 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5735 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5736 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5737 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5738 */ 5739 /* binop/2addr vA, vB */ 5740 mov r9, rINST, lsr #8 @ r9<- A+ 5741 mov r3, rINST, lsr #12 @ r3<- B 5742 and r9, r9, #15 5743 GET_VREG(r1, r3) @ r1<- vB 5744 GET_VREG(r0, r9) @ r0<- vA 5745 .if 0 5746 cmp r1, #0 @ is second operand zero? 5747 beq common_errDivideByZero 5748 .endif 5749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5750 5751 and r1, r1, #31 @ optional op; may set condition codes 5752 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5753 GET_INST_OPCODE(ip) @ extract opcode from rINST 5754 SET_VREG(r0, r9) @ vAA<- r0 5755 GOTO_OPCODE(ip) @ jump to next instruction 5756 /* 10-13 instructions */ 5757 5758 5759 5760/* ------------------------------ */ 5761 .balign 64 5762.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5763/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5764/* File: armv5te/binopWide2addr.S */ 5765 /* 5766 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5767 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5768 * This could be an ARM instruction or a function call. (If the result 5769 * comes back in a register other than r0, you can override "result".) 5770 * 5771 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5772 * vCC (r1). Useful for integer division and modulus. 5773 * 5774 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5775 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5776 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5777 * rem-double/2addr 5778 */ 5779 /* binop/2addr vA, vB */ 5780 mov r9, rINST, lsr #8 @ r9<- A+ 5781 mov r1, rINST, lsr #12 @ r1<- B 5782 and r9, r9, #15 5783 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5784 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5785 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5786 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5787 .if 0 5788 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5789 beq common_errDivideByZero 5790 .endif 5791 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5792 5793 adds r0, r0, r2 @ optional op; may set condition codes 5794 adc r1, r1, r3 @ result<- op, r0-r3 changed 5795 GET_INST_OPCODE(ip) @ extract opcode from rINST 5796 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5797 GOTO_OPCODE(ip) @ jump to next instruction 5798 /* 12-15 instructions */ 5799 5800 5801 5802/* ------------------------------ */ 5803 .balign 64 5804.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5805/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5806/* File: armv5te/binopWide2addr.S */ 5807 /* 5808 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5809 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5810 * This could be an ARM instruction or a function call. (If the result 5811 * comes back in a register other than r0, you can override "result".) 5812 * 5813 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5814 * vCC (r1). Useful for integer division and modulus. 5815 * 5816 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5817 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5818 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5819 * rem-double/2addr 5820 */ 5821 /* binop/2addr vA, vB */ 5822 mov r9, rINST, lsr #8 @ r9<- A+ 5823 mov r1, rINST, lsr #12 @ r1<- B 5824 and r9, r9, #15 5825 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5826 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5827 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5828 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5829 .if 0 5830 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5831 beq common_errDivideByZero 5832 .endif 5833 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5834 5835 subs r0, r0, r2 @ optional op; may set condition codes 5836 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5837 GET_INST_OPCODE(ip) @ extract opcode from rINST 5838 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5839 GOTO_OPCODE(ip) @ jump to next instruction 5840 /* 12-15 instructions */ 5841 5842 5843 5844/* ------------------------------ */ 5845 .balign 64 5846.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5847/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5848 /* 5849 * Signed 64-bit integer multiply, "/2addr" version. 5850 * 5851 * See OP_MUL_LONG for an explanation. 5852 * 5853 * We get a little tight on registers, so to avoid looking up &fp[A] 5854 * again we stuff it into rINST. 5855 */ 5856 /* mul-long/2addr vA, vB */ 5857 mov r9, rINST, lsr #8 @ r9<- A+ 5858 mov r1, rINST, lsr #12 @ r1<- B 5859 and r9, r9, #15 5860 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5861 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5862 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5863 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5864 mul ip, r2, r1 @ ip<- ZxW 5865 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5866 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5867 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5868 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5869 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5870 GET_INST_OPCODE(ip) @ extract opcode from rINST 5871 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5872 GOTO_OPCODE(ip) @ jump to next instruction 5873 5874 5875/* ------------------------------ */ 5876 .balign 64 5877.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5878/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5879/* File: armv5te/binopWide2addr.S */ 5880 /* 5881 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5882 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5883 * This could be an ARM instruction or a function call. (If the result 5884 * comes back in a register other than r0, you can override "result".) 5885 * 5886 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5887 * vCC (r1). Useful for integer division and modulus. 5888 * 5889 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5890 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5891 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5892 * rem-double/2addr 5893 */ 5894 /* binop/2addr vA, vB */ 5895 mov r9, rINST, lsr #8 @ r9<- A+ 5896 mov r1, rINST, lsr #12 @ r1<- B 5897 and r9, r9, #15 5898 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5899 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5900 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5901 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5902 .if 1 5903 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5904 beq common_errDivideByZero 5905 .endif 5906 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5907 5908 @ optional op; may set condition codes 5909 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5910 GET_INST_OPCODE(ip) @ extract opcode from rINST 5911 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5912 GOTO_OPCODE(ip) @ jump to next instruction 5913 /* 12-15 instructions */ 5914 5915 5916 5917/* ------------------------------ */ 5918 .balign 64 5919.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5920/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5921/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5922/* File: armv5te/binopWide2addr.S */ 5923 /* 5924 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5925 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5926 * This could be an ARM instruction or a function call. (If the result 5927 * comes back in a register other than r0, you can override "result".) 5928 * 5929 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5930 * vCC (r1). Useful for integer division and modulus. 5931 * 5932 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5933 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5934 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5935 * rem-double/2addr 5936 */ 5937 /* binop/2addr vA, vB */ 5938 mov r9, rINST, lsr #8 @ r9<- A+ 5939 mov r1, rINST, lsr #12 @ r1<- B 5940 and r9, r9, #15 5941 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5942 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5943 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5944 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5945 .if 1 5946 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5947 beq common_errDivideByZero 5948 .endif 5949 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5950 5951 @ optional op; may set condition codes 5952 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5953 GET_INST_OPCODE(ip) @ extract opcode from rINST 5954 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5955 GOTO_OPCODE(ip) @ jump to next instruction 5956 /* 12-15 instructions */ 5957 5958 5959 5960/* ------------------------------ */ 5961 .balign 64 5962.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5963/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5964/* File: armv5te/binopWide2addr.S */ 5965 /* 5966 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5967 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5968 * This could be an ARM instruction or a function call. (If the result 5969 * comes back in a register other than r0, you can override "result".) 5970 * 5971 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5972 * vCC (r1). Useful for integer division and modulus. 5973 * 5974 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5975 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5976 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5977 * rem-double/2addr 5978 */ 5979 /* binop/2addr vA, vB */ 5980 mov r9, rINST, lsr #8 @ r9<- A+ 5981 mov r1, rINST, lsr #12 @ r1<- B 5982 and r9, r9, #15 5983 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5984 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5985 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5986 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5987 .if 0 5988 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5989 beq common_errDivideByZero 5990 .endif 5991 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5992 5993 and r0, r0, r2 @ optional op; may set condition codes 5994 and r1, r1, r3 @ result<- op, r0-r3 changed 5995 GET_INST_OPCODE(ip) @ extract opcode from rINST 5996 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5997 GOTO_OPCODE(ip) @ jump to next instruction 5998 /* 12-15 instructions */ 5999 6000 6001 6002/* ------------------------------ */ 6003 .balign 64 6004.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6005/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6006/* File: armv5te/binopWide2addr.S */ 6007 /* 6008 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6009 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6010 * This could be an ARM instruction or a function call. (If the result 6011 * comes back in a register other than r0, you can override "result".) 6012 * 6013 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6014 * vCC (r1). Useful for integer division and modulus. 6015 * 6016 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6017 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6018 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6019 * rem-double/2addr 6020 */ 6021 /* binop/2addr vA, vB */ 6022 mov r9, rINST, lsr #8 @ r9<- A+ 6023 mov r1, rINST, lsr #12 @ r1<- B 6024 and r9, r9, #15 6025 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6026 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6027 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6028 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6029 .if 0 6030 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6031 beq common_errDivideByZero 6032 .endif 6033 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6034 6035 orr r0, r0, r2 @ optional op; may set condition codes 6036 orr r1, r1, r3 @ result<- op, r0-r3 changed 6037 GET_INST_OPCODE(ip) @ extract opcode from rINST 6038 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6039 GOTO_OPCODE(ip) @ jump to next instruction 6040 /* 12-15 instructions */ 6041 6042 6043 6044/* ------------------------------ */ 6045 .balign 64 6046.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6047/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6048/* File: armv5te/binopWide2addr.S */ 6049 /* 6050 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6051 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6052 * This could be an ARM instruction or a function call. (If the result 6053 * comes back in a register other than r0, you can override "result".) 6054 * 6055 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6056 * vCC (r1). Useful for integer division and modulus. 6057 * 6058 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6059 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6060 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6061 * rem-double/2addr 6062 */ 6063 /* binop/2addr vA, vB */ 6064 mov r9, rINST, lsr #8 @ r9<- A+ 6065 mov r1, rINST, lsr #12 @ r1<- B 6066 and r9, r9, #15 6067 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6068 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6069 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6070 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6071 .if 0 6072 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6073 beq common_errDivideByZero 6074 .endif 6075 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6076 6077 eor r0, r0, r2 @ optional op; may set condition codes 6078 eor r1, r1, r3 @ result<- op, r0-r3 changed 6079 GET_INST_OPCODE(ip) @ extract opcode from rINST 6080 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6081 GOTO_OPCODE(ip) @ jump to next instruction 6082 /* 12-15 instructions */ 6083 6084 6085 6086/* ------------------------------ */ 6087 .balign 64 6088.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6089/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6090 /* 6091 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6092 * 32-bit shift distance. 6093 */ 6094 /* shl-long/2addr vA, vB */ 6095 mov r9, rINST, lsr #8 @ r9<- A+ 6096 mov r3, rINST, lsr #12 @ r3<- B 6097 and r9, r9, #15 6098 GET_VREG(r2, r3) @ r2<- vB 6099 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6100 and r2, r2, #63 @ r2<- r2 & 0x3f 6101 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6102 6103 mov r1, r1, asl r2 @ r1<- r1 << r2 6104 rsb r3, r2, #32 @ r3<- 32 - r2 6105 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6106 subs ip, r2, #32 @ ip<- r2 - 32 6107 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6108 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6109 mov r0, r0, asl r2 @ r0<- r0 << r2 6110 b .LOP_SHL_LONG_2ADDR_finish 6111 6112/* ------------------------------ */ 6113 .balign 64 6114.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6115/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6116 /* 6117 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6118 * 32-bit shift distance. 6119 */ 6120 /* shr-long/2addr vA, vB */ 6121 mov r9, rINST, lsr #8 @ r9<- A+ 6122 mov r3, rINST, lsr #12 @ r3<- B 6123 and r9, r9, #15 6124 GET_VREG(r2, r3) @ r2<- vB 6125 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6126 and r2, r2, #63 @ r2<- r2 & 0x3f 6127 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6128 6129 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6130 rsb r3, r2, #32 @ r3<- 32 - r2 6131 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6132 subs ip, r2, #32 @ ip<- r2 - 32 6133 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6134 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6135 mov r1, r1, asr r2 @ r1<- r1 >> r2 6136 b .LOP_SHR_LONG_2ADDR_finish 6137 6138/* ------------------------------ */ 6139 .balign 64 6140.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6141/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6142 /* 6143 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6144 * 32-bit shift distance. 6145 */ 6146 /* ushr-long/2addr vA, vB */ 6147 mov r9, rINST, lsr #8 @ r9<- A+ 6148 mov r3, rINST, lsr #12 @ r3<- B 6149 and r9, r9, #15 6150 GET_VREG(r2, r3) @ r2<- vB 6151 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6152 and r2, r2, #63 @ r2<- r2 & 0x3f 6153 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6154 6155 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6156 rsb r3, r2, #32 @ r3<- 32 - r2 6157 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6158 subs ip, r2, #32 @ ip<- r2 - 32 6159 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6160 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6161 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6162 b .LOP_USHR_LONG_2ADDR_finish 6163 6164/* ------------------------------ */ 6165 .balign 64 6166.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6167/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6168/* File: arm-vfp/fbinop2addr.S */ 6169 /* 6170 * Generic 32-bit floating point "/2addr" binary operation. Provide 6171 * an "instr" line that specifies an instruction that performs 6172 * "s2 = s0 op s1". 6173 * 6174 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6175 */ 6176 /* binop/2addr vA, vB */ 6177 mov r3, rINST, lsr #12 @ r3<- B 6178 mov r9, rINST, lsr #8 @ r9<- A+ 6179 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6180 and r9, r9, #15 @ r9<- A 6181 flds s1, [r3] @ s1<- vB 6182 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6183 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6184 flds s0, [r9] @ s0<- vA 6185 6186 fadds s2, s0, s1 @ s2<- op 6187 GET_INST_OPCODE(ip) @ extract opcode from rINST 6188 fsts s2, [r9] @ vAA<- s2 6189 GOTO_OPCODE(ip) @ jump to next instruction 6190 6191 6192/* ------------------------------ */ 6193 .balign 64 6194.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6195/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6196/* File: arm-vfp/fbinop2addr.S */ 6197 /* 6198 * Generic 32-bit floating point "/2addr" binary operation. Provide 6199 * an "instr" line that specifies an instruction that performs 6200 * "s2 = s0 op s1". 6201 * 6202 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6203 */ 6204 /* binop/2addr vA, vB */ 6205 mov r3, rINST, lsr #12 @ r3<- B 6206 mov r9, rINST, lsr #8 @ r9<- A+ 6207 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6208 and r9, r9, #15 @ r9<- A 6209 flds s1, [r3] @ s1<- vB 6210 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6211 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6212 flds s0, [r9] @ s0<- vA 6213 6214 fsubs s2, s0, s1 @ s2<- op 6215 GET_INST_OPCODE(ip) @ extract opcode from rINST 6216 fsts s2, [r9] @ vAA<- s2 6217 GOTO_OPCODE(ip) @ jump to next instruction 6218 6219 6220/* ------------------------------ */ 6221 .balign 64 6222.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6223/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6224/* File: arm-vfp/fbinop2addr.S */ 6225 /* 6226 * Generic 32-bit floating point "/2addr" binary operation. Provide 6227 * an "instr" line that specifies an instruction that performs 6228 * "s2 = s0 op s1". 6229 * 6230 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6231 */ 6232 /* binop/2addr vA, vB */ 6233 mov r3, rINST, lsr #12 @ r3<- B 6234 mov r9, rINST, lsr #8 @ r9<- A+ 6235 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6236 and r9, r9, #15 @ r9<- A 6237 flds s1, [r3] @ s1<- vB 6238 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6239 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6240 flds s0, [r9] @ s0<- vA 6241 6242 fmuls s2, s0, s1 @ s2<- op 6243 GET_INST_OPCODE(ip) @ extract opcode from rINST 6244 fsts s2, [r9] @ vAA<- s2 6245 GOTO_OPCODE(ip) @ jump to next instruction 6246 6247 6248/* ------------------------------ */ 6249 .balign 64 6250.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6251/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6252/* File: arm-vfp/fbinop2addr.S */ 6253 /* 6254 * Generic 32-bit floating point "/2addr" binary operation. Provide 6255 * an "instr" line that specifies an instruction that performs 6256 * "s2 = s0 op s1". 6257 * 6258 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6259 */ 6260 /* binop/2addr vA, vB */ 6261 mov r3, rINST, lsr #12 @ r3<- B 6262 mov r9, rINST, lsr #8 @ r9<- A+ 6263 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6264 and r9, r9, #15 @ r9<- A 6265 flds s1, [r3] @ s1<- vB 6266 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6267 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6268 flds s0, [r9] @ s0<- vA 6269 6270 fdivs s2, s0, s1 @ s2<- op 6271 GET_INST_OPCODE(ip) @ extract opcode from rINST 6272 fsts s2, [r9] @ vAA<- s2 6273 GOTO_OPCODE(ip) @ jump to next instruction 6274 6275 6276/* ------------------------------ */ 6277 .balign 64 6278.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6279/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6280/* EABI doesn't define a float remainder function, but libm does */ 6281/* File: armv5te/binop2addr.S */ 6282 /* 6283 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6284 * that specifies an instruction that performs "result = r0 op r1". 6285 * This could be an ARM instruction or a function call. (If the result 6286 * comes back in a register other than r0, you can override "result".) 6287 * 6288 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6289 * vCC (r1). Useful for integer division and modulus. 6290 * 6291 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6292 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6293 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6294 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6295 */ 6296 /* binop/2addr vA, vB */ 6297 mov r9, rINST, lsr #8 @ r9<- A+ 6298 mov r3, rINST, lsr #12 @ r3<- B 6299 and r9, r9, #15 6300 GET_VREG(r1, r3) @ r1<- vB 6301 GET_VREG(r0, r9) @ r0<- vA 6302 .if 0 6303 cmp r1, #0 @ is second operand zero? 6304 beq common_errDivideByZero 6305 .endif 6306 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6307 6308 @ optional op; may set condition codes 6309 bl fmodf @ r0<- op, r0-r3 changed 6310 GET_INST_OPCODE(ip) @ extract opcode from rINST 6311 SET_VREG(r0, r9) @ vAA<- r0 6312 GOTO_OPCODE(ip) @ jump to next instruction 6313 /* 10-13 instructions */ 6314 6315 6316 6317/* ------------------------------ */ 6318 .balign 64 6319.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6320/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6321/* File: arm-vfp/fbinopWide2addr.S */ 6322 /* 6323 * Generic 64-bit floating point "/2addr" binary operation. Provide 6324 * an "instr" line that specifies an instruction that performs 6325 * "d2 = d0 op d1". 6326 * 6327 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6328 * div-double/2addr 6329 */ 6330 /* binop/2addr vA, vB */ 6331 mov r3, rINST, lsr #12 @ r3<- B 6332 mov r9, rINST, lsr #8 @ r9<- A+ 6333 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6334 and r9, r9, #15 @ r9<- A 6335 fldd d1, [r3] @ d1<- vB 6336 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6337 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6338 fldd d0, [r9] @ d0<- vA 6339 6340 faddd d2, d0, d1 @ d2<- op 6341 GET_INST_OPCODE(ip) @ extract opcode from rINST 6342 fstd d2, [r9] @ vAA<- d2 6343 GOTO_OPCODE(ip) @ jump to next instruction 6344 6345 6346/* ------------------------------ */ 6347 .balign 64 6348.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6349/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6350/* File: arm-vfp/fbinopWide2addr.S */ 6351 /* 6352 * Generic 64-bit floating point "/2addr" binary operation. Provide 6353 * an "instr" line that specifies an instruction that performs 6354 * "d2 = d0 op d1". 6355 * 6356 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6357 * div-double/2addr 6358 */ 6359 /* binop/2addr vA, vB */ 6360 mov r3, rINST, lsr #12 @ r3<- B 6361 mov r9, rINST, lsr #8 @ r9<- A+ 6362 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6363 and r9, r9, #15 @ r9<- A 6364 fldd d1, [r3] @ d1<- vB 6365 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6366 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6367 fldd d0, [r9] @ d0<- vA 6368 6369 fsubd d2, d0, d1 @ d2<- op 6370 GET_INST_OPCODE(ip) @ extract opcode from rINST 6371 fstd d2, [r9] @ vAA<- d2 6372 GOTO_OPCODE(ip) @ jump to next instruction 6373 6374 6375/* ------------------------------ */ 6376 .balign 64 6377.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6378/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6379/* File: arm-vfp/fbinopWide2addr.S */ 6380 /* 6381 * Generic 64-bit floating point "/2addr" binary operation. Provide 6382 * an "instr" line that specifies an instruction that performs 6383 * "d2 = d0 op d1". 6384 * 6385 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6386 * div-double/2addr 6387 */ 6388 /* binop/2addr vA, vB */ 6389 mov r3, rINST, lsr #12 @ r3<- B 6390 mov r9, rINST, lsr #8 @ r9<- A+ 6391 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6392 and r9, r9, #15 @ r9<- A 6393 fldd d1, [r3] @ d1<- vB 6394 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6395 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6396 fldd d0, [r9] @ d0<- vA 6397 6398 fmuld d2, d0, d1 @ d2<- op 6399 GET_INST_OPCODE(ip) @ extract opcode from rINST 6400 fstd d2, [r9] @ vAA<- d2 6401 GOTO_OPCODE(ip) @ jump to next instruction 6402 6403 6404/* ------------------------------ */ 6405 .balign 64 6406.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6407/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6408/* File: arm-vfp/fbinopWide2addr.S */ 6409 /* 6410 * Generic 64-bit floating point "/2addr" binary operation. Provide 6411 * an "instr" line that specifies an instruction that performs 6412 * "d2 = d0 op d1". 6413 * 6414 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6415 * div-double/2addr 6416 */ 6417 /* binop/2addr vA, vB */ 6418 mov r3, rINST, lsr #12 @ r3<- B 6419 mov r9, rINST, lsr #8 @ r9<- A+ 6420 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6421 and r9, r9, #15 @ r9<- A 6422 fldd d1, [r3] @ d1<- vB 6423 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6424 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6425 fldd d0, [r9] @ d0<- vA 6426 6427 fdivd d2, d0, d1 @ d2<- op 6428 GET_INST_OPCODE(ip) @ extract opcode from rINST 6429 fstd d2, [r9] @ vAA<- d2 6430 GOTO_OPCODE(ip) @ jump to next instruction 6431 6432 6433/* ------------------------------ */ 6434 .balign 64 6435.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6436/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6437/* EABI doesn't define a double remainder function, but libm does */ 6438/* File: armv5te/binopWide2addr.S */ 6439 /* 6440 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6441 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6442 * This could be an ARM instruction or a function call. (If the result 6443 * comes back in a register other than r0, you can override "result".) 6444 * 6445 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6446 * vCC (r1). Useful for integer division and modulus. 6447 * 6448 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6449 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6450 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6451 * rem-double/2addr 6452 */ 6453 /* binop/2addr vA, vB */ 6454 mov r9, rINST, lsr #8 @ r9<- A+ 6455 mov r1, rINST, lsr #12 @ r1<- B 6456 and r9, r9, #15 6457 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6458 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6459 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6460 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6461 .if 0 6462 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6463 beq common_errDivideByZero 6464 .endif 6465 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6466 6467 @ optional op; may set condition codes 6468 bl fmod @ result<- op, r0-r3 changed 6469 GET_INST_OPCODE(ip) @ extract opcode from rINST 6470 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6471 GOTO_OPCODE(ip) @ jump to next instruction 6472 /* 12-15 instructions */ 6473 6474 6475 6476/* ------------------------------ */ 6477 .balign 64 6478.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6479/* File: armv5te/OP_ADD_INT_LIT16.S */ 6480/* File: armv5te/binopLit16.S */ 6481 /* 6482 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6483 * that specifies an instruction that performs "result = r0 op r1". 6484 * This could be an ARM instruction or a function call. (If the result 6485 * comes back in a register other than r0, you can override "result".) 6486 * 6487 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6488 * vCC (r1). Useful for integer division and modulus. 6489 * 6490 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6491 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6492 */ 6493 /* binop/lit16 vA, vB, #+CCCC */ 6494 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6495 mov r2, rINST, lsr #12 @ r2<- B 6496 mov r9, rINST, lsr #8 @ r9<- A+ 6497 GET_VREG(r0, r2) @ r0<- vB 6498 and r9, r9, #15 6499 .if 0 6500 cmp r1, #0 @ is second operand zero? 6501 beq common_errDivideByZero 6502 .endif 6503 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6504 6505 add r0, r0, r1 @ r0<- op, r0-r3 changed 6506 GET_INST_OPCODE(ip) @ extract opcode from rINST 6507 SET_VREG(r0, r9) @ vAA<- r0 6508 GOTO_OPCODE(ip) @ jump to next instruction 6509 /* 10-13 instructions */ 6510 6511 6512 6513/* ------------------------------ */ 6514 .balign 64 6515.L_OP_RSUB_INT: /* 0xd1 */ 6516/* File: armv5te/OP_RSUB_INT.S */ 6517/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6518/* File: armv5te/binopLit16.S */ 6519 /* 6520 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6521 * that specifies an instruction that performs "result = r0 op r1". 6522 * This could be an ARM instruction or a function call. (If the result 6523 * comes back in a register other than r0, you can override "result".) 6524 * 6525 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6526 * vCC (r1). Useful for integer division and modulus. 6527 * 6528 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6529 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6530 */ 6531 /* binop/lit16 vA, vB, #+CCCC */ 6532 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6533 mov r2, rINST, lsr #12 @ r2<- B 6534 mov r9, rINST, lsr #8 @ r9<- A+ 6535 GET_VREG(r0, r2) @ r0<- vB 6536 and r9, r9, #15 6537 .if 0 6538 cmp r1, #0 @ is second operand zero? 6539 beq common_errDivideByZero 6540 .endif 6541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6542 6543 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6544 GET_INST_OPCODE(ip) @ extract opcode from rINST 6545 SET_VREG(r0, r9) @ vAA<- r0 6546 GOTO_OPCODE(ip) @ jump to next instruction 6547 /* 10-13 instructions */ 6548 6549 6550 6551/* ------------------------------ */ 6552 .balign 64 6553.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6554/* File: armv5te/OP_MUL_INT_LIT16.S */ 6555/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6556/* File: armv5te/binopLit16.S */ 6557 /* 6558 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6559 * that specifies an instruction that performs "result = r0 op r1". 6560 * This could be an ARM instruction or a function call. (If the result 6561 * comes back in a register other than r0, you can override "result".) 6562 * 6563 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6564 * vCC (r1). Useful for integer division and modulus. 6565 * 6566 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6567 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6568 */ 6569 /* binop/lit16 vA, vB, #+CCCC */ 6570 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6571 mov r2, rINST, lsr #12 @ r2<- B 6572 mov r9, rINST, lsr #8 @ r9<- A+ 6573 GET_VREG(r0, r2) @ r0<- vB 6574 and r9, r9, #15 6575 .if 0 6576 cmp r1, #0 @ is second operand zero? 6577 beq common_errDivideByZero 6578 .endif 6579 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6580 6581 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6582 GET_INST_OPCODE(ip) @ extract opcode from rINST 6583 SET_VREG(r0, r9) @ vAA<- r0 6584 GOTO_OPCODE(ip) @ jump to next instruction 6585 /* 10-13 instructions */ 6586 6587 6588 6589/* ------------------------------ */ 6590 .balign 64 6591.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6592/* File: armv5te/OP_DIV_INT_LIT16.S */ 6593/* File: armv5te/binopLit16.S */ 6594 /* 6595 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6596 * that specifies an instruction that performs "result = r0 op r1". 6597 * This could be an ARM instruction or a function call. (If the result 6598 * comes back in a register other than r0, you can override "result".) 6599 * 6600 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6601 * vCC (r1). Useful for integer division and modulus. 6602 * 6603 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6604 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6605 */ 6606 /* binop/lit16 vA, vB, #+CCCC */ 6607 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6608 mov r2, rINST, lsr #12 @ r2<- B 6609 mov r9, rINST, lsr #8 @ r9<- A+ 6610 GET_VREG(r0, r2) @ r0<- vB 6611 and r9, r9, #15 6612 .if 1 6613 cmp r1, #0 @ is second operand zero? 6614 beq common_errDivideByZero 6615 .endif 6616 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6617 6618 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6619 GET_INST_OPCODE(ip) @ extract opcode from rINST 6620 SET_VREG(r0, r9) @ vAA<- r0 6621 GOTO_OPCODE(ip) @ jump to next instruction 6622 /* 10-13 instructions */ 6623 6624 6625 6626/* ------------------------------ */ 6627 .balign 64 6628.L_OP_REM_INT_LIT16: /* 0xd4 */ 6629/* File: armv5te/OP_REM_INT_LIT16.S */ 6630/* idivmod returns quotient in r0 and remainder in r1 */ 6631/* File: armv5te/binopLit16.S */ 6632 /* 6633 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6634 * that specifies an instruction that performs "result = r0 op r1". 6635 * This could be an ARM instruction or a function call. (If the result 6636 * comes back in a register other than r0, you can override "result".) 6637 * 6638 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6639 * vCC (r1). Useful for integer division and modulus. 6640 * 6641 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6642 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6643 */ 6644 /* binop/lit16 vA, vB, #+CCCC */ 6645 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6646 mov r2, rINST, lsr #12 @ r2<- B 6647 mov r9, rINST, lsr #8 @ r9<- A+ 6648 GET_VREG(r0, r2) @ r0<- vB 6649 and r9, r9, #15 6650 .if 1 6651 cmp r1, #0 @ is second operand zero? 6652 beq common_errDivideByZero 6653 .endif 6654 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6655 6656 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6657 GET_INST_OPCODE(ip) @ extract opcode from rINST 6658 SET_VREG(r1, r9) @ vAA<- r1 6659 GOTO_OPCODE(ip) @ jump to next instruction 6660 /* 10-13 instructions */ 6661 6662 6663 6664/* ------------------------------ */ 6665 .balign 64 6666.L_OP_AND_INT_LIT16: /* 0xd5 */ 6667/* File: armv5te/OP_AND_INT_LIT16.S */ 6668/* File: armv5te/binopLit16.S */ 6669 /* 6670 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6671 * that specifies an instruction that performs "result = r0 op r1". 6672 * This could be an ARM instruction or a function call. (If the result 6673 * comes back in a register other than r0, you can override "result".) 6674 * 6675 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6676 * vCC (r1). Useful for integer division and modulus. 6677 * 6678 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6679 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6680 */ 6681 /* binop/lit16 vA, vB, #+CCCC */ 6682 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6683 mov r2, rINST, lsr #12 @ r2<- B 6684 mov r9, rINST, lsr #8 @ r9<- A+ 6685 GET_VREG(r0, r2) @ r0<- vB 6686 and r9, r9, #15 6687 .if 0 6688 cmp r1, #0 @ is second operand zero? 6689 beq common_errDivideByZero 6690 .endif 6691 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6692 6693 and r0, r0, r1 @ r0<- op, r0-r3 changed 6694 GET_INST_OPCODE(ip) @ extract opcode from rINST 6695 SET_VREG(r0, r9) @ vAA<- r0 6696 GOTO_OPCODE(ip) @ jump to next instruction 6697 /* 10-13 instructions */ 6698 6699 6700 6701/* ------------------------------ */ 6702 .balign 64 6703.L_OP_OR_INT_LIT16: /* 0xd6 */ 6704/* File: armv5te/OP_OR_INT_LIT16.S */ 6705/* File: armv5te/binopLit16.S */ 6706 /* 6707 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6708 * that specifies an instruction that performs "result = r0 op r1". 6709 * This could be an ARM instruction or a function call. (If the result 6710 * comes back in a register other than r0, you can override "result".) 6711 * 6712 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6713 * vCC (r1). Useful for integer division and modulus. 6714 * 6715 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6716 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6717 */ 6718 /* binop/lit16 vA, vB, #+CCCC */ 6719 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6720 mov r2, rINST, lsr #12 @ r2<- B 6721 mov r9, rINST, lsr #8 @ r9<- A+ 6722 GET_VREG(r0, r2) @ r0<- vB 6723 and r9, r9, #15 6724 .if 0 6725 cmp r1, #0 @ is second operand zero? 6726 beq common_errDivideByZero 6727 .endif 6728 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6729 6730 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6731 GET_INST_OPCODE(ip) @ extract opcode from rINST 6732 SET_VREG(r0, r9) @ vAA<- r0 6733 GOTO_OPCODE(ip) @ jump to next instruction 6734 /* 10-13 instructions */ 6735 6736 6737 6738/* ------------------------------ */ 6739 .balign 64 6740.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6741/* File: armv5te/OP_XOR_INT_LIT16.S */ 6742/* File: armv5te/binopLit16.S */ 6743 /* 6744 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6745 * that specifies an instruction that performs "result = r0 op r1". 6746 * This could be an ARM instruction or a function call. (If the result 6747 * comes back in a register other than r0, you can override "result".) 6748 * 6749 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6750 * vCC (r1). Useful for integer division and modulus. 6751 * 6752 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6753 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6754 */ 6755 /* binop/lit16 vA, vB, #+CCCC */ 6756 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6757 mov r2, rINST, lsr #12 @ r2<- B 6758 mov r9, rINST, lsr #8 @ r9<- A+ 6759 GET_VREG(r0, r2) @ r0<- vB 6760 and r9, r9, #15 6761 .if 0 6762 cmp r1, #0 @ is second operand zero? 6763 beq common_errDivideByZero 6764 .endif 6765 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6766 6767 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6768 GET_INST_OPCODE(ip) @ extract opcode from rINST 6769 SET_VREG(r0, r9) @ vAA<- r0 6770 GOTO_OPCODE(ip) @ jump to next instruction 6771 /* 10-13 instructions */ 6772 6773 6774 6775/* ------------------------------ */ 6776 .balign 64 6777.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6778/* File: armv5te/OP_ADD_INT_LIT8.S */ 6779/* File: armv5te/binopLit8.S */ 6780 /* 6781 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6782 * that specifies an instruction that performs "result = r0 op r1". 6783 * This could be an ARM instruction or a function call. (If the result 6784 * comes back in a register other than r0, you can override "result".) 6785 * 6786 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6787 * vCC (r1). Useful for integer division and modulus. 6788 * 6789 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6790 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6791 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6792 */ 6793 /* binop/lit8 vAA, vBB, #+CC */ 6794 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6795 mov r9, rINST, lsr #8 @ r9<- AA 6796 and r2, r3, #255 @ r2<- BB 6797 GET_VREG(r0, r2) @ r0<- vBB 6798 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6799 .if 0 6800 @cmp r1, #0 @ is second operand zero? 6801 beq common_errDivideByZero 6802 .endif 6803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6804 6805 @ optional op; may set condition codes 6806 add r0, r0, r1 @ r0<- op, r0-r3 changed 6807 GET_INST_OPCODE(ip) @ extract opcode from rINST 6808 SET_VREG(r0, r9) @ vAA<- r0 6809 GOTO_OPCODE(ip) @ jump to next instruction 6810 /* 10-12 instructions */ 6811 6812 6813 6814/* ------------------------------ */ 6815 .balign 64 6816.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6817/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6818/* File: armv5te/binopLit8.S */ 6819 /* 6820 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6821 * that specifies an instruction that performs "result = r0 op r1". 6822 * This could be an ARM instruction or a function call. (If the result 6823 * comes back in a register other than r0, you can override "result".) 6824 * 6825 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6826 * vCC (r1). Useful for integer division and modulus. 6827 * 6828 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6829 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6830 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6831 */ 6832 /* binop/lit8 vAA, vBB, #+CC */ 6833 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6834 mov r9, rINST, lsr #8 @ r9<- AA 6835 and r2, r3, #255 @ r2<- BB 6836 GET_VREG(r0, r2) @ r0<- vBB 6837 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6838 .if 0 6839 @cmp r1, #0 @ is second operand zero? 6840 beq common_errDivideByZero 6841 .endif 6842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6843 6844 @ optional op; may set condition codes 6845 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6846 GET_INST_OPCODE(ip) @ extract opcode from rINST 6847 SET_VREG(r0, r9) @ vAA<- r0 6848 GOTO_OPCODE(ip) @ jump to next instruction 6849 /* 10-12 instructions */ 6850 6851 6852 6853/* ------------------------------ */ 6854 .balign 64 6855.L_OP_MUL_INT_LIT8: /* 0xda */ 6856/* File: armv5te/OP_MUL_INT_LIT8.S */ 6857/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6858/* File: armv5te/binopLit8.S */ 6859 /* 6860 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6861 * that specifies an instruction that performs "result = r0 op r1". 6862 * This could be an ARM instruction or a function call. (If the result 6863 * comes back in a register other than r0, you can override "result".) 6864 * 6865 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6866 * vCC (r1). Useful for integer division and modulus. 6867 * 6868 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6869 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6870 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6871 */ 6872 /* binop/lit8 vAA, vBB, #+CC */ 6873 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6874 mov r9, rINST, lsr #8 @ r9<- AA 6875 and r2, r3, #255 @ r2<- BB 6876 GET_VREG(r0, r2) @ r0<- vBB 6877 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6878 .if 0 6879 @cmp r1, #0 @ is second operand zero? 6880 beq common_errDivideByZero 6881 .endif 6882 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6883 6884 @ optional op; may set condition codes 6885 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6886 GET_INST_OPCODE(ip) @ extract opcode from rINST 6887 SET_VREG(r0, r9) @ vAA<- r0 6888 GOTO_OPCODE(ip) @ jump to next instruction 6889 /* 10-12 instructions */ 6890 6891 6892 6893/* ------------------------------ */ 6894 .balign 64 6895.L_OP_DIV_INT_LIT8: /* 0xdb */ 6896/* File: armv5te/OP_DIV_INT_LIT8.S */ 6897/* File: armv5te/binopLit8.S */ 6898 /* 6899 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6900 * that specifies an instruction that performs "result = r0 op r1". 6901 * This could be an ARM instruction or a function call. (If the result 6902 * comes back in a register other than r0, you can override "result".) 6903 * 6904 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6905 * vCC (r1). Useful for integer division and modulus. 6906 * 6907 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6908 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6909 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6910 */ 6911 /* binop/lit8 vAA, vBB, #+CC */ 6912 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6913 mov r9, rINST, lsr #8 @ r9<- AA 6914 and r2, r3, #255 @ r2<- BB 6915 GET_VREG(r0, r2) @ r0<- vBB 6916 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6917 .if 1 6918 @cmp r1, #0 @ is second operand zero? 6919 beq common_errDivideByZero 6920 .endif 6921 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6922 6923 @ optional op; may set condition codes 6924 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6925 GET_INST_OPCODE(ip) @ extract opcode from rINST 6926 SET_VREG(r0, r9) @ vAA<- r0 6927 GOTO_OPCODE(ip) @ jump to next instruction 6928 /* 10-12 instructions */ 6929 6930 6931 6932/* ------------------------------ */ 6933 .balign 64 6934.L_OP_REM_INT_LIT8: /* 0xdc */ 6935/* File: armv5te/OP_REM_INT_LIT8.S */ 6936/* idivmod returns quotient in r0 and remainder in r1 */ 6937/* File: armv5te/binopLit8.S */ 6938 /* 6939 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6940 * that specifies an instruction that performs "result = r0 op r1". 6941 * This could be an ARM instruction or a function call. (If the result 6942 * comes back in a register other than r0, you can override "result".) 6943 * 6944 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6945 * vCC (r1). Useful for integer division and modulus. 6946 * 6947 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6948 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6949 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6950 */ 6951 /* binop/lit8 vAA, vBB, #+CC */ 6952 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6953 mov r9, rINST, lsr #8 @ r9<- AA 6954 and r2, r3, #255 @ r2<- BB 6955 GET_VREG(r0, r2) @ r0<- vBB 6956 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6957 .if 1 6958 @cmp r1, #0 @ is second operand zero? 6959 beq common_errDivideByZero 6960 .endif 6961 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6962 6963 @ optional op; may set condition codes 6964 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6965 GET_INST_OPCODE(ip) @ extract opcode from rINST 6966 SET_VREG(r1, r9) @ vAA<- r1 6967 GOTO_OPCODE(ip) @ jump to next instruction 6968 /* 10-12 instructions */ 6969 6970 6971 6972/* ------------------------------ */ 6973 .balign 64 6974.L_OP_AND_INT_LIT8: /* 0xdd */ 6975/* File: armv5te/OP_AND_INT_LIT8.S */ 6976/* File: armv5te/binopLit8.S */ 6977 /* 6978 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6979 * that specifies an instruction that performs "result = r0 op r1". 6980 * This could be an ARM instruction or a function call. (If the result 6981 * comes back in a register other than r0, you can override "result".) 6982 * 6983 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6984 * vCC (r1). Useful for integer division and modulus. 6985 * 6986 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6987 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6988 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6989 */ 6990 /* binop/lit8 vAA, vBB, #+CC */ 6991 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6992 mov r9, rINST, lsr #8 @ r9<- AA 6993 and r2, r3, #255 @ r2<- BB 6994 GET_VREG(r0, r2) @ r0<- vBB 6995 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6996 .if 0 6997 @cmp r1, #0 @ is second operand zero? 6998 beq common_errDivideByZero 6999 .endif 7000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7001 7002 @ optional op; may set condition codes 7003 and r0, r0, r1 @ r0<- op, r0-r3 changed 7004 GET_INST_OPCODE(ip) @ extract opcode from rINST 7005 SET_VREG(r0, r9) @ vAA<- r0 7006 GOTO_OPCODE(ip) @ jump to next instruction 7007 /* 10-12 instructions */ 7008 7009 7010 7011/* ------------------------------ */ 7012 .balign 64 7013.L_OP_OR_INT_LIT8: /* 0xde */ 7014/* File: armv5te/OP_OR_INT_LIT8.S */ 7015/* File: armv5te/binopLit8.S */ 7016 /* 7017 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7018 * that specifies an instruction that performs "result = r0 op r1". 7019 * This could be an ARM instruction or a function call. (If the result 7020 * comes back in a register other than r0, you can override "result".) 7021 * 7022 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7023 * vCC (r1). Useful for integer division and modulus. 7024 * 7025 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7026 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7027 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7028 */ 7029 /* binop/lit8 vAA, vBB, #+CC */ 7030 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7031 mov r9, rINST, lsr #8 @ r9<- AA 7032 and r2, r3, #255 @ r2<- BB 7033 GET_VREG(r0, r2) @ r0<- vBB 7034 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7035 .if 0 7036 @cmp r1, #0 @ is second operand zero? 7037 beq common_errDivideByZero 7038 .endif 7039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7040 7041 @ optional op; may set condition codes 7042 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7043 GET_INST_OPCODE(ip) @ extract opcode from rINST 7044 SET_VREG(r0, r9) @ vAA<- r0 7045 GOTO_OPCODE(ip) @ jump to next instruction 7046 /* 10-12 instructions */ 7047 7048 7049 7050/* ------------------------------ */ 7051 .balign 64 7052.L_OP_XOR_INT_LIT8: /* 0xdf */ 7053/* File: armv5te/OP_XOR_INT_LIT8.S */ 7054/* File: armv5te/binopLit8.S */ 7055 /* 7056 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7057 * that specifies an instruction that performs "result = r0 op r1". 7058 * This could be an ARM instruction or a function call. (If the result 7059 * comes back in a register other than r0, you can override "result".) 7060 * 7061 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7062 * vCC (r1). Useful for integer division and modulus. 7063 * 7064 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7065 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7066 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7067 */ 7068 /* binop/lit8 vAA, vBB, #+CC */ 7069 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7070 mov r9, rINST, lsr #8 @ r9<- AA 7071 and r2, r3, #255 @ r2<- BB 7072 GET_VREG(r0, r2) @ r0<- vBB 7073 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7074 .if 0 7075 @cmp r1, #0 @ is second operand zero? 7076 beq common_errDivideByZero 7077 .endif 7078 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7079 7080 @ optional op; may set condition codes 7081 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7082 GET_INST_OPCODE(ip) @ extract opcode from rINST 7083 SET_VREG(r0, r9) @ vAA<- r0 7084 GOTO_OPCODE(ip) @ jump to next instruction 7085 /* 10-12 instructions */ 7086 7087 7088 7089/* ------------------------------ */ 7090 .balign 64 7091.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7092/* File: armv5te/OP_SHL_INT_LIT8.S */ 7093/* File: armv5te/binopLit8.S */ 7094 /* 7095 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7096 * that specifies an instruction that performs "result = r0 op r1". 7097 * This could be an ARM instruction or a function call. (If the result 7098 * comes back in a register other than r0, you can override "result".) 7099 * 7100 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7101 * vCC (r1). Useful for integer division and modulus. 7102 * 7103 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7104 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7105 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7106 */ 7107 /* binop/lit8 vAA, vBB, #+CC */ 7108 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7109 mov r9, rINST, lsr #8 @ r9<- AA 7110 and r2, r3, #255 @ r2<- BB 7111 GET_VREG(r0, r2) @ r0<- vBB 7112 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7113 .if 0 7114 @cmp r1, #0 @ is second operand zero? 7115 beq common_errDivideByZero 7116 .endif 7117 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7118 7119 and r1, r1, #31 @ optional op; may set condition codes 7120 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7121 GET_INST_OPCODE(ip) @ extract opcode from rINST 7122 SET_VREG(r0, r9) @ vAA<- r0 7123 GOTO_OPCODE(ip) @ jump to next instruction 7124 /* 10-12 instructions */ 7125 7126 7127 7128/* ------------------------------ */ 7129 .balign 64 7130.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7131/* File: armv5te/OP_SHR_INT_LIT8.S */ 7132/* File: armv5te/binopLit8.S */ 7133 /* 7134 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7135 * that specifies an instruction that performs "result = r0 op r1". 7136 * This could be an ARM instruction or a function call. (If the result 7137 * comes back in a register other than r0, you can override "result".) 7138 * 7139 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7140 * vCC (r1). Useful for integer division and modulus. 7141 * 7142 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7143 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7144 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7145 */ 7146 /* binop/lit8 vAA, vBB, #+CC */ 7147 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7148 mov r9, rINST, lsr #8 @ r9<- AA 7149 and r2, r3, #255 @ r2<- BB 7150 GET_VREG(r0, r2) @ r0<- vBB 7151 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7152 .if 0 7153 @cmp r1, #0 @ is second operand zero? 7154 beq common_errDivideByZero 7155 .endif 7156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7157 7158 and r1, r1, #31 @ optional op; may set condition codes 7159 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7160 GET_INST_OPCODE(ip) @ extract opcode from rINST 7161 SET_VREG(r0, r9) @ vAA<- r0 7162 GOTO_OPCODE(ip) @ jump to next instruction 7163 /* 10-12 instructions */ 7164 7165 7166 7167/* ------------------------------ */ 7168 .balign 64 7169.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7170/* File: armv5te/OP_USHR_INT_LIT8.S */ 7171/* File: armv5te/binopLit8.S */ 7172 /* 7173 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7174 * that specifies an instruction that performs "result = r0 op r1". 7175 * This could be an ARM instruction or a function call. (If the result 7176 * comes back in a register other than r0, you can override "result".) 7177 * 7178 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7179 * vCC (r1). Useful for integer division and modulus. 7180 * 7181 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7182 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7183 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7184 */ 7185 /* binop/lit8 vAA, vBB, #+CC */ 7186 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7187 mov r9, rINST, lsr #8 @ r9<- AA 7188 and r2, r3, #255 @ r2<- BB 7189 GET_VREG(r0, r2) @ r0<- vBB 7190 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7191 .if 0 7192 @cmp r1, #0 @ is second operand zero? 7193 beq common_errDivideByZero 7194 .endif 7195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7196 7197 and r1, r1, #31 @ optional op; may set condition codes 7198 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7199 GET_INST_OPCODE(ip) @ extract opcode from rINST 7200 SET_VREG(r0, r9) @ vAA<- r0 7201 GOTO_OPCODE(ip) @ jump to next instruction 7202 /* 10-12 instructions */ 7203 7204 7205 7206/* ------------------------------ */ 7207 .balign 64 7208.L_OP_UNUSED_E3: /* 0xe3 */ 7209/* File: armv5te/OP_UNUSED_E3.S */ 7210/* File: armv5te/unused.S */ 7211 bl common_abort 7212 7213 7214 7215/* ------------------------------ */ 7216 .balign 64 7217.L_OP_UNUSED_E4: /* 0xe4 */ 7218/* File: armv5te/OP_UNUSED_E4.S */ 7219/* File: armv5te/unused.S */ 7220 bl common_abort 7221 7222 7223 7224/* ------------------------------ */ 7225 .balign 64 7226.L_OP_UNUSED_E5: /* 0xe5 */ 7227/* File: armv5te/OP_UNUSED_E5.S */ 7228/* File: armv5te/unused.S */ 7229 bl common_abort 7230 7231 7232 7233/* ------------------------------ */ 7234 .balign 64 7235.L_OP_UNUSED_E6: /* 0xe6 */ 7236/* File: armv5te/OP_UNUSED_E6.S */ 7237/* File: armv5te/unused.S */ 7238 bl common_abort 7239 7240 7241 7242/* ------------------------------ */ 7243 .balign 64 7244.L_OP_UNUSED_E7: /* 0xe7 */ 7245/* File: armv5te/OP_UNUSED_E7.S */ 7246/* File: armv5te/unused.S */ 7247 bl common_abort 7248 7249 7250 7251/* ------------------------------ */ 7252 .balign 64 7253.L_OP_UNUSED_E8: /* 0xe8 */ 7254/* File: armv5te/OP_UNUSED_E8.S */ 7255/* File: armv5te/unused.S */ 7256 bl common_abort 7257 7258 7259 7260/* ------------------------------ */ 7261 .balign 64 7262.L_OP_UNUSED_E9: /* 0xe9 */ 7263/* File: armv5te/OP_UNUSED_E9.S */ 7264/* File: armv5te/unused.S */ 7265 bl common_abort 7266 7267 7268 7269/* ------------------------------ */ 7270 .balign 64 7271.L_OP_UNUSED_EA: /* 0xea */ 7272/* File: armv5te/OP_UNUSED_EA.S */ 7273/* File: armv5te/unused.S */ 7274 bl common_abort 7275 7276 7277 7278/* ------------------------------ */ 7279 .balign 64 7280.L_OP_UNUSED_EB: /* 0xeb */ 7281/* File: armv5te/OP_UNUSED_EB.S */ 7282/* File: armv5te/unused.S */ 7283 bl common_abort 7284 7285 7286 7287/* ------------------------------ */ 7288 .balign 64 7289.L_OP_BREAKPOINT: /* 0xec */ 7290/* File: armv5te/OP_BREAKPOINT.S */ 7291/* File: armv5te/unused.S */ 7292 bl common_abort 7293 7294 7295 7296/* ------------------------------ */ 7297 .balign 64 7298.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7299/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7300 /* 7301 * Handle a throw-verification-error instruction. This throws an 7302 * exception for an error discovered during verification. The 7303 * exception is indicated by AA, with some detail provided by BBBB. 7304 */ 7305 /* op AA, ref@BBBB */ 7306 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7307 FETCH(r2, 1) @ r2<- BBBB 7308 EXPORT_PC() @ export the PC 7309 mov r1, rINST, lsr #8 @ r1<- AA 7310 bl dvmThrowVerificationError @ always throws 7311 b common_exceptionThrown @ handle exception 7312 7313 7314/* ------------------------------ */ 7315 .balign 64 7316.L_OP_EXECUTE_INLINE: /* 0xee */ 7317/* File: armv5te/OP_EXECUTE_INLINE.S */ 7318 /* 7319 * Execute a "native inline" instruction. 7320 * 7321 * We need to call an InlineOp4Func: 7322 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7323 * 7324 * The first four args are in r0-r3, pointer to return value storage 7325 * is on the stack. The function's return value is a flag that tells 7326 * us if an exception was thrown. 7327 */ 7328 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7329 FETCH(r10, 1) @ r10<- BBBB 7330 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7331 EXPORT_PC() @ can throw 7332 sub sp, sp, #8 @ make room for arg, +64 bit align 7333 mov r0, rINST, lsr #12 @ r0<- B 7334 str r1, [sp] @ push &glue->retval 7335 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7336 add sp, sp, #8 @ pop stack 7337 cmp r0, #0 @ test boolean result of inline 7338 beq common_exceptionThrown @ returned false, handle exception 7339 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7340 GET_INST_OPCODE(ip) @ extract opcode from rINST 7341 GOTO_OPCODE(ip) @ jump to next instruction 7342 7343/* ------------------------------ */ 7344 .balign 64 7345.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7346/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7347 /* 7348 * Execute a "native inline" instruction, using "/range" semantics. 7349 * Same idea as execute-inline, but we get the args differently. 7350 * 7351 * We need to call an InlineOp4Func: 7352 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7353 * 7354 * The first four args are in r0-r3, pointer to return value storage 7355 * is on the stack. The function's return value is a flag that tells 7356 * us if an exception was thrown. 7357 */ 7358 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7359 FETCH(r10, 1) @ r10<- BBBB 7360 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7361 EXPORT_PC() @ can throw 7362 sub sp, sp, #8 @ make room for arg, +64 bit align 7363 mov r0, rINST, lsr #8 @ r0<- AA 7364 str r1, [sp] @ push &glue->retval 7365 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7366 add sp, sp, #8 @ pop stack 7367 cmp r0, #0 @ test boolean result of inline 7368 beq common_exceptionThrown @ returned false, handle exception 7369 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7370 GET_INST_OPCODE(ip) @ extract opcode from rINST 7371 GOTO_OPCODE(ip) @ jump to next instruction 7372 7373/* ------------------------------ */ 7374 .balign 64 7375.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7376/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7377 /* 7378 * invoke-direct-empty is a no-op in a "standard" interpreter. 7379 */ 7380 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7381 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7382 GOTO_OPCODE(ip) @ execute it 7383 7384/* ------------------------------ */ 7385 .balign 64 7386.L_OP_UNUSED_F1: /* 0xf1 */ 7387/* File: armv5te/OP_UNUSED_F1.S */ 7388/* File: armv5te/unused.S */ 7389 bl common_abort 7390 7391 7392 7393/* ------------------------------ */ 7394 .balign 64 7395.L_OP_IGET_QUICK: /* 0xf2 */ 7396/* File: armv5te/OP_IGET_QUICK.S */ 7397 /* For: iget-quick, iget-object-quick */ 7398 /* op vA, vB, offset@CCCC */ 7399 mov r2, rINST, lsr #12 @ r2<- B 7400 GET_VREG(r3, r2) @ r3<- object we're operating on 7401 FETCH(r1, 1) @ r1<- field byte offset 7402 cmp r3, #0 @ check object for null 7403 mov r2, rINST, lsr #8 @ r2<- A(+) 7404 beq common_errNullObject @ object was null 7405 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7407 and r2, r2, #15 7408 GET_INST_OPCODE(ip) @ extract opcode from rINST 7409 SET_VREG(r0, r2) @ fp[A]<- r0 7410 GOTO_OPCODE(ip) @ jump to next instruction 7411 7412 7413/* ------------------------------ */ 7414 .balign 64 7415.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7416/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7417 /* iget-wide-quick vA, vB, offset@CCCC */ 7418 mov r2, rINST, lsr #12 @ r2<- B 7419 GET_VREG(r3, r2) @ r3<- object we're operating on 7420 FETCH(r1, 1) @ r1<- field byte offset 7421 cmp r3, #0 @ check object for null 7422 mov r2, rINST, lsr #8 @ r2<- A(+) 7423 beq common_errNullObject @ object was null 7424 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7425 and r2, r2, #15 7426 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7427 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7428 GET_INST_OPCODE(ip) @ extract opcode from rINST 7429 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7430 GOTO_OPCODE(ip) @ jump to next instruction 7431 7432 7433/* ------------------------------ */ 7434 .balign 64 7435.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7436/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7437/* File: armv5te/OP_IGET_QUICK.S */ 7438 /* For: iget-quick, iget-object-quick */ 7439 /* op vA, vB, offset@CCCC */ 7440 mov r2, rINST, lsr #12 @ r2<- B 7441 GET_VREG(r3, r2) @ r3<- object we're operating on 7442 FETCH(r1, 1) @ r1<- field byte offset 7443 cmp r3, #0 @ check object for null 7444 mov r2, rINST, lsr #8 @ r2<- A(+) 7445 beq common_errNullObject @ object was null 7446 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7448 and r2, r2, #15 7449 GET_INST_OPCODE(ip) @ extract opcode from rINST 7450 SET_VREG(r0, r2) @ fp[A]<- r0 7451 GOTO_OPCODE(ip) @ jump to next instruction 7452 7453 7454 7455/* ------------------------------ */ 7456 .balign 64 7457.L_OP_IPUT_QUICK: /* 0xf5 */ 7458/* File: armv5te/OP_IPUT_QUICK.S */ 7459 /* For: iput-quick, iput-object-quick */ 7460 /* op vA, vB, offset@CCCC */ 7461 mov r2, rINST, lsr #12 @ r2<- B 7462 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7463 FETCH(r1, 1) @ r1<- field byte offset 7464 cmp r3, #0 @ check object for null 7465 mov r2, rINST, lsr #8 @ r2<- A(+) 7466 beq common_errNullObject @ object was null 7467 and r2, r2, #15 7468 GET_VREG(r0, r2) @ r0<- fp[A] 7469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7470 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7471 GET_INST_OPCODE(ip) @ extract opcode from rINST 7472 GOTO_OPCODE(ip) @ jump to next instruction 7473 7474 7475/* ------------------------------ */ 7476 .balign 64 7477.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7478/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7479 /* iput-wide-quick vA, vB, offset@CCCC */ 7480 mov r0, rINST, lsr #8 @ r0<- A(+) 7481 mov r1, rINST, lsr #12 @ r1<- B 7482 and r0, r0, #15 7483 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7484 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7485 cmp r2, #0 @ check object for null 7486 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7487 beq common_errNullObject @ object was null 7488 FETCH(r3, 1) @ r3<- field byte offset 7489 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7490 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7491 GET_INST_OPCODE(ip) @ extract opcode from rINST 7492 GOTO_OPCODE(ip) @ jump to next instruction 7493 7494 7495/* ------------------------------ */ 7496 .balign 64 7497.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7498/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7499/* File: armv5te/OP_IPUT_QUICK.S */ 7500 /* For: iput-quick, iput-object-quick */ 7501 /* op vA, vB, offset@CCCC */ 7502 mov r2, rINST, lsr #12 @ r2<- B 7503 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7504 FETCH(r1, 1) @ r1<- field byte offset 7505 cmp r3, #0 @ check object for null 7506 mov r2, rINST, lsr #8 @ r2<- A(+) 7507 beq common_errNullObject @ object was null 7508 and r2, r2, #15 7509 GET_VREG(r0, r2) @ r0<- fp[A] 7510 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7511 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7512 GET_INST_OPCODE(ip) @ extract opcode from rINST 7513 GOTO_OPCODE(ip) @ jump to next instruction 7514 7515 7516 7517/* ------------------------------ */ 7518 .balign 64 7519.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7520/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7521 /* 7522 * Handle an optimized virtual method call. 7523 * 7524 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7525 */ 7526 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7527 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7528 FETCH(r3, 2) @ r3<- FEDC or CCCC 7529 FETCH(r1, 1) @ r1<- BBBB 7530 .if (!0) 7531 and r3, r3, #15 @ r3<- C (or stays CCCC) 7532 .endif 7533 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7534 cmp r2, #0 @ is "this" null? 7535 beq common_errNullObject @ null "this", throw exception 7536 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7537 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7538 EXPORT_PC() @ invoke must export 7539 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7540 bl common_invokeMethodNoRange @ continue on 7541 7542/* ------------------------------ */ 7543 .balign 64 7544.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7545/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7546/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7547 /* 7548 * Handle an optimized virtual method call. 7549 * 7550 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7551 */ 7552 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7553 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7554 FETCH(r3, 2) @ r3<- FEDC or CCCC 7555 FETCH(r1, 1) @ r1<- BBBB 7556 .if (!1) 7557 and r3, r3, #15 @ r3<- C (or stays CCCC) 7558 .endif 7559 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7560 cmp r2, #0 @ is "this" null? 7561 beq common_errNullObject @ null "this", throw exception 7562 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7563 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7564 EXPORT_PC() @ invoke must export 7565 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7566 bl common_invokeMethodRange @ continue on 7567 7568 7569/* ------------------------------ */ 7570 .balign 64 7571.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7572/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7573 /* 7574 * Handle an optimized "super" method call. 7575 * 7576 * for: [opt] invoke-super-quick, invoke-super-quick/range 7577 */ 7578 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7579 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7580 FETCH(r10, 2) @ r10<- GFED or CCCC 7581 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7582 .if (!0) 7583 and r10, r10, #15 @ r10<- D (or stays CCCC) 7584 .endif 7585 FETCH(r1, 1) @ r1<- BBBB 7586 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7587 EXPORT_PC() @ must export for invoke 7588 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7589 GET_VREG(r3, r10) @ r3<- "this" 7590 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7591 cmp r3, #0 @ null "this" ref? 7592 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7593 beq common_errNullObject @ "this" is null, throw exception 7594 bl common_invokeMethodNoRange @ continue on 7595 7596 7597/* ------------------------------ */ 7598 .balign 64 7599.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7600/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7601/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7602 /* 7603 * Handle an optimized "super" method call. 7604 * 7605 * for: [opt] invoke-super-quick, invoke-super-quick/range 7606 */ 7607 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7608 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7609 FETCH(r10, 2) @ r10<- GFED or CCCC 7610 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7611 .if (!1) 7612 and r10, r10, #15 @ r10<- D (or stays CCCC) 7613 .endif 7614 FETCH(r1, 1) @ r1<- BBBB 7615 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7616 EXPORT_PC() @ must export for invoke 7617 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7618 GET_VREG(r3, r10) @ r3<- "this" 7619 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7620 cmp r3, #0 @ null "this" ref? 7621 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7622 beq common_errNullObject @ "this" is null, throw exception 7623 bl common_invokeMethodRange @ continue on 7624 7625 7626 7627/* ------------------------------ */ 7628 .balign 64 7629.L_OP_UNUSED_FC: /* 0xfc */ 7630/* File: armv5te/OP_UNUSED_FC.S */ 7631/* File: armv5te/unused.S */ 7632 bl common_abort 7633 7634 7635 7636/* ------------------------------ */ 7637 .balign 64 7638.L_OP_UNUSED_FD: /* 0xfd */ 7639/* File: armv5te/OP_UNUSED_FD.S */ 7640/* File: armv5te/unused.S */ 7641 bl common_abort 7642 7643 7644 7645/* ------------------------------ */ 7646 .balign 64 7647.L_OP_UNUSED_FE: /* 0xfe */ 7648/* File: armv5te/OP_UNUSED_FE.S */ 7649/* File: armv5te/unused.S */ 7650 bl common_abort 7651 7652 7653 7654/* ------------------------------ */ 7655 .balign 64 7656.L_OP_UNUSED_FF: /* 0xff */ 7657/* File: armv5te/OP_UNUSED_FF.S */ 7658/* File: armv5te/unused.S */ 7659 bl common_abort 7660 7661 7662 7663 7664 .balign 64 7665 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7666 .global dvmAsmInstructionEnd 7667dvmAsmInstructionEnd: 7668 7669/* 7670 * =========================================================================== 7671 * Sister implementations 7672 * =========================================================================== 7673 */ 7674 .global dvmAsmSisterStart 7675 .type dvmAsmSisterStart, %function 7676 .text 7677 .balign 4 7678dvmAsmSisterStart: 7679 7680/* continuation for OP_CONST_STRING */ 7681 7682 /* 7683 * Continuation if the String has not yet been resolved. 7684 * r1: BBBB (String ref) 7685 * r9: target register 7686 */ 7687.LOP_CONST_STRING_resolve: 7688 EXPORT_PC() 7689 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7690 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7691 bl dvmResolveString @ r0<- String reference 7692 cmp r0, #0 @ failed? 7693 beq common_exceptionThrown @ yup, handle the exception 7694 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7695 GET_INST_OPCODE(ip) @ extract opcode from rINST 7696 SET_VREG(r0, r9) @ vAA<- r0 7697 GOTO_OPCODE(ip) @ jump to next instruction 7698 7699 7700/* continuation for OP_CONST_STRING_JUMBO */ 7701 7702 /* 7703 * Continuation if the String has not yet been resolved. 7704 * r1: BBBBBBBB (String ref) 7705 * r9: target register 7706 */ 7707.LOP_CONST_STRING_JUMBO_resolve: 7708 EXPORT_PC() 7709 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7710 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7711 bl dvmResolveString @ r0<- String reference 7712 cmp r0, #0 @ failed? 7713 beq common_exceptionThrown @ yup, handle the exception 7714 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7715 GET_INST_OPCODE(ip) @ extract opcode from rINST 7716 SET_VREG(r0, r9) @ vAA<- r0 7717 GOTO_OPCODE(ip) @ jump to next instruction 7718 7719 7720/* continuation for OP_CONST_CLASS */ 7721 7722 /* 7723 * Continuation if the Class has not yet been resolved. 7724 * r1: BBBB (Class ref) 7725 * r9: target register 7726 */ 7727.LOP_CONST_CLASS_resolve: 7728 EXPORT_PC() 7729 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7730 mov r2, #1 @ r2<- true 7731 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7732 bl dvmResolveClass @ r0<- Class reference 7733 cmp r0, #0 @ failed? 7734 beq common_exceptionThrown @ yup, handle the exception 7735 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7736 GET_INST_OPCODE(ip) @ extract opcode from rINST 7737 SET_VREG(r0, r9) @ vAA<- r0 7738 GOTO_OPCODE(ip) @ jump to next instruction 7739 7740 7741/* continuation for OP_CHECK_CAST */ 7742 7743 /* 7744 * Trivial test failed, need to perform full check. This is common. 7745 * r0 holds obj->clazz 7746 * r1 holds class resolved from BBBB 7747 * r9 holds object 7748 */ 7749.LOP_CHECK_CAST_fullcheck: 7750 bl dvmInstanceofNonTrivial @ r0<- boolean result 7751 cmp r0, #0 @ failed? 7752 bne .LOP_CHECK_CAST_okay @ no, success 7753 7754 @ A cast has failed. We need to throw a ClassCastException with the 7755 @ class of the object that failed to be cast. 7756 EXPORT_PC() @ about to throw 7757 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7758 ldr r0, .LstrClassCastExceptionPtr 7759 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7760 bl dvmThrowExceptionWithClassMessage 7761 b common_exceptionThrown 7762 7763 /* 7764 * Resolution required. This is the least-likely path. 7765 * 7766 * r2 holds BBBB 7767 * r9 holds object 7768 */ 7769.LOP_CHECK_CAST_resolve: 7770 EXPORT_PC() @ resolve() could throw 7771 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7772 mov r1, r2 @ r1<- BBBB 7773 mov r2, #0 @ r2<- false 7774 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7775 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7776 cmp r0, #0 @ got null? 7777 beq common_exceptionThrown @ yes, handle exception 7778 mov r1, r0 @ r1<- class resolved from BBB 7779 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7780 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7781 7782.LstrClassCastExceptionPtr: 7783 .word .LstrClassCastException 7784 7785 7786/* continuation for OP_INSTANCE_OF */ 7787 7788 /* 7789 * Trivial test failed, need to perform full check. This is common. 7790 * r0 holds obj->clazz 7791 * r1 holds class resolved from BBBB 7792 * r9 holds A 7793 */ 7794.LOP_INSTANCE_OF_fullcheck: 7795 bl dvmInstanceofNonTrivial @ r0<- boolean result 7796 @ fall through to OP_INSTANCE_OF_store 7797 7798 /* 7799 * r0 holds boolean result 7800 * r9 holds A 7801 */ 7802.LOP_INSTANCE_OF_store: 7803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7804 SET_VREG(r0, r9) @ vA<- r0 7805 GET_INST_OPCODE(ip) @ extract opcode from rINST 7806 GOTO_OPCODE(ip) @ jump to next instruction 7807 7808 /* 7809 * Trivial test succeeded, save and bail. 7810 * r9 holds A 7811 */ 7812.LOP_INSTANCE_OF_trivial: 7813 mov r0, #1 @ indicate success 7814 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7816 SET_VREG(r0, r9) @ vA<- r0 7817 GET_INST_OPCODE(ip) @ extract opcode from rINST 7818 GOTO_OPCODE(ip) @ jump to next instruction 7819 7820 /* 7821 * Resolution required. This is the least-likely path. 7822 * 7823 * r3 holds BBBB 7824 * r9 holds A 7825 */ 7826.LOP_INSTANCE_OF_resolve: 7827 EXPORT_PC() @ resolve() could throw 7828 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7829 mov r1, r3 @ r1<- BBBB 7830 mov r2, #1 @ r2<- true 7831 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7832 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7833 cmp r0, #0 @ got null? 7834 beq common_exceptionThrown @ yes, handle exception 7835 mov r1, r0 @ r1<- class resolved from BBB 7836 mov r3, rINST, lsr #12 @ r3<- B 7837 GET_VREG(r0, r3) @ r0<- vB (object) 7838 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7839 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7840 7841 7842/* continuation for OP_NEW_INSTANCE */ 7843 7844 .balign 32 @ minimize cache lines 7845.LOP_NEW_INSTANCE_finish: @ r0=new object 7846 mov r3, rINST, lsr #8 @ r3<- AA 7847 cmp r0, #0 @ failed? 7848 beq common_exceptionThrown @ yes, handle the exception 7849 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7850 GET_INST_OPCODE(ip) @ extract opcode from rINST 7851 SET_VREG(r0, r3) @ vAA<- r0 7852 GOTO_OPCODE(ip) @ jump to next instruction 7853 7854 /* 7855 * Class initialization required. 7856 * 7857 * r0 holds class object 7858 */ 7859.LOP_NEW_INSTANCE_needinit: 7860 mov r9, r0 @ save r0 7861 bl dvmInitClass @ initialize class 7862 cmp r0, #0 @ check boolean result 7863 mov r0, r9 @ restore r0 7864 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7865 b common_exceptionThrown @ failed, deal with init exception 7866 7867 /* 7868 * Resolution required. This is the least-likely path. 7869 * 7870 * r1 holds BBBB 7871 */ 7872.LOP_NEW_INSTANCE_resolve: 7873 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7874 mov r2, #0 @ r2<- false 7875 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7876 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7877 cmp r0, #0 @ got null? 7878 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7879 b common_exceptionThrown @ yes, handle exception 7880 7881.LstrInstantiationErrorPtr: 7882 .word .LstrInstantiationError 7883 7884 7885/* continuation for OP_NEW_ARRAY */ 7886 7887 7888 /* 7889 * Resolve class. (This is an uncommon case.) 7890 * 7891 * r1 holds array length 7892 * r2 holds class ref CCCC 7893 */ 7894.LOP_NEW_ARRAY_resolve: 7895 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7896 mov r9, r1 @ r9<- length (save) 7897 mov r1, r2 @ r1<- CCCC 7898 mov r2, #0 @ r2<- false 7899 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7900 bl dvmResolveClass @ r0<- call(clazz, ref) 7901 cmp r0, #0 @ got null? 7902 mov r1, r9 @ r1<- length (restore) 7903 beq common_exceptionThrown @ yes, handle exception 7904 @ fall through to OP_NEW_ARRAY_finish 7905 7906 /* 7907 * Finish allocation. 7908 * 7909 * r0 holds class 7910 * r1 holds array length 7911 */ 7912.LOP_NEW_ARRAY_finish: 7913 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7914 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7915 cmp r0, #0 @ failed? 7916 mov r2, rINST, lsr #8 @ r2<- A+ 7917 beq common_exceptionThrown @ yes, handle the exception 7918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7919 and r2, r2, #15 @ r2<- A 7920 GET_INST_OPCODE(ip) @ extract opcode from rINST 7921 SET_VREG(r0, r2) @ vA<- r0 7922 GOTO_OPCODE(ip) @ jump to next instruction 7923 7924 7925/* continuation for OP_FILLED_NEW_ARRAY */ 7926 7927 /* 7928 * On entry: 7929 * r0 holds array class 7930 * r10 holds AA or BA 7931 */ 7932.LOP_FILLED_NEW_ARRAY_continue: 7933 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7934 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7935 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7936 .if 0 7937 mov r1, r10 @ r1<- AA (length) 7938 .else 7939 mov r1, r10, lsr #4 @ r1<- B (length) 7940 .endif 7941 cmp r3, #'I' @ array of ints? 7942 cmpne r3, #'L' @ array of objects? 7943 cmpne r3, #'[' @ array of arrays? 7944 mov r9, r1 @ save length in r9 7945 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7946 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7947 cmp r0, #0 @ null return? 7948 beq common_exceptionThrown @ alloc failed, handle exception 7949 7950 FETCH(r1, 2) @ r1<- FEDC or CCCC 7951 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7952 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7953 subs r9, r9, #1 @ length--, check for neg 7954 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7955 bmi 2f @ was zero, bail 7956 7957 @ copy values from registers into the array 7958 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7959 .if 0 7960 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79611: ldr r3, [r2], #4 @ r3<- *r2++ 7962 subs r9, r9, #1 @ count-- 7963 str r3, [r0], #4 @ *contents++ = vX 7964 bpl 1b 7965 @ continue at 2 7966 .else 7967 cmp r9, #4 @ length was initially 5? 7968 and r2, r10, #15 @ r2<- A 7969 bne 1f @ <= 4 args, branch 7970 GET_VREG(r3, r2) @ r3<- vA 7971 sub r9, r9, #1 @ count-- 7972 str r3, [r0, #16] @ contents[4] = vA 79731: and r2, r1, #15 @ r2<- F/E/D/C 7974 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7975 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7976 subs r9, r9, #1 @ count-- 7977 str r3, [r0], #4 @ *contents++ = vX 7978 bpl 1b 7979 @ continue at 2 7980 .endif 7981 79822: 7983 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7984 GOTO_OPCODE(ip) @ execute it 7985 7986 /* 7987 * Throw an exception indicating that we have not implemented this 7988 * mode of filled-new-array. 7989 */ 7990.LOP_FILLED_NEW_ARRAY_notimpl: 7991 ldr r0, .L_strInternalError 7992 ldr r1, .L_strFilledNewArrayNotImpl 7993 bl dvmThrowException 7994 b common_exceptionThrown 7995 7996 .if (!0) @ define in one or the other, not both 7997.L_strFilledNewArrayNotImpl: 7998 .word .LstrFilledNewArrayNotImpl 7999.L_strInternalError: 8000 .word .LstrInternalError 8001 .endif 8002 8003 8004/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8005 8006 /* 8007 * On entry: 8008 * r0 holds array class 8009 * r10 holds AA or BA 8010 */ 8011.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8012 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8013 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8014 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8015 .if 1 8016 mov r1, r10 @ r1<- AA (length) 8017 .else 8018 mov r1, r10, lsr #4 @ r1<- B (length) 8019 .endif 8020 cmp r3, #'I' @ array of ints? 8021 cmpne r3, #'L' @ array of objects? 8022 cmpne r3, #'[' @ array of arrays? 8023 mov r9, r1 @ save length in r9 8024 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8025 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8026 cmp r0, #0 @ null return? 8027 beq common_exceptionThrown @ alloc failed, handle exception 8028 8029 FETCH(r1, 2) @ r1<- FEDC or CCCC 8030 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8031 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8032 subs r9, r9, #1 @ length--, check for neg 8033 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8034 bmi 2f @ was zero, bail 8035 8036 @ copy values from registers into the array 8037 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8038 .if 1 8039 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80401: ldr r3, [r2], #4 @ r3<- *r2++ 8041 subs r9, r9, #1 @ count-- 8042 str r3, [r0], #4 @ *contents++ = vX 8043 bpl 1b 8044 @ continue at 2 8045 .else 8046 cmp r9, #4 @ length was initially 5? 8047 and r2, r10, #15 @ r2<- A 8048 bne 1f @ <= 4 args, branch 8049 GET_VREG(r3, r2) @ r3<- vA 8050 sub r9, r9, #1 @ count-- 8051 str r3, [r0, #16] @ contents[4] = vA 80521: and r2, r1, #15 @ r2<- F/E/D/C 8053 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8054 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8055 subs r9, r9, #1 @ count-- 8056 str r3, [r0], #4 @ *contents++ = vX 8057 bpl 1b 8058 @ continue at 2 8059 .endif 8060 80612: 8062 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8063 GOTO_OPCODE(ip) @ execute it 8064 8065 /* 8066 * Throw an exception indicating that we have not implemented this 8067 * mode of filled-new-array. 8068 */ 8069.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8070 ldr r0, .L_strInternalError 8071 ldr r1, .L_strFilledNewArrayNotImpl 8072 bl dvmThrowException 8073 b common_exceptionThrown 8074 8075 .if (!1) @ define in one or the other, not both 8076.L_strFilledNewArrayNotImpl: 8077 .word .LstrFilledNewArrayNotImpl 8078.L_strInternalError: 8079 .word .LstrInternalError 8080 .endif 8081 8082 8083/* continuation for OP_CMPL_FLOAT */ 8084.LOP_CMPL_FLOAT_finish: 8085 SET_VREG(r0, r9) @ vAA<- r0 8086 GOTO_OPCODE(ip) @ jump to next instruction 8087 8088 8089/* continuation for OP_CMPG_FLOAT */ 8090.LOP_CMPG_FLOAT_finish: 8091 SET_VREG(r0, r9) @ vAA<- r0 8092 GOTO_OPCODE(ip) @ jump to next instruction 8093 8094 8095/* continuation for OP_CMPL_DOUBLE */ 8096.LOP_CMPL_DOUBLE_finish: 8097 SET_VREG(r0, r9) @ vAA<- r0 8098 GOTO_OPCODE(ip) @ jump to next instruction 8099 8100 8101/* continuation for OP_CMPG_DOUBLE */ 8102.LOP_CMPG_DOUBLE_finish: 8103 SET_VREG(r0, r9) @ vAA<- r0 8104 GOTO_OPCODE(ip) @ jump to next instruction 8105 8106 8107/* continuation for OP_CMP_LONG */ 8108 8109.LOP_CMP_LONG_less: 8110 mvn r1, #0 @ r1<- -1 8111 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8112 @ instead, we just replicate the tail end. 8113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8114 SET_VREG(r1, r9) @ vAA<- r1 8115 GET_INST_OPCODE(ip) @ extract opcode from rINST 8116 GOTO_OPCODE(ip) @ jump to next instruction 8117 8118.LOP_CMP_LONG_greater: 8119 mov r1, #1 @ r1<- 1 8120 @ fall through to _finish 8121 8122.LOP_CMP_LONG_finish: 8123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8124 SET_VREG(r1, r9) @ vAA<- r1 8125 GET_INST_OPCODE(ip) @ extract opcode from rINST 8126 GOTO_OPCODE(ip) @ jump to next instruction 8127 8128 8129/* continuation for OP_AGET_WIDE */ 8130 8131.LOP_AGET_WIDE_finish: 8132 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8133 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8134 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8135 GET_INST_OPCODE(ip) @ extract opcode from rINST 8136 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8137 GOTO_OPCODE(ip) @ jump to next instruction 8138 8139 8140/* continuation for OP_APUT_WIDE */ 8141 8142.LOP_APUT_WIDE_finish: 8143 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8144 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8145 GET_INST_OPCODE(ip) @ extract opcode from rINST 8146 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8147 GOTO_OPCODE(ip) @ jump to next instruction 8148 8149 8150/* continuation for OP_APUT_OBJECT */ 8151 /* 8152 * On entry: 8153 * r1 = vBB (arrayObj) 8154 * r9 = vAA (obj) 8155 * r10 = offset into array (vBB + vCC * width) 8156 */ 8157.LOP_APUT_OBJECT_finish: 8158 cmp r9, #0 @ storing null reference? 8159 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8160 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8161 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8162 bl dvmCanPutArrayElement @ test object type vs. array type 8163 cmp r0, #0 @ okay? 8164 beq common_errArrayStore @ no 8165.LOP_APUT_OBJECT_skip_check: 8166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8167 GET_INST_OPCODE(ip) @ extract opcode from rINST 8168 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8169 GOTO_OPCODE(ip) @ jump to next instruction 8170 8171 8172/* continuation for OP_IGET */ 8173 8174 /* 8175 * Currently: 8176 * r0 holds resolved field 8177 * r9 holds object 8178 */ 8179.LOP_IGET_finish: 8180 @bl common_squeak0 8181 cmp r9, #0 @ check object for null 8182 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8183 beq common_errNullObject @ object was null 8184 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8185 mov r2, rINST, lsr #8 @ r2<- A+ 8186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8187 and r2, r2, #15 @ r2<- A 8188 GET_INST_OPCODE(ip) @ extract opcode from rINST 8189 SET_VREG(r0, r2) @ fp[A]<- r0 8190 GOTO_OPCODE(ip) @ jump to next instruction 8191 8192 8193/* continuation for OP_IGET_WIDE */ 8194 8195 /* 8196 * Currently: 8197 * r0 holds resolved field 8198 * r9 holds object 8199 */ 8200.LOP_IGET_WIDE_finish: 8201 cmp r9, #0 @ check object for null 8202 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8203 beq common_errNullObject @ object was null 8204 mov r2, rINST, lsr #8 @ r2<- A+ 8205 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8206 and r2, r2, #15 @ r2<- A 8207 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8208 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8209 GET_INST_OPCODE(ip) @ extract opcode from rINST 8210 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8211 GOTO_OPCODE(ip) @ jump to next instruction 8212 8213 8214/* continuation for OP_IGET_OBJECT */ 8215 8216 /* 8217 * Currently: 8218 * r0 holds resolved field 8219 * r9 holds object 8220 */ 8221.LOP_IGET_OBJECT_finish: 8222 @bl common_squeak0 8223 cmp r9, #0 @ check object for null 8224 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8225 beq common_errNullObject @ object was null 8226 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8227 mov r2, rINST, lsr #8 @ r2<- A+ 8228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8229 and r2, r2, #15 @ r2<- A 8230 GET_INST_OPCODE(ip) @ extract opcode from rINST 8231 SET_VREG(r0, r2) @ fp[A]<- r0 8232 GOTO_OPCODE(ip) @ jump to next instruction 8233 8234 8235/* continuation for OP_IGET_BOOLEAN */ 8236 8237 /* 8238 * Currently: 8239 * r0 holds resolved field 8240 * r9 holds object 8241 */ 8242.LOP_IGET_BOOLEAN_finish: 8243 @bl common_squeak1 8244 cmp r9, #0 @ check object for null 8245 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8246 beq common_errNullObject @ object was null 8247 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8248 mov r2, rINST, lsr #8 @ r2<- A+ 8249 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8250 and r2, r2, #15 @ r2<- A 8251 GET_INST_OPCODE(ip) @ extract opcode from rINST 8252 SET_VREG(r0, r2) @ fp[A]<- r0 8253 GOTO_OPCODE(ip) @ jump to next instruction 8254 8255 8256/* continuation for OP_IGET_BYTE */ 8257 8258 /* 8259 * Currently: 8260 * r0 holds resolved field 8261 * r9 holds object 8262 */ 8263.LOP_IGET_BYTE_finish: 8264 @bl common_squeak2 8265 cmp r9, #0 @ check object for null 8266 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8267 beq common_errNullObject @ object was null 8268 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8269 mov r2, rINST, lsr #8 @ r2<- A+ 8270 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8271 and r2, r2, #15 @ r2<- A 8272 GET_INST_OPCODE(ip) @ extract opcode from rINST 8273 SET_VREG(r0, r2) @ fp[A]<- r0 8274 GOTO_OPCODE(ip) @ jump to next instruction 8275 8276 8277/* continuation for OP_IGET_CHAR */ 8278 8279 /* 8280 * Currently: 8281 * r0 holds resolved field 8282 * r9 holds object 8283 */ 8284.LOP_IGET_CHAR_finish: 8285 @bl common_squeak3 8286 cmp r9, #0 @ check object for null 8287 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8288 beq common_errNullObject @ object was null 8289 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8290 mov r2, rINST, lsr #8 @ r2<- A+ 8291 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8292 and r2, r2, #15 @ r2<- A 8293 GET_INST_OPCODE(ip) @ extract opcode from rINST 8294 SET_VREG(r0, r2) @ fp[A]<- r0 8295 GOTO_OPCODE(ip) @ jump to next instruction 8296 8297 8298/* continuation for OP_IGET_SHORT */ 8299 8300 /* 8301 * Currently: 8302 * r0 holds resolved field 8303 * r9 holds object 8304 */ 8305.LOP_IGET_SHORT_finish: 8306 @bl common_squeak4 8307 cmp r9, #0 @ check object for null 8308 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8309 beq common_errNullObject @ object was null 8310 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8311 mov r2, rINST, lsr #8 @ r2<- A+ 8312 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8313 and r2, r2, #15 @ r2<- A 8314 GET_INST_OPCODE(ip) @ extract opcode from rINST 8315 SET_VREG(r0, r2) @ fp[A]<- r0 8316 GOTO_OPCODE(ip) @ jump to next instruction 8317 8318 8319/* continuation for OP_IPUT */ 8320 8321 /* 8322 * Currently: 8323 * r0 holds resolved field 8324 * r9 holds object 8325 */ 8326.LOP_IPUT_finish: 8327 @bl common_squeak0 8328 mov r1, rINST, lsr #8 @ r1<- A+ 8329 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8330 and r1, r1, #15 @ r1<- A 8331 cmp r9, #0 @ check object for null 8332 GET_VREG(r0, r1) @ r0<- fp[A] 8333 beq common_errNullObject @ object was null 8334 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8335 GET_INST_OPCODE(ip) @ extract opcode from rINST 8336 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8337 GOTO_OPCODE(ip) @ jump to next instruction 8338 8339 8340/* continuation for OP_IPUT_WIDE */ 8341 8342 /* 8343 * Currently: 8344 * r0 holds resolved field 8345 * r9 holds object 8346 */ 8347.LOP_IPUT_WIDE_finish: 8348 mov r2, rINST, lsr #8 @ r2<- A+ 8349 cmp r9, #0 @ check object for null 8350 and r2, r2, #15 @ r2<- A 8351 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8352 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8353 beq common_errNullObject @ object was null 8354 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8355 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8356 GET_INST_OPCODE(ip) @ extract opcode from rINST 8357 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8358 GOTO_OPCODE(ip) @ jump to next instruction 8359 8360 8361/* continuation for OP_IPUT_OBJECT */ 8362 8363 /* 8364 * Currently: 8365 * r0 holds resolved field 8366 * r9 holds object 8367 */ 8368.LOP_IPUT_OBJECT_finish: 8369 @bl common_squeak0 8370 mov r1, rINST, lsr #8 @ r1<- A+ 8371 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8372 and r1, r1, #15 @ r1<- A 8373 cmp r9, #0 @ check object for null 8374 GET_VREG(r0, r1) @ r0<- fp[A] 8375 beq common_errNullObject @ object was null 8376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8377 GET_INST_OPCODE(ip) @ extract opcode from rINST 8378 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8379 GOTO_OPCODE(ip) @ jump to next instruction 8380 8381 8382/* continuation for OP_IPUT_BOOLEAN */ 8383 8384 /* 8385 * Currently: 8386 * r0 holds resolved field 8387 * r9 holds object 8388 */ 8389.LOP_IPUT_BOOLEAN_finish: 8390 @bl common_squeak1 8391 mov r1, rINST, lsr #8 @ r1<- A+ 8392 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8393 and r1, r1, #15 @ r1<- A 8394 cmp r9, #0 @ check object for null 8395 GET_VREG(r0, r1) @ r0<- fp[A] 8396 beq common_errNullObject @ object was null 8397 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8398 GET_INST_OPCODE(ip) @ extract opcode from rINST 8399 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8400 GOTO_OPCODE(ip) @ jump to next instruction 8401 8402 8403/* continuation for OP_IPUT_BYTE */ 8404 8405 /* 8406 * Currently: 8407 * r0 holds resolved field 8408 * r9 holds object 8409 */ 8410.LOP_IPUT_BYTE_finish: 8411 @bl common_squeak2 8412 mov r1, rINST, lsr #8 @ r1<- A+ 8413 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8414 and r1, r1, #15 @ r1<- A 8415 cmp r9, #0 @ check object for null 8416 GET_VREG(r0, r1) @ r0<- fp[A] 8417 beq common_errNullObject @ object was null 8418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8419 GET_INST_OPCODE(ip) @ extract opcode from rINST 8420 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8421 GOTO_OPCODE(ip) @ jump to next instruction 8422 8423 8424/* continuation for OP_IPUT_CHAR */ 8425 8426 /* 8427 * Currently: 8428 * r0 holds resolved field 8429 * r9 holds object 8430 */ 8431.LOP_IPUT_CHAR_finish: 8432 @bl common_squeak3 8433 mov r1, rINST, lsr #8 @ r1<- A+ 8434 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8435 and r1, r1, #15 @ r1<- A 8436 cmp r9, #0 @ check object for null 8437 GET_VREG(r0, r1) @ r0<- fp[A] 8438 beq common_errNullObject @ object was null 8439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8440 GET_INST_OPCODE(ip) @ extract opcode from rINST 8441 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8442 GOTO_OPCODE(ip) @ jump to next instruction 8443 8444 8445/* continuation for OP_IPUT_SHORT */ 8446 8447 /* 8448 * Currently: 8449 * r0 holds resolved field 8450 * r9 holds object 8451 */ 8452.LOP_IPUT_SHORT_finish: 8453 @bl common_squeak4 8454 mov r1, rINST, lsr #8 @ r1<- A+ 8455 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8456 and r1, r1, #15 @ r1<- A 8457 cmp r9, #0 @ check object for null 8458 GET_VREG(r0, r1) @ r0<- fp[A] 8459 beq common_errNullObject @ object was null 8460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8461 GET_INST_OPCODE(ip) @ extract opcode from rINST 8462 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8463 GOTO_OPCODE(ip) @ jump to next instruction 8464 8465 8466/* continuation for OP_SGET */ 8467 8468 /* 8469 * Continuation if the field has not yet been resolved. 8470 * r1: BBBB field ref 8471 */ 8472.LOP_SGET_resolve: 8473 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8474 EXPORT_PC() @ resolve() could throw, so export now 8475 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8476 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8477 cmp r0, #0 @ success? 8478 bne .LOP_SGET_finish @ yes, finish 8479 b common_exceptionThrown @ no, handle exception 8480 8481 8482/* continuation for OP_SGET_WIDE */ 8483 8484 /* 8485 * Continuation if the field has not yet been resolved. 8486 * r1: BBBB field ref 8487 */ 8488.LOP_SGET_WIDE_resolve: 8489 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8490 EXPORT_PC() @ resolve() could throw, so export now 8491 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8492 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8493 cmp r0, #0 @ success? 8494 bne .LOP_SGET_WIDE_finish @ yes, finish 8495 b common_exceptionThrown @ no, handle exception 8496 8497 8498/* continuation for OP_SGET_OBJECT */ 8499 8500 /* 8501 * Continuation if the field has not yet been resolved. 8502 * r1: BBBB field ref 8503 */ 8504.LOP_SGET_OBJECT_resolve: 8505 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8506 EXPORT_PC() @ resolve() could throw, so export now 8507 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8508 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8509 cmp r0, #0 @ success? 8510 bne .LOP_SGET_OBJECT_finish @ yes, finish 8511 b common_exceptionThrown @ no, handle exception 8512 8513 8514/* continuation for OP_SGET_BOOLEAN */ 8515 8516 /* 8517 * Continuation if the field has not yet been resolved. 8518 * r1: BBBB field ref 8519 */ 8520.LOP_SGET_BOOLEAN_resolve: 8521 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8522 EXPORT_PC() @ resolve() could throw, so export now 8523 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8524 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8525 cmp r0, #0 @ success? 8526 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8527 b common_exceptionThrown @ no, handle exception 8528 8529 8530/* continuation for OP_SGET_BYTE */ 8531 8532 /* 8533 * Continuation if the field has not yet been resolved. 8534 * r1: BBBB field ref 8535 */ 8536.LOP_SGET_BYTE_resolve: 8537 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8538 EXPORT_PC() @ resolve() could throw, so export now 8539 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8540 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8541 cmp r0, #0 @ success? 8542 bne .LOP_SGET_BYTE_finish @ yes, finish 8543 b common_exceptionThrown @ no, handle exception 8544 8545 8546/* continuation for OP_SGET_CHAR */ 8547 8548 /* 8549 * Continuation if the field has not yet been resolved. 8550 * r1: BBBB field ref 8551 */ 8552.LOP_SGET_CHAR_resolve: 8553 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8554 EXPORT_PC() @ resolve() could throw, so export now 8555 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8556 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8557 cmp r0, #0 @ success? 8558 bne .LOP_SGET_CHAR_finish @ yes, finish 8559 b common_exceptionThrown @ no, handle exception 8560 8561 8562/* continuation for OP_SGET_SHORT */ 8563 8564 /* 8565 * Continuation if the field has not yet been resolved. 8566 * r1: BBBB field ref 8567 */ 8568.LOP_SGET_SHORT_resolve: 8569 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8570 EXPORT_PC() @ resolve() could throw, so export now 8571 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8572 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8573 cmp r0, #0 @ success? 8574 bne .LOP_SGET_SHORT_finish @ yes, finish 8575 b common_exceptionThrown @ no, handle exception 8576 8577 8578/* continuation for OP_SPUT */ 8579 8580 /* 8581 * Continuation if the field has not yet been resolved. 8582 * r1: BBBB field ref 8583 */ 8584.LOP_SPUT_resolve: 8585 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8586 EXPORT_PC() @ resolve() could throw, so export now 8587 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8588 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8589 cmp r0, #0 @ success? 8590 bne .LOP_SPUT_finish @ yes, finish 8591 b common_exceptionThrown @ no, handle exception 8592 8593 8594/* continuation for OP_SPUT_WIDE */ 8595 8596 /* 8597 * Continuation if the field has not yet been resolved. 8598 * r1: BBBB field ref 8599 * r9: &fp[AA] 8600 */ 8601.LOP_SPUT_WIDE_resolve: 8602 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8603 EXPORT_PC() @ resolve() could throw, so export now 8604 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8605 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8606 cmp r0, #0 @ success? 8607 bne .LOP_SPUT_WIDE_finish @ yes, finish 8608 b common_exceptionThrown @ no, handle exception 8609 8610 8611/* continuation for OP_SPUT_OBJECT */ 8612 8613 /* 8614 * Continuation if the field has not yet been resolved. 8615 * r1: BBBB field ref 8616 */ 8617.LOP_SPUT_OBJECT_resolve: 8618 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8619 EXPORT_PC() @ resolve() could throw, so export now 8620 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8621 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8622 cmp r0, #0 @ success? 8623 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8624 b common_exceptionThrown @ no, handle exception 8625 8626 8627/* continuation for OP_SPUT_BOOLEAN */ 8628 8629 /* 8630 * Continuation if the field has not yet been resolved. 8631 * r1: BBBB field ref 8632 */ 8633.LOP_SPUT_BOOLEAN_resolve: 8634 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8635 EXPORT_PC() @ resolve() could throw, so export now 8636 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8637 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8638 cmp r0, #0 @ success? 8639 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8640 b common_exceptionThrown @ no, handle exception 8641 8642 8643/* continuation for OP_SPUT_BYTE */ 8644 8645 /* 8646 * Continuation if the field has not yet been resolved. 8647 * r1: BBBB field ref 8648 */ 8649.LOP_SPUT_BYTE_resolve: 8650 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8651 EXPORT_PC() @ resolve() could throw, so export now 8652 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8653 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8654 cmp r0, #0 @ success? 8655 bne .LOP_SPUT_BYTE_finish @ yes, finish 8656 b common_exceptionThrown @ no, handle exception 8657 8658 8659/* continuation for OP_SPUT_CHAR */ 8660 8661 /* 8662 * Continuation if the field has not yet been resolved. 8663 * r1: BBBB field ref 8664 */ 8665.LOP_SPUT_CHAR_resolve: 8666 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8667 EXPORT_PC() @ resolve() could throw, so export now 8668 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8669 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8670 cmp r0, #0 @ success? 8671 bne .LOP_SPUT_CHAR_finish @ yes, finish 8672 b common_exceptionThrown @ no, handle exception 8673 8674 8675/* continuation for OP_SPUT_SHORT */ 8676 8677 /* 8678 * Continuation if the field has not yet been resolved. 8679 * r1: BBBB field ref 8680 */ 8681.LOP_SPUT_SHORT_resolve: 8682 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8683 EXPORT_PC() @ resolve() could throw, so export now 8684 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8685 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8686 cmp r0, #0 @ success? 8687 bne .LOP_SPUT_SHORT_finish @ yes, finish 8688 b common_exceptionThrown @ no, handle exception 8689 8690 8691/* continuation for OP_INVOKE_VIRTUAL */ 8692 8693 /* 8694 * At this point: 8695 * r0 = resolved base method 8696 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8697 */ 8698.LOP_INVOKE_VIRTUAL_continue: 8699 GET_VREG(r1, r10) @ r1<- "this" ptr 8700 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8701 cmp r1, #0 @ is "this" null? 8702 beq common_errNullObject @ null "this", throw exception 8703 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8704 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8705 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8706 bl common_invokeMethodNoRange @ continue on 8707 8708 8709/* continuation for OP_INVOKE_SUPER */ 8710 8711 /* 8712 * At this point: 8713 * r0 = resolved base method 8714 * r9 = method->clazz 8715 */ 8716.LOP_INVOKE_SUPER_continue: 8717 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8718 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8719 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8720 EXPORT_PC() @ must export for invoke 8721 cmp r2, r3 @ compare (methodIndex, vtableCount) 8722 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8723 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8724 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8725 bl common_invokeMethodNoRange @ continue on 8726 8727.LOP_INVOKE_SUPER_resolve: 8728 mov r0, r9 @ r0<- method->clazz 8729 mov r2, #METHOD_VIRTUAL @ resolver method type 8730 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8731 cmp r0, #0 @ got null? 8732 bne .LOP_INVOKE_SUPER_continue @ no, continue 8733 b common_exceptionThrown @ yes, handle exception 8734 8735 /* 8736 * Throw a NoSuchMethodError with the method name as the message. 8737 * r0 = resolved base method 8738 */ 8739.LOP_INVOKE_SUPER_nsm: 8740 ldr r1, [r0, #offMethod_name] @ r1<- method name 8741 b common_errNoSuchMethod 8742 8743 8744/* continuation for OP_INVOKE_DIRECT */ 8745 8746 /* 8747 * On entry: 8748 * r1 = reference (BBBB or CCCC) 8749 * r10 = "this" register 8750 */ 8751.LOP_INVOKE_DIRECT_resolve: 8752 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8753 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8754 mov r2, #METHOD_DIRECT @ resolver method type 8755 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8756 cmp r0, #0 @ got null? 8757 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8758 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8759 b common_exceptionThrown @ yes, handle exception 8760 8761 8762/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8763 8764 /* 8765 * At this point: 8766 * r0 = resolved base method 8767 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8768 */ 8769.LOP_INVOKE_VIRTUAL_RANGE_continue: 8770 GET_VREG(r1, r10) @ r1<- "this" ptr 8771 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8772 cmp r1, #0 @ is "this" null? 8773 beq common_errNullObject @ null "this", throw exception 8774 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8775 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8776 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8777 bl common_invokeMethodRange @ continue on 8778 8779 8780/* continuation for OP_INVOKE_SUPER_RANGE */ 8781 8782 /* 8783 * At this point: 8784 * r0 = resolved base method 8785 * r9 = method->clazz 8786 */ 8787.LOP_INVOKE_SUPER_RANGE_continue: 8788 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8789 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8790 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8791 EXPORT_PC() @ must export for invoke 8792 cmp r2, r3 @ compare (methodIndex, vtableCount) 8793 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8794 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8795 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8796 bl common_invokeMethodRange @ continue on 8797 8798.LOP_INVOKE_SUPER_RANGE_resolve: 8799 mov r0, r9 @ r0<- method->clazz 8800 mov r2, #METHOD_VIRTUAL @ resolver method type 8801 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8802 cmp r0, #0 @ got null? 8803 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8804 b common_exceptionThrown @ yes, handle exception 8805 8806 /* 8807 * Throw a NoSuchMethodError with the method name as the message. 8808 * r0 = resolved base method 8809 */ 8810.LOP_INVOKE_SUPER_RANGE_nsm: 8811 ldr r1, [r0, #offMethod_name] @ r1<- method name 8812 b common_errNoSuchMethod 8813 8814 8815/* continuation for OP_INVOKE_DIRECT_RANGE */ 8816 8817 /* 8818 * On entry: 8819 * r1 = reference (BBBB or CCCC) 8820 * r10 = "this" register 8821 */ 8822.LOP_INVOKE_DIRECT_RANGE_resolve: 8823 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8824 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8825 mov r2, #METHOD_DIRECT @ resolver method type 8826 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8827 cmp r0, #0 @ got null? 8828 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8829 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8830 b common_exceptionThrown @ yes, handle exception 8831 8832 8833/* continuation for OP_FLOAT_TO_LONG */ 8834/* 8835 * Convert the float in r0 to a long in r0/r1. 8836 * 8837 * We have to clip values to long min/max per the specification. The 8838 * expected common case is a "reasonable" value that converts directly 8839 * to modest integer. The EABI convert function isn't doing this for us. 8840 */ 8841f2l_doconv: 8842 stmfd sp!, {r4, lr} 8843 mov r1, #0x5f000000 @ (float)maxlong 8844 mov r4, r0 8845 bl __aeabi_fcmpge @ is arg >= maxlong? 8846 cmp r0, #0 @ nonzero == yes 8847 mvnne r0, #0 @ return maxlong (7fffffff) 8848 mvnne r1, #0x80000000 8849 ldmnefd sp!, {r4, pc} 8850 8851 mov r0, r4 @ recover arg 8852 mov r1, #0xdf000000 @ (float)minlong 8853 bl __aeabi_fcmple @ is arg <= minlong? 8854 cmp r0, #0 @ nonzero == yes 8855 movne r0, #0 @ return minlong (80000000) 8856 movne r1, #0x80000000 8857 ldmnefd sp!, {r4, pc} 8858 8859 mov r0, r4 @ recover arg 8860 mov r1, r4 8861 bl __aeabi_fcmpeq @ is arg == self? 8862 cmp r0, #0 @ zero == no 8863 moveq r1, #0 @ return zero for NaN 8864 ldmeqfd sp!, {r4, pc} 8865 8866 mov r0, r4 @ recover arg 8867 bl __aeabi_f2lz @ convert float to long 8868 ldmfd sp!, {r4, pc} 8869 8870 8871/* continuation for OP_DOUBLE_TO_LONG */ 8872/* 8873 * Convert the double in r0/r1 to a long in r0/r1. 8874 * 8875 * We have to clip values to long min/max per the specification. The 8876 * expected common case is a "reasonable" value that converts directly 8877 * to modest integer. The EABI convert function isn't doing this for us. 8878 */ 8879d2l_doconv: 8880 stmfd sp!, {r4, r5, lr} @ save regs 8881 mov r3, #0x43000000 @ maxlong, as a double (high word) 8882 add r3, #0x00e00000 @ 0x43e00000 8883 mov r2, #0 @ maxlong, as a double (low word) 8884 sub sp, sp, #4 @ align for EABI 8885 mov r4, r0 @ save a copy of r0 8886 mov r5, r1 @ and r1 8887 bl __aeabi_dcmpge @ is arg >= maxlong? 8888 cmp r0, #0 @ nonzero == yes 8889 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8890 mvnne r1, #0x80000000 8891 bne 1f 8892 8893 mov r0, r4 @ recover arg 8894 mov r1, r5 8895 mov r3, #0xc3000000 @ minlong, as a double (high word) 8896 add r3, #0x00e00000 @ 0xc3e00000 8897 mov r2, #0 @ minlong, as a double (low word) 8898 bl __aeabi_dcmple @ is arg <= minlong? 8899 cmp r0, #0 @ nonzero == yes 8900 movne r0, #0 @ return minlong (8000000000000000) 8901 movne r1, #0x80000000 8902 bne 1f 8903 8904 mov r0, r4 @ recover arg 8905 mov r1, r5 8906 mov r2, r4 @ compare against self 8907 mov r3, r5 8908 bl __aeabi_dcmpeq @ is arg == self? 8909 cmp r0, #0 @ zero == no 8910 moveq r1, #0 @ return zero for NaN 8911 beq 1f 8912 8913 mov r0, r4 @ recover arg 8914 mov r1, r5 8915 bl __aeabi_d2lz @ convert double to long 8916 89171: 8918 add sp, sp, #4 8919 ldmfd sp!, {r4, r5, pc} 8920 8921 8922/* continuation for OP_MUL_LONG */ 8923 8924.LOP_MUL_LONG_finish: 8925 GET_INST_OPCODE(ip) @ extract opcode from rINST 8926 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8927 GOTO_OPCODE(ip) @ jump to next instruction 8928 8929 8930/* continuation for OP_SHL_LONG */ 8931 8932.LOP_SHL_LONG_finish: 8933 mov r0, r0, asl r2 @ r0<- r0 << r2 8934 GET_INST_OPCODE(ip) @ extract opcode from rINST 8935 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8936 GOTO_OPCODE(ip) @ jump to next instruction 8937 8938 8939/* continuation for OP_SHR_LONG */ 8940 8941.LOP_SHR_LONG_finish: 8942 mov r1, r1, asr r2 @ r1<- r1 >> r2 8943 GET_INST_OPCODE(ip) @ extract opcode from rINST 8944 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8945 GOTO_OPCODE(ip) @ jump to next instruction 8946 8947 8948/* continuation for OP_USHR_LONG */ 8949 8950.LOP_USHR_LONG_finish: 8951 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8952 GET_INST_OPCODE(ip) @ extract opcode from rINST 8953 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8954 GOTO_OPCODE(ip) @ jump to next instruction 8955 8956 8957/* continuation for OP_SHL_LONG_2ADDR */ 8958 8959.LOP_SHL_LONG_2ADDR_finish: 8960 GET_INST_OPCODE(ip) @ extract opcode from rINST 8961 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8962 GOTO_OPCODE(ip) @ jump to next instruction 8963 8964 8965/* continuation for OP_SHR_LONG_2ADDR */ 8966 8967.LOP_SHR_LONG_2ADDR_finish: 8968 GET_INST_OPCODE(ip) @ extract opcode from rINST 8969 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8970 GOTO_OPCODE(ip) @ jump to next instruction 8971 8972 8973/* continuation for OP_USHR_LONG_2ADDR */ 8974 8975.LOP_USHR_LONG_2ADDR_finish: 8976 GET_INST_OPCODE(ip) @ extract opcode from rINST 8977 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8978 GOTO_OPCODE(ip) @ jump to next instruction 8979 8980 8981/* continuation for OP_EXECUTE_INLINE */ 8982 8983 /* 8984 * Extract args, call function. 8985 * r0 = #of args (0-4) 8986 * r10 = call index 8987 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8988 * 8989 * Other ideas: 8990 * - Use a jump table from the main piece to jump directly into the 8991 * AND/LDR pairs. Costs a data load, saves a branch. 8992 * - Have five separate pieces that do the loading, so we can work the 8993 * interleave a little better. Increases code size. 8994 */ 8995.LOP_EXECUTE_INLINE_continue: 8996 rsb r0, r0, #4 @ r0<- 4-r0 8997 FETCH(r9, 2) @ r9<- FEDC 8998 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8999 bl common_abort @ (skipped due to ARM prefetch) 90004: and ip, r9, #0xf000 @ isolate F 9001 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 90023: and ip, r9, #0x0f00 @ isolate E 9003 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 90042: and ip, r9, #0x00f0 @ isolate D 9005 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 90061: and ip, r9, #0x000f @ isolate C 9007 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 90080: 9009 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9010 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9011 @ (not reached) 9012 9013.LOP_EXECUTE_INLINE_table: 9014 .word gDvmInlineOpsTable 9015 9016 9017/* continuation for OP_EXECUTE_INLINE_RANGE */ 9018 9019 /* 9020 * Extract args, call function. 9021 * r0 = #of args (0-4) 9022 * r10 = call index 9023 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9024 */ 9025.LOP_EXECUTE_INLINE_RANGE_continue: 9026 rsb r0, r0, #4 @ r0<- 4-r0 9027 FETCH(r9, 2) @ r9<- CCCC 9028 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9029 bl common_abort @ (skipped due to ARM prefetch) 90304: add ip, r9, #3 @ base+3 9031 GET_VREG(r3, ip) @ r3<- vBase[3] 90323: add ip, r9, #2 @ base+2 9033 GET_VREG(r2, ip) @ r2<- vBase[2] 90342: add ip, r9, #1 @ base+1 9035 GET_VREG(r1, ip) @ r1<- vBase[1] 90361: add ip, r9, #0 @ (nop) 9037 GET_VREG(r0, ip) @ r0<- vBase[0] 90380: 9039 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9040 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9041 @ (not reached) 9042 9043.LOP_EXECUTE_INLINE_RANGE_table: 9044 .word gDvmInlineOpsTable 9045 9046 9047 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9048 .global dvmAsmSisterEnd 9049dvmAsmSisterEnd: 9050 9051/* File: armv5te/footer.S */ 9052 9053/* 9054 * =========================================================================== 9055 * Common subroutines and data 9056 * =========================================================================== 9057 */ 9058 9059 9060 9061 .text 9062 .align 2 9063 9064#if defined(WITH_JIT) 9065#if defined(WITH_SELF_VERIFICATION) 9066 .global dvmJitToInterpPunt 9067dvmJitToInterpPunt: 9068 mov r2,#kSVSPunt @ r2<- interpreter entry point 9069 b dvmJitSelfVerificationEnd @ doesn't return 9070 9071 .global dvmJitToInterpSingleStep 9072dvmJitToInterpSingleStep: 9073 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9074 b dvmJitSelfVerificationEnd @ doesn't return 9075 9076 .global dvmJitToTraceSelect 9077dvmJitToTraceSelect: 9078 ldr r0,[lr, #-1] @ pass our target PC 9079 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9080 b dvmJitSelfVerificationEnd @ doesn't return 9081 9082 .global dvmJitToBackwardBranch 9083dvmJitToBackwardBranch: 9084 ldr r0,[lr, #-1] @ pass our target PC 9085 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9086 b dvmJitSelfVerificationEnd @ doesn't return 9087 9088 .global dvmJitToInterpNormal 9089dvmJitToInterpNormal: 9090 ldr r0,[lr, #-1] @ pass our target PC 9091 mov r2,#kSVSNormal @ r2<- interpreter entry point 9092 b dvmJitSelfVerificationEnd @ doesn't return 9093 9094 .global dvmJitToInterpNoChain 9095dvmJitToInterpNoChain: 9096 mov r0,rPC @ pass our target PC 9097 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9098 b dvmJitSelfVerificationEnd @ doesn't return 9099#else 9100/* 9101 * Return from the translation cache to the interpreter when the compiler is 9102 * having issues translating/executing a Dalvik instruction. We have to skip 9103 * the code cache lookup otherwise it is possible to indefinitely bouce 9104 * between the interpreter and the code cache if the instruction that fails 9105 * to be compiled happens to be at a trace start. 9106 */ 9107 .global dvmJitToInterpPunt 9108dvmJitToInterpPunt: 9109 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9110 mov rPC, r0 9111#ifdef EXIT_STATS 9112 mov r0,lr 9113 bl dvmBumpPunt; 9114#endif 9115 EXPORT_PC() 9116 mov r0, #0 9117 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9118 adrl rIBASE, dvmAsmInstructionStart 9119 FETCH_INST() 9120 GET_INST_OPCODE(ip) 9121 GOTO_OPCODE(ip) 9122 9123/* 9124 * Return to the interpreter to handle a single instruction. 9125 * On entry: 9126 * r0 <= PC 9127 * r1 <= PC of resume instruction 9128 * lr <= resume point in translation 9129 */ 9130 .global dvmJitToInterpSingleStep 9131dvmJitToInterpSingleStep: 9132 str lr,[rGLUE,#offGlue_jitResume] 9133 str r1,[rGLUE,#offGlue_jitResumePC] 9134 mov r1,#kInterpEntryInstr 9135 @ enum is 4 byte in aapcs-EABI 9136 str r1, [rGLUE, #offGlue_entryPoint] 9137 mov rPC,r0 9138 EXPORT_PC() 9139 9140 adrl rIBASE, dvmAsmInstructionStart 9141 mov r2,#kJitSingleStep @ Ask for single step and then revert 9142 str r2,[rGLUE,#offGlue_jitState] 9143 mov r1,#1 @ set changeInterp to bail to debug interp 9144 b common_gotoBail 9145 9146 9147/* 9148 * Return from the translation cache and immediately request 9149 * a translation for the exit target. Commonly used following 9150 * invokes. 9151 */ 9152 .global dvmJitToTraceSelect 9153dvmJitToTraceSelect: 9154 ldr rPC,[lr, #-1] @ get our target PC 9155 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9156 add rINST,lr,#-5 @ save start of chain branch 9157 mov r0,rPC 9158 bl dvmJitGetCodeAddr @ Is there a translation? 9159 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9160 cmp r0,#0 9161 beq 2f 9162 mov r1,rINST 9163 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9164 mov r1, rPC @ arg1 of translation may need this 9165 mov lr, #0 @ in case target is HANDLER_INTERPRET 9166 cmp r0,#0 @ successful chain? 9167 bxne r0 @ continue native execution 9168 b toInterpreter @ didn't chain - resume with interpreter 9169 9170/* No translation, so request one if profiling isn't disabled*/ 91712: 9172 adrl rIBASE, dvmAsmInstructionStart 9173 GET_JIT_PROF_TABLE(r0) 9174 FETCH_INST() 9175 cmp r0, #0 9176 bne common_selectTrace 9177 GET_INST_OPCODE(ip) 9178 GOTO_OPCODE(ip) 9179 9180/* 9181 * Return from the translation cache to the interpreter. 9182 * The return was done with a BLX from thumb mode, and 9183 * the following 32-bit word contains the target rPC value. 9184 * Note that lr (r14) will have its low-order bit set to denote 9185 * its thumb-mode origin. 9186 * 9187 * We'll need to stash our lr origin away, recover the new 9188 * target and then check to see if there is a translation available 9189 * for our new target. If so, we do a translation chain and 9190 * go back to native execution. Otherwise, it's back to the 9191 * interpreter (after treating this entry as a potential 9192 * trace start). 9193 */ 9194 .global dvmJitToInterpNormal 9195dvmJitToInterpNormal: 9196 ldr rPC,[lr, #-1] @ get our target PC 9197 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9198 add rINST,lr,#-5 @ save start of chain branch 9199#ifdef EXIT_STATS 9200 bl dvmBumpNormal 9201#endif 9202 mov r0,rPC 9203 bl dvmJitGetCodeAddr @ Is there a translation? 9204 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9205 cmp r0,#0 9206 beq toInterpreter @ go if not, otherwise do chain 9207 mov r1,rINST 9208 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9209 mov r1, rPC @ arg1 of translation may need this 9210 mov lr, #0 @ in case target is HANDLER_INTERPRET 9211 cmp r0,#0 @ successful chain? 9212 bxne r0 @ continue native execution 9213 b toInterpreter @ didn't chain - resume with interpreter 9214 9215/* 9216 * Return from the translation cache to the interpreter to do method invocation. 9217 * Check if translation exists for the callee, but don't chain to it. 9218 */ 9219 .global dvmJitToInterpNoChain 9220dvmJitToInterpNoChain: 9221#ifdef EXIT_STATS 9222 bl dvmBumpNoChain 9223#endif 9224 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9225 mov r0,rPC 9226 bl dvmJitGetCodeAddr @ Is there a translation? 9227 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9228 mov r1, rPC @ arg1 of translation may need this 9229 mov lr, #0 @ in case target is HANDLER_INTERPRET 9230 cmp r0,#0 9231 bxne r0 @ continue native execution if so 9232#endif 9233 9234/* 9235 * No translation, restore interpreter regs and start interpreting. 9236 * rGLUE & rFP were preserved in the translated code, and rPC has 9237 * already been restored by the time we get here. We'll need to set 9238 * up rIBASE & rINST, and load the address of the JitTable into r0. 9239 */ 9240toInterpreter: 9241 EXPORT_PC() 9242 adrl rIBASE, dvmAsmInstructionStart 9243 FETCH_INST() 9244 GET_JIT_PROF_TABLE(r0) 9245 @ NOTE: intended fallthrough 9246/* 9247 * Common code to update potential trace start counter, and initiate 9248 * a trace-build if appropriate. On entry, rPC should point to the 9249 * next instruction to execute, and rINST should be already loaded with 9250 * the next opcode word, and r0 holds a pointer to the jit profile 9251 * table (pJitProfTable). 9252 */ 9253common_testUpdateProfile: 9254 cmp r0,#0 9255 GET_INST_OPCODE(ip) 9256 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9257 9258common_updateProfile: 9259 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9260 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9261 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9262 GET_INST_OPCODE(ip) 9263 subs r1,r1,#1 @ decrement counter 9264 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9265 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9266 9267/* 9268 * Here, we switch to the debug interpreter to request 9269 * trace selection. First, though, check to see if there 9270 * is already a native translation in place (and, if so, 9271 * jump to it now). 9272 */ 9273 GET_JIT_THRESHOLD(r1) 9274 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9275 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9276 EXPORT_PC() 9277 mov r0,rPC 9278 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9279 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9280 mov r1, rPC @ arg1 of translation may need this 9281 mov lr, #0 @ in case target is HANDLER_INTERPRET 9282 cmp r0,#0 9283#if !defined(WITH_SELF_VERIFICATION) 9284 bxne r0 @ jump to the translation 9285#else 9286 beq common_selectTrace 9287 /* 9288 * At this point, we have a target translation. However, if 9289 * that translation is actually the interpret-only pseudo-translation 9290 * we want to treat it the same as no translation. 9291 */ 9292 mov r10, r0 @ save target 9293 bl dvmCompilerGetInterpretTemplate 9294 cmp r0, r10 @ special case? 9295 bne dvmJitSelfVerificationStart @ set up self verification 9296 GET_INST_OPCODE(ip) 9297 GOTO_OPCODE(ip) 9298 /* no return */ 9299#endif 9300 9301common_selectTrace: 9302 mov r2,#kJitTSelectRequest @ ask for trace selection 9303 str r2,[rGLUE,#offGlue_jitState] 9304 mov r2,#kInterpEntryInstr @ normal entry reason 9305 str r2,[rGLUE,#offGlue_entryPoint] 9306 mov r1,#1 @ set changeInterp 9307 b common_gotoBail 9308 9309#if defined(WITH_SELF_VERIFICATION) 9310/* 9311 * Save PC and registers to shadow memory for self verification mode 9312 * before jumping to native translation. 9313 * On entry, r10 contains the address of the target translation. 9314 */ 9315dvmJitSelfVerificationStart: 9316 mov r0,rPC @ r0<- program counter 9317 mov r1,rFP @ r1<- frame pointer 9318 mov r2,rGLUE @ r2<- InterpState pointer 9319 mov r3,r10 @ r3<- target translation 9320 bl dvmSelfVerificationSaveState @ save registers to shadow space 9321 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9322 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9323 bx r10 @ jump to the translation 9324 9325/* 9326 * Restore PC, registers, and interpState to original values 9327 * before jumping back to the interpreter. 9328 */ 9329dvmJitSelfVerificationEnd: 9330 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9331 mov r1, #0 9332 str r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9333 mov r1,rFP @ pass ending fp 9334 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9335 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9336 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9337 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9338 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9339 cmp r1,#0 @ check for punt condition 9340 beq 1f 9341 mov r2,#kJitSelfVerification @ ask for self verification 9342 str r2,[rGLUE,#offGlue_jitState] 9343 mov r2,#kInterpEntryInstr @ normal entry reason 9344 str r2,[rGLUE,#offGlue_entryPoint] 9345 mov r1,#1 @ set changeInterp 9346 b common_gotoBail 9347 93481: @ exit to interpreter without check 9349 EXPORT_PC() 9350 adrl rIBASE, dvmAsmInstructionStart 9351 FETCH_INST() 9352 GET_INST_OPCODE(ip) 9353 GOTO_OPCODE(ip) 9354#endif 9355 9356#endif 9357 9358/* 9359 * Common code when a backward branch is taken. 9360 * 9361 * On entry: 9362 * r9 is PC adjustment *in bytes* 9363 */ 9364common_backwardBranch: 9365 mov r0, #kInterpEntryInstr 9366 bl common_periodicChecks 9367#if defined(WITH_JIT) 9368 GET_JIT_PROF_TABLE(r0) 9369 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9370 cmp r0,#0 9371 bne common_updateProfile 9372 GET_INST_OPCODE(ip) 9373 GOTO_OPCODE(ip) 9374#else 9375 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9376 GET_INST_OPCODE(ip) @ extract opcode from rINST 9377 GOTO_OPCODE(ip) @ jump to next instruction 9378#endif 9379 9380 9381/* 9382 * Need to see if the thread needs to be suspended or debugger/profiler 9383 * activity has begun. 9384 * 9385 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9386 * have to do the second ldr. 9387 * 9388 * TODO: reduce this so we're just checking a single location. 9389 * 9390 * On entry: 9391 * r0 is reentry type, e.g. kInterpEntryInstr 9392 * r9 is trampoline PC adjustment *in bytes* 9393 */ 9394common_periodicChecks: 9395 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9396 9397 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9398 str r0, [rGLUE, #offGlue_entryPoint] 9399 9400#if defined(WITH_DEBUGGER) 9401 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9402#endif 9403#if defined(WITH_PROFILER) 9404 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9405#endif 9406 9407 ldr r3, [r3] @ r3<- suspendCount (int) 9408 9409#if defined(WITH_DEBUGGER) 9410 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9411#endif 9412#if defined (WITH_PROFILER) 9413 ldr r2, [r2] @ r2<- activeProfilers (int) 9414#endif 9415 9416 cmp r3, #0 @ suspend pending? 9417 bne 2f @ yes, do full suspension check 9418 9419#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9420# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9421 orrs r1, r1, r2 @ r1<- r1 | r2 9422 cmp r1, #0 @ debugger attached or profiler started? 9423# elif defined(WITH_DEBUGGER) 9424 cmp r1, #0 @ debugger attached? 9425# elif defined(WITH_PROFILER) 9426 cmp r2, #0 @ profiler started? 9427# endif 9428 bne 3f @ debugger/profiler, switch interp 9429#endif 9430 9431 bx lr @ nothing to do, return 9432 94332: @ check suspend 9434#if defined(WITH_JIT) 9435 /* 9436 * Refresh the Jit's cached copy of profile table pointer. This pointer 9437 * doubles as the Jit's on/off switch. 9438 */ 9439 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable 9440 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9441 ldr r3, [r3] @ r10 <- pJitProfTable 9442 EXPORT_PC() @ need for precise GC 9443 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9444#else 9445 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9446 EXPORT_PC() @ need for precise GC 9447#endif 9448 b dvmCheckSuspendPending @ suspend if necessary, then return 9449 94503: @ debugger/profiler enabled, bail out 9451 add rPC, rPC, r9 @ update rPC 9452 mov r1, #1 @ "want switch" = true 9453 b common_gotoBail 9454 9455 9456/* 9457 * The equivalent of "goto bail", this calls through the "bail handler". 9458 * 9459 * State registers will be saved to the "glue" area before bailing. 9460 * 9461 * On entry: 9462 * r1 is "bool changeInterp", indicating if we want to switch to the 9463 * other interpreter or just bail all the way out 9464 */ 9465common_gotoBail: 9466 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9467 mov r0, rGLUE @ r0<- glue ptr 9468 b dvmMterpStdBail @ call(glue, changeInterp) 9469 9470 @add r1, r1, #1 @ using (boolean+1) 9471 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9472 @bl _longjmp @ does not return 9473 @bl common_abort 9474 9475 9476/* 9477 * Common code for method invocation with range. 9478 * 9479 * On entry: 9480 * r0 is "Method* methodToCall", the method we're trying to call 9481 */ 9482common_invokeMethodRange: 9483.LinvokeNewRange: 9484 @ prepare to copy args to "outs" area of current frame 9485 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9486 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9487 beq .LinvokeArgsDone @ if no args, skip the rest 9488 FETCH(r1, 2) @ r1<- CCCC 9489 9490 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9491 @ (very few methods have > 10 args; could unroll for common cases) 9492 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9493 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9494 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94951: ldr r1, [r3], #4 @ val = *fp++ 9496 subs r2, r2, #1 @ count-- 9497 str r1, [r10], #4 @ *outs++ = val 9498 bne 1b @ ...while count != 0 9499 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9500 b .LinvokeArgsDone 9501 9502/* 9503 * Common code for method invocation without range. 9504 * 9505 * On entry: 9506 * r0 is "Method* methodToCall", the method we're trying to call 9507 */ 9508common_invokeMethodNoRange: 9509.LinvokeNewNoRange: 9510 @ prepare to copy args to "outs" area of current frame 9511 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9512 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9513 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9514 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9515 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9516 beq .LinvokeArgsDone 9517 9518 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9519.LinvokeNonRange: 9520 rsb r2, r2, #5 @ r2<- 5-r2 9521 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9522 bl common_abort @ (skipped due to ARM prefetch) 95235: and ip, rINST, #0x0f00 @ isolate A 9524 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9525 mov r0, r0 @ nop 9526 str r2, [r10, #-4]! @ *--outs = vA 95274: and ip, r1, #0xf000 @ isolate G 9528 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9529 mov r0, r0 @ nop 9530 str r2, [r10, #-4]! @ *--outs = vG 95313: and ip, r1, #0x0f00 @ isolate F 9532 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9533 mov r0, r0 @ nop 9534 str r2, [r10, #-4]! @ *--outs = vF 95352: and ip, r1, #0x00f0 @ isolate E 9536 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9537 mov r0, r0 @ nop 9538 str r2, [r10, #-4]! @ *--outs = vE 95391: and ip, r1, #0x000f @ isolate D 9540 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9541 mov r0, r0 @ nop 9542 str r2, [r10, #-4]! @ *--outs = vD 95430: @ fall through to .LinvokeArgsDone 9544 9545.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9546 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9547 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9548 @ find space for the new stack frame, check for overflow 9549 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9550 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9551 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9552@ bl common_dumpRegs 9553 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9554 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9555 cmp r3, r9 @ bottom < interpStackEnd? 9556 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9557 blt .LstackOverflow @ yes, this frame will overflow stack 9558 9559 @ set up newSaveArea 9560#ifdef EASY_GDB 9561 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9562 str ip, [r10, #offStackSaveArea_prevSave] 9563#endif 9564 str rFP, [r10, #offStackSaveArea_prevFrame] 9565 str rPC, [r10, #offStackSaveArea_savedPc] 9566#if defined(WITH_JIT) 9567 mov r9, #0 9568 str r9, [r10, #offStackSaveArea_returnAddr] 9569#endif 9570 str r0, [r10, #offStackSaveArea_method] 9571 tst r3, #ACC_NATIVE 9572 bne .LinvokeNative 9573 9574 /* 9575 stmfd sp!, {r0-r3} 9576 bl common_printNewline 9577 mov r0, rFP 9578 mov r1, #0 9579 bl dvmDumpFp 9580 ldmfd sp!, {r0-r3} 9581 stmfd sp!, {r0-r3} 9582 mov r0, r1 9583 mov r1, r10 9584 bl dvmDumpFp 9585 bl common_printNewline 9586 ldmfd sp!, {r0-r3} 9587 */ 9588 9589 ldrh r9, [r2] @ r9 <- load INST from new PC 9590 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9591 mov rPC, r2 @ publish new rPC 9592 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9593 9594 @ Update "glue" values for the new method 9595 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9596 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9597 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9598#if defined(WITH_JIT) 9599 GET_JIT_PROF_TABLE(r0) 9600 mov rFP, r1 @ fp = newFp 9601 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9602 mov rINST, r9 @ publish new rINST 9603 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9604 cmp r0,#0 9605 bne common_updateProfile 9606 GOTO_OPCODE(ip) @ jump to next instruction 9607#else 9608 mov rFP, r1 @ fp = newFp 9609 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9610 mov rINST, r9 @ publish new rINST 9611 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9612 GOTO_OPCODE(ip) @ jump to next instruction 9613#endif 9614 9615.LinvokeNative: 9616 @ Prep for the native call 9617 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9618 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9619 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9620 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9621 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9622 mov r9, r3 @ r9<- glue->self (preserve) 9623 9624 mov r2, r0 @ r2<- methodToCall 9625 mov r0, r1 @ r0<- newFp (points to args) 9626 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9627 9628#ifdef ASSIST_DEBUGGER 9629 /* insert fake function header to help gdb find the stack frame */ 9630 b .Lskip 9631 .type dalvik_mterp, %function 9632dalvik_mterp: 9633 .fnstart 9634 MTERP_ENTRY1 9635 MTERP_ENTRY2 9636.Lskip: 9637#endif 9638 9639 @mov lr, pc @ set return addr 9640 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9641 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9642 9643#if defined(WITH_JIT) 9644 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9645#endif 9646 9647 @ native return; r9=self, r10=newSaveArea 9648 @ equivalent to dvmPopJniLocals 9649 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9650 ldr r1, [r9, #offThread_exception] @ check for exception 9651#if defined(WITH_JIT) 9652 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9653#endif 9654 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9655 cmp r1, #0 @ null? 9656 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9657#if defined(WITH_JIT) 9658 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9659#endif 9660 bne common_exceptionThrown @ no, handle exception 9661 9662 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9663 GET_INST_OPCODE(ip) @ extract opcode from rINST 9664 GOTO_OPCODE(ip) @ jump to next instruction 9665 9666.LstackOverflow: @ r0=methodToCall 9667 mov r1, r0 @ r1<- methodToCall 9668 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9669 bl dvmHandleStackOverflow 9670 b common_exceptionThrown 9671#ifdef ASSIST_DEBUGGER 9672 .fnend 9673#endif 9674 9675 9676 /* 9677 * Common code for method invocation, calling through "glue code". 9678 * 9679 * TODO: now that we have range and non-range invoke handlers, this 9680 * needs to be split into two. Maybe just create entry points 9681 * that set r9 and jump here? 9682 * 9683 * On entry: 9684 * r0 is "Method* methodToCall", the method we're trying to call 9685 * r9 is "bool methodCallRange", indicating if this is a /range variant 9686 */ 9687 .if 0 9688.LinvokeOld: 9689 sub sp, sp, #8 @ space for args + pad 9690 FETCH(ip, 2) @ ip<- FEDC or CCCC 9691 mov r2, r0 @ A2<- methodToCall 9692 mov r0, rGLUE @ A0<- glue 9693 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9694 mov r1, r9 @ A1<- methodCallRange 9695 mov r3, rINST, lsr #8 @ A3<- AA 9696 str ip, [sp, #0] @ A4<- ip 9697 bl dvmMterp_invokeMethod @ call the C invokeMethod 9698 add sp, sp, #8 @ remove arg area 9699 b common_resumeAfterGlueCall @ continue to next instruction 9700 .endif 9701 9702 9703 9704/* 9705 * Common code for handling a return instruction. 9706 * 9707 * This does not return. 9708 */ 9709common_returnFromMethod: 9710.LreturnNew: 9711 mov r0, #kInterpEntryReturn 9712 mov r9, #0 9713 bl common_periodicChecks 9714 9715 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9716 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9717 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9718 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9719 @ r2<- method we're returning to 9720 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9721 cmp r2, #0 @ is this a break frame? 9722 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9723 mov r1, #0 @ "want switch" = false 9724 beq common_gotoBail @ break frame, bail out completely 9725 9726 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9727 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9728 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9729 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9730#if defined(WITH_JIT) 9731 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 9732 GET_JIT_PROF_TABLE(r0) 9733 mov rPC, r9 @ publish new rPC 9734 str r1, [rGLUE, #offGlue_methodClassDex] 9735 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 9736 cmp r10, #0 @ caller is compiled code 9737 blxne r10 9738 GET_INST_OPCODE(ip) @ extract opcode from rINST 9739 cmp r0,#0 9740 bne common_updateProfile 9741 GOTO_OPCODE(ip) @ jump to next instruction 9742#else 9743 GET_INST_OPCODE(ip) @ extract opcode from rINST 9744 mov rPC, r9 @ publish new rPC 9745 str r1, [rGLUE, #offGlue_methodClassDex] 9746 GOTO_OPCODE(ip) @ jump to next instruction 9747#endif 9748 9749 /* 9750 * Return handling, calls through "glue code". 9751 */ 9752 .if 0 9753.LreturnOld: 9754 SAVE_PC_FP_TO_GLUE() @ export state 9755 mov r0, rGLUE @ arg to function 9756 bl dvmMterp_returnFromMethod 9757 b common_resumeAfterGlueCall 9758 .endif 9759 9760 9761/* 9762 * Somebody has thrown an exception. Handle it. 9763 * 9764 * If the exception processing code returns to us (instead of falling 9765 * out of the interpreter), continue with whatever the next instruction 9766 * now happens to be. 9767 * 9768 * This does not return. 9769 */ 9770 .global dvmMterpCommonExceptionThrown 9771dvmMterpCommonExceptionThrown: 9772common_exceptionThrown: 9773.LexceptionNew: 9774 mov r0, #kInterpEntryThrow 9775 mov r9, #0 9776 bl common_periodicChecks 9777 9778#if defined(WITH_JIT) 9779 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9780 str r2,[rGLUE,#offGlue_jitState] 9781#endif 9782 9783 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9784 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9785 mov r1, r10 @ r1<- self 9786 mov r0, r9 @ r0<- exception 9787 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9788 mov r3, #0 @ r3<- NULL 9789 str r3, [r10, #offThread_exception] @ self->exception = NULL 9790 9791 /* set up args and a local for "&fp" */ 9792 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9793 str rFP, [sp, #-4]! @ *--sp = fp 9794 mov ip, sp @ ip<- &fp 9795 mov r3, #0 @ r3<- false 9796 str ip, [sp, #-4]! @ *--sp = &fp 9797 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9798 mov r0, r10 @ r0<- self 9799 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9800 mov r2, r9 @ r2<- exception 9801 sub r1, rPC, r1 @ r1<- pc - method->insns 9802 mov r1, r1, asr #1 @ r1<- offset in code units 9803 9804 /* call, r0 gets catchRelPc (a code-unit offset) */ 9805 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9806 9807 /* fix earlier stack overflow if necessary; may trash rFP */ 9808 ldrb r1, [r10, #offThread_stackOverflowed] 9809 cmp r1, #0 @ did we overflow earlier? 9810 beq 1f @ no, skip ahead 9811 mov rFP, r0 @ save relPc result in rFP 9812 mov r0, r10 @ r0<- self 9813 mov r1, r9 @ r1<- exception 9814 bl dvmCleanupStackOverflow @ call(self) 9815 mov r0, rFP @ restore result 98161: 9817 9818 /* update frame pointer and check result from dvmFindCatchBlock */ 9819 ldr rFP, [sp, #4] @ retrieve the updated rFP 9820 cmp r0, #0 @ is catchRelPc < 0? 9821 add sp, sp, #8 @ restore stack 9822 bmi .LnotCaughtLocally 9823 9824 /* adjust locals to match self->curFrame and updated PC */ 9825 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9826 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9827 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9828 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9829 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9830 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9831 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9832 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9833 9834 /* release the tracked alloc on the exception */ 9835 mov r0, r9 @ r0<- exception 9836 mov r1, r10 @ r1<- self 9837 bl dvmReleaseTrackedAlloc @ release the exception 9838 9839 /* restore the exception if the handler wants it */ 9840 FETCH_INST() @ load rINST from rPC 9841 GET_INST_OPCODE(ip) @ extract opcode from rINST 9842 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9843 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9844 GOTO_OPCODE(ip) @ jump to next instruction 9845 9846.LnotCaughtLocally: @ r9=exception, r10=self 9847 /* fix stack overflow if necessary */ 9848 ldrb r1, [r10, #offThread_stackOverflowed] 9849 cmp r1, #0 @ did we overflow earlier? 9850 movne r0, r10 @ if yes: r0<- self 9851 movne r1, r9 @ if yes: r1<- exception 9852 blne dvmCleanupStackOverflow @ if yes: call(self) 9853 9854 @ may want to show "not caught locally" debug messages here 9855#if DVM_SHOW_EXCEPTION >= 2 9856 /* call __android_log_print(prio, tag, format, ...) */ 9857 /* "Exception %s from %s:%d not caught locally" */ 9858 @ dvmLineNumFromPC(method, pc - method->insns) 9859 ldr r0, [rGLUE, #offGlue_method] 9860 ldr r1, [r0, #offMethod_insns] 9861 sub r1, rPC, r1 9862 asr r1, r1, #1 9863 bl dvmLineNumFromPC 9864 str r0, [sp, #-4]! 9865 @ dvmGetMethodSourceFile(method) 9866 ldr r0, [rGLUE, #offGlue_method] 9867 bl dvmGetMethodSourceFile 9868 str r0, [sp, #-4]! 9869 @ exception->clazz->descriptor 9870 ldr r3, [r9, #offObject_clazz] 9871 ldr r3, [r3, #offClassObject_descriptor] 9872 @ 9873 ldr r2, strExceptionNotCaughtLocally 9874 ldr r1, strLogTag 9875 mov r0, #3 @ LOG_DEBUG 9876 bl __android_log_print 9877#endif 9878 str r9, [r10, #offThread_exception] @ restore exception 9879 mov r0, r9 @ r0<- exception 9880 mov r1, r10 @ r1<- self 9881 bl dvmReleaseTrackedAlloc @ release the exception 9882 mov r1, #0 @ "want switch" = false 9883 b common_gotoBail @ bail out 9884 9885 9886 /* 9887 * Exception handling, calls through "glue code". 9888 */ 9889 .if 0 9890.LexceptionOld: 9891 SAVE_PC_FP_TO_GLUE() @ export state 9892 mov r0, rGLUE @ arg to function 9893 bl dvmMterp_exceptionThrown 9894 b common_resumeAfterGlueCall 9895 .endif 9896 9897 9898/* 9899 * After returning from a "glued" function, pull out the updated 9900 * values and start executing at the next instruction. 9901 */ 9902common_resumeAfterGlueCall: 9903 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9904 FETCH_INST() @ load rINST from rPC 9905 GET_INST_OPCODE(ip) @ extract opcode from rINST 9906 GOTO_OPCODE(ip) @ jump to next instruction 9907 9908/* 9909 * Invalid array index. 9910 */ 9911common_errArrayIndex: 9912 EXPORT_PC() 9913 ldr r0, strArrayIndexException 9914 mov r1, #0 9915 bl dvmThrowException 9916 b common_exceptionThrown 9917 9918/* 9919 * Invalid array value. 9920 */ 9921common_errArrayStore: 9922 EXPORT_PC() 9923 ldr r0, strArrayStoreException 9924 mov r1, #0 9925 bl dvmThrowException 9926 b common_exceptionThrown 9927 9928/* 9929 * Integer divide or mod by zero. 9930 */ 9931common_errDivideByZero: 9932 EXPORT_PC() 9933 ldr r0, strArithmeticException 9934 ldr r1, strDivideByZero 9935 bl dvmThrowException 9936 b common_exceptionThrown 9937 9938/* 9939 * Attempt to allocate an array with a negative size. 9940 */ 9941common_errNegativeArraySize: 9942 EXPORT_PC() 9943 ldr r0, strNegativeArraySizeException 9944 mov r1, #0 9945 bl dvmThrowException 9946 b common_exceptionThrown 9947 9948/* 9949 * Invocation of a non-existent method. 9950 */ 9951common_errNoSuchMethod: 9952 EXPORT_PC() 9953 ldr r0, strNoSuchMethodError 9954 mov r1, #0 9955 bl dvmThrowException 9956 b common_exceptionThrown 9957 9958/* 9959 * We encountered a null object when we weren't expecting one. We 9960 * export the PC, throw a NullPointerException, and goto the exception 9961 * processing code. 9962 */ 9963common_errNullObject: 9964 EXPORT_PC() 9965 ldr r0, strNullPointerException 9966 mov r1, #0 9967 bl dvmThrowException 9968 b common_exceptionThrown 9969 9970/* 9971 * For debugging, cause an immediate fault. The source address will 9972 * be in lr (use a bl instruction to jump here). 9973 */ 9974common_abort: 9975 ldr pc, .LdeadFood 9976.LdeadFood: 9977 .word 0xdeadf00d 9978 9979/* 9980 * Spit out a "we were here", preserving all registers. (The attempt 9981 * to save ip won't work, but we need to save an even number of 9982 * registers for EABI 64-bit stack alignment.) 9983 */ 9984 .macro SQUEAK num 9985common_squeak\num: 9986 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9987 ldr r0, strSqueak 9988 mov r1, #\num 9989 bl printf 9990 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9991 bx lr 9992 .endm 9993 9994 SQUEAK 0 9995 SQUEAK 1 9996 SQUEAK 2 9997 SQUEAK 3 9998 SQUEAK 4 9999 SQUEAK 5 10000 10001/* 10002 * Spit out the number in r0, preserving registers. 10003 */ 10004common_printNum: 10005 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10006 mov r1, r0 10007 ldr r0, strSqueak 10008 bl printf 10009 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10010 bx lr 10011 10012/* 10013 * Print a newline, preserving registers. 10014 */ 10015common_printNewline: 10016 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10017 ldr r0, strNewline 10018 bl printf 10019 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10020 bx lr 10021 10022 /* 10023 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10024 */ 10025common_printHex: 10026 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10027 mov r1, r0 10028 ldr r0, strPrintHex 10029 bl printf 10030 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10031 bx lr 10032 10033/* 10034 * Print the 64-bit quantity in r0-r1, preserving registers. 10035 */ 10036common_printLong: 10037 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10038 mov r3, r1 10039 mov r2, r0 10040 ldr r0, strPrintLong 10041 bl printf 10042 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10043 bx lr 10044 10045/* 10046 * Print full method info. Pass the Method* in r0. Preserves regs. 10047 */ 10048common_printMethod: 10049 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10050 bl dvmMterpPrintMethod 10051 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10052 bx lr 10053 10054/* 10055 * Call a C helper function that dumps regs and possibly some 10056 * additional info. Requires the C function to be compiled in. 10057 */ 10058 .if 0 10059common_dumpRegs: 10060 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10061 bl dvmMterpDumpArmRegs 10062 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10063 bx lr 10064 .endif 10065 10066#if 0 10067/* 10068 * Experiment on VFP mode. 10069 * 10070 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10071 * 10072 * Updates the bits specified by "mask", setting them to the values in "val". 10073 */ 10074setFPSCR: 10075 and r0, r0, r1 @ make sure no stray bits are set 10076 fmrx r2, fpscr @ get VFP reg 10077 mvn r1, r1 @ bit-invert mask 10078 and r2, r2, r1 @ clear masked bits 10079 orr r2, r2, r0 @ set specified bits 10080 fmxr fpscr, r2 @ set VFP reg 10081 mov r0, r2 @ return new value 10082 bx lr 10083 10084 .align 2 10085 .global dvmConfigureFP 10086 .type dvmConfigureFP, %function 10087dvmConfigureFP: 10088 stmfd sp!, {ip, lr} 10089 /* 0x03000000 sets DN/FZ */ 10090 /* 0x00009f00 clears the six exception enable flags */ 10091 bl common_squeak0 10092 mov r0, #0x03000000 @ r0<- 0x03000000 10093 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10094 bl setFPSCR 10095 ldmfd sp!, {ip, pc} 10096#endif 10097 10098 10099/* 10100 * String references, must be close to the code that uses them. 10101 */ 10102 .align 2 10103strArithmeticException: 10104 .word .LstrArithmeticException 10105strArrayIndexException: 10106 .word .LstrArrayIndexException 10107strArrayStoreException: 10108 .word .LstrArrayStoreException 10109strDivideByZero: 10110 .word .LstrDivideByZero 10111strNegativeArraySizeException: 10112 .word .LstrNegativeArraySizeException 10113strNoSuchMethodError: 10114 .word .LstrNoSuchMethodError 10115strNullPointerException: 10116 .word .LstrNullPointerException 10117 10118strLogTag: 10119 .word .LstrLogTag 10120strExceptionNotCaughtLocally: 10121 .word .LstrExceptionNotCaughtLocally 10122 10123strNewline: 10124 .word .LstrNewline 10125strSqueak: 10126 .word .LstrSqueak 10127strPrintHex: 10128 .word .LstrPrintHex 10129strPrintLong: 10130 .word .LstrPrintLong 10131 10132/* 10133 * Zero-terminated ASCII string data. 10134 * 10135 * On ARM we have two choices: do like gcc does, and LDR from a .word 10136 * with the address, or use an ADR pseudo-op to get the address 10137 * directly. ADR saves 4 bytes and an indirection, but it's using a 10138 * PC-relative addressing mode and hence has a limited range, which 10139 * makes it not work well with mergeable string sections. 10140 */ 10141 .section .rodata.str1.4,"aMS",%progbits,1 10142 10143.LstrBadEntryPoint: 10144 .asciz "Bad entry point %d\n" 10145.LstrArithmeticException: 10146 .asciz "Ljava/lang/ArithmeticException;" 10147.LstrArrayIndexException: 10148 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10149.LstrArrayStoreException: 10150 .asciz "Ljava/lang/ArrayStoreException;" 10151.LstrClassCastException: 10152 .asciz "Ljava/lang/ClassCastException;" 10153.LstrDivideByZero: 10154 .asciz "divide by zero" 10155.LstrFilledNewArrayNotImpl: 10156 .asciz "filled-new-array only implemented for objects and 'int'" 10157.LstrInternalError: 10158 .asciz "Ljava/lang/InternalError;" 10159.LstrInstantiationError: 10160 .asciz "Ljava/lang/InstantiationError;" 10161.LstrNegativeArraySizeException: 10162 .asciz "Ljava/lang/NegativeArraySizeException;" 10163.LstrNoSuchMethodError: 10164 .asciz "Ljava/lang/NoSuchMethodError;" 10165.LstrNullPointerException: 10166 .asciz "Ljava/lang/NullPointerException;" 10167 10168.LstrLogTag: 10169 .asciz "mterp" 10170.LstrExceptionNotCaughtLocally: 10171 .asciz "Exception %s from %s:%d not caught locally\n" 10172 10173.LstrNewline: 10174 .asciz "\n" 10175.LstrSqueak: 10176 .asciz "<%d>" 10177.LstrPrintHex: 10178 .asciz "<0x%x>" 10179.LstrPrintLong: 10180 .asciz "<%lld>" 10181 10182 10183