InterpAsm-armv5te-vfp.S revision 4fbba1f95b3e27bdc5f5572bb0420b5f928aa54e
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 205/* File: armv5te/platform.S */ 206/* 207 * =========================================================================== 208 * CPU-version-specific defines 209 * =========================================================================== 210 */ 211 212/* 213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 214 * one-way branch. 215 * 216 * May modify IP. Does not modify LR. 217 */ 218.macro LDR_PC source 219 ldr pc, \source 220.endm 221 222/* 223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 224 * Jump to subroutine. 225 * 226 * May modify IP and LR. 227 */ 228.macro LDR_PC_LR source 229 mov lr, pc 230 ldr pc, \source 231.endm 232 233/* 234 * Macro for "LDMFD SP!, {...regs...,PC}". 235 * 236 * May modify IP and LR. 237 */ 238.macro LDMFD_PC regs 239 ldmfd sp!, {\regs,pc} 240.endm 241 242 243/* File: armv5te/entry.S */ 244/* 245 * Copyright (C) 2008 The Android Open Source Project 246 * 247 * Licensed under the Apache License, Version 2.0 (the "License"); 248 * you may not use this file except in compliance with the License. 249 * You may obtain a copy of the License at 250 * 251 * http://www.apache.org/licenses/LICENSE-2.0 252 * 253 * Unless required by applicable law or agreed to in writing, software 254 * distributed under the License is distributed on an "AS IS" BASIS, 255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 256 * See the License for the specific language governing permissions and 257 * limitations under the License. 258 */ 259/* 260 * Interpreter entry point. 261 */ 262 263/* 264 * We don't have formal stack frames, so gdb scans upward in the code 265 * to find the start of the function (a label with the %function type), 266 * and then looks at the next few instructions to figure out what 267 * got pushed onto the stack. From this it figures out how to restore 268 * the registers, including PC, for the previous stack frame. If gdb 269 * sees a non-function label, it stops scanning, so either we need to 270 * have nothing but assembler-local labels between the entry point and 271 * the break, or we need to fake it out. 272 * 273 * When this is defined, we add some stuff to make gdb less confused. 274 */ 275#define ASSIST_DEBUGGER 1 276 277 .text 278 .align 2 279 .global dvmMterpStdRun 280 .type dvmMterpStdRun, %function 281 282/* 283 * On entry: 284 * r0 MterpGlue* glue 285 * 286 * This function returns a boolean "changeInterp" value. The return comes 287 * via a call to dvmMterpStdBail(). 288 */ 289dvmMterpStdRun: 290#define MTERP_ENTRY1 \ 291 .save {r4-r10,fp,lr}; \ 292 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 293#define MTERP_ENTRY2 \ 294 .pad #4; \ 295 sub sp, sp, #4 @ align 64 296 297 .fnstart 298 MTERP_ENTRY1 299 MTERP_ENTRY2 300 301 /* save stack pointer, add magic word for debuggerd */ 302 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 303 304 /* set up "named" registers, figure out entry point */ 305 mov rGLUE, r0 @ set rGLUE 306 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 307 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 308 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 309 cmp r1, #kInterpEntryInstr @ usual case? 310 bne .Lnot_instr @ no, handle it 311 312#if defined(WITH_JIT) 313.Lno_singleStep: 314 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 315 /* Entry is always a possible trace start */ 316 GET_JIT_PROF_TABLE(r0) 317 FETCH_INST() 318 mov r1, #0 @ prepare the value for the new state 319 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 320 cmp r0,#0 321 bne common_updateProfile 322 GET_INST_OPCODE(ip) 323 GOTO_OPCODE(ip) 324#else 325 /* start executing the instruction at rPC */ 326 FETCH_INST() @ load rINST from rPC 327 GET_INST_OPCODE(ip) @ extract opcode from rINST 328 GOTO_OPCODE(ip) @ jump to next instruction 329#endif 330 331.Lnot_instr: 332 cmp r1, #kInterpEntryReturn @ were we returning from a method? 333 beq common_returnFromMethod 334 335.Lnot_return: 336 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 337 beq common_exceptionThrown 338 339#if defined(WITH_JIT) 340.Lnot_throw: 341 ldr r0,[rGLUE, #offGlue_jitResume] 342 ldr r2,[rGLUE, #offGlue_jitResumePC] 343 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 344 bne .Lbad_arg 345 cmp rPC,r2 346 bne .Lno_singleStep @ must have branched, don't resume 347 mov r1, #kInterpEntryInstr 348 strb r1, [rGLUE, #offGlue_entryPoint] 349 ldr rINST, .LdvmCompilerTemplate 350 bx r0 @ re-enter the translation 351.LdvmCompilerTemplate: 352 .word dvmCompilerTemplateStart 353#endif 354 355.Lbad_arg: 356 ldr r0, strBadEntryPoint 357 @ r1 holds value of entryPoint 358 bl printf 359 bl dvmAbort 360 .fnend 361 362 363 .global dvmMterpStdBail 364 .type dvmMterpStdBail, %function 365 366/* 367 * Restore the stack pointer and PC from the save point established on entry. 368 * This is essentially the same as a longjmp, but should be cheaper. The 369 * last instruction causes us to return to whoever called dvmMterpStdRun. 370 * 371 * We pushed some registers on the stack in dvmMterpStdRun, then saved 372 * SP and LR. Here we restore SP, restore the registers, and then restore 373 * LR to PC. 374 * 375 * On entry: 376 * r0 MterpGlue* glue 377 * r1 bool changeInterp 378 */ 379dvmMterpStdBail: 380 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 381 mov r0, r1 @ return the changeInterp value 382 add sp, sp, #4 @ un-align 64 383 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 384 385 386/* 387 * String references. 388 */ 389strBadEntryPoint: 390 .word .LstrBadEntryPoint 391 392 393 394 .global dvmAsmInstructionStart 395 .type dvmAsmInstructionStart, %function 396dvmAsmInstructionStart = .L_OP_NOP 397 .text 398 399/* ------------------------------ */ 400 .balign 64 401.L_OP_NOP: /* 0x00 */ 402/* File: armv5te/OP_NOP.S */ 403 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 404 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 405 GOTO_OPCODE(ip) @ execute it 406 407#ifdef ASSIST_DEBUGGER 408 /* insert fake function header to help gdb find the stack frame */ 409 .type dalvik_inst, %function 410dalvik_inst: 411 .fnstart 412 MTERP_ENTRY1 413 MTERP_ENTRY2 414 .fnend 415#endif 416 417 418/* ------------------------------ */ 419 .balign 64 420.L_OP_MOVE: /* 0x01 */ 421/* File: armv5te/OP_MOVE.S */ 422 /* for move, move-object, long-to-int */ 423 /* op vA, vB */ 424 mov r1, rINST, lsr #12 @ r1<- B from 15:12 425 mov r0, rINST, lsr #8 @ r0<- A from 11:8 426 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 427 GET_VREG(r2, r1) @ r2<- fp[B] 428 and r0, r0, #15 429 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 430 SET_VREG(r2, r0) @ fp[A]<- r2 431 GOTO_OPCODE(ip) @ execute next instruction 432 433 434/* ------------------------------ */ 435 .balign 64 436.L_OP_MOVE_FROM16: /* 0x02 */ 437/* File: armv5te/OP_MOVE_FROM16.S */ 438 /* for: move/from16, move-object/from16 */ 439 /* op vAA, vBBBB */ 440 FETCH(r1, 1) @ r1<- BBBB 441 mov r0, rINST, lsr #8 @ r0<- AA 442 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 443 GET_VREG(r2, r1) @ r2<- fp[BBBB] 444 GET_INST_OPCODE(ip) @ extract opcode from rINST 445 SET_VREG(r2, r0) @ fp[AA]<- r2 446 GOTO_OPCODE(ip) @ jump to next instruction 447 448 449/* ------------------------------ */ 450 .balign 64 451.L_OP_MOVE_16: /* 0x03 */ 452/* File: armv5te/OP_MOVE_16.S */ 453 /* for: move/16, move-object/16 */ 454 /* op vAAAA, vBBBB */ 455 FETCH(r1, 2) @ r1<- BBBB 456 FETCH(r0, 1) @ r0<- AAAA 457 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 458 GET_VREG(r2, r1) @ r2<- fp[BBBB] 459 GET_INST_OPCODE(ip) @ extract opcode from rINST 460 SET_VREG(r2, r0) @ fp[AAAA]<- r2 461 GOTO_OPCODE(ip) @ jump to next instruction 462 463 464/* ------------------------------ */ 465 .balign 64 466.L_OP_MOVE_WIDE: /* 0x04 */ 467/* File: armv5te/OP_MOVE_WIDE.S */ 468 /* move-wide vA, vB */ 469 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 470 mov r2, rINST, lsr #8 @ r2<- A(+) 471 mov r3, rINST, lsr #12 @ r3<- B 472 and r2, r2, #15 473 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 474 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 475 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 476 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 477 GET_INST_OPCODE(ip) @ extract opcode from rINST 478 stmia r2, {r0-r1} @ fp[A]<- r0/r1 479 GOTO_OPCODE(ip) @ jump to next instruction 480 481 482/* ------------------------------ */ 483 .balign 64 484.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 485/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 486 /* move-wide/from16 vAA, vBBBB */ 487 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 488 FETCH(r3, 1) @ r3<- BBBB 489 mov r2, rINST, lsr #8 @ r2<- AA 490 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 491 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 492 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 493 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 494 GET_INST_OPCODE(ip) @ extract opcode from rINST 495 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 496 GOTO_OPCODE(ip) @ jump to next instruction 497 498 499/* ------------------------------ */ 500 .balign 64 501.L_OP_MOVE_WIDE_16: /* 0x06 */ 502/* File: armv5te/OP_MOVE_WIDE_16.S */ 503 /* move-wide/16 vAAAA, vBBBB */ 504 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 505 FETCH(r3, 2) @ r3<- BBBB 506 FETCH(r2, 1) @ r2<- AAAA 507 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 508 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 509 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 510 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 511 GET_INST_OPCODE(ip) @ extract opcode from rINST 512 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 513 GOTO_OPCODE(ip) @ jump to next instruction 514 515 516/* ------------------------------ */ 517 .balign 64 518.L_OP_MOVE_OBJECT: /* 0x07 */ 519/* File: armv5te/OP_MOVE_OBJECT.S */ 520/* File: armv5te/OP_MOVE.S */ 521 /* for move, move-object, long-to-int */ 522 /* op vA, vB */ 523 mov r1, rINST, lsr #12 @ r1<- B from 15:12 524 mov r0, rINST, lsr #8 @ r0<- A from 11:8 525 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 526 GET_VREG(r2, r1) @ r2<- fp[B] 527 and r0, r0, #15 528 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 529 SET_VREG(r2, r0) @ fp[A]<- r2 530 GOTO_OPCODE(ip) @ execute next instruction 531 532 533 534/* ------------------------------ */ 535 .balign 64 536.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 537/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 538/* File: armv5te/OP_MOVE_FROM16.S */ 539 /* for: move/from16, move-object/from16 */ 540 /* op vAA, vBBBB */ 541 FETCH(r1, 1) @ r1<- BBBB 542 mov r0, rINST, lsr #8 @ r0<- AA 543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 544 GET_VREG(r2, r1) @ r2<- fp[BBBB] 545 GET_INST_OPCODE(ip) @ extract opcode from rINST 546 SET_VREG(r2, r0) @ fp[AA]<- r2 547 GOTO_OPCODE(ip) @ jump to next instruction 548 549 550 551/* ------------------------------ */ 552 .balign 64 553.L_OP_MOVE_OBJECT_16: /* 0x09 */ 554/* File: armv5te/OP_MOVE_OBJECT_16.S */ 555/* File: armv5te/OP_MOVE_16.S */ 556 /* for: move/16, move-object/16 */ 557 /* op vAAAA, vBBBB */ 558 FETCH(r1, 2) @ r1<- BBBB 559 FETCH(r0, 1) @ r0<- AAAA 560 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 561 GET_VREG(r2, r1) @ r2<- fp[BBBB] 562 GET_INST_OPCODE(ip) @ extract opcode from rINST 563 SET_VREG(r2, r0) @ fp[AAAA]<- r2 564 GOTO_OPCODE(ip) @ jump to next instruction 565 566 567 568/* ------------------------------ */ 569 .balign 64 570.L_OP_MOVE_RESULT: /* 0x0a */ 571/* File: armv5te/OP_MOVE_RESULT.S */ 572 /* for: move-result, move-result-object */ 573 /* op vAA */ 574 mov r2, rINST, lsr #8 @ r2<- AA 575 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 576 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 577 GET_INST_OPCODE(ip) @ extract opcode from rINST 578 SET_VREG(r0, r2) @ fp[AA]<- r0 579 GOTO_OPCODE(ip) @ jump to next instruction 580 581 582/* ------------------------------ */ 583 .balign 64 584.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 585/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 586 /* move-result-wide vAA */ 587 mov r2, rINST, lsr #8 @ r2<- AA 588 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 589 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 590 ldmia r3, {r0-r1} @ r0/r1<- retval.j 591 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 592 GET_INST_OPCODE(ip) @ extract opcode from rINST 593 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 594 GOTO_OPCODE(ip) @ jump to next instruction 595 596 597/* ------------------------------ */ 598 .balign 64 599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 601/* File: armv5te/OP_MOVE_RESULT.S */ 602 /* for: move-result, move-result-object */ 603 /* op vAA */ 604 mov r2, rINST, lsr #8 @ r2<- AA 605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 606 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 607 GET_INST_OPCODE(ip) @ extract opcode from rINST 608 SET_VREG(r0, r2) @ fp[AA]<- r0 609 GOTO_OPCODE(ip) @ jump to next instruction 610 611 612 613/* ------------------------------ */ 614 .balign 64 615.L_OP_MOVE_EXCEPTION: /* 0x0d */ 616/* File: armv5te/OP_MOVE_EXCEPTION.S */ 617 /* move-exception vAA */ 618 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 619 mov r2, rINST, lsr #8 @ r2<- AA 620 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 621 mov r1, #0 @ r1<- 0 622 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 623 SET_VREG(r3, r2) @ fp[AA]<- exception obj 624 GET_INST_OPCODE(ip) @ extract opcode from rINST 625 str r1, [r0, #offThread_exception] @ dvmClearException bypass 626 GOTO_OPCODE(ip) @ jump to next instruction 627 628 629/* ------------------------------ */ 630 .balign 64 631.L_OP_RETURN_VOID: /* 0x0e */ 632/* File: armv5te/OP_RETURN_VOID.S */ 633 b common_returnFromMethod 634 635 636/* ------------------------------ */ 637 .balign 64 638.L_OP_RETURN: /* 0x0f */ 639/* File: armv5te/OP_RETURN.S */ 640 /* 641 * Return a 32-bit value. Copies the return value into the "glue" 642 * structure, then jumps to the return handler. 643 * 644 * for: return, return-object 645 */ 646 /* op vAA */ 647 mov r2, rINST, lsr #8 @ r2<- AA 648 GET_VREG(r0, r2) @ r0<- vAA 649 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 650 b common_returnFromMethod 651 652 653/* ------------------------------ */ 654 .balign 64 655.L_OP_RETURN_WIDE: /* 0x10 */ 656/* File: armv5te/OP_RETURN_WIDE.S */ 657 /* 658 * Return a 64-bit value. Copies the return value into the "glue" 659 * structure, then jumps to the return handler. 660 */ 661 /* return-wide vAA */ 662 mov r2, rINST, lsr #8 @ r2<- AA 663 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 664 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 665 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 666 stmia r3, {r0-r1} @ retval<- r0/r1 667 b common_returnFromMethod 668 669 670/* ------------------------------ */ 671 .balign 64 672.L_OP_RETURN_OBJECT: /* 0x11 */ 673/* File: armv5te/OP_RETURN_OBJECT.S */ 674/* File: armv5te/OP_RETURN.S */ 675 /* 676 * Return a 32-bit value. Copies the return value into the "glue" 677 * structure, then jumps to the return handler. 678 * 679 * for: return, return-object 680 */ 681 /* op vAA */ 682 mov r2, rINST, lsr #8 @ r2<- AA 683 GET_VREG(r0, r2) @ r0<- vAA 684 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 685 b common_returnFromMethod 686 687 688 689/* ------------------------------ */ 690 .balign 64 691.L_OP_CONST_4: /* 0x12 */ 692/* File: armv5te/OP_CONST_4.S */ 693 /* const/4 vA, #+B */ 694 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 695 mov r0, rINST, lsr #8 @ r0<- A+ 696 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 697 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 698 and r0, r0, #15 699 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 700 SET_VREG(r1, r0) @ fp[A]<- r1 701 GOTO_OPCODE(ip) @ execute next instruction 702 703 704/* ------------------------------ */ 705 .balign 64 706.L_OP_CONST_16: /* 0x13 */ 707/* File: armv5te/OP_CONST_16.S */ 708 /* const/16 vAA, #+BBBB */ 709 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 710 mov r3, rINST, lsr #8 @ r3<- AA 711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 712 SET_VREG(r0, r3) @ vAA<- r0 713 GET_INST_OPCODE(ip) @ extract opcode from rINST 714 GOTO_OPCODE(ip) @ jump to next instruction 715 716 717/* ------------------------------ */ 718 .balign 64 719.L_OP_CONST: /* 0x14 */ 720/* File: armv5te/OP_CONST.S */ 721 /* const vAA, #+BBBBbbbb */ 722 mov r3, rINST, lsr #8 @ r3<- AA 723 FETCH(r0, 1) @ r0<- bbbb (low) 724 FETCH(r1, 2) @ r1<- BBBB (high) 725 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 726 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 727 GET_INST_OPCODE(ip) @ extract opcode from rINST 728 SET_VREG(r0, r3) @ vAA<- r0 729 GOTO_OPCODE(ip) @ jump to next instruction 730 731 732/* ------------------------------ */ 733 .balign 64 734.L_OP_CONST_HIGH16: /* 0x15 */ 735/* File: armv5te/OP_CONST_HIGH16.S */ 736 /* const/high16 vAA, #+BBBB0000 */ 737 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 738 mov r3, rINST, lsr #8 @ r3<- AA 739 mov r0, r0, lsl #16 @ r0<- BBBB0000 740 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 741 SET_VREG(r0, r3) @ vAA<- r0 742 GET_INST_OPCODE(ip) @ extract opcode from rINST 743 GOTO_OPCODE(ip) @ jump to next instruction 744 745 746/* ------------------------------ */ 747 .balign 64 748.L_OP_CONST_WIDE_16: /* 0x16 */ 749/* File: armv5te/OP_CONST_WIDE_16.S */ 750 /* const-wide/16 vAA, #+BBBB */ 751 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 752 mov r3, rINST, lsr #8 @ r3<- AA 753 mov r1, r0, asr #31 @ r1<- ssssssss 754 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 755 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 756 GET_INST_OPCODE(ip) @ extract opcode from rINST 757 stmia r3, {r0-r1} @ vAA<- r0/r1 758 GOTO_OPCODE(ip) @ jump to next instruction 759 760 761/* ------------------------------ */ 762 .balign 64 763.L_OP_CONST_WIDE_32: /* 0x17 */ 764/* File: armv5te/OP_CONST_WIDE_32.S */ 765 /* const-wide/32 vAA, #+BBBBbbbb */ 766 FETCH(r0, 1) @ r0<- 0000bbbb (low) 767 mov r3, rINST, lsr #8 @ r3<- AA 768 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 769 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 770 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 771 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 772 mov r1, r0, asr #31 @ r1<- ssssssss 773 GET_INST_OPCODE(ip) @ extract opcode from rINST 774 stmia r3, {r0-r1} @ vAA<- r0/r1 775 GOTO_OPCODE(ip) @ jump to next instruction 776 777 778/* ------------------------------ */ 779 .balign 64 780.L_OP_CONST_WIDE: /* 0x18 */ 781/* File: armv5te/OP_CONST_WIDE.S */ 782 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 783 FETCH(r0, 1) @ r0<- bbbb (low) 784 FETCH(r1, 2) @ r1<- BBBB (low middle) 785 FETCH(r2, 3) @ r2<- hhhh (high middle) 786 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 787 FETCH(r3, 4) @ r3<- HHHH (high) 788 mov r9, rINST, lsr #8 @ r9<- AA 789 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 790 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 791 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 792 GET_INST_OPCODE(ip) @ extract opcode from rINST 793 stmia r9, {r0-r1} @ vAA<- r0/r1 794 GOTO_OPCODE(ip) @ jump to next instruction 795 796 797/* ------------------------------ */ 798 .balign 64 799.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 800/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 801 /* const-wide/high16 vAA, #+BBBB000000000000 */ 802 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 803 mov r3, rINST, lsr #8 @ r3<- AA 804 mov r0, #0 @ r0<- 00000000 805 mov r1, r1, lsl #16 @ r1<- BBBB0000 806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 807 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 808 GET_INST_OPCODE(ip) @ extract opcode from rINST 809 stmia r3, {r0-r1} @ vAA<- r0/r1 810 GOTO_OPCODE(ip) @ jump to next instruction 811 812 813/* ------------------------------ */ 814 .balign 64 815.L_OP_CONST_STRING: /* 0x1a */ 816/* File: armv5te/OP_CONST_STRING.S */ 817 /* const/string vAA, String@BBBB */ 818 FETCH(r1, 1) @ r1<- BBBB 819 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 820 mov r9, rINST, lsr #8 @ r9<- AA 821 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 822 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 823 cmp r0, #0 @ not yet resolved? 824 beq .LOP_CONST_STRING_resolve 825 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 826 GET_INST_OPCODE(ip) @ extract opcode from rINST 827 SET_VREG(r0, r9) @ vAA<- r0 828 GOTO_OPCODE(ip) @ jump to next instruction 829 830/* ------------------------------ */ 831 .balign 64 832.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 833/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 834 /* const/string vAA, String@BBBBBBBB */ 835 FETCH(r0, 1) @ r0<- bbbb (low) 836 FETCH(r1, 2) @ r1<- BBBB (high) 837 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 838 mov r9, rINST, lsr #8 @ r9<- AA 839 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 840 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 841 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 842 cmp r0, #0 843 beq .LOP_CONST_STRING_JUMBO_resolve 844 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 845 GET_INST_OPCODE(ip) @ extract opcode from rINST 846 SET_VREG(r0, r9) @ vAA<- r0 847 GOTO_OPCODE(ip) @ jump to next instruction 848 849/* ------------------------------ */ 850 .balign 64 851.L_OP_CONST_CLASS: /* 0x1c */ 852/* File: armv5te/OP_CONST_CLASS.S */ 853 /* const/class vAA, Class@BBBB */ 854 FETCH(r1, 1) @ r1<- BBBB 855 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 856 mov r9, rINST, lsr #8 @ r9<- AA 857 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 858 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 859 cmp r0, #0 @ not yet resolved? 860 beq .LOP_CONST_CLASS_resolve 861 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 862 GET_INST_OPCODE(ip) @ extract opcode from rINST 863 SET_VREG(r0, r9) @ vAA<- r0 864 GOTO_OPCODE(ip) @ jump to next instruction 865 866/* ------------------------------ */ 867 .balign 64 868.L_OP_MONITOR_ENTER: /* 0x1d */ 869/* File: armv5te/OP_MONITOR_ENTER.S */ 870 /* 871 * Synchronize on an object. 872 */ 873 /* monitor-enter vAA */ 874 mov r2, rINST, lsr #8 @ r2<- AA 875 GET_VREG(r1, r2) @ r1<- vAA (object) 876 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 877 cmp r1, #0 @ null object? 878 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 879 beq common_errNullObject @ null object, throw an exception 880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 881 bl dvmLockObject @ call(self, obj) 882#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 883 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 884 ldr r1, [r0, #offThread_exception] @ check for exception 885 cmp r1, #0 886 bne common_exceptionThrown @ exception raised, bail out 887#endif 888 GET_INST_OPCODE(ip) @ extract opcode from rINST 889 GOTO_OPCODE(ip) @ jump to next instruction 890 891 892/* ------------------------------ */ 893 .balign 64 894.L_OP_MONITOR_EXIT: /* 0x1e */ 895/* File: armv5te/OP_MONITOR_EXIT.S */ 896 /* 897 * Unlock an object. 898 * 899 * Exceptions that occur when unlocking a monitor need to appear as 900 * if they happened at the following instruction. See the Dalvik 901 * instruction spec. 902 */ 903 /* monitor-exit vAA */ 904 mov r2, rINST, lsr #8 @ r2<- AA 905 EXPORT_PC() @ before fetch: export the PC 906 GET_VREG(r1, r2) @ r1<- vAA (object) 907 cmp r1, #0 @ null object? 908 beq common_errNullObject @ yes 909 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 910 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 911 cmp r0, #0 @ failed? 912 beq common_exceptionThrown @ yes, exception is pending 913 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 914 GET_INST_OPCODE(ip) @ extract opcode from rINST 915 GOTO_OPCODE(ip) @ jump to next instruction 916 917 918/* ------------------------------ */ 919 .balign 64 920.L_OP_CHECK_CAST: /* 0x1f */ 921/* File: armv5te/OP_CHECK_CAST.S */ 922 /* 923 * Check to see if a cast from one class to another is allowed. 924 */ 925 /* check-cast vAA, class@BBBB */ 926 mov r3, rINST, lsr #8 @ r3<- AA 927 FETCH(r2, 1) @ r2<- BBBB 928 GET_VREG(r9, r3) @ r9<- object 929 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 930 cmp r9, #0 @ is object null? 931 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 932 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 933 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 934 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 935 cmp r1, #0 @ have we resolved this before? 936 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 937.LOP_CHECK_CAST_resolved: 938 cmp r0, r1 @ same class (trivial success)? 939 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 940.LOP_CHECK_CAST_okay: 941 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 942 GET_INST_OPCODE(ip) @ extract opcode from rINST 943 GOTO_OPCODE(ip) @ jump to next instruction 944 945/* ------------------------------ */ 946 .balign 64 947.L_OP_INSTANCE_OF: /* 0x20 */ 948/* File: armv5te/OP_INSTANCE_OF.S */ 949 /* 950 * Check to see if an object reference is an instance of a class. 951 * 952 * Most common situation is a non-null object, being compared against 953 * an already-resolved class. 954 */ 955 /* instance-of vA, vB, class@CCCC */ 956 mov r3, rINST, lsr #12 @ r3<- B 957 mov r9, rINST, lsr #8 @ r9<- A+ 958 GET_VREG(r0, r3) @ r0<- vB (object) 959 and r9, r9, #15 @ r9<- A 960 cmp r0, #0 @ is object null? 961 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 962 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 963 FETCH(r3, 1) @ r3<- CCCC 964 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 965 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 966 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 967 cmp r1, #0 @ have we resolved this before? 968 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 969.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 970 cmp r0, r1 @ same class (trivial success)? 971 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 972 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 973 974/* ------------------------------ */ 975 .balign 64 976.L_OP_ARRAY_LENGTH: /* 0x21 */ 977/* File: armv5te/OP_ARRAY_LENGTH.S */ 978 /* 979 * Return the length of an array. 980 */ 981 mov r1, rINST, lsr #12 @ r1<- B 982 mov r2, rINST, lsr #8 @ r2<- A+ 983 GET_VREG(r0, r1) @ r0<- vB (object ref) 984 and r2, r2, #15 @ r2<- A 985 cmp r0, #0 @ is object null? 986 beq common_errNullObject @ yup, fail 987 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 988 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 989 GET_INST_OPCODE(ip) @ extract opcode from rINST 990 SET_VREG(r3, r2) @ vB<- length 991 GOTO_OPCODE(ip) @ jump to next instruction 992 993 994/* ------------------------------ */ 995 .balign 64 996.L_OP_NEW_INSTANCE: /* 0x22 */ 997/* File: armv5te/OP_NEW_INSTANCE.S */ 998 /* 999 * Create a new instance of a class. 1000 */ 1001 /* new-instance vAA, class@BBBB */ 1002 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1003 FETCH(r1, 1) @ r1<- BBBB 1004 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1005 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1006 EXPORT_PC() @ req'd for init, resolve, alloc 1007 cmp r0, #0 @ already resolved? 1008 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1009.LOP_NEW_INSTANCE_resolved: @ r0=class 1010 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1011 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1012 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1013.LOP_NEW_INSTANCE_initialized: @ r0=class 1014 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1015 bl dvmAllocObject @ r0<- new object 1016 b .LOP_NEW_INSTANCE_finish @ continue 1017 1018/* ------------------------------ */ 1019 .balign 64 1020.L_OP_NEW_ARRAY: /* 0x23 */ 1021/* File: armv5te/OP_NEW_ARRAY.S */ 1022 /* 1023 * Allocate an array of objects, specified with the array class 1024 * and a count. 1025 * 1026 * The verifier guarantees that this is an array class, so we don't 1027 * check for it here. 1028 */ 1029 /* new-array vA, vB, class@CCCC */ 1030 mov r0, rINST, lsr #12 @ r0<- B 1031 FETCH(r2, 1) @ r2<- CCCC 1032 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1033 GET_VREG(r1, r0) @ r1<- vB (array length) 1034 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1035 cmp r1, #0 @ check length 1036 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1037 bmi common_errNegativeArraySize @ negative length, bail 1038 cmp r0, #0 @ already resolved? 1039 EXPORT_PC() @ req'd for resolve, alloc 1040 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1041 b .LOP_NEW_ARRAY_resolve @ do resolve now 1042 1043/* ------------------------------ */ 1044 .balign 64 1045.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1046/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1047 /* 1048 * Create a new array with elements filled from registers. 1049 * 1050 * for: filled-new-array, filled-new-array/range 1051 */ 1052 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1053 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1054 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1055 FETCH(r1, 1) @ r1<- BBBB 1056 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1057 EXPORT_PC() @ need for resolve and alloc 1058 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1059 mov r10, rINST, lsr #8 @ r10<- AA or BA 1060 cmp r0, #0 @ already resolved? 1061 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10628: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1063 mov r2, #0 @ r2<- false 1064 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1065 bl dvmResolveClass @ r0<- call(clazz, ref) 1066 cmp r0, #0 @ got null? 1067 beq common_exceptionThrown @ yes, handle exception 1068 b .LOP_FILLED_NEW_ARRAY_continue 1069 1070/* ------------------------------ */ 1071 .balign 64 1072.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1073/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1074/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1075 /* 1076 * Create a new array with elements filled from registers. 1077 * 1078 * for: filled-new-array, filled-new-array/range 1079 */ 1080 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1081 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1082 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1083 FETCH(r1, 1) @ r1<- BBBB 1084 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1085 EXPORT_PC() @ need for resolve and alloc 1086 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1087 mov r10, rINST, lsr #8 @ r10<- AA or BA 1088 cmp r0, #0 @ already resolved? 1089 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10908: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1091 mov r2, #0 @ r2<- false 1092 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1093 bl dvmResolveClass @ r0<- call(clazz, ref) 1094 cmp r0, #0 @ got null? 1095 beq common_exceptionThrown @ yes, handle exception 1096 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1097 1098 1099/* ------------------------------ */ 1100 .balign 64 1101.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1102/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1103 /* fill-array-data vAA, +BBBBBBBB */ 1104 FETCH(r0, 1) @ r0<- bbbb (lo) 1105 FETCH(r1, 2) @ r1<- BBBB (hi) 1106 mov r3, rINST, lsr #8 @ r3<- AA 1107 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1108 GET_VREG(r0, r3) @ r0<- vAA (array object) 1109 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1110 EXPORT_PC(); 1111 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1112 cmp r0, #0 @ 0 means an exception is thrown 1113 beq common_exceptionThrown @ has exception 1114 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1115 GET_INST_OPCODE(ip) @ extract opcode from rINST 1116 GOTO_OPCODE(ip) @ jump to next instruction 1117 1118/* ------------------------------ */ 1119 .balign 64 1120.L_OP_THROW: /* 0x27 */ 1121/* File: armv5te/OP_THROW.S */ 1122 /* 1123 * Throw an exception object in the current thread. 1124 */ 1125 /* throw vAA */ 1126 mov r2, rINST, lsr #8 @ r2<- AA 1127 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1128 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1129 cmp r1, #0 @ null object? 1130 beq common_errNullObject @ yes, throw an NPE instead 1131 @ bypass dvmSetException, just store it 1132 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1133 b common_exceptionThrown 1134 1135 1136/* ------------------------------ */ 1137 .balign 64 1138.L_OP_GOTO: /* 0x28 */ 1139/* File: armv5te/OP_GOTO.S */ 1140 /* 1141 * Unconditional branch, 8-bit offset. 1142 * 1143 * The branch distance is a signed code-unit offset, which we need to 1144 * double to get a byte offset. 1145 */ 1146 /* goto +AA */ 1147 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1148 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1149 mov r9, r9, lsl #1 @ r9<- byte offset 1150 bmi common_backwardBranch @ backward branch, do periodic checks 1151#if defined(WITH_JIT) 1152 GET_JIT_PROF_TABLE(r0) 1153 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1154 cmp r0,#0 1155 bne common_updateProfile 1156 GET_INST_OPCODE(ip) @ extract opcode from rINST 1157 GOTO_OPCODE(ip) @ jump to next instruction 1158#else 1159 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1160 GET_INST_OPCODE(ip) @ extract opcode from rINST 1161 GOTO_OPCODE(ip) @ jump to next instruction 1162#endif 1163 1164/* ------------------------------ */ 1165 .balign 64 1166.L_OP_GOTO_16: /* 0x29 */ 1167/* File: armv5te/OP_GOTO_16.S */ 1168 /* 1169 * Unconditional branch, 16-bit offset. 1170 * 1171 * The branch distance is a signed code-unit offset, which we need to 1172 * double to get a byte offset. 1173 */ 1174 /* goto/16 +AAAA */ 1175 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1176 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1177 bmi common_backwardBranch @ backward branch, do periodic checks 1178#if defined(WITH_JIT) 1179 GET_JIT_PROF_TABLE(r0) 1180 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1181 cmp r0,#0 1182 bne common_updateProfile 1183 GET_INST_OPCODE(ip) @ extract opcode from rINST 1184 GOTO_OPCODE(ip) @ jump to next instruction 1185#else 1186 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1187 GET_INST_OPCODE(ip) @ extract opcode from rINST 1188 GOTO_OPCODE(ip) @ jump to next instruction 1189#endif 1190 1191 1192/* ------------------------------ */ 1193 .balign 64 1194.L_OP_GOTO_32: /* 0x2a */ 1195/* File: armv5te/OP_GOTO_32.S */ 1196 /* 1197 * Unconditional branch, 32-bit offset. 1198 * 1199 * The branch distance is a signed code-unit offset, which we need to 1200 * double to get a byte offset. 1201 * 1202 * Unlike most opcodes, this one is allowed to branch to itself, so 1203 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1204 * instruction doesn't affect the V flag, so we need to clear it 1205 * explicitly. 1206 */ 1207 /* goto/32 +AAAAAAAA */ 1208 FETCH(r0, 1) @ r0<- aaaa (lo) 1209 FETCH(r1, 2) @ r1<- AAAA (hi) 1210 cmp ip, ip @ (clear V flag during stall) 1211 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1212 mov r9, r0, asl #1 @ r9<- byte offset 1213 ble common_backwardBranch @ backward branch, do periodic checks 1214#if defined(WITH_JIT) 1215 GET_JIT_PROF_TABLE(r0) 1216 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1217 cmp r0,#0 1218 bne common_updateProfile 1219 GET_INST_OPCODE(ip) @ extract opcode from rINST 1220 GOTO_OPCODE(ip) @ jump to next instruction 1221#else 1222 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1223 GET_INST_OPCODE(ip) @ extract opcode from rINST 1224 GOTO_OPCODE(ip) @ jump to next instruction 1225#endif 1226 1227/* ------------------------------ */ 1228 .balign 64 1229.L_OP_PACKED_SWITCH: /* 0x2b */ 1230/* File: armv5te/OP_PACKED_SWITCH.S */ 1231 /* 1232 * Handle a packed-switch or sparse-switch instruction. In both cases 1233 * we decode it and hand it off to a helper function. 1234 * 1235 * We don't really expect backward branches in a switch statement, but 1236 * they're perfectly legal, so we check for them here. 1237 * 1238 * for: packed-switch, sparse-switch 1239 */ 1240 /* op vAA, +BBBB */ 1241 FETCH(r0, 1) @ r0<- bbbb (lo) 1242 FETCH(r1, 2) @ r1<- BBBB (hi) 1243 mov r3, rINST, lsr #8 @ r3<- AA 1244 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1245 GET_VREG(r1, r3) @ r1<- vAA 1246 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1247 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1248 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1249 bmi common_backwardBranch @ backward branch, do periodic checks 1250 beq common_backwardBranch @ (want to use BLE but V is unknown) 1251#if defined(WITH_JIT) 1252 GET_JIT_PROF_TABLE(r0) 1253 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1254 cmp r0,#0 1255 bne common_updateProfile 1256 GET_INST_OPCODE(ip) @ extract opcode from rINST 1257 GOTO_OPCODE(ip) @ jump to next instruction 1258#else 1259 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1260 GET_INST_OPCODE(ip) @ extract opcode from rINST 1261 GOTO_OPCODE(ip) @ jump to next instruction 1262#endif 1263 1264 1265/* ------------------------------ */ 1266 .balign 64 1267.L_OP_SPARSE_SWITCH: /* 0x2c */ 1268/* File: armv5te/OP_SPARSE_SWITCH.S */ 1269/* File: armv5te/OP_PACKED_SWITCH.S */ 1270 /* 1271 * Handle a packed-switch or sparse-switch instruction. In both cases 1272 * we decode it and hand it off to a helper function. 1273 * 1274 * We don't really expect backward branches in a switch statement, but 1275 * they're perfectly legal, so we check for them here. 1276 * 1277 * for: packed-switch, sparse-switch 1278 */ 1279 /* op vAA, +BBBB */ 1280 FETCH(r0, 1) @ r0<- bbbb (lo) 1281 FETCH(r1, 2) @ r1<- BBBB (hi) 1282 mov r3, rINST, lsr #8 @ r3<- AA 1283 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1284 GET_VREG(r1, r3) @ r1<- vAA 1285 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1286 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1287 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1288 bmi common_backwardBranch @ backward branch, do periodic checks 1289 beq common_backwardBranch @ (want to use BLE but V is unknown) 1290#if defined(WITH_JIT) 1291 GET_JIT_PROF_TABLE(r0) 1292 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1293 cmp r0,#0 1294 bne common_updateProfile 1295 GET_INST_OPCODE(ip) @ extract opcode from rINST 1296 GOTO_OPCODE(ip) @ jump to next instruction 1297#else 1298 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1299 GET_INST_OPCODE(ip) @ extract opcode from rINST 1300 GOTO_OPCODE(ip) @ jump to next instruction 1301#endif 1302 1303 1304 1305/* ------------------------------ */ 1306 .balign 64 1307.L_OP_CMPL_FLOAT: /* 0x2d */ 1308/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1309 /* 1310 * Compare two floating-point values. Puts 0, 1, or -1 into the 1311 * destination register based on the results of the comparison. 1312 * 1313 * int compare(x, y) { 1314 * if (x == y) { 1315 * return 0; 1316 * } else if (x > y) { 1317 * return 1; 1318 * } else if (x < y) { 1319 * return -1; 1320 * } else { 1321 * return -1; 1322 * } 1323 * } 1324 */ 1325 /* op vAA, vBB, vCC */ 1326 FETCH(r0, 1) @ r0<- CCBB 1327 mov r9, rINST, lsr #8 @ r9<- AA 1328 and r2, r0, #255 @ r2<- BB 1329 mov r3, r0, lsr #8 @ r3<- CC 1330 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1331 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1332 flds s0, [r2] @ s0<- vBB 1333 flds s1, [r3] @ s1<- vCC 1334 fcmpes s0, s1 @ compare (vBB, vCC) 1335 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1336 mvn r0, #0 @ r0<- -1 (default) 1337 GET_INST_OPCODE(ip) @ extract opcode from rINST 1338 fmstat @ export status flags 1339 movgt r0, #1 @ (greater than) r1<- 1 1340 moveq r0, #0 @ (equal) r1<- 0 1341 b .LOP_CMPL_FLOAT_finish @ argh 1342 1343 1344/* ------------------------------ */ 1345 .balign 64 1346.L_OP_CMPG_FLOAT: /* 0x2e */ 1347/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1348 /* 1349 * Compare two floating-point values. Puts 0, 1, or -1 into the 1350 * destination register based on the results of the comparison. 1351 * 1352 * int compare(x, y) { 1353 * if (x == y) { 1354 * return 0; 1355 * } else if (x < y) { 1356 * return -1; 1357 * } else if (x > y) { 1358 * return 1; 1359 * } else { 1360 * return 1; 1361 * } 1362 * } 1363 */ 1364 /* op vAA, vBB, vCC */ 1365 FETCH(r0, 1) @ r0<- CCBB 1366 mov r9, rINST, lsr #8 @ r9<- AA 1367 and r2, r0, #255 @ r2<- BB 1368 mov r3, r0, lsr #8 @ r3<- CC 1369 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1370 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1371 flds s0, [r2] @ s0<- vBB 1372 flds s1, [r3] @ s1<- vCC 1373 fcmpes s0, s1 @ compare (vBB, vCC) 1374 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1375 mov r0, #1 @ r0<- 1 (default) 1376 GET_INST_OPCODE(ip) @ extract opcode from rINST 1377 fmstat @ export status flags 1378 mvnmi r0, #0 @ (less than) r1<- -1 1379 moveq r0, #0 @ (equal) r1<- 0 1380 b .LOP_CMPG_FLOAT_finish @ argh 1381 1382 1383/* ------------------------------ */ 1384 .balign 64 1385.L_OP_CMPL_DOUBLE: /* 0x2f */ 1386/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1387 /* 1388 * Compare two floating-point values. Puts 0, 1, or -1 into the 1389 * destination register based on the results of the comparison. 1390 * 1391 * int compare(x, y) { 1392 * if (x == y) { 1393 * return 0; 1394 * } else if (x > y) { 1395 * return 1; 1396 * } else if (x < y) { 1397 * return -1; 1398 * } else { 1399 * return -1; 1400 * } 1401 * } 1402 */ 1403 /* op vAA, vBB, vCC */ 1404 FETCH(r0, 1) @ r0<- CCBB 1405 mov r9, rINST, lsr #8 @ r9<- AA 1406 and r2, r0, #255 @ r2<- BB 1407 mov r3, r0, lsr #8 @ r3<- CC 1408 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1409 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1410 fldd d0, [r2] @ d0<- vBB 1411 fldd d1, [r3] @ d1<- vCC 1412 fcmped d0, d1 @ compare (vBB, vCC) 1413 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1414 mvn r0, #0 @ r0<- -1 (default) 1415 GET_INST_OPCODE(ip) @ extract opcode from rINST 1416 fmstat @ export status flags 1417 movgt r0, #1 @ (greater than) r1<- 1 1418 moveq r0, #0 @ (equal) r1<- 0 1419 b .LOP_CMPL_DOUBLE_finish @ argh 1420 1421 1422/* ------------------------------ */ 1423 .balign 64 1424.L_OP_CMPG_DOUBLE: /* 0x30 */ 1425/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1426 /* 1427 * Compare two floating-point values. Puts 0, 1, or -1 into the 1428 * destination register based on the results of the comparison. 1429 * 1430 * int compare(x, y) { 1431 * if (x == y) { 1432 * return 0; 1433 * } else if (x < y) { 1434 * return -1; 1435 * } else if (x > y) { 1436 * return 1; 1437 * } else { 1438 * return 1; 1439 * } 1440 * } 1441 */ 1442 /* op vAA, vBB, vCC */ 1443 FETCH(r0, 1) @ r0<- CCBB 1444 mov r9, rINST, lsr #8 @ r9<- AA 1445 and r2, r0, #255 @ r2<- BB 1446 mov r3, r0, lsr #8 @ r3<- CC 1447 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1448 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1449 fldd d0, [r2] @ d0<- vBB 1450 fldd d1, [r3] @ d1<- vCC 1451 fcmped d0, d1 @ compare (vBB, vCC) 1452 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1453 mov r0, #1 @ r0<- 1 (default) 1454 GET_INST_OPCODE(ip) @ extract opcode from rINST 1455 fmstat @ export status flags 1456 mvnmi r0, #0 @ (less than) r1<- -1 1457 moveq r0, #0 @ (equal) r1<- 0 1458 b .LOP_CMPG_DOUBLE_finish @ argh 1459 1460 1461/* ------------------------------ */ 1462 .balign 64 1463.L_OP_CMP_LONG: /* 0x31 */ 1464/* File: armv5te/OP_CMP_LONG.S */ 1465 /* 1466 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1467 * register based on the results of the comparison. 1468 * 1469 * We load the full values with LDM, but in practice many values could 1470 * be resolved by only looking at the high word. This could be made 1471 * faster or slower by splitting the LDM into a pair of LDRs. 1472 * 1473 * If we just wanted to set condition flags, we could do this: 1474 * subs ip, r0, r2 1475 * sbcs ip, r1, r3 1476 * subeqs ip, r0, r2 1477 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1478 * integer value, which we can do with 2 conditional mov/mvn instructions 1479 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1480 * us a constant 5-cycle path plus a branch at the end to the 1481 * instruction epilogue code. The multi-compare approach below needs 1482 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1483 * in the worst case (the 64-bit values are equal). 1484 */ 1485 /* cmp-long vAA, vBB, vCC */ 1486 FETCH(r0, 1) @ r0<- CCBB 1487 mov r9, rINST, lsr #8 @ r9<- AA 1488 and r2, r0, #255 @ r2<- BB 1489 mov r3, r0, lsr #8 @ r3<- CC 1490 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1491 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1492 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1493 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1494 cmp r1, r3 @ compare (vBB+1, vCC+1) 1495 blt .LOP_CMP_LONG_less @ signed compare on high part 1496 bgt .LOP_CMP_LONG_greater 1497 subs r1, r0, r2 @ r1<- r0 - r2 1498 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1499 bne .LOP_CMP_LONG_less 1500 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1501 1502/* ------------------------------ */ 1503 .balign 64 1504.L_OP_IF_EQ: /* 0x32 */ 1505/* File: armv5te/OP_IF_EQ.S */ 1506/* File: armv5te/bincmp.S */ 1507 /* 1508 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1509 * fragment that specifies the *reverse* comparison to perform, e.g. 1510 * for "if-le" you would use "gt". 1511 * 1512 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1513 */ 1514 /* if-cmp vA, vB, +CCCC */ 1515 mov r0, rINST, lsr #8 @ r0<- A+ 1516 mov r1, rINST, lsr #12 @ r1<- B 1517 and r0, r0, #15 1518 GET_VREG(r3, r1) @ r3<- vB 1519 GET_VREG(r2, r0) @ r2<- vA 1520 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1521 cmp r2, r3 @ compare (vA, vB) 1522 bne 1f @ branch to 1 if comparison failed 1523 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1524 movs r9, r9, asl #1 @ convert to bytes, check sign 1525 bmi common_backwardBranch @ yes, do periodic checks 15261: 1527#if defined(WITH_JIT) 1528 GET_JIT_PROF_TABLE(r0) 1529 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1530 b common_testUpdateProfile 1531#else 1532 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1533 GET_INST_OPCODE(ip) @ extract opcode from rINST 1534 GOTO_OPCODE(ip) @ jump to next instruction 1535#endif 1536 1537 1538 1539/* ------------------------------ */ 1540 .balign 64 1541.L_OP_IF_NE: /* 0x33 */ 1542/* File: armv5te/OP_IF_NE.S */ 1543/* File: armv5te/bincmp.S */ 1544 /* 1545 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1546 * fragment that specifies the *reverse* comparison to perform, e.g. 1547 * for "if-le" you would use "gt". 1548 * 1549 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1550 */ 1551 /* if-cmp vA, vB, +CCCC */ 1552 mov r0, rINST, lsr #8 @ r0<- A+ 1553 mov r1, rINST, lsr #12 @ r1<- B 1554 and r0, r0, #15 1555 GET_VREG(r3, r1) @ r3<- vB 1556 GET_VREG(r2, r0) @ r2<- vA 1557 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1558 cmp r2, r3 @ compare (vA, vB) 1559 beq 1f @ branch to 1 if comparison failed 1560 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1561 movs r9, r9, asl #1 @ convert to bytes, check sign 1562 bmi common_backwardBranch @ yes, do periodic checks 15631: 1564#if defined(WITH_JIT) 1565 GET_JIT_PROF_TABLE(r0) 1566 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 b common_testUpdateProfile 1568#else 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 GET_INST_OPCODE(ip) @ extract opcode from rINST 1571 GOTO_OPCODE(ip) @ jump to next instruction 1572#endif 1573 1574 1575 1576/* ------------------------------ */ 1577 .balign 64 1578.L_OP_IF_LT: /* 0x34 */ 1579/* File: armv5te/OP_IF_LT.S */ 1580/* File: armv5te/bincmp.S */ 1581 /* 1582 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1583 * fragment that specifies the *reverse* comparison to perform, e.g. 1584 * for "if-le" you would use "gt". 1585 * 1586 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1587 */ 1588 /* if-cmp vA, vB, +CCCC */ 1589 mov r0, rINST, lsr #8 @ r0<- A+ 1590 mov r1, rINST, lsr #12 @ r1<- B 1591 and r0, r0, #15 1592 GET_VREG(r3, r1) @ r3<- vB 1593 GET_VREG(r2, r0) @ r2<- vA 1594 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1595 cmp r2, r3 @ compare (vA, vB) 1596 bge 1f @ branch to 1 if comparison failed 1597 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1598 movs r9, r9, asl #1 @ convert to bytes, check sign 1599 bmi common_backwardBranch @ yes, do periodic checks 16001: 1601#if defined(WITH_JIT) 1602 GET_JIT_PROF_TABLE(r0) 1603 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1604 b common_testUpdateProfile 1605#else 1606 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1607 GET_INST_OPCODE(ip) @ extract opcode from rINST 1608 GOTO_OPCODE(ip) @ jump to next instruction 1609#endif 1610 1611 1612 1613/* ------------------------------ */ 1614 .balign 64 1615.L_OP_IF_GE: /* 0x35 */ 1616/* File: armv5te/OP_IF_GE.S */ 1617/* File: armv5te/bincmp.S */ 1618 /* 1619 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1620 * fragment that specifies the *reverse* comparison to perform, e.g. 1621 * for "if-le" you would use "gt". 1622 * 1623 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1624 */ 1625 /* if-cmp vA, vB, +CCCC */ 1626 mov r0, rINST, lsr #8 @ r0<- A+ 1627 mov r1, rINST, lsr #12 @ r1<- B 1628 and r0, r0, #15 1629 GET_VREG(r3, r1) @ r3<- vB 1630 GET_VREG(r2, r0) @ r2<- vA 1631 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1632 cmp r2, r3 @ compare (vA, vB) 1633 blt 1f @ branch to 1 if comparison failed 1634 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1635 movs r9, r9, asl #1 @ convert to bytes, check sign 1636 bmi common_backwardBranch @ yes, do periodic checks 16371: 1638#if defined(WITH_JIT) 1639 GET_JIT_PROF_TABLE(r0) 1640 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1641 b common_testUpdateProfile 1642#else 1643 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1644 GET_INST_OPCODE(ip) @ extract opcode from rINST 1645 GOTO_OPCODE(ip) @ jump to next instruction 1646#endif 1647 1648 1649 1650/* ------------------------------ */ 1651 .balign 64 1652.L_OP_IF_GT: /* 0x36 */ 1653/* File: armv5te/OP_IF_GT.S */ 1654/* File: armv5te/bincmp.S */ 1655 /* 1656 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1657 * fragment that specifies the *reverse* comparison to perform, e.g. 1658 * for "if-le" you would use "gt". 1659 * 1660 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1661 */ 1662 /* if-cmp vA, vB, +CCCC */ 1663 mov r0, rINST, lsr #8 @ r0<- A+ 1664 mov r1, rINST, lsr #12 @ r1<- B 1665 and r0, r0, #15 1666 GET_VREG(r3, r1) @ r3<- vB 1667 GET_VREG(r2, r0) @ r2<- vA 1668 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1669 cmp r2, r3 @ compare (vA, vB) 1670 ble 1f @ branch to 1 if comparison failed 1671 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1672 movs r9, r9, asl #1 @ convert to bytes, check sign 1673 bmi common_backwardBranch @ yes, do periodic checks 16741: 1675#if defined(WITH_JIT) 1676 GET_JIT_PROF_TABLE(r0) 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 b common_testUpdateProfile 1679#else 1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1681 GET_INST_OPCODE(ip) @ extract opcode from rINST 1682 GOTO_OPCODE(ip) @ jump to next instruction 1683#endif 1684 1685 1686 1687/* ------------------------------ */ 1688 .balign 64 1689.L_OP_IF_LE: /* 0x37 */ 1690/* File: armv5te/OP_IF_LE.S */ 1691/* File: armv5te/bincmp.S */ 1692 /* 1693 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1694 * fragment that specifies the *reverse* comparison to perform, e.g. 1695 * for "if-le" you would use "gt". 1696 * 1697 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1698 */ 1699 /* if-cmp vA, vB, +CCCC */ 1700 mov r0, rINST, lsr #8 @ r0<- A+ 1701 mov r1, rINST, lsr #12 @ r1<- B 1702 and r0, r0, #15 1703 GET_VREG(r3, r1) @ r3<- vB 1704 GET_VREG(r2, r0) @ r2<- vA 1705 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1706 cmp r2, r3 @ compare (vA, vB) 1707 bgt 1f @ branch to 1 if comparison failed 1708 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1709 movs r9, r9, asl #1 @ convert to bytes, check sign 1710 bmi common_backwardBranch @ yes, do periodic checks 17111: 1712#if defined(WITH_JIT) 1713 GET_JIT_PROF_TABLE(r0) 1714 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1715 b common_testUpdateProfile 1716#else 1717 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1718 GET_INST_OPCODE(ip) @ extract opcode from rINST 1719 GOTO_OPCODE(ip) @ jump to next instruction 1720#endif 1721 1722 1723 1724/* ------------------------------ */ 1725 .balign 64 1726.L_OP_IF_EQZ: /* 0x38 */ 1727/* File: armv5te/OP_IF_EQZ.S */ 1728/* File: armv5te/zcmp.S */ 1729 /* 1730 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1731 * fragment that specifies the *reverse* comparison to perform, e.g. 1732 * for "if-le" you would use "gt". 1733 * 1734 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1735 */ 1736 /* if-cmp vAA, +BBBB */ 1737 mov r0, rINST, lsr #8 @ r0<- AA 1738 GET_VREG(r2, r0) @ r2<- vAA 1739 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1740 cmp r2, #0 @ compare (vA, 0) 1741 bne 1f @ branch to 1 if comparison failed 1742 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1743 movs r9, r9, asl #1 @ convert to bytes, check sign 1744 bmi common_backwardBranch @ backward branch, do periodic checks 17451: 1746#if defined(WITH_JIT) 1747 GET_JIT_PROF_TABLE(r0) 1748 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1749 cmp r0,#0 1750 bne common_updateProfile 1751 GET_INST_OPCODE(ip) @ extract opcode from rINST 1752 GOTO_OPCODE(ip) @ jump to next instruction 1753#else 1754 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1755 GET_INST_OPCODE(ip) @ extract opcode from rINST 1756 GOTO_OPCODE(ip) @ jump to next instruction 1757#endif 1758 1759 1760 1761/* ------------------------------ */ 1762 .balign 64 1763.L_OP_IF_NEZ: /* 0x39 */ 1764/* File: armv5te/OP_IF_NEZ.S */ 1765/* File: armv5te/zcmp.S */ 1766 /* 1767 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1768 * fragment that specifies the *reverse* comparison to perform, e.g. 1769 * for "if-le" you would use "gt". 1770 * 1771 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1772 */ 1773 /* if-cmp vAA, +BBBB */ 1774 mov r0, rINST, lsr #8 @ r0<- AA 1775 GET_VREG(r2, r0) @ r2<- vAA 1776 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1777 cmp r2, #0 @ compare (vA, 0) 1778 beq 1f @ branch to 1 if comparison failed 1779 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1780 movs r9, r9, asl #1 @ convert to bytes, check sign 1781 bmi common_backwardBranch @ backward branch, do periodic checks 17821: 1783#if defined(WITH_JIT) 1784 GET_JIT_PROF_TABLE(r0) 1785 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1786 cmp r0,#0 1787 bne common_updateProfile 1788 GET_INST_OPCODE(ip) @ extract opcode from rINST 1789 GOTO_OPCODE(ip) @ jump to next instruction 1790#else 1791 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1792 GET_INST_OPCODE(ip) @ extract opcode from rINST 1793 GOTO_OPCODE(ip) @ jump to next instruction 1794#endif 1795 1796 1797 1798/* ------------------------------ */ 1799 .balign 64 1800.L_OP_IF_LTZ: /* 0x3a */ 1801/* File: armv5te/OP_IF_LTZ.S */ 1802/* File: armv5te/zcmp.S */ 1803 /* 1804 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1805 * fragment that specifies the *reverse* comparison to perform, e.g. 1806 * for "if-le" you would use "gt". 1807 * 1808 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1809 */ 1810 /* if-cmp vAA, +BBBB */ 1811 mov r0, rINST, lsr #8 @ r0<- AA 1812 GET_VREG(r2, r0) @ r2<- vAA 1813 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1814 cmp r2, #0 @ compare (vA, 0) 1815 bge 1f @ branch to 1 if comparison failed 1816 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1817 movs r9, r9, asl #1 @ convert to bytes, check sign 1818 bmi common_backwardBranch @ backward branch, do periodic checks 18191: 1820#if defined(WITH_JIT) 1821 GET_JIT_PROF_TABLE(r0) 1822 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1823 cmp r0,#0 1824 bne common_updateProfile 1825 GET_INST_OPCODE(ip) @ extract opcode from rINST 1826 GOTO_OPCODE(ip) @ jump to next instruction 1827#else 1828 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1829 GET_INST_OPCODE(ip) @ extract opcode from rINST 1830 GOTO_OPCODE(ip) @ jump to next instruction 1831#endif 1832 1833 1834 1835/* ------------------------------ */ 1836 .balign 64 1837.L_OP_IF_GEZ: /* 0x3b */ 1838/* File: armv5te/OP_IF_GEZ.S */ 1839/* File: armv5te/zcmp.S */ 1840 /* 1841 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1842 * fragment that specifies the *reverse* comparison to perform, e.g. 1843 * for "if-le" you would use "gt". 1844 * 1845 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1846 */ 1847 /* if-cmp vAA, +BBBB */ 1848 mov r0, rINST, lsr #8 @ r0<- AA 1849 GET_VREG(r2, r0) @ r2<- vAA 1850 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1851 cmp r2, #0 @ compare (vA, 0) 1852 blt 1f @ branch to 1 if comparison failed 1853 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1854 movs r9, r9, asl #1 @ convert to bytes, check sign 1855 bmi common_backwardBranch @ backward branch, do periodic checks 18561: 1857#if defined(WITH_JIT) 1858 GET_JIT_PROF_TABLE(r0) 1859 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1860 cmp r0,#0 1861 bne common_updateProfile 1862 GET_INST_OPCODE(ip) @ extract opcode from rINST 1863 GOTO_OPCODE(ip) @ jump to next instruction 1864#else 1865 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1866 GET_INST_OPCODE(ip) @ extract opcode from rINST 1867 GOTO_OPCODE(ip) @ jump to next instruction 1868#endif 1869 1870 1871 1872/* ------------------------------ */ 1873 .balign 64 1874.L_OP_IF_GTZ: /* 0x3c */ 1875/* File: armv5te/OP_IF_GTZ.S */ 1876/* File: armv5te/zcmp.S */ 1877 /* 1878 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1879 * fragment that specifies the *reverse* comparison to perform, e.g. 1880 * for "if-le" you would use "gt". 1881 * 1882 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1883 */ 1884 /* if-cmp vAA, +BBBB */ 1885 mov r0, rINST, lsr #8 @ r0<- AA 1886 GET_VREG(r2, r0) @ r2<- vAA 1887 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1888 cmp r2, #0 @ compare (vA, 0) 1889 ble 1f @ branch to 1 if comparison failed 1890 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1891 movs r9, r9, asl #1 @ convert to bytes, check sign 1892 bmi common_backwardBranch @ backward branch, do periodic checks 18931: 1894#if defined(WITH_JIT) 1895 GET_JIT_PROF_TABLE(r0) 1896 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1897 cmp r0,#0 1898 bne common_updateProfile 1899 GET_INST_OPCODE(ip) @ extract opcode from rINST 1900 GOTO_OPCODE(ip) @ jump to next instruction 1901#else 1902 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1903 GET_INST_OPCODE(ip) @ extract opcode from rINST 1904 GOTO_OPCODE(ip) @ jump to next instruction 1905#endif 1906 1907 1908 1909/* ------------------------------ */ 1910 .balign 64 1911.L_OP_IF_LEZ: /* 0x3d */ 1912/* File: armv5te/OP_IF_LEZ.S */ 1913/* File: armv5te/zcmp.S */ 1914 /* 1915 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1916 * fragment that specifies the *reverse* comparison to perform, e.g. 1917 * for "if-le" you would use "gt". 1918 * 1919 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1920 */ 1921 /* if-cmp vAA, +BBBB */ 1922 mov r0, rINST, lsr #8 @ r0<- AA 1923 GET_VREG(r2, r0) @ r2<- vAA 1924 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1925 cmp r2, #0 @ compare (vA, 0) 1926 bgt 1f @ branch to 1 if comparison failed 1927 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1928 movs r9, r9, asl #1 @ convert to bytes, check sign 1929 bmi common_backwardBranch @ backward branch, do periodic checks 19301: 1931#if defined(WITH_JIT) 1932 GET_JIT_PROF_TABLE(r0) 1933 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1934 cmp r0,#0 1935 bne common_updateProfile 1936 GET_INST_OPCODE(ip) @ extract opcode from rINST 1937 GOTO_OPCODE(ip) @ jump to next instruction 1938#else 1939 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1940 GET_INST_OPCODE(ip) @ extract opcode from rINST 1941 GOTO_OPCODE(ip) @ jump to next instruction 1942#endif 1943 1944 1945 1946/* ------------------------------ */ 1947 .balign 64 1948.L_OP_UNUSED_3E: /* 0x3e */ 1949/* File: armv5te/OP_UNUSED_3E.S */ 1950/* File: armv5te/unused.S */ 1951 bl common_abort 1952 1953 1954 1955/* ------------------------------ */ 1956 .balign 64 1957.L_OP_UNUSED_3F: /* 0x3f */ 1958/* File: armv5te/OP_UNUSED_3F.S */ 1959/* File: armv5te/unused.S */ 1960 bl common_abort 1961 1962 1963 1964/* ------------------------------ */ 1965 .balign 64 1966.L_OP_UNUSED_40: /* 0x40 */ 1967/* File: armv5te/OP_UNUSED_40.S */ 1968/* File: armv5te/unused.S */ 1969 bl common_abort 1970 1971 1972 1973/* ------------------------------ */ 1974 .balign 64 1975.L_OP_UNUSED_41: /* 0x41 */ 1976/* File: armv5te/OP_UNUSED_41.S */ 1977/* File: armv5te/unused.S */ 1978 bl common_abort 1979 1980 1981 1982/* ------------------------------ */ 1983 .balign 64 1984.L_OP_UNUSED_42: /* 0x42 */ 1985/* File: armv5te/OP_UNUSED_42.S */ 1986/* File: armv5te/unused.S */ 1987 bl common_abort 1988 1989 1990 1991/* ------------------------------ */ 1992 .balign 64 1993.L_OP_UNUSED_43: /* 0x43 */ 1994/* File: armv5te/OP_UNUSED_43.S */ 1995/* File: armv5te/unused.S */ 1996 bl common_abort 1997 1998 1999 2000/* ------------------------------ */ 2001 .balign 64 2002.L_OP_AGET: /* 0x44 */ 2003/* File: armv5te/OP_AGET.S */ 2004 /* 2005 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2006 * 2007 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2008 * instructions. We use a pair of FETCH_Bs instead. 2009 * 2010 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2011 */ 2012 /* op vAA, vBB, vCC */ 2013 FETCH_B(r2, 1, 0) @ r2<- BB 2014 mov r9, rINST, lsr #8 @ r9<- AA 2015 FETCH_B(r3, 1, 1) @ r3<- CC 2016 GET_VREG(r0, r2) @ r0<- vBB (array object) 2017 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2018 cmp r0, #0 @ null array object? 2019 beq common_errNullObject @ yes, bail 2020 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2021 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2022 cmp r1, r3 @ compare unsigned index, length 2023 bcs common_errArrayIndex @ index >= length, bail 2024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2025 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2026 GET_INST_OPCODE(ip) @ extract opcode from rINST 2027 SET_VREG(r2, r9) @ vAA<- r2 2028 GOTO_OPCODE(ip) @ jump to next instruction 2029 2030 2031/* ------------------------------ */ 2032 .balign 64 2033.L_OP_AGET_WIDE: /* 0x45 */ 2034/* File: armv5te/OP_AGET_WIDE.S */ 2035 /* 2036 * Array get, 64 bits. vAA <- vBB[vCC]. 2037 * 2038 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2039 */ 2040 /* aget-wide vAA, vBB, vCC */ 2041 FETCH(r0, 1) @ r0<- CCBB 2042 mov r9, rINST, lsr #8 @ r9<- AA 2043 and r2, r0, #255 @ r2<- BB 2044 mov r3, r0, lsr #8 @ r3<- CC 2045 GET_VREG(r0, r2) @ r0<- vBB (array object) 2046 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2047 cmp r0, #0 @ null array object? 2048 beq common_errNullObject @ yes, bail 2049 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2050 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2051 cmp r1, r3 @ compare unsigned index, length 2052 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2053 b common_errArrayIndex @ index >= length, bail 2054 @ May want to swap the order of these two branches depending on how the 2055 @ branch prediction (if any) handles conditional forward branches vs. 2056 @ unconditional forward branches. 2057 2058/* ------------------------------ */ 2059 .balign 64 2060.L_OP_AGET_OBJECT: /* 0x46 */ 2061/* File: armv5te/OP_AGET_OBJECT.S */ 2062/* File: armv5te/OP_AGET.S */ 2063 /* 2064 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2065 * 2066 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2067 * instructions. We use a pair of FETCH_Bs instead. 2068 * 2069 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2070 */ 2071 /* op vAA, vBB, vCC */ 2072 FETCH_B(r2, 1, 0) @ r2<- BB 2073 mov r9, rINST, lsr #8 @ r9<- AA 2074 FETCH_B(r3, 1, 1) @ r3<- CC 2075 GET_VREG(r0, r2) @ r0<- vBB (array object) 2076 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2077 cmp r0, #0 @ null array object? 2078 beq common_errNullObject @ yes, bail 2079 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2080 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2081 cmp r1, r3 @ compare unsigned index, length 2082 bcs common_errArrayIndex @ index >= length, bail 2083 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2084 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2085 GET_INST_OPCODE(ip) @ extract opcode from rINST 2086 SET_VREG(r2, r9) @ vAA<- r2 2087 GOTO_OPCODE(ip) @ jump to next instruction 2088 2089 2090 2091/* ------------------------------ */ 2092 .balign 64 2093.L_OP_AGET_BOOLEAN: /* 0x47 */ 2094/* File: armv5te/OP_AGET_BOOLEAN.S */ 2095/* File: armv5te/OP_AGET.S */ 2096 /* 2097 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2098 * 2099 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2100 * instructions. We use a pair of FETCH_Bs instead. 2101 * 2102 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2103 */ 2104 /* op vAA, vBB, vCC */ 2105 FETCH_B(r2, 1, 0) @ r2<- BB 2106 mov r9, rINST, lsr #8 @ r9<- AA 2107 FETCH_B(r3, 1, 1) @ r3<- CC 2108 GET_VREG(r0, r2) @ r0<- vBB (array object) 2109 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2110 cmp r0, #0 @ null array object? 2111 beq common_errNullObject @ yes, bail 2112 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2113 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2114 cmp r1, r3 @ compare unsigned index, length 2115 bcs common_errArrayIndex @ index >= length, bail 2116 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2117 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2118 GET_INST_OPCODE(ip) @ extract opcode from rINST 2119 SET_VREG(r2, r9) @ vAA<- r2 2120 GOTO_OPCODE(ip) @ jump to next instruction 2121 2122 2123 2124/* ------------------------------ */ 2125 .balign 64 2126.L_OP_AGET_BYTE: /* 0x48 */ 2127/* File: armv5te/OP_AGET_BYTE.S */ 2128/* File: armv5te/OP_AGET.S */ 2129 /* 2130 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2131 * 2132 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2133 * instructions. We use a pair of FETCH_Bs instead. 2134 * 2135 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2136 */ 2137 /* op vAA, vBB, vCC */ 2138 FETCH_B(r2, 1, 0) @ r2<- BB 2139 mov r9, rINST, lsr #8 @ r9<- AA 2140 FETCH_B(r3, 1, 1) @ r3<- CC 2141 GET_VREG(r0, r2) @ r0<- vBB (array object) 2142 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2143 cmp r0, #0 @ null array object? 2144 beq common_errNullObject @ yes, bail 2145 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2146 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2147 cmp r1, r3 @ compare unsigned index, length 2148 bcs common_errArrayIndex @ index >= length, bail 2149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2150 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2151 GET_INST_OPCODE(ip) @ extract opcode from rINST 2152 SET_VREG(r2, r9) @ vAA<- r2 2153 GOTO_OPCODE(ip) @ jump to next instruction 2154 2155 2156 2157/* ------------------------------ */ 2158 .balign 64 2159.L_OP_AGET_CHAR: /* 0x49 */ 2160/* File: armv5te/OP_AGET_CHAR.S */ 2161/* File: armv5te/OP_AGET.S */ 2162 /* 2163 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2164 * 2165 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2166 * instructions. We use a pair of FETCH_Bs instead. 2167 * 2168 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2169 */ 2170 /* op vAA, vBB, vCC */ 2171 FETCH_B(r2, 1, 0) @ r2<- BB 2172 mov r9, rINST, lsr #8 @ r9<- AA 2173 FETCH_B(r3, 1, 1) @ r3<- CC 2174 GET_VREG(r0, r2) @ r0<- vBB (array object) 2175 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2176 cmp r0, #0 @ null array object? 2177 beq common_errNullObject @ yes, bail 2178 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2179 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2180 cmp r1, r3 @ compare unsigned index, length 2181 bcs common_errArrayIndex @ index >= length, bail 2182 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2183 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2184 GET_INST_OPCODE(ip) @ extract opcode from rINST 2185 SET_VREG(r2, r9) @ vAA<- r2 2186 GOTO_OPCODE(ip) @ jump to next instruction 2187 2188 2189 2190/* ------------------------------ */ 2191 .balign 64 2192.L_OP_AGET_SHORT: /* 0x4a */ 2193/* File: armv5te/OP_AGET_SHORT.S */ 2194/* File: armv5te/OP_AGET.S */ 2195 /* 2196 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2197 * 2198 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2199 * instructions. We use a pair of FETCH_Bs instead. 2200 * 2201 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2202 */ 2203 /* op vAA, vBB, vCC */ 2204 FETCH_B(r2, 1, 0) @ r2<- BB 2205 mov r9, rINST, lsr #8 @ r9<- AA 2206 FETCH_B(r3, 1, 1) @ r3<- CC 2207 GET_VREG(r0, r2) @ r0<- vBB (array object) 2208 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2209 cmp r0, #0 @ null array object? 2210 beq common_errNullObject @ yes, bail 2211 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2212 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2213 cmp r1, r3 @ compare unsigned index, length 2214 bcs common_errArrayIndex @ index >= length, bail 2215 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2216 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2217 GET_INST_OPCODE(ip) @ extract opcode from rINST 2218 SET_VREG(r2, r9) @ vAA<- r2 2219 GOTO_OPCODE(ip) @ jump to next instruction 2220 2221 2222 2223/* ------------------------------ */ 2224 .balign 64 2225.L_OP_APUT: /* 0x4b */ 2226/* File: armv5te/OP_APUT.S */ 2227 /* 2228 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2229 * 2230 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2231 * instructions. We use a pair of FETCH_Bs instead. 2232 * 2233 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2234 */ 2235 /* op vAA, vBB, vCC */ 2236 FETCH_B(r2, 1, 0) @ r2<- BB 2237 mov r9, rINST, lsr #8 @ r9<- AA 2238 FETCH_B(r3, 1, 1) @ r3<- CC 2239 GET_VREG(r0, r2) @ r0<- vBB (array object) 2240 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2241 cmp r0, #0 @ null array object? 2242 beq common_errNullObject @ yes, bail 2243 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2244 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2245 cmp r1, r3 @ compare unsigned index, length 2246 bcs common_errArrayIndex @ index >= length, bail 2247 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2248 GET_VREG(r2, r9) @ r2<- vAA 2249 GET_INST_OPCODE(ip) @ extract opcode from rINST 2250 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2251 GOTO_OPCODE(ip) @ jump to next instruction 2252 2253 2254/* ------------------------------ */ 2255 .balign 64 2256.L_OP_APUT_WIDE: /* 0x4c */ 2257/* File: armv5te/OP_APUT_WIDE.S */ 2258 /* 2259 * Array put, 64 bits. vBB[vCC] <- vAA. 2260 * 2261 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2262 */ 2263 /* aput-wide vAA, vBB, vCC */ 2264 FETCH(r0, 1) @ r0<- CCBB 2265 mov r9, rINST, lsr #8 @ r9<- AA 2266 and r2, r0, #255 @ r2<- BB 2267 mov r3, r0, lsr #8 @ r3<- CC 2268 GET_VREG(r0, r2) @ r0<- vBB (array object) 2269 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2270 cmp r0, #0 @ null array object? 2271 beq common_errNullObject @ yes, bail 2272 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2273 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2274 cmp r1, r3 @ compare unsigned index, length 2275 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2276 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2277 b common_errArrayIndex @ index >= length, bail 2278 @ May want to swap the order of these two branches depending on how the 2279 @ branch prediction (if any) handles conditional forward branches vs. 2280 @ unconditional forward branches. 2281 2282/* ------------------------------ */ 2283 .balign 64 2284.L_OP_APUT_OBJECT: /* 0x4d */ 2285/* File: armv5te/OP_APUT_OBJECT.S */ 2286 /* 2287 * Store an object into an array. vBB[vCC] <- vAA. 2288 * 2289 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2290 * instructions. We use a pair of FETCH_Bs instead. 2291 */ 2292 /* op vAA, vBB, vCC */ 2293 FETCH(r0, 1) @ r0<- CCBB 2294 mov r9, rINST, lsr #8 @ r9<- AA 2295 and r2, r0, #255 @ r2<- BB 2296 mov r3, r0, lsr #8 @ r3<- CC 2297 GET_VREG(r1, r2) @ r1<- vBB (array object) 2298 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2299 cmp r1, #0 @ null array object? 2300 GET_VREG(r9, r9) @ r9<- vAA 2301 beq common_errNullObject @ yes, bail 2302 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2303 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2304 cmp r0, r3 @ compare unsigned index, length 2305 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2306 b common_errArrayIndex @ index >= length, bail 2307 2308 2309/* ------------------------------ */ 2310 .balign 64 2311.L_OP_APUT_BOOLEAN: /* 0x4e */ 2312/* File: armv5te/OP_APUT_BOOLEAN.S */ 2313/* File: armv5te/OP_APUT.S */ 2314 /* 2315 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2316 * 2317 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2318 * instructions. We use a pair of FETCH_Bs instead. 2319 * 2320 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2321 */ 2322 /* op vAA, vBB, vCC */ 2323 FETCH_B(r2, 1, 0) @ r2<- BB 2324 mov r9, rINST, lsr #8 @ r9<- AA 2325 FETCH_B(r3, 1, 1) @ r3<- CC 2326 GET_VREG(r0, r2) @ r0<- vBB (array object) 2327 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2328 cmp r0, #0 @ null array object? 2329 beq common_errNullObject @ yes, bail 2330 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2331 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2332 cmp r1, r3 @ compare unsigned index, length 2333 bcs common_errArrayIndex @ index >= length, bail 2334 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2335 GET_VREG(r2, r9) @ r2<- vAA 2336 GET_INST_OPCODE(ip) @ extract opcode from rINST 2337 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2338 GOTO_OPCODE(ip) @ jump to next instruction 2339 2340 2341 2342/* ------------------------------ */ 2343 .balign 64 2344.L_OP_APUT_BYTE: /* 0x4f */ 2345/* File: armv5te/OP_APUT_BYTE.S */ 2346/* File: armv5te/OP_APUT.S */ 2347 /* 2348 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2349 * 2350 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2351 * instructions. We use a pair of FETCH_Bs instead. 2352 * 2353 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2354 */ 2355 /* op vAA, vBB, vCC */ 2356 FETCH_B(r2, 1, 0) @ r2<- BB 2357 mov r9, rINST, lsr #8 @ r9<- AA 2358 FETCH_B(r3, 1, 1) @ r3<- CC 2359 GET_VREG(r0, r2) @ r0<- vBB (array object) 2360 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2361 cmp r0, #0 @ null array object? 2362 beq common_errNullObject @ yes, bail 2363 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2364 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2365 cmp r1, r3 @ compare unsigned index, length 2366 bcs common_errArrayIndex @ index >= length, bail 2367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2368 GET_VREG(r2, r9) @ r2<- vAA 2369 GET_INST_OPCODE(ip) @ extract opcode from rINST 2370 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2371 GOTO_OPCODE(ip) @ jump to next instruction 2372 2373 2374 2375/* ------------------------------ */ 2376 .balign 64 2377.L_OP_APUT_CHAR: /* 0x50 */ 2378/* File: armv5te/OP_APUT_CHAR.S */ 2379/* File: armv5te/OP_APUT.S */ 2380 /* 2381 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2382 * 2383 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2384 * instructions. We use a pair of FETCH_Bs instead. 2385 * 2386 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2387 */ 2388 /* op vAA, vBB, vCC */ 2389 FETCH_B(r2, 1, 0) @ r2<- BB 2390 mov r9, rINST, lsr #8 @ r9<- AA 2391 FETCH_B(r3, 1, 1) @ r3<- CC 2392 GET_VREG(r0, r2) @ r0<- vBB (array object) 2393 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2394 cmp r0, #0 @ null array object? 2395 beq common_errNullObject @ yes, bail 2396 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2397 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2398 cmp r1, r3 @ compare unsigned index, length 2399 bcs common_errArrayIndex @ index >= length, bail 2400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2401 GET_VREG(r2, r9) @ r2<- vAA 2402 GET_INST_OPCODE(ip) @ extract opcode from rINST 2403 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2404 GOTO_OPCODE(ip) @ jump to next instruction 2405 2406 2407 2408/* ------------------------------ */ 2409 .balign 64 2410.L_OP_APUT_SHORT: /* 0x51 */ 2411/* File: armv5te/OP_APUT_SHORT.S */ 2412/* File: armv5te/OP_APUT.S */ 2413 /* 2414 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2415 * 2416 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2417 * instructions. We use a pair of FETCH_Bs instead. 2418 * 2419 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2420 */ 2421 /* op vAA, vBB, vCC */ 2422 FETCH_B(r2, 1, 0) @ r2<- BB 2423 mov r9, rINST, lsr #8 @ r9<- AA 2424 FETCH_B(r3, 1, 1) @ r3<- CC 2425 GET_VREG(r0, r2) @ r0<- vBB (array object) 2426 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2427 cmp r0, #0 @ null array object? 2428 beq common_errNullObject @ yes, bail 2429 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2430 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2431 cmp r1, r3 @ compare unsigned index, length 2432 bcs common_errArrayIndex @ index >= length, bail 2433 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2434 GET_VREG(r2, r9) @ r2<- vAA 2435 GET_INST_OPCODE(ip) @ extract opcode from rINST 2436 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2437 GOTO_OPCODE(ip) @ jump to next instruction 2438 2439 2440 2441/* ------------------------------ */ 2442 .balign 64 2443.L_OP_IGET: /* 0x52 */ 2444/* File: armv5te/OP_IGET.S */ 2445 /* 2446 * General 32-bit instance field get. 2447 * 2448 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2449 */ 2450 /* op vA, vB, field@CCCC */ 2451 mov r0, rINST, lsr #12 @ r0<- B 2452 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2453 FETCH(r1, 1) @ r1<- field ref CCCC 2454 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2455 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2456 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2457 cmp r0, #0 @ is resolved entry null? 2458 bne .LOP_IGET_finish @ no, already resolved 24598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2460 EXPORT_PC() @ resolve() could throw 2461 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2462 bl dvmResolveInstField @ r0<- resolved InstField ptr 2463 cmp r0, #0 2464 bne .LOP_IGET_finish 2465 b common_exceptionThrown 2466 2467/* ------------------------------ */ 2468 .balign 64 2469.L_OP_IGET_WIDE: /* 0x53 */ 2470/* File: armv5te/OP_IGET_WIDE.S */ 2471 /* 2472 * Wide 32-bit instance field get. 2473 */ 2474 /* iget-wide vA, vB, field@CCCC */ 2475 mov r0, rINST, lsr #12 @ r0<- B 2476 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2477 FETCH(r1, 1) @ r1<- field ref CCCC 2478 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2479 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2480 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2481 cmp r0, #0 @ is resolved entry null? 2482 bne .LOP_IGET_WIDE_finish @ no, already resolved 24838: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2484 EXPORT_PC() @ resolve() could throw 2485 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2486 bl dvmResolveInstField @ r0<- resolved InstField ptr 2487 cmp r0, #0 2488 bne .LOP_IGET_WIDE_finish 2489 b common_exceptionThrown 2490 2491/* ------------------------------ */ 2492 .balign 64 2493.L_OP_IGET_OBJECT: /* 0x54 */ 2494/* File: armv5te/OP_IGET_OBJECT.S */ 2495/* File: armv5te/OP_IGET.S */ 2496 /* 2497 * General 32-bit instance field get. 2498 * 2499 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2500 */ 2501 /* op vA, vB, field@CCCC */ 2502 mov r0, rINST, lsr #12 @ r0<- B 2503 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2504 FETCH(r1, 1) @ r1<- field ref CCCC 2505 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2506 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2507 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2508 cmp r0, #0 @ is resolved entry null? 2509 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25108: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2511 EXPORT_PC() @ resolve() could throw 2512 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2513 bl dvmResolveInstField @ r0<- resolved InstField ptr 2514 cmp r0, #0 2515 bne .LOP_IGET_OBJECT_finish 2516 b common_exceptionThrown 2517 2518 2519/* ------------------------------ */ 2520 .balign 64 2521.L_OP_IGET_BOOLEAN: /* 0x55 */ 2522/* File: armv5te/OP_IGET_BOOLEAN.S */ 2523@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2524/* File: armv5te/OP_IGET.S */ 2525 /* 2526 * General 32-bit instance field get. 2527 * 2528 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2529 */ 2530 /* op vA, vB, field@CCCC */ 2531 mov r0, rINST, lsr #12 @ r0<- B 2532 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2533 FETCH(r1, 1) @ r1<- field ref CCCC 2534 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2535 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2536 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2537 cmp r0, #0 @ is resolved entry null? 2538 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2540 EXPORT_PC() @ resolve() could throw 2541 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2542 bl dvmResolveInstField @ r0<- resolved InstField ptr 2543 cmp r0, #0 2544 bne .LOP_IGET_BOOLEAN_finish 2545 b common_exceptionThrown 2546 2547 2548/* ------------------------------ */ 2549 .balign 64 2550.L_OP_IGET_BYTE: /* 0x56 */ 2551/* File: armv5te/OP_IGET_BYTE.S */ 2552@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2553/* File: armv5te/OP_IGET.S */ 2554 /* 2555 * General 32-bit instance field get. 2556 * 2557 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2558 */ 2559 /* op vA, vB, field@CCCC */ 2560 mov r0, rINST, lsr #12 @ r0<- B 2561 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2562 FETCH(r1, 1) @ r1<- field ref CCCC 2563 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2564 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2565 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2566 cmp r0, #0 @ is resolved entry null? 2567 bne .LOP_IGET_BYTE_finish @ no, already resolved 25688: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2569 EXPORT_PC() @ resolve() could throw 2570 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2571 bl dvmResolveInstField @ r0<- resolved InstField ptr 2572 cmp r0, #0 2573 bne .LOP_IGET_BYTE_finish 2574 b common_exceptionThrown 2575 2576 2577/* ------------------------------ */ 2578 .balign 64 2579.L_OP_IGET_CHAR: /* 0x57 */ 2580/* File: armv5te/OP_IGET_CHAR.S */ 2581@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2582/* File: armv5te/OP_IGET.S */ 2583 /* 2584 * General 32-bit instance field get. 2585 * 2586 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2587 */ 2588 /* op vA, vB, field@CCCC */ 2589 mov r0, rINST, lsr #12 @ r0<- B 2590 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2591 FETCH(r1, 1) @ r1<- field ref CCCC 2592 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2593 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2594 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2595 cmp r0, #0 @ is resolved entry null? 2596 bne .LOP_IGET_CHAR_finish @ no, already resolved 25978: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2598 EXPORT_PC() @ resolve() could throw 2599 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2600 bl dvmResolveInstField @ r0<- resolved InstField ptr 2601 cmp r0, #0 2602 bne .LOP_IGET_CHAR_finish 2603 b common_exceptionThrown 2604 2605 2606/* ------------------------------ */ 2607 .balign 64 2608.L_OP_IGET_SHORT: /* 0x58 */ 2609/* File: armv5te/OP_IGET_SHORT.S */ 2610@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2611/* File: armv5te/OP_IGET.S */ 2612 /* 2613 * General 32-bit instance field get. 2614 * 2615 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2616 */ 2617 /* op vA, vB, field@CCCC */ 2618 mov r0, rINST, lsr #12 @ r0<- B 2619 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2620 FETCH(r1, 1) @ r1<- field ref CCCC 2621 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2622 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2623 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2624 cmp r0, #0 @ is resolved entry null? 2625 bne .LOP_IGET_SHORT_finish @ no, already resolved 26268: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2627 EXPORT_PC() @ resolve() could throw 2628 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2629 bl dvmResolveInstField @ r0<- resolved InstField ptr 2630 cmp r0, #0 2631 bne .LOP_IGET_SHORT_finish 2632 b common_exceptionThrown 2633 2634 2635/* ------------------------------ */ 2636 .balign 64 2637.L_OP_IPUT: /* 0x59 */ 2638/* File: armv5te/OP_IPUT.S */ 2639 /* 2640 * General 32-bit instance field put. 2641 * 2642 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2643 */ 2644 /* op vA, vB, field@CCCC */ 2645 mov r0, rINST, lsr #12 @ r0<- B 2646 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2647 FETCH(r1, 1) @ r1<- field ref CCCC 2648 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2649 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2650 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2651 cmp r0, #0 @ is resolved entry null? 2652 bne .LOP_IPUT_finish @ no, already resolved 26538: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2654 EXPORT_PC() @ resolve() could throw 2655 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2656 bl dvmResolveInstField @ r0<- resolved InstField ptr 2657 cmp r0, #0 @ success? 2658 bne .LOP_IPUT_finish @ yes, finish up 2659 b common_exceptionThrown 2660 2661/* ------------------------------ */ 2662 .balign 64 2663.L_OP_IPUT_WIDE: /* 0x5a */ 2664/* File: armv5te/OP_IPUT_WIDE.S */ 2665 /* iput-wide vA, vB, field@CCCC */ 2666 mov r0, rINST, lsr #12 @ r0<- B 2667 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2668 FETCH(r1, 1) @ r1<- field ref CCCC 2669 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2670 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2671 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2672 cmp r0, #0 @ is resolved entry null? 2673 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26748: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2675 EXPORT_PC() @ resolve() could throw 2676 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2677 bl dvmResolveInstField @ r0<- resolved InstField ptr 2678 cmp r0, #0 @ success? 2679 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2680 b common_exceptionThrown 2681 2682/* ------------------------------ */ 2683 .balign 64 2684.L_OP_IPUT_OBJECT: /* 0x5b */ 2685/* File: armv5te/OP_IPUT_OBJECT.S */ 2686/* File: armv5te/OP_IPUT.S */ 2687 /* 2688 * General 32-bit instance field put. 2689 * 2690 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2691 */ 2692 /* op vA, vB, field@CCCC */ 2693 mov r0, rINST, lsr #12 @ r0<- B 2694 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2695 FETCH(r1, 1) @ r1<- field ref CCCC 2696 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2697 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2698 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2699 cmp r0, #0 @ is resolved entry null? 2700 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27018: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2702 EXPORT_PC() @ resolve() could throw 2703 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2704 bl dvmResolveInstField @ r0<- resolved InstField ptr 2705 cmp r0, #0 @ success? 2706 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2707 b common_exceptionThrown 2708 2709 2710/* ------------------------------ */ 2711 .balign 64 2712.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2713/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2714@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2715/* File: armv5te/OP_IPUT.S */ 2716 /* 2717 * General 32-bit instance field put. 2718 * 2719 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2720 */ 2721 /* op vA, vB, field@CCCC */ 2722 mov r0, rINST, lsr #12 @ r0<- B 2723 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2724 FETCH(r1, 1) @ r1<- field ref CCCC 2725 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2726 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2727 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2728 cmp r0, #0 @ is resolved entry null? 2729 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27308: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2731 EXPORT_PC() @ resolve() could throw 2732 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2733 bl dvmResolveInstField @ r0<- resolved InstField ptr 2734 cmp r0, #0 @ success? 2735 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2736 b common_exceptionThrown 2737 2738 2739/* ------------------------------ */ 2740 .balign 64 2741.L_OP_IPUT_BYTE: /* 0x5d */ 2742/* File: armv5te/OP_IPUT_BYTE.S */ 2743@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2744/* File: armv5te/OP_IPUT.S */ 2745 /* 2746 * General 32-bit instance field put. 2747 * 2748 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2749 */ 2750 /* op vA, vB, field@CCCC */ 2751 mov r0, rINST, lsr #12 @ r0<- B 2752 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2753 FETCH(r1, 1) @ r1<- field ref CCCC 2754 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2755 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2756 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2757 cmp r0, #0 @ is resolved entry null? 2758 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2760 EXPORT_PC() @ resolve() could throw 2761 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2762 bl dvmResolveInstField @ r0<- resolved InstField ptr 2763 cmp r0, #0 @ success? 2764 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2765 b common_exceptionThrown 2766 2767 2768/* ------------------------------ */ 2769 .balign 64 2770.L_OP_IPUT_CHAR: /* 0x5e */ 2771/* File: armv5te/OP_IPUT_CHAR.S */ 2772@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2773/* File: armv5te/OP_IPUT.S */ 2774 /* 2775 * General 32-bit instance field put. 2776 * 2777 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2778 */ 2779 /* op vA, vB, field@CCCC */ 2780 mov r0, rINST, lsr #12 @ r0<- B 2781 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2782 FETCH(r1, 1) @ r1<- field ref CCCC 2783 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2784 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2785 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2786 cmp r0, #0 @ is resolved entry null? 2787 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27888: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2789 EXPORT_PC() @ resolve() could throw 2790 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2791 bl dvmResolveInstField @ r0<- resolved InstField ptr 2792 cmp r0, #0 @ success? 2793 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2794 b common_exceptionThrown 2795 2796 2797/* ------------------------------ */ 2798 .balign 64 2799.L_OP_IPUT_SHORT: /* 0x5f */ 2800/* File: armv5te/OP_IPUT_SHORT.S */ 2801@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2802/* File: armv5te/OP_IPUT.S */ 2803 /* 2804 * General 32-bit instance field put. 2805 * 2806 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2807 */ 2808 /* op vA, vB, field@CCCC */ 2809 mov r0, rINST, lsr #12 @ r0<- B 2810 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2811 FETCH(r1, 1) @ r1<- field ref CCCC 2812 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2813 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2814 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2815 cmp r0, #0 @ is resolved entry null? 2816 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28178: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2818 EXPORT_PC() @ resolve() could throw 2819 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2820 bl dvmResolveInstField @ r0<- resolved InstField ptr 2821 cmp r0, #0 @ success? 2822 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2823 b common_exceptionThrown 2824 2825 2826/* ------------------------------ */ 2827 .balign 64 2828.L_OP_SGET: /* 0x60 */ 2829/* File: armv5te/OP_SGET.S */ 2830 /* 2831 * General 32-bit SGET handler. 2832 * 2833 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2834 */ 2835 /* op vAA, field@BBBB */ 2836 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2837 FETCH(r1, 1) @ r1<- field ref BBBB 2838 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2839 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2840 cmp r0, #0 @ is resolved entry null? 2841 beq .LOP_SGET_resolve @ yes, do resolve 2842.LOP_SGET_finish: @ field ptr in r0 2843 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2844 mov r2, rINST, lsr #8 @ r2<- AA 2845 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2846 SET_VREG(r1, r2) @ fp[AA]<- r1 2847 GET_INST_OPCODE(ip) @ extract opcode from rINST 2848 GOTO_OPCODE(ip) @ jump to next instruction 2849 2850/* ------------------------------ */ 2851 .balign 64 2852.L_OP_SGET_WIDE: /* 0x61 */ 2853/* File: armv5te/OP_SGET_WIDE.S */ 2854 /* 2855 * 64-bit SGET handler. 2856 */ 2857 /* sget-wide vAA, field@BBBB */ 2858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2859 FETCH(r1, 1) @ r1<- field ref BBBB 2860 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2861 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2862 cmp r0, #0 @ is resolved entry null? 2863 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2864.LOP_SGET_WIDE_finish: 2865 mov r1, rINST, lsr #8 @ r1<- AA 2866 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2867 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2868 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2869 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2870 GET_INST_OPCODE(ip) @ extract opcode from rINST 2871 GOTO_OPCODE(ip) @ jump to next instruction 2872 2873/* ------------------------------ */ 2874 .balign 64 2875.L_OP_SGET_OBJECT: /* 0x62 */ 2876/* File: armv5te/OP_SGET_OBJECT.S */ 2877/* File: armv5te/OP_SGET.S */ 2878 /* 2879 * General 32-bit SGET handler. 2880 * 2881 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2882 */ 2883 /* op vAA, field@BBBB */ 2884 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2885 FETCH(r1, 1) @ r1<- field ref BBBB 2886 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2887 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2888 cmp r0, #0 @ is resolved entry null? 2889 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2890.LOP_SGET_OBJECT_finish: @ field ptr in r0 2891 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2892 mov r2, rINST, lsr #8 @ r2<- AA 2893 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2894 SET_VREG(r1, r2) @ fp[AA]<- r1 2895 GET_INST_OPCODE(ip) @ extract opcode from rINST 2896 GOTO_OPCODE(ip) @ jump to next instruction 2897 2898 2899/* ------------------------------ */ 2900 .balign 64 2901.L_OP_SGET_BOOLEAN: /* 0x63 */ 2902/* File: armv5te/OP_SGET_BOOLEAN.S */ 2903/* File: armv5te/OP_SGET.S */ 2904 /* 2905 * General 32-bit SGET handler. 2906 * 2907 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2908 */ 2909 /* op vAA, field@BBBB */ 2910 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2911 FETCH(r1, 1) @ r1<- field ref BBBB 2912 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2913 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2914 cmp r0, #0 @ is resolved entry null? 2915 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2916.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2917 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2918 mov r2, rINST, lsr #8 @ r2<- AA 2919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2920 SET_VREG(r1, r2) @ fp[AA]<- r1 2921 GET_INST_OPCODE(ip) @ extract opcode from rINST 2922 GOTO_OPCODE(ip) @ jump to next instruction 2923 2924 2925/* ------------------------------ */ 2926 .balign 64 2927.L_OP_SGET_BYTE: /* 0x64 */ 2928/* File: armv5te/OP_SGET_BYTE.S */ 2929/* File: armv5te/OP_SGET.S */ 2930 /* 2931 * General 32-bit SGET handler. 2932 * 2933 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2934 */ 2935 /* op vAA, field@BBBB */ 2936 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2937 FETCH(r1, 1) @ r1<- field ref BBBB 2938 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2939 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2940 cmp r0, #0 @ is resolved entry null? 2941 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2942.LOP_SGET_BYTE_finish: @ field ptr in r0 2943 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2944 mov r2, rINST, lsr #8 @ r2<- AA 2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2946 SET_VREG(r1, r2) @ fp[AA]<- r1 2947 GET_INST_OPCODE(ip) @ extract opcode from rINST 2948 GOTO_OPCODE(ip) @ jump to next instruction 2949 2950 2951/* ------------------------------ */ 2952 .balign 64 2953.L_OP_SGET_CHAR: /* 0x65 */ 2954/* File: armv5te/OP_SGET_CHAR.S */ 2955/* File: armv5te/OP_SGET.S */ 2956 /* 2957 * General 32-bit SGET handler. 2958 * 2959 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2960 */ 2961 /* op vAA, field@BBBB */ 2962 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2963 FETCH(r1, 1) @ r1<- field ref BBBB 2964 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2965 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2966 cmp r0, #0 @ is resolved entry null? 2967 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2968.LOP_SGET_CHAR_finish: @ field ptr in r0 2969 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2970 mov r2, rINST, lsr #8 @ r2<- AA 2971 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2972 SET_VREG(r1, r2) @ fp[AA]<- r1 2973 GET_INST_OPCODE(ip) @ extract opcode from rINST 2974 GOTO_OPCODE(ip) @ jump to next instruction 2975 2976 2977/* ------------------------------ */ 2978 .balign 64 2979.L_OP_SGET_SHORT: /* 0x66 */ 2980/* File: armv5te/OP_SGET_SHORT.S */ 2981/* File: armv5te/OP_SGET.S */ 2982 /* 2983 * General 32-bit SGET handler. 2984 * 2985 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2986 */ 2987 /* op vAA, field@BBBB */ 2988 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2989 FETCH(r1, 1) @ r1<- field ref BBBB 2990 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2991 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2992 cmp r0, #0 @ is resolved entry null? 2993 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2994.LOP_SGET_SHORT_finish: @ field ptr in r0 2995 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2996 mov r2, rINST, lsr #8 @ r2<- AA 2997 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2998 SET_VREG(r1, r2) @ fp[AA]<- r1 2999 GET_INST_OPCODE(ip) @ extract opcode from rINST 3000 GOTO_OPCODE(ip) @ jump to next instruction 3001 3002 3003/* ------------------------------ */ 3004 .balign 64 3005.L_OP_SPUT: /* 0x67 */ 3006/* File: armv5te/OP_SPUT.S */ 3007 /* 3008 * General 32-bit SPUT handler. 3009 * 3010 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3011 */ 3012 /* op vAA, field@BBBB */ 3013 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3014 FETCH(r1, 1) @ r1<- field ref BBBB 3015 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3016 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3017 cmp r0, #0 @ is resolved entry null? 3018 beq .LOP_SPUT_resolve @ yes, do resolve 3019.LOP_SPUT_finish: @ field ptr in r0 3020 mov r2, rINST, lsr #8 @ r2<- AA 3021 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3022 GET_VREG(r1, r2) @ r1<- fp[AA] 3023 GET_INST_OPCODE(ip) @ extract opcode from rINST 3024 str r1, [r0, #offStaticField_value] @ field<- vAA 3025 GOTO_OPCODE(ip) @ jump to next instruction 3026 3027/* ------------------------------ */ 3028 .balign 64 3029.L_OP_SPUT_WIDE: /* 0x68 */ 3030/* File: armv5te/OP_SPUT_WIDE.S */ 3031 /* 3032 * 64-bit SPUT handler. 3033 */ 3034 /* sput-wide vAA, field@BBBB */ 3035 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3036 FETCH(r1, 1) @ r1<- field ref BBBB 3037 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3038 mov r9, rINST, lsr #8 @ r9<- AA 3039 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3040 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3041 cmp r0, #0 @ is resolved entry null? 3042 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3043.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3044 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3045 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3046 GET_INST_OPCODE(ip) @ extract opcode from rINST 3047 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3048 GOTO_OPCODE(ip) @ jump to next instruction 3049 3050/* ------------------------------ */ 3051 .balign 64 3052.L_OP_SPUT_OBJECT: /* 0x69 */ 3053/* File: armv5te/OP_SPUT_OBJECT.S */ 3054/* File: armv5te/OP_SPUT.S */ 3055 /* 3056 * General 32-bit SPUT handler. 3057 * 3058 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3059 */ 3060 /* op vAA, field@BBBB */ 3061 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3062 FETCH(r1, 1) @ r1<- field ref BBBB 3063 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3064 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3065 cmp r0, #0 @ is resolved entry null? 3066 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3067.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3068 mov r2, rINST, lsr #8 @ r2<- AA 3069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3070 GET_VREG(r1, r2) @ r1<- fp[AA] 3071 GET_INST_OPCODE(ip) @ extract opcode from rINST 3072 str r1, [r0, #offStaticField_value] @ field<- vAA 3073 GOTO_OPCODE(ip) @ jump to next instruction 3074 3075 3076/* ------------------------------ */ 3077 .balign 64 3078.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3079/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3080/* File: armv5te/OP_SPUT.S */ 3081 /* 3082 * General 32-bit SPUT handler. 3083 * 3084 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3085 */ 3086 /* op vAA, field@BBBB */ 3087 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3088 FETCH(r1, 1) @ r1<- field ref BBBB 3089 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3090 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3091 cmp r0, #0 @ is resolved entry null? 3092 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3093.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3094 mov r2, rINST, lsr #8 @ r2<- AA 3095 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3096 GET_VREG(r1, r2) @ r1<- fp[AA] 3097 GET_INST_OPCODE(ip) @ extract opcode from rINST 3098 str r1, [r0, #offStaticField_value] @ field<- vAA 3099 GOTO_OPCODE(ip) @ jump to next instruction 3100 3101 3102/* ------------------------------ */ 3103 .balign 64 3104.L_OP_SPUT_BYTE: /* 0x6b */ 3105/* File: armv5te/OP_SPUT_BYTE.S */ 3106/* File: armv5te/OP_SPUT.S */ 3107 /* 3108 * General 32-bit SPUT handler. 3109 * 3110 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3111 */ 3112 /* op vAA, field@BBBB */ 3113 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3114 FETCH(r1, 1) @ r1<- field ref BBBB 3115 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3116 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3117 cmp r0, #0 @ is resolved entry null? 3118 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3119.LOP_SPUT_BYTE_finish: @ field ptr in r0 3120 mov r2, rINST, lsr #8 @ r2<- AA 3121 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3122 GET_VREG(r1, r2) @ r1<- fp[AA] 3123 GET_INST_OPCODE(ip) @ extract opcode from rINST 3124 str r1, [r0, #offStaticField_value] @ field<- vAA 3125 GOTO_OPCODE(ip) @ jump to next instruction 3126 3127 3128/* ------------------------------ */ 3129 .balign 64 3130.L_OP_SPUT_CHAR: /* 0x6c */ 3131/* File: armv5te/OP_SPUT_CHAR.S */ 3132/* File: armv5te/OP_SPUT.S */ 3133 /* 3134 * General 32-bit SPUT handler. 3135 * 3136 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3137 */ 3138 /* op vAA, field@BBBB */ 3139 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3140 FETCH(r1, 1) @ r1<- field ref BBBB 3141 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3142 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3143 cmp r0, #0 @ is resolved entry null? 3144 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3145.LOP_SPUT_CHAR_finish: @ field ptr in r0 3146 mov r2, rINST, lsr #8 @ r2<- AA 3147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3148 GET_VREG(r1, r2) @ r1<- fp[AA] 3149 GET_INST_OPCODE(ip) @ extract opcode from rINST 3150 str r1, [r0, #offStaticField_value] @ field<- vAA 3151 GOTO_OPCODE(ip) @ jump to next instruction 3152 3153 3154/* ------------------------------ */ 3155 .balign 64 3156.L_OP_SPUT_SHORT: /* 0x6d */ 3157/* File: armv5te/OP_SPUT_SHORT.S */ 3158/* File: armv5te/OP_SPUT.S */ 3159 /* 3160 * General 32-bit SPUT handler. 3161 * 3162 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3163 */ 3164 /* op vAA, field@BBBB */ 3165 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3166 FETCH(r1, 1) @ r1<- field ref BBBB 3167 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3168 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3169 cmp r0, #0 @ is resolved entry null? 3170 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3171.LOP_SPUT_SHORT_finish: @ field ptr in r0 3172 mov r2, rINST, lsr #8 @ r2<- AA 3173 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3174 GET_VREG(r1, r2) @ r1<- fp[AA] 3175 GET_INST_OPCODE(ip) @ extract opcode from rINST 3176 str r1, [r0, #offStaticField_value] @ field<- vAA 3177 GOTO_OPCODE(ip) @ jump to next instruction 3178 3179 3180/* ------------------------------ */ 3181 .balign 64 3182.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3183/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3184 /* 3185 * Handle a virtual method call. 3186 * 3187 * for: invoke-virtual, invoke-virtual/range 3188 */ 3189 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3190 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3191 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3192 FETCH(r1, 1) @ r1<- BBBB 3193 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3194 FETCH(r10, 2) @ r10<- GFED or CCCC 3195 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3196 .if (!0) 3197 and r10, r10, #15 @ r10<- D (or stays CCCC) 3198 .endif 3199 cmp r0, #0 @ already resolved? 3200 EXPORT_PC() @ must export for invoke 3201 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3202 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3203 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3204 mov r2, #METHOD_VIRTUAL @ resolver method type 3205 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3206 cmp r0, #0 @ got null? 3207 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3208 b common_exceptionThrown @ yes, handle exception 3209 3210/* ------------------------------ */ 3211 .balign 64 3212.L_OP_INVOKE_SUPER: /* 0x6f */ 3213/* File: armv5te/OP_INVOKE_SUPER.S */ 3214 /* 3215 * Handle a "super" method call. 3216 * 3217 * for: invoke-super, invoke-super/range 3218 */ 3219 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3220 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3221 FETCH(r10, 2) @ r10<- GFED or CCCC 3222 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3223 .if (!0) 3224 and r10, r10, #15 @ r10<- D (or stays CCCC) 3225 .endif 3226 FETCH(r1, 1) @ r1<- BBBB 3227 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3228 GET_VREG(r2, r10) @ r2<- "this" ptr 3229 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3230 cmp r2, #0 @ null "this"? 3231 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3232 beq common_errNullObject @ null "this", throw exception 3233 cmp r0, #0 @ already resolved? 3234 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3235 EXPORT_PC() @ must export for invoke 3236 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3237 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3238 3239/* ------------------------------ */ 3240 .balign 64 3241.L_OP_INVOKE_DIRECT: /* 0x70 */ 3242/* File: armv5te/OP_INVOKE_DIRECT.S */ 3243 /* 3244 * Handle a direct method call. 3245 * 3246 * (We could defer the "is 'this' pointer null" test to the common 3247 * method invocation code, and use a flag to indicate that static 3248 * calls don't count. If we do this as part of copying the arguments 3249 * out we could avoiding loading the first arg twice.) 3250 * 3251 * for: invoke-direct, invoke-direct/range 3252 */ 3253 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3254 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3255 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3256 FETCH(r1, 1) @ r1<- BBBB 3257 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3258 FETCH(r10, 2) @ r10<- GFED or CCCC 3259 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3260 .if (!0) 3261 and r10, r10, #15 @ r10<- D (or stays CCCC) 3262 .endif 3263 cmp r0, #0 @ already resolved? 3264 EXPORT_PC() @ must export for invoke 3265 GET_VREG(r2, r10) @ r2<- "this" ptr 3266 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3267.LOP_INVOKE_DIRECT_finish: 3268 cmp r2, #0 @ null "this" ref? 3269 bne common_invokeMethodNoRange @ no, continue on 3270 b common_errNullObject @ yes, throw exception 3271 3272/* ------------------------------ */ 3273 .balign 64 3274.L_OP_INVOKE_STATIC: /* 0x71 */ 3275/* File: armv5te/OP_INVOKE_STATIC.S */ 3276 /* 3277 * Handle a static method call. 3278 * 3279 * for: invoke-static, invoke-static/range 3280 */ 3281 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3282 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3283 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3284 FETCH(r1, 1) @ r1<- BBBB 3285 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3286 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3287 cmp r0, #0 @ already resolved? 3288 EXPORT_PC() @ must export for invoke 3289 bne common_invokeMethodNoRange @ yes, continue on 32900: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3291 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3292 mov r2, #METHOD_STATIC @ resolver method type 3293 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3294 cmp r0, #0 @ got null? 3295 bne common_invokeMethodNoRange @ no, continue 3296 b common_exceptionThrown @ yes, handle exception 3297 3298 3299/* ------------------------------ */ 3300 .balign 64 3301.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3302/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3303 /* 3304 * Handle an interface method call. 3305 * 3306 * for: invoke-interface, invoke-interface/range 3307 */ 3308 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3309 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3310 FETCH(r2, 2) @ r2<- FEDC or CCCC 3311 FETCH(r1, 1) @ r1<- BBBB 3312 .if (!0) 3313 and r2, r2, #15 @ r2<- C (or stays CCCC) 3314 .endif 3315 EXPORT_PC() @ must export for invoke 3316 GET_VREG(r0, r2) @ r0<- first arg ("this") 3317 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3318 cmp r0, #0 @ null obj? 3319 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3320 beq common_errNullObject @ yes, fail 3321 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3322 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3323 cmp r0, #0 @ failed? 3324 beq common_exceptionThrown @ yes, handle exception 3325 b common_invokeMethodNoRange @ jump to common handler 3326 3327 3328/* ------------------------------ */ 3329 .balign 64 3330.L_OP_UNUSED_73: /* 0x73 */ 3331/* File: armv5te/OP_UNUSED_73.S */ 3332/* File: armv5te/unused.S */ 3333 bl common_abort 3334 3335 3336 3337/* ------------------------------ */ 3338 .balign 64 3339.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3340/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3341/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3342 /* 3343 * Handle a virtual method call. 3344 * 3345 * for: invoke-virtual, invoke-virtual/range 3346 */ 3347 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3348 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3349 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3350 FETCH(r1, 1) @ r1<- BBBB 3351 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3352 FETCH(r10, 2) @ r10<- GFED or CCCC 3353 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3354 .if (!1) 3355 and r10, r10, #15 @ r10<- D (or stays CCCC) 3356 .endif 3357 cmp r0, #0 @ already resolved? 3358 EXPORT_PC() @ must export for invoke 3359 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3360 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3361 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3362 mov r2, #METHOD_VIRTUAL @ resolver method type 3363 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3364 cmp r0, #0 @ got null? 3365 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3366 b common_exceptionThrown @ yes, handle exception 3367 3368 3369/* ------------------------------ */ 3370 .balign 64 3371.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3372/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3373/* File: armv5te/OP_INVOKE_SUPER.S */ 3374 /* 3375 * Handle a "super" method call. 3376 * 3377 * for: invoke-super, invoke-super/range 3378 */ 3379 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3380 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3381 FETCH(r10, 2) @ r10<- GFED or CCCC 3382 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3383 .if (!1) 3384 and r10, r10, #15 @ r10<- D (or stays CCCC) 3385 .endif 3386 FETCH(r1, 1) @ r1<- BBBB 3387 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3388 GET_VREG(r2, r10) @ r2<- "this" ptr 3389 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3390 cmp r2, #0 @ null "this"? 3391 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3392 beq common_errNullObject @ null "this", throw exception 3393 cmp r0, #0 @ already resolved? 3394 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3395 EXPORT_PC() @ must export for invoke 3396 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3397 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3398 3399 3400/* ------------------------------ */ 3401 .balign 64 3402.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3403/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3404/* File: armv5te/OP_INVOKE_DIRECT.S */ 3405 /* 3406 * Handle a direct method call. 3407 * 3408 * (We could defer the "is 'this' pointer null" test to the common 3409 * method invocation code, and use a flag to indicate that static 3410 * calls don't count. If we do this as part of copying the arguments 3411 * out we could avoiding loading the first arg twice.) 3412 * 3413 * for: invoke-direct, invoke-direct/range 3414 */ 3415 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3416 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3417 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3418 FETCH(r1, 1) @ r1<- BBBB 3419 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3420 FETCH(r10, 2) @ r10<- GFED or CCCC 3421 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3422 .if (!1) 3423 and r10, r10, #15 @ r10<- D (or stays CCCC) 3424 .endif 3425 cmp r0, #0 @ already resolved? 3426 EXPORT_PC() @ must export for invoke 3427 GET_VREG(r2, r10) @ r2<- "this" ptr 3428 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3429.LOP_INVOKE_DIRECT_RANGE_finish: 3430 cmp r2, #0 @ null "this" ref? 3431 bne common_invokeMethodRange @ no, continue on 3432 b common_errNullObject @ yes, throw exception 3433 3434 3435/* ------------------------------ */ 3436 .balign 64 3437.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3438/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3439/* File: armv5te/OP_INVOKE_STATIC.S */ 3440 /* 3441 * Handle a static method call. 3442 * 3443 * for: invoke-static, invoke-static/range 3444 */ 3445 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3446 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3447 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3448 FETCH(r1, 1) @ r1<- BBBB 3449 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3450 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3451 cmp r0, #0 @ already resolved? 3452 EXPORT_PC() @ must export for invoke 3453 bne common_invokeMethodRange @ yes, continue on 34540: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3455 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3456 mov r2, #METHOD_STATIC @ resolver method type 3457 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3458 cmp r0, #0 @ got null? 3459 bne common_invokeMethodRange @ no, continue 3460 b common_exceptionThrown @ yes, handle exception 3461 3462 3463 3464/* ------------------------------ */ 3465 .balign 64 3466.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3467/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3468/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3469 /* 3470 * Handle an interface method call. 3471 * 3472 * for: invoke-interface, invoke-interface/range 3473 */ 3474 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3475 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3476 FETCH(r2, 2) @ r2<- FEDC or CCCC 3477 FETCH(r1, 1) @ r1<- BBBB 3478 .if (!1) 3479 and r2, r2, #15 @ r2<- C (or stays CCCC) 3480 .endif 3481 EXPORT_PC() @ must export for invoke 3482 GET_VREG(r0, r2) @ r0<- first arg ("this") 3483 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3484 cmp r0, #0 @ null obj? 3485 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3486 beq common_errNullObject @ yes, fail 3487 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3488 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3489 cmp r0, #0 @ failed? 3490 beq common_exceptionThrown @ yes, handle exception 3491 b common_invokeMethodRange @ jump to common handler 3492 3493 3494 3495/* ------------------------------ */ 3496 .balign 64 3497.L_OP_UNUSED_79: /* 0x79 */ 3498/* File: armv5te/OP_UNUSED_79.S */ 3499/* File: armv5te/unused.S */ 3500 bl common_abort 3501 3502 3503 3504/* ------------------------------ */ 3505 .balign 64 3506.L_OP_UNUSED_7A: /* 0x7a */ 3507/* File: armv5te/OP_UNUSED_7A.S */ 3508/* File: armv5te/unused.S */ 3509 bl common_abort 3510 3511 3512 3513/* ------------------------------ */ 3514 .balign 64 3515.L_OP_NEG_INT: /* 0x7b */ 3516/* File: armv5te/OP_NEG_INT.S */ 3517/* File: armv5te/unop.S */ 3518 /* 3519 * Generic 32-bit unary operation. Provide an "instr" line that 3520 * specifies an instruction that performs "result = op r0". 3521 * This could be an ARM instruction or a function call. 3522 * 3523 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3524 * int-to-byte, int-to-char, int-to-short 3525 */ 3526 /* unop vA, vB */ 3527 mov r3, rINST, lsr #12 @ r3<- B 3528 mov r9, rINST, lsr #8 @ r9<- A+ 3529 GET_VREG(r0, r3) @ r0<- vB 3530 and r9, r9, #15 3531 @ optional op; may set condition codes 3532 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3533 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3534 GET_INST_OPCODE(ip) @ extract opcode from rINST 3535 SET_VREG(r0, r9) @ vAA<- r0 3536 GOTO_OPCODE(ip) @ jump to next instruction 3537 /* 9-10 instructions */ 3538 3539 3540/* ------------------------------ */ 3541 .balign 64 3542.L_OP_NOT_INT: /* 0x7c */ 3543/* File: armv5te/OP_NOT_INT.S */ 3544/* File: armv5te/unop.S */ 3545 /* 3546 * Generic 32-bit unary operation. Provide an "instr" line that 3547 * specifies an instruction that performs "result = op r0". 3548 * This could be an ARM instruction or a function call. 3549 * 3550 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3551 * int-to-byte, int-to-char, int-to-short 3552 */ 3553 /* unop vA, vB */ 3554 mov r3, rINST, lsr #12 @ r3<- B 3555 mov r9, rINST, lsr #8 @ r9<- A+ 3556 GET_VREG(r0, r3) @ r0<- vB 3557 and r9, r9, #15 3558 @ optional op; may set condition codes 3559 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3560 mvn r0, r0 @ r0<- op, r0-r3 changed 3561 GET_INST_OPCODE(ip) @ extract opcode from rINST 3562 SET_VREG(r0, r9) @ vAA<- r0 3563 GOTO_OPCODE(ip) @ jump to next instruction 3564 /* 9-10 instructions */ 3565 3566 3567/* ------------------------------ */ 3568 .balign 64 3569.L_OP_NEG_LONG: /* 0x7d */ 3570/* File: armv5te/OP_NEG_LONG.S */ 3571/* File: armv5te/unopWide.S */ 3572 /* 3573 * Generic 64-bit unary operation. Provide an "instr" line that 3574 * specifies an instruction that performs "result = op r0/r1". 3575 * This could be an ARM instruction or a function call. 3576 * 3577 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3578 */ 3579 /* unop vA, vB */ 3580 mov r9, rINST, lsr #8 @ r9<- A+ 3581 mov r3, rINST, lsr #12 @ r3<- B 3582 and r9, r9, #15 3583 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3584 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3585 ldmia r3, {r0-r1} @ r0/r1<- vAA 3586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3587 rsbs r0, r0, #0 @ optional op; may set condition codes 3588 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3589 GET_INST_OPCODE(ip) @ extract opcode from rINST 3590 stmia r9, {r0-r1} @ vAA<- r0/r1 3591 GOTO_OPCODE(ip) @ jump to next instruction 3592 /* 12-13 instructions */ 3593 3594 3595 3596/* ------------------------------ */ 3597 .balign 64 3598.L_OP_NOT_LONG: /* 0x7e */ 3599/* File: armv5te/OP_NOT_LONG.S */ 3600/* File: armv5te/unopWide.S */ 3601 /* 3602 * Generic 64-bit unary operation. Provide an "instr" line that 3603 * specifies an instruction that performs "result = op r0/r1". 3604 * This could be an ARM instruction or a function call. 3605 * 3606 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3607 */ 3608 /* unop vA, vB */ 3609 mov r9, rINST, lsr #8 @ r9<- A+ 3610 mov r3, rINST, lsr #12 @ r3<- B 3611 and r9, r9, #15 3612 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3613 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3614 ldmia r3, {r0-r1} @ r0/r1<- vAA 3615 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3616 mvn r0, r0 @ optional op; may set condition codes 3617 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3618 GET_INST_OPCODE(ip) @ extract opcode from rINST 3619 stmia r9, {r0-r1} @ vAA<- r0/r1 3620 GOTO_OPCODE(ip) @ jump to next instruction 3621 /* 12-13 instructions */ 3622 3623 3624 3625/* ------------------------------ */ 3626 .balign 64 3627.L_OP_NEG_FLOAT: /* 0x7f */ 3628/* File: armv5te/OP_NEG_FLOAT.S */ 3629/* File: armv5te/unop.S */ 3630 /* 3631 * Generic 32-bit unary operation. Provide an "instr" line that 3632 * specifies an instruction that performs "result = op r0". 3633 * This could be an ARM instruction or a function call. 3634 * 3635 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3636 * int-to-byte, int-to-char, int-to-short 3637 */ 3638 /* unop vA, vB */ 3639 mov r3, rINST, lsr #12 @ r3<- B 3640 mov r9, rINST, lsr #8 @ r9<- A+ 3641 GET_VREG(r0, r3) @ r0<- vB 3642 and r9, r9, #15 3643 @ optional op; may set condition codes 3644 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3645 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3646 GET_INST_OPCODE(ip) @ extract opcode from rINST 3647 SET_VREG(r0, r9) @ vAA<- r0 3648 GOTO_OPCODE(ip) @ jump to next instruction 3649 /* 9-10 instructions */ 3650 3651 3652/* ------------------------------ */ 3653 .balign 64 3654.L_OP_NEG_DOUBLE: /* 0x80 */ 3655/* File: armv5te/OP_NEG_DOUBLE.S */ 3656/* File: armv5te/unopWide.S */ 3657 /* 3658 * Generic 64-bit unary operation. Provide an "instr" line that 3659 * specifies an instruction that performs "result = op r0/r1". 3660 * This could be an ARM instruction or a function call. 3661 * 3662 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3663 */ 3664 /* unop vA, vB */ 3665 mov r9, rINST, lsr #8 @ r9<- A+ 3666 mov r3, rINST, lsr #12 @ r3<- B 3667 and r9, r9, #15 3668 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3669 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3670 ldmia r3, {r0-r1} @ r0/r1<- vAA 3671 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3672 @ optional op; may set condition codes 3673 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3674 GET_INST_OPCODE(ip) @ extract opcode from rINST 3675 stmia r9, {r0-r1} @ vAA<- r0/r1 3676 GOTO_OPCODE(ip) @ jump to next instruction 3677 /* 12-13 instructions */ 3678 3679 3680 3681/* ------------------------------ */ 3682 .balign 64 3683.L_OP_INT_TO_LONG: /* 0x81 */ 3684/* File: armv5te/OP_INT_TO_LONG.S */ 3685/* File: armv5te/unopWider.S */ 3686 /* 3687 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3688 * that specifies an instruction that performs "result = op r0", where 3689 * "result" is a 64-bit quantity in r0/r1. 3690 * 3691 * For: int-to-long, int-to-double, float-to-long, float-to-double 3692 */ 3693 /* unop vA, vB */ 3694 mov r9, rINST, lsr #8 @ r9<- A+ 3695 mov r3, rINST, lsr #12 @ r3<- B 3696 and r9, r9, #15 3697 GET_VREG(r0, r3) @ r0<- vB 3698 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3699 @ optional op; may set condition codes 3700 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3701 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3702 GET_INST_OPCODE(ip) @ extract opcode from rINST 3703 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3704 GOTO_OPCODE(ip) @ jump to next instruction 3705 /* 10-11 instructions */ 3706 3707 3708/* ------------------------------ */ 3709 .balign 64 3710.L_OP_INT_TO_FLOAT: /* 0x82 */ 3711/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3712/* File: arm-vfp/funop.S */ 3713 /* 3714 * Generic 32-bit unary floating-point operation. Provide an "instr" 3715 * line that specifies an instruction that performs "s1 = op s0". 3716 * 3717 * for: int-to-float, float-to-int 3718 */ 3719 /* unop vA, vB */ 3720 mov r3, rINST, lsr #12 @ r3<- B 3721 mov r9, rINST, lsr #8 @ r9<- A+ 3722 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3723 flds s0, [r3] @ s0<- vB 3724 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3725 and r9, r9, #15 @ r9<- A 3726 fsitos s1, s0 @ s1<- op 3727 GET_INST_OPCODE(ip) @ extract opcode from rINST 3728 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3729 fsts s1, [r9] @ vA<- s1 3730 GOTO_OPCODE(ip) @ jump to next instruction 3731 3732 3733/* ------------------------------ */ 3734 .balign 64 3735.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3736/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3737/* File: arm-vfp/funopWider.S */ 3738 /* 3739 * Generic 32bit-to-64bit floating point unary operation. Provide an 3740 * "instr" line that specifies an instruction that performs "d0 = op s0". 3741 * 3742 * For: int-to-double, float-to-double 3743 */ 3744 /* unop vA, vB */ 3745 mov r3, rINST, lsr #12 @ r3<- B 3746 mov r9, rINST, lsr #8 @ r9<- A+ 3747 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3748 flds s0, [r3] @ s0<- vB 3749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3750 and r9, r9, #15 @ r9<- A 3751 fsitod d0, s0 @ d0<- op 3752 GET_INST_OPCODE(ip) @ extract opcode from rINST 3753 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3754 fstd d0, [r9] @ vA<- d0 3755 GOTO_OPCODE(ip) @ jump to next instruction 3756 3757 3758/* ------------------------------ */ 3759 .balign 64 3760.L_OP_LONG_TO_INT: /* 0x84 */ 3761/* File: armv5te/OP_LONG_TO_INT.S */ 3762/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3763/* File: armv5te/OP_MOVE.S */ 3764 /* for move, move-object, long-to-int */ 3765 /* op vA, vB */ 3766 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3767 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3768 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3769 GET_VREG(r2, r1) @ r2<- fp[B] 3770 and r0, r0, #15 3771 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3772 SET_VREG(r2, r0) @ fp[A]<- r2 3773 GOTO_OPCODE(ip) @ execute next instruction 3774 3775 3776 3777/* ------------------------------ */ 3778 .balign 64 3779.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3780/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3781/* File: armv5te/unopNarrower.S */ 3782 /* 3783 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3784 * that specifies an instruction that performs "result = op r0/r1", where 3785 * "result" is a 32-bit quantity in r0. 3786 * 3787 * For: long-to-float, double-to-int, double-to-float 3788 * 3789 * (This would work for long-to-int, but that instruction is actually 3790 * an exact match for OP_MOVE.) 3791 */ 3792 /* unop vA, vB */ 3793 mov r3, rINST, lsr #12 @ r3<- B 3794 mov r9, rINST, lsr #8 @ r9<- A+ 3795 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3796 and r9, r9, #15 3797 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3798 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3799 @ optional op; may set condition codes 3800 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3801 GET_INST_OPCODE(ip) @ extract opcode from rINST 3802 SET_VREG(r0, r9) @ vA<- r0 3803 GOTO_OPCODE(ip) @ jump to next instruction 3804 /* 10-11 instructions */ 3805 3806 3807/* ------------------------------ */ 3808 .balign 64 3809.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3810/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3811/* File: armv5te/unopWide.S */ 3812 /* 3813 * Generic 64-bit unary operation. Provide an "instr" line that 3814 * specifies an instruction that performs "result = op r0/r1". 3815 * This could be an ARM instruction or a function call. 3816 * 3817 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3818 */ 3819 /* unop vA, vB */ 3820 mov r9, rINST, lsr #8 @ r9<- A+ 3821 mov r3, rINST, lsr #12 @ r3<- B 3822 and r9, r9, #15 3823 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3825 ldmia r3, {r0-r1} @ r0/r1<- vAA 3826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3827 @ optional op; may set condition codes 3828 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3829 GET_INST_OPCODE(ip) @ extract opcode from rINST 3830 stmia r9, {r0-r1} @ vAA<- r0/r1 3831 GOTO_OPCODE(ip) @ jump to next instruction 3832 /* 12-13 instructions */ 3833 3834 3835 3836/* ------------------------------ */ 3837 .balign 64 3838.L_OP_FLOAT_TO_INT: /* 0x87 */ 3839/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3840/* File: arm-vfp/funop.S */ 3841 /* 3842 * Generic 32-bit unary floating-point operation. Provide an "instr" 3843 * line that specifies an instruction that performs "s1 = op s0". 3844 * 3845 * for: int-to-float, float-to-int 3846 */ 3847 /* unop vA, vB */ 3848 mov r3, rINST, lsr #12 @ r3<- B 3849 mov r9, rINST, lsr #8 @ r9<- A+ 3850 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3851 flds s0, [r3] @ s0<- vB 3852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3853 and r9, r9, #15 @ r9<- A 3854 ftosizs s1, s0 @ s1<- op 3855 GET_INST_OPCODE(ip) @ extract opcode from rINST 3856 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3857 fsts s1, [r9] @ vA<- s1 3858 GOTO_OPCODE(ip) @ jump to next instruction 3859 3860 3861/* ------------------------------ */ 3862 .balign 64 3863.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3864/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3865@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3866/* File: armv5te/unopWider.S */ 3867 /* 3868 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3869 * that specifies an instruction that performs "result = op r0", where 3870 * "result" is a 64-bit quantity in r0/r1. 3871 * 3872 * For: int-to-long, int-to-double, float-to-long, float-to-double 3873 */ 3874 /* unop vA, vB */ 3875 mov r9, rINST, lsr #8 @ r9<- A+ 3876 mov r3, rINST, lsr #12 @ r3<- B 3877 and r9, r9, #15 3878 GET_VREG(r0, r3) @ r0<- vB 3879 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3880 @ optional op; may set condition codes 3881 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3882 bl f2l_doconv @ r0<- op, r0-r3 changed 3883 GET_INST_OPCODE(ip) @ extract opcode from rINST 3884 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3885 GOTO_OPCODE(ip) @ jump to next instruction 3886 /* 10-11 instructions */ 3887 3888 3889 3890/* ------------------------------ */ 3891 .balign 64 3892.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3893/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3894/* File: arm-vfp/funopWider.S */ 3895 /* 3896 * Generic 32bit-to-64bit floating point unary operation. Provide an 3897 * "instr" line that specifies an instruction that performs "d0 = op s0". 3898 * 3899 * For: int-to-double, float-to-double 3900 */ 3901 /* unop vA, vB */ 3902 mov r3, rINST, lsr #12 @ r3<- B 3903 mov r9, rINST, lsr #8 @ r9<- A+ 3904 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3905 flds s0, [r3] @ s0<- vB 3906 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3907 and r9, r9, #15 @ r9<- A 3908 fcvtds d0, s0 @ d0<- op 3909 GET_INST_OPCODE(ip) @ extract opcode from rINST 3910 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3911 fstd d0, [r9] @ vA<- d0 3912 GOTO_OPCODE(ip) @ jump to next instruction 3913 3914 3915/* ------------------------------ */ 3916 .balign 64 3917.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3918/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3919/* File: arm-vfp/funopNarrower.S */ 3920 /* 3921 * Generic 64bit-to-32bit unary floating point operation. Provide an 3922 * "instr" line that specifies an instruction that performs "s0 = op d0". 3923 * 3924 * For: double-to-int, double-to-float 3925 */ 3926 /* unop vA, vB */ 3927 mov r3, rINST, lsr #12 @ r3<- B 3928 mov r9, rINST, lsr #8 @ r9<- A+ 3929 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3930 fldd d0, [r3] @ d0<- vB 3931 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3932 and r9, r9, #15 @ r9<- A 3933 ftosizd s0, d0 @ s0<- op 3934 GET_INST_OPCODE(ip) @ extract opcode from rINST 3935 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3936 fsts s0, [r9] @ vA<- s0 3937 GOTO_OPCODE(ip) @ jump to next instruction 3938 3939 3940/* ------------------------------ */ 3941 .balign 64 3942.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3943/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3944@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3945/* File: armv5te/unopWide.S */ 3946 /* 3947 * Generic 64-bit unary operation. Provide an "instr" line that 3948 * specifies an instruction that performs "result = op r0/r1". 3949 * This could be an ARM instruction or a function call. 3950 * 3951 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3952 */ 3953 /* unop vA, vB */ 3954 mov r9, rINST, lsr #8 @ r9<- A+ 3955 mov r3, rINST, lsr #12 @ r3<- B 3956 and r9, r9, #15 3957 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3958 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3959 ldmia r3, {r0-r1} @ r0/r1<- vAA 3960 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3961 @ optional op; may set condition codes 3962 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3963 GET_INST_OPCODE(ip) @ extract opcode from rINST 3964 stmia r9, {r0-r1} @ vAA<- r0/r1 3965 GOTO_OPCODE(ip) @ jump to next instruction 3966 /* 12-13 instructions */ 3967 3968 3969 3970 3971/* ------------------------------ */ 3972 .balign 64 3973.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3974/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3975/* File: arm-vfp/funopNarrower.S */ 3976 /* 3977 * Generic 64bit-to-32bit unary floating point operation. Provide an 3978 * "instr" line that specifies an instruction that performs "s0 = op d0". 3979 * 3980 * For: double-to-int, double-to-float 3981 */ 3982 /* unop vA, vB */ 3983 mov r3, rINST, lsr #12 @ r3<- B 3984 mov r9, rINST, lsr #8 @ r9<- A+ 3985 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3986 fldd d0, [r3] @ d0<- vB 3987 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3988 and r9, r9, #15 @ r9<- A 3989 fcvtsd s0, d0 @ s0<- op 3990 GET_INST_OPCODE(ip) @ extract opcode from rINST 3991 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3992 fsts s0, [r9] @ vA<- s0 3993 GOTO_OPCODE(ip) @ jump to next instruction 3994 3995 3996/* ------------------------------ */ 3997 .balign 64 3998.L_OP_INT_TO_BYTE: /* 0x8d */ 3999/* File: armv5te/OP_INT_TO_BYTE.S */ 4000/* File: armv5te/unop.S */ 4001 /* 4002 * Generic 32-bit unary operation. Provide an "instr" line that 4003 * specifies an instruction that performs "result = op r0". 4004 * This could be an ARM instruction or a function call. 4005 * 4006 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4007 * int-to-byte, int-to-char, int-to-short 4008 */ 4009 /* unop vA, vB */ 4010 mov r3, rINST, lsr #12 @ r3<- B 4011 mov r9, rINST, lsr #8 @ r9<- A+ 4012 GET_VREG(r0, r3) @ r0<- vB 4013 and r9, r9, #15 4014 mov r0, r0, asl #24 @ optional op; may set condition codes 4015 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4016 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4017 GET_INST_OPCODE(ip) @ extract opcode from rINST 4018 SET_VREG(r0, r9) @ vAA<- r0 4019 GOTO_OPCODE(ip) @ jump to next instruction 4020 /* 9-10 instructions */ 4021 4022 4023/* ------------------------------ */ 4024 .balign 64 4025.L_OP_INT_TO_CHAR: /* 0x8e */ 4026/* File: armv5te/OP_INT_TO_CHAR.S */ 4027/* File: armv5te/unop.S */ 4028 /* 4029 * Generic 32-bit unary operation. Provide an "instr" line that 4030 * specifies an instruction that performs "result = op r0". 4031 * This could be an ARM instruction or a function call. 4032 * 4033 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4034 * int-to-byte, int-to-char, int-to-short 4035 */ 4036 /* unop vA, vB */ 4037 mov r3, rINST, lsr #12 @ r3<- B 4038 mov r9, rINST, lsr #8 @ r9<- A+ 4039 GET_VREG(r0, r3) @ r0<- vB 4040 and r9, r9, #15 4041 mov r0, r0, asl #16 @ optional op; may set condition codes 4042 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4043 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4044 GET_INST_OPCODE(ip) @ extract opcode from rINST 4045 SET_VREG(r0, r9) @ vAA<- r0 4046 GOTO_OPCODE(ip) @ jump to next instruction 4047 /* 9-10 instructions */ 4048 4049 4050/* ------------------------------ */ 4051 .balign 64 4052.L_OP_INT_TO_SHORT: /* 0x8f */ 4053/* File: armv5te/OP_INT_TO_SHORT.S */ 4054/* File: armv5te/unop.S */ 4055 /* 4056 * Generic 32-bit unary operation. Provide an "instr" line that 4057 * specifies an instruction that performs "result = op r0". 4058 * This could be an ARM instruction or a function call. 4059 * 4060 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4061 * int-to-byte, int-to-char, int-to-short 4062 */ 4063 /* unop vA, vB */ 4064 mov r3, rINST, lsr #12 @ r3<- B 4065 mov r9, rINST, lsr #8 @ r9<- A+ 4066 GET_VREG(r0, r3) @ r0<- vB 4067 and r9, r9, #15 4068 mov r0, r0, asl #16 @ optional op; may set condition codes 4069 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4070 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4071 GET_INST_OPCODE(ip) @ extract opcode from rINST 4072 SET_VREG(r0, r9) @ vAA<- r0 4073 GOTO_OPCODE(ip) @ jump to next instruction 4074 /* 9-10 instructions */ 4075 4076 4077/* ------------------------------ */ 4078 .balign 64 4079.L_OP_ADD_INT: /* 0x90 */ 4080/* File: armv5te/OP_ADD_INT.S */ 4081/* File: armv5te/binop.S */ 4082 /* 4083 * Generic 32-bit binary operation. Provide an "instr" line that 4084 * specifies an instruction that performs "result = r0 op r1". 4085 * This could be an ARM instruction or a function call. (If the result 4086 * comes back in a register other than r0, you can override "result".) 4087 * 4088 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4089 * vCC (r1). Useful for integer division and modulus. Note that we 4090 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4091 * handles it correctly. 4092 * 4093 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4094 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4095 * mul-float, div-float, rem-float 4096 */ 4097 /* binop vAA, vBB, vCC */ 4098 FETCH(r0, 1) @ r0<- CCBB 4099 mov r9, rINST, lsr #8 @ r9<- AA 4100 mov r3, r0, lsr #8 @ r3<- CC 4101 and r2, r0, #255 @ r2<- BB 4102 GET_VREG(r1, r3) @ r1<- vCC 4103 GET_VREG(r0, r2) @ r0<- vBB 4104 .if 0 4105 cmp r1, #0 @ is second operand zero? 4106 beq common_errDivideByZero 4107 .endif 4108 4109 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4110 @ optional op; may set condition codes 4111 add r0, r0, r1 @ r0<- op, r0-r3 changed 4112 GET_INST_OPCODE(ip) @ extract opcode from rINST 4113 SET_VREG(r0, r9) @ vAA<- r0 4114 GOTO_OPCODE(ip) @ jump to next instruction 4115 /* 11-14 instructions */ 4116 4117 4118 4119/* ------------------------------ */ 4120 .balign 64 4121.L_OP_SUB_INT: /* 0x91 */ 4122/* File: armv5te/OP_SUB_INT.S */ 4123/* File: armv5te/binop.S */ 4124 /* 4125 * Generic 32-bit binary operation. Provide an "instr" line that 4126 * specifies an instruction that performs "result = r0 op r1". 4127 * This could be an ARM instruction or a function call. (If the result 4128 * comes back in a register other than r0, you can override "result".) 4129 * 4130 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4131 * vCC (r1). Useful for integer division and modulus. Note that we 4132 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4133 * handles it correctly. 4134 * 4135 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4136 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4137 * mul-float, div-float, rem-float 4138 */ 4139 /* binop vAA, vBB, vCC */ 4140 FETCH(r0, 1) @ r0<- CCBB 4141 mov r9, rINST, lsr #8 @ r9<- AA 4142 mov r3, r0, lsr #8 @ r3<- CC 4143 and r2, r0, #255 @ r2<- BB 4144 GET_VREG(r1, r3) @ r1<- vCC 4145 GET_VREG(r0, r2) @ r0<- vBB 4146 .if 0 4147 cmp r1, #0 @ is second operand zero? 4148 beq common_errDivideByZero 4149 .endif 4150 4151 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4152 @ optional op; may set condition codes 4153 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4154 GET_INST_OPCODE(ip) @ extract opcode from rINST 4155 SET_VREG(r0, r9) @ vAA<- r0 4156 GOTO_OPCODE(ip) @ jump to next instruction 4157 /* 11-14 instructions */ 4158 4159 4160 4161/* ------------------------------ */ 4162 .balign 64 4163.L_OP_MUL_INT: /* 0x92 */ 4164/* File: armv5te/OP_MUL_INT.S */ 4165/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4166/* File: armv5te/binop.S */ 4167 /* 4168 * Generic 32-bit binary operation. Provide an "instr" line that 4169 * specifies an instruction that performs "result = r0 op r1". 4170 * This could be an ARM instruction or a function call. (If the result 4171 * comes back in a register other than r0, you can override "result".) 4172 * 4173 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4174 * vCC (r1). Useful for integer division and modulus. Note that we 4175 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4176 * handles it correctly. 4177 * 4178 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4179 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4180 * mul-float, div-float, rem-float 4181 */ 4182 /* binop vAA, vBB, vCC */ 4183 FETCH(r0, 1) @ r0<- CCBB 4184 mov r9, rINST, lsr #8 @ r9<- AA 4185 mov r3, r0, lsr #8 @ r3<- CC 4186 and r2, r0, #255 @ r2<- BB 4187 GET_VREG(r1, r3) @ r1<- vCC 4188 GET_VREG(r0, r2) @ r0<- vBB 4189 .if 0 4190 cmp r1, #0 @ is second operand zero? 4191 beq common_errDivideByZero 4192 .endif 4193 4194 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4195 @ optional op; may set condition codes 4196 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4197 GET_INST_OPCODE(ip) @ extract opcode from rINST 4198 SET_VREG(r0, r9) @ vAA<- r0 4199 GOTO_OPCODE(ip) @ jump to next instruction 4200 /* 11-14 instructions */ 4201 4202 4203 4204/* ------------------------------ */ 4205 .balign 64 4206.L_OP_DIV_INT: /* 0x93 */ 4207/* File: armv5te/OP_DIV_INT.S */ 4208/* File: armv5te/binop.S */ 4209 /* 4210 * Generic 32-bit binary operation. Provide an "instr" line that 4211 * specifies an instruction that performs "result = r0 op r1". 4212 * This could be an ARM instruction or a function call. (If the result 4213 * comes back in a register other than r0, you can override "result".) 4214 * 4215 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4216 * vCC (r1). Useful for integer division and modulus. Note that we 4217 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4218 * handles it correctly. 4219 * 4220 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4221 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4222 * mul-float, div-float, rem-float 4223 */ 4224 /* binop vAA, vBB, vCC */ 4225 FETCH(r0, 1) @ r0<- CCBB 4226 mov r9, rINST, lsr #8 @ r9<- AA 4227 mov r3, r0, lsr #8 @ r3<- CC 4228 and r2, r0, #255 @ r2<- BB 4229 GET_VREG(r1, r3) @ r1<- vCC 4230 GET_VREG(r0, r2) @ r0<- vBB 4231 .if 1 4232 cmp r1, #0 @ is second operand zero? 4233 beq common_errDivideByZero 4234 .endif 4235 4236 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4237 @ optional op; may set condition codes 4238 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4239 GET_INST_OPCODE(ip) @ extract opcode from rINST 4240 SET_VREG(r0, r9) @ vAA<- r0 4241 GOTO_OPCODE(ip) @ jump to next instruction 4242 /* 11-14 instructions */ 4243 4244 4245 4246/* ------------------------------ */ 4247 .balign 64 4248.L_OP_REM_INT: /* 0x94 */ 4249/* File: armv5te/OP_REM_INT.S */ 4250/* idivmod returns quotient in r0 and remainder in r1 */ 4251/* File: armv5te/binop.S */ 4252 /* 4253 * Generic 32-bit binary operation. Provide an "instr" line that 4254 * specifies an instruction that performs "result = r0 op r1". 4255 * This could be an ARM instruction or a function call. (If the result 4256 * comes back in a register other than r0, you can override "result".) 4257 * 4258 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4259 * vCC (r1). Useful for integer division and modulus. Note that we 4260 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4261 * handles it correctly. 4262 * 4263 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4264 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4265 * mul-float, div-float, rem-float 4266 */ 4267 /* binop vAA, vBB, vCC */ 4268 FETCH(r0, 1) @ r0<- CCBB 4269 mov r9, rINST, lsr #8 @ r9<- AA 4270 mov r3, r0, lsr #8 @ r3<- CC 4271 and r2, r0, #255 @ r2<- BB 4272 GET_VREG(r1, r3) @ r1<- vCC 4273 GET_VREG(r0, r2) @ r0<- vBB 4274 .if 1 4275 cmp r1, #0 @ is second operand zero? 4276 beq common_errDivideByZero 4277 .endif 4278 4279 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4280 @ optional op; may set condition codes 4281 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4282 GET_INST_OPCODE(ip) @ extract opcode from rINST 4283 SET_VREG(r1, r9) @ vAA<- r1 4284 GOTO_OPCODE(ip) @ jump to next instruction 4285 /* 11-14 instructions */ 4286 4287 4288 4289/* ------------------------------ */ 4290 .balign 64 4291.L_OP_AND_INT: /* 0x95 */ 4292/* File: armv5te/OP_AND_INT.S */ 4293/* File: armv5te/binop.S */ 4294 /* 4295 * Generic 32-bit binary operation. Provide an "instr" line that 4296 * specifies an instruction that performs "result = r0 op r1". 4297 * This could be an ARM instruction or a function call. (If the result 4298 * comes back in a register other than r0, you can override "result".) 4299 * 4300 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4301 * vCC (r1). Useful for integer division and modulus. Note that we 4302 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4303 * handles it correctly. 4304 * 4305 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4306 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4307 * mul-float, div-float, rem-float 4308 */ 4309 /* binop vAA, vBB, vCC */ 4310 FETCH(r0, 1) @ r0<- CCBB 4311 mov r9, rINST, lsr #8 @ r9<- AA 4312 mov r3, r0, lsr #8 @ r3<- CC 4313 and r2, r0, #255 @ r2<- BB 4314 GET_VREG(r1, r3) @ r1<- vCC 4315 GET_VREG(r0, r2) @ r0<- vBB 4316 .if 0 4317 cmp r1, #0 @ is second operand zero? 4318 beq common_errDivideByZero 4319 .endif 4320 4321 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4322 @ optional op; may set condition codes 4323 and r0, r0, r1 @ r0<- op, r0-r3 changed 4324 GET_INST_OPCODE(ip) @ extract opcode from rINST 4325 SET_VREG(r0, r9) @ vAA<- r0 4326 GOTO_OPCODE(ip) @ jump to next instruction 4327 /* 11-14 instructions */ 4328 4329 4330 4331/* ------------------------------ */ 4332 .balign 64 4333.L_OP_OR_INT: /* 0x96 */ 4334/* File: armv5te/OP_OR_INT.S */ 4335/* File: armv5te/binop.S */ 4336 /* 4337 * Generic 32-bit binary operation. Provide an "instr" line that 4338 * specifies an instruction that performs "result = r0 op r1". 4339 * This could be an ARM instruction or a function call. (If the result 4340 * comes back in a register other than r0, you can override "result".) 4341 * 4342 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4343 * vCC (r1). Useful for integer division and modulus. Note that we 4344 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4345 * handles it correctly. 4346 * 4347 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4348 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4349 * mul-float, div-float, rem-float 4350 */ 4351 /* binop vAA, vBB, vCC */ 4352 FETCH(r0, 1) @ r0<- CCBB 4353 mov r9, rINST, lsr #8 @ r9<- AA 4354 mov r3, r0, lsr #8 @ r3<- CC 4355 and r2, r0, #255 @ r2<- BB 4356 GET_VREG(r1, r3) @ r1<- vCC 4357 GET_VREG(r0, r2) @ r0<- vBB 4358 .if 0 4359 cmp r1, #0 @ is second operand zero? 4360 beq common_errDivideByZero 4361 .endif 4362 4363 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4364 @ optional op; may set condition codes 4365 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4366 GET_INST_OPCODE(ip) @ extract opcode from rINST 4367 SET_VREG(r0, r9) @ vAA<- r0 4368 GOTO_OPCODE(ip) @ jump to next instruction 4369 /* 11-14 instructions */ 4370 4371 4372 4373/* ------------------------------ */ 4374 .balign 64 4375.L_OP_XOR_INT: /* 0x97 */ 4376/* File: armv5te/OP_XOR_INT.S */ 4377/* File: armv5te/binop.S */ 4378 /* 4379 * Generic 32-bit binary operation. Provide an "instr" line that 4380 * specifies an instruction that performs "result = r0 op r1". 4381 * This could be an ARM instruction or a function call. (If the result 4382 * comes back in a register other than r0, you can override "result".) 4383 * 4384 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4385 * vCC (r1). Useful for integer division and modulus. Note that we 4386 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4387 * handles it correctly. 4388 * 4389 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4390 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4391 * mul-float, div-float, rem-float 4392 */ 4393 /* binop vAA, vBB, vCC */ 4394 FETCH(r0, 1) @ r0<- CCBB 4395 mov r9, rINST, lsr #8 @ r9<- AA 4396 mov r3, r0, lsr #8 @ r3<- CC 4397 and r2, r0, #255 @ r2<- BB 4398 GET_VREG(r1, r3) @ r1<- vCC 4399 GET_VREG(r0, r2) @ r0<- vBB 4400 .if 0 4401 cmp r1, #0 @ is second operand zero? 4402 beq common_errDivideByZero 4403 .endif 4404 4405 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4406 @ optional op; may set condition codes 4407 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4408 GET_INST_OPCODE(ip) @ extract opcode from rINST 4409 SET_VREG(r0, r9) @ vAA<- r0 4410 GOTO_OPCODE(ip) @ jump to next instruction 4411 /* 11-14 instructions */ 4412 4413 4414 4415/* ------------------------------ */ 4416 .balign 64 4417.L_OP_SHL_INT: /* 0x98 */ 4418/* File: armv5te/OP_SHL_INT.S */ 4419/* File: armv5te/binop.S */ 4420 /* 4421 * Generic 32-bit binary operation. Provide an "instr" line that 4422 * specifies an instruction that performs "result = r0 op r1". 4423 * This could be an ARM instruction or a function call. (If the result 4424 * comes back in a register other than r0, you can override "result".) 4425 * 4426 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4427 * vCC (r1). Useful for integer division and modulus. Note that we 4428 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4429 * handles it correctly. 4430 * 4431 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4432 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4433 * mul-float, div-float, rem-float 4434 */ 4435 /* binop vAA, vBB, vCC */ 4436 FETCH(r0, 1) @ r0<- CCBB 4437 mov r9, rINST, lsr #8 @ r9<- AA 4438 mov r3, r0, lsr #8 @ r3<- CC 4439 and r2, r0, #255 @ r2<- BB 4440 GET_VREG(r1, r3) @ r1<- vCC 4441 GET_VREG(r0, r2) @ r0<- vBB 4442 .if 0 4443 cmp r1, #0 @ is second operand zero? 4444 beq common_errDivideByZero 4445 .endif 4446 4447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4448 and r1, r1, #31 @ optional op; may set condition codes 4449 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4450 GET_INST_OPCODE(ip) @ extract opcode from rINST 4451 SET_VREG(r0, r9) @ vAA<- r0 4452 GOTO_OPCODE(ip) @ jump to next instruction 4453 /* 11-14 instructions */ 4454 4455 4456 4457/* ------------------------------ */ 4458 .balign 64 4459.L_OP_SHR_INT: /* 0x99 */ 4460/* File: armv5te/OP_SHR_INT.S */ 4461/* File: armv5te/binop.S */ 4462 /* 4463 * Generic 32-bit binary operation. Provide an "instr" line that 4464 * specifies an instruction that performs "result = r0 op r1". 4465 * This could be an ARM instruction or a function call. (If the result 4466 * comes back in a register other than r0, you can override "result".) 4467 * 4468 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4469 * vCC (r1). Useful for integer division and modulus. Note that we 4470 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4471 * handles it correctly. 4472 * 4473 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4474 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4475 * mul-float, div-float, rem-float 4476 */ 4477 /* binop vAA, vBB, vCC */ 4478 FETCH(r0, 1) @ r0<- CCBB 4479 mov r9, rINST, lsr #8 @ r9<- AA 4480 mov r3, r0, lsr #8 @ r3<- CC 4481 and r2, r0, #255 @ r2<- BB 4482 GET_VREG(r1, r3) @ r1<- vCC 4483 GET_VREG(r0, r2) @ r0<- vBB 4484 .if 0 4485 cmp r1, #0 @ is second operand zero? 4486 beq common_errDivideByZero 4487 .endif 4488 4489 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4490 and r1, r1, #31 @ optional op; may set condition codes 4491 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4492 GET_INST_OPCODE(ip) @ extract opcode from rINST 4493 SET_VREG(r0, r9) @ vAA<- r0 4494 GOTO_OPCODE(ip) @ jump to next instruction 4495 /* 11-14 instructions */ 4496 4497 4498 4499/* ------------------------------ */ 4500 .balign 64 4501.L_OP_USHR_INT: /* 0x9a */ 4502/* File: armv5te/OP_USHR_INT.S */ 4503/* File: armv5te/binop.S */ 4504 /* 4505 * Generic 32-bit binary operation. Provide an "instr" line that 4506 * specifies an instruction that performs "result = r0 op r1". 4507 * This could be an ARM instruction or a function call. (If the result 4508 * comes back in a register other than r0, you can override "result".) 4509 * 4510 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4511 * vCC (r1). Useful for integer division and modulus. Note that we 4512 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4513 * handles it correctly. 4514 * 4515 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4516 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4517 * mul-float, div-float, rem-float 4518 */ 4519 /* binop vAA, vBB, vCC */ 4520 FETCH(r0, 1) @ r0<- CCBB 4521 mov r9, rINST, lsr #8 @ r9<- AA 4522 mov r3, r0, lsr #8 @ r3<- CC 4523 and r2, r0, #255 @ r2<- BB 4524 GET_VREG(r1, r3) @ r1<- vCC 4525 GET_VREG(r0, r2) @ r0<- vBB 4526 .if 0 4527 cmp r1, #0 @ is second operand zero? 4528 beq common_errDivideByZero 4529 .endif 4530 4531 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4532 and r1, r1, #31 @ optional op; may set condition codes 4533 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4534 GET_INST_OPCODE(ip) @ extract opcode from rINST 4535 SET_VREG(r0, r9) @ vAA<- r0 4536 GOTO_OPCODE(ip) @ jump to next instruction 4537 /* 11-14 instructions */ 4538 4539 4540 4541/* ------------------------------ */ 4542 .balign 64 4543.L_OP_ADD_LONG: /* 0x9b */ 4544/* File: armv5te/OP_ADD_LONG.S */ 4545/* File: armv5te/binopWide.S */ 4546 /* 4547 * Generic 64-bit binary operation. Provide an "instr" line that 4548 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4549 * This could be an ARM instruction or a function call. (If the result 4550 * comes back in a register other than r0, you can override "result".) 4551 * 4552 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4553 * vCC (r1). Useful for integer division and modulus. 4554 * 4555 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4556 * xor-long, add-double, sub-double, mul-double, div-double, 4557 * rem-double 4558 * 4559 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4560 */ 4561 /* binop vAA, vBB, vCC */ 4562 FETCH(r0, 1) @ r0<- CCBB 4563 mov r9, rINST, lsr #8 @ r9<- AA 4564 and r2, r0, #255 @ r2<- BB 4565 mov r3, r0, lsr #8 @ r3<- CC 4566 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4567 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4568 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4569 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4570 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4571 .if 0 4572 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4573 beq common_errDivideByZero 4574 .endif 4575 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4576 4577 adds r0, r0, r2 @ optional op; may set condition codes 4578 adc r1, r1, r3 @ result<- op, r0-r3 changed 4579 GET_INST_OPCODE(ip) @ extract opcode from rINST 4580 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4581 GOTO_OPCODE(ip) @ jump to next instruction 4582 /* 14-17 instructions */ 4583 4584 4585 4586/* ------------------------------ */ 4587 .balign 64 4588.L_OP_SUB_LONG: /* 0x9c */ 4589/* File: armv5te/OP_SUB_LONG.S */ 4590/* File: armv5te/binopWide.S */ 4591 /* 4592 * Generic 64-bit binary operation. Provide an "instr" line that 4593 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4594 * This could be an ARM instruction or a function call. (If the result 4595 * comes back in a register other than r0, you can override "result".) 4596 * 4597 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4598 * vCC (r1). Useful for integer division and modulus. 4599 * 4600 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4601 * xor-long, add-double, sub-double, mul-double, div-double, 4602 * rem-double 4603 * 4604 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4605 */ 4606 /* binop vAA, vBB, vCC */ 4607 FETCH(r0, 1) @ r0<- CCBB 4608 mov r9, rINST, lsr #8 @ r9<- AA 4609 and r2, r0, #255 @ r2<- BB 4610 mov r3, r0, lsr #8 @ r3<- CC 4611 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4612 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4613 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4614 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4615 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4616 .if 0 4617 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4618 beq common_errDivideByZero 4619 .endif 4620 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4621 4622 subs r0, r0, r2 @ optional op; may set condition codes 4623 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4624 GET_INST_OPCODE(ip) @ extract opcode from rINST 4625 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4626 GOTO_OPCODE(ip) @ jump to next instruction 4627 /* 14-17 instructions */ 4628 4629 4630 4631/* ------------------------------ */ 4632 .balign 64 4633.L_OP_MUL_LONG: /* 0x9d */ 4634/* File: armv5te/OP_MUL_LONG.S */ 4635 /* 4636 * Signed 64-bit integer multiply. 4637 * 4638 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4639 * WX 4640 * x YZ 4641 * -------- 4642 * ZW ZX 4643 * YW YX 4644 * 4645 * The low word of the result holds ZX, the high word holds 4646 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4647 * it doesn't fit in the low 64 bits. 4648 * 4649 * Unlike most ARM math operations, multiply instructions have 4650 * restrictions on using the same register more than once (Rd and Rm 4651 * cannot be the same). 4652 */ 4653 /* mul-long vAA, vBB, vCC */ 4654 FETCH(r0, 1) @ r0<- CCBB 4655 and r2, r0, #255 @ r2<- BB 4656 mov r3, r0, lsr #8 @ r3<- CC 4657 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4658 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4659 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4660 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4661 mul ip, r2, r1 @ ip<- ZxW 4662 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4663 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4664 mov r0, rINST, lsr #8 @ r0<- AA 4665 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4666 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4667 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4668 b .LOP_MUL_LONG_finish 4669 4670/* ------------------------------ */ 4671 .balign 64 4672.L_OP_DIV_LONG: /* 0x9e */ 4673/* File: armv5te/OP_DIV_LONG.S */ 4674/* File: armv5te/binopWide.S */ 4675 /* 4676 * Generic 64-bit binary operation. Provide an "instr" line that 4677 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4678 * This could be an ARM instruction or a function call. (If the result 4679 * comes back in a register other than r0, you can override "result".) 4680 * 4681 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4682 * vCC (r1). Useful for integer division and modulus. 4683 * 4684 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4685 * xor-long, add-double, sub-double, mul-double, div-double, 4686 * rem-double 4687 * 4688 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4689 */ 4690 /* binop vAA, vBB, vCC */ 4691 FETCH(r0, 1) @ r0<- CCBB 4692 mov r9, rINST, lsr #8 @ r9<- AA 4693 and r2, r0, #255 @ r2<- BB 4694 mov r3, r0, lsr #8 @ r3<- CC 4695 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4696 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4697 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4698 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4699 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4700 .if 1 4701 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4702 beq common_errDivideByZero 4703 .endif 4704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4705 4706 @ optional op; may set condition codes 4707 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4708 GET_INST_OPCODE(ip) @ extract opcode from rINST 4709 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4710 GOTO_OPCODE(ip) @ jump to next instruction 4711 /* 14-17 instructions */ 4712 4713 4714 4715/* ------------------------------ */ 4716 .balign 64 4717.L_OP_REM_LONG: /* 0x9f */ 4718/* File: armv5te/OP_REM_LONG.S */ 4719/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4720/* File: armv5te/binopWide.S */ 4721 /* 4722 * Generic 64-bit binary operation. Provide an "instr" line that 4723 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4724 * This could be an ARM instruction or a function call. (If the result 4725 * comes back in a register other than r0, you can override "result".) 4726 * 4727 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4728 * vCC (r1). Useful for integer division and modulus. 4729 * 4730 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4731 * xor-long, add-double, sub-double, mul-double, div-double, 4732 * rem-double 4733 * 4734 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4735 */ 4736 /* binop vAA, vBB, vCC */ 4737 FETCH(r0, 1) @ r0<- CCBB 4738 mov r9, rINST, lsr #8 @ r9<- AA 4739 and r2, r0, #255 @ r2<- BB 4740 mov r3, r0, lsr #8 @ r3<- CC 4741 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4742 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4743 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4744 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4745 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4746 .if 1 4747 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4748 beq common_errDivideByZero 4749 .endif 4750 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4751 4752 @ optional op; may set condition codes 4753 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4754 GET_INST_OPCODE(ip) @ extract opcode from rINST 4755 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4756 GOTO_OPCODE(ip) @ jump to next instruction 4757 /* 14-17 instructions */ 4758 4759 4760 4761/* ------------------------------ */ 4762 .balign 64 4763.L_OP_AND_LONG: /* 0xa0 */ 4764/* File: armv5te/OP_AND_LONG.S */ 4765/* File: armv5te/binopWide.S */ 4766 /* 4767 * Generic 64-bit binary operation. Provide an "instr" line that 4768 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4769 * This could be an ARM instruction or a function call. (If the result 4770 * comes back in a register other than r0, you can override "result".) 4771 * 4772 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4773 * vCC (r1). Useful for integer division and modulus. 4774 * 4775 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4776 * xor-long, add-double, sub-double, mul-double, div-double, 4777 * rem-double 4778 * 4779 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4780 */ 4781 /* binop vAA, vBB, vCC */ 4782 FETCH(r0, 1) @ r0<- CCBB 4783 mov r9, rINST, lsr #8 @ r9<- AA 4784 and r2, r0, #255 @ r2<- BB 4785 mov r3, r0, lsr #8 @ r3<- CC 4786 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4787 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4788 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4789 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4790 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4791 .if 0 4792 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4793 beq common_errDivideByZero 4794 .endif 4795 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4796 4797 and r0, r0, r2 @ optional op; may set condition codes 4798 and r1, r1, r3 @ result<- op, r0-r3 changed 4799 GET_INST_OPCODE(ip) @ extract opcode from rINST 4800 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4801 GOTO_OPCODE(ip) @ jump to next instruction 4802 /* 14-17 instructions */ 4803 4804 4805 4806/* ------------------------------ */ 4807 .balign 64 4808.L_OP_OR_LONG: /* 0xa1 */ 4809/* File: armv5te/OP_OR_LONG.S */ 4810/* File: armv5te/binopWide.S */ 4811 /* 4812 * Generic 64-bit binary operation. Provide an "instr" line that 4813 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4814 * This could be an ARM instruction or a function call. (If the result 4815 * comes back in a register other than r0, you can override "result".) 4816 * 4817 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4818 * vCC (r1). Useful for integer division and modulus. 4819 * 4820 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4821 * xor-long, add-double, sub-double, mul-double, div-double, 4822 * rem-double 4823 * 4824 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4825 */ 4826 /* binop vAA, vBB, vCC */ 4827 FETCH(r0, 1) @ r0<- CCBB 4828 mov r9, rINST, lsr #8 @ r9<- AA 4829 and r2, r0, #255 @ r2<- BB 4830 mov r3, r0, lsr #8 @ r3<- CC 4831 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4832 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4833 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4834 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4835 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4836 .if 0 4837 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4838 beq common_errDivideByZero 4839 .endif 4840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4841 4842 orr r0, r0, r2 @ optional op; may set condition codes 4843 orr r1, r1, r3 @ result<- op, r0-r3 changed 4844 GET_INST_OPCODE(ip) @ extract opcode from rINST 4845 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4846 GOTO_OPCODE(ip) @ jump to next instruction 4847 /* 14-17 instructions */ 4848 4849 4850 4851/* ------------------------------ */ 4852 .balign 64 4853.L_OP_XOR_LONG: /* 0xa2 */ 4854/* File: armv5te/OP_XOR_LONG.S */ 4855/* File: armv5te/binopWide.S */ 4856 /* 4857 * Generic 64-bit binary operation. Provide an "instr" line that 4858 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4859 * This could be an ARM instruction or a function call. (If the result 4860 * comes back in a register other than r0, you can override "result".) 4861 * 4862 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4863 * vCC (r1). Useful for integer division and modulus. 4864 * 4865 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4866 * xor-long, add-double, sub-double, mul-double, div-double, 4867 * rem-double 4868 * 4869 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4870 */ 4871 /* binop vAA, vBB, vCC */ 4872 FETCH(r0, 1) @ r0<- CCBB 4873 mov r9, rINST, lsr #8 @ r9<- AA 4874 and r2, r0, #255 @ r2<- BB 4875 mov r3, r0, lsr #8 @ r3<- CC 4876 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4877 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4878 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4879 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4880 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4881 .if 0 4882 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4883 beq common_errDivideByZero 4884 .endif 4885 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4886 4887 eor r0, r0, r2 @ optional op; may set condition codes 4888 eor r1, r1, r3 @ result<- op, r0-r3 changed 4889 GET_INST_OPCODE(ip) @ extract opcode from rINST 4890 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4891 GOTO_OPCODE(ip) @ jump to next instruction 4892 /* 14-17 instructions */ 4893 4894 4895 4896/* ------------------------------ */ 4897 .balign 64 4898.L_OP_SHL_LONG: /* 0xa3 */ 4899/* File: armv5te/OP_SHL_LONG.S */ 4900 /* 4901 * Long integer shift. This is different from the generic 32/64-bit 4902 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4903 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4904 * 6 bits of the shift distance. 4905 */ 4906 /* shl-long vAA, vBB, vCC */ 4907 FETCH(r0, 1) @ r0<- CCBB 4908 mov r9, rINST, lsr #8 @ r9<- AA 4909 and r3, r0, #255 @ r3<- BB 4910 mov r0, r0, lsr #8 @ r0<- CC 4911 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4912 GET_VREG(r2, r0) @ r2<- vCC 4913 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4914 and r2, r2, #63 @ r2<- r2 & 0x3f 4915 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4916 4917 mov r1, r1, asl r2 @ r1<- r1 << r2 4918 rsb r3, r2, #32 @ r3<- 32 - r2 4919 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4920 subs ip, r2, #32 @ ip<- r2 - 32 4921 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4923 b .LOP_SHL_LONG_finish 4924 4925/* ------------------------------ */ 4926 .balign 64 4927.L_OP_SHR_LONG: /* 0xa4 */ 4928/* File: armv5te/OP_SHR_LONG.S */ 4929 /* 4930 * Long integer shift. This is different from the generic 32/64-bit 4931 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4932 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4933 * 6 bits of the shift distance. 4934 */ 4935 /* shr-long vAA, vBB, vCC */ 4936 FETCH(r0, 1) @ r0<- CCBB 4937 mov r9, rINST, lsr #8 @ r9<- AA 4938 and r3, r0, #255 @ r3<- BB 4939 mov r0, r0, lsr #8 @ r0<- CC 4940 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4941 GET_VREG(r2, r0) @ r2<- vCC 4942 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4943 and r2, r2, #63 @ r0<- r0 & 0x3f 4944 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4945 4946 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4947 rsb r3, r2, #32 @ r3<- 32 - r2 4948 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4949 subs ip, r2, #32 @ ip<- r2 - 32 4950 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4952 b .LOP_SHR_LONG_finish 4953 4954/* ------------------------------ */ 4955 .balign 64 4956.L_OP_USHR_LONG: /* 0xa5 */ 4957/* File: armv5te/OP_USHR_LONG.S */ 4958 /* 4959 * Long integer shift. This is different from the generic 32/64-bit 4960 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4961 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4962 * 6 bits of the shift distance. 4963 */ 4964 /* ushr-long vAA, vBB, vCC */ 4965 FETCH(r0, 1) @ r0<- CCBB 4966 mov r9, rINST, lsr #8 @ r9<- AA 4967 and r3, r0, #255 @ r3<- BB 4968 mov r0, r0, lsr #8 @ r0<- CC 4969 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4970 GET_VREG(r2, r0) @ r2<- vCC 4971 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4972 and r2, r2, #63 @ r0<- r0 & 0x3f 4973 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4974 4975 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4976 rsb r3, r2, #32 @ r3<- 32 - r2 4977 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4978 subs ip, r2, #32 @ ip<- r2 - 32 4979 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4980 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4981 b .LOP_USHR_LONG_finish 4982 4983/* ------------------------------ */ 4984 .balign 64 4985.L_OP_ADD_FLOAT: /* 0xa6 */ 4986/* File: arm-vfp/OP_ADD_FLOAT.S */ 4987/* File: arm-vfp/fbinop.S */ 4988 /* 4989 * Generic 32-bit floating-point operation. Provide an "instr" line that 4990 * specifies an instruction that performs "s2 = s0 op s1". Because we 4991 * use the "softfp" ABI, this must be an instruction, not a function call. 4992 * 4993 * For: add-float, sub-float, mul-float, div-float 4994 */ 4995 /* floatop vAA, vBB, vCC */ 4996 FETCH(r0, 1) @ r0<- CCBB 4997 mov r9, rINST, lsr #8 @ r9<- AA 4998 mov r3, r0, lsr #8 @ r3<- CC 4999 and r2, r0, #255 @ r2<- BB 5000 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5001 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5002 flds s1, [r3] @ s1<- vCC 5003 flds s0, [r2] @ s0<- vBB 5004 5005 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5006 fadds s2, s0, s1 @ s2<- op 5007 GET_INST_OPCODE(ip) @ extract opcode from rINST 5008 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5009 fsts s2, [r9] @ vAA<- s2 5010 GOTO_OPCODE(ip) @ jump to next instruction 5011 5012 5013/* ------------------------------ */ 5014 .balign 64 5015.L_OP_SUB_FLOAT: /* 0xa7 */ 5016/* File: arm-vfp/OP_SUB_FLOAT.S */ 5017/* File: arm-vfp/fbinop.S */ 5018 /* 5019 * Generic 32-bit floating-point operation. Provide an "instr" line that 5020 * specifies an instruction that performs "s2 = s0 op s1". Because we 5021 * use the "softfp" ABI, this must be an instruction, not a function call. 5022 * 5023 * For: add-float, sub-float, mul-float, div-float 5024 */ 5025 /* floatop vAA, vBB, vCC */ 5026 FETCH(r0, 1) @ r0<- CCBB 5027 mov r9, rINST, lsr #8 @ r9<- AA 5028 mov r3, r0, lsr #8 @ r3<- CC 5029 and r2, r0, #255 @ r2<- BB 5030 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5031 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5032 flds s1, [r3] @ s1<- vCC 5033 flds s0, [r2] @ s0<- vBB 5034 5035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5036 fsubs s2, s0, s1 @ s2<- op 5037 GET_INST_OPCODE(ip) @ extract opcode from rINST 5038 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5039 fsts s2, [r9] @ vAA<- s2 5040 GOTO_OPCODE(ip) @ jump to next instruction 5041 5042 5043/* ------------------------------ */ 5044 .balign 64 5045.L_OP_MUL_FLOAT: /* 0xa8 */ 5046/* File: arm-vfp/OP_MUL_FLOAT.S */ 5047/* File: arm-vfp/fbinop.S */ 5048 /* 5049 * Generic 32-bit floating-point operation. Provide an "instr" line that 5050 * specifies an instruction that performs "s2 = s0 op s1". Because we 5051 * use the "softfp" ABI, this must be an instruction, not a function call. 5052 * 5053 * For: add-float, sub-float, mul-float, div-float 5054 */ 5055 /* floatop vAA, vBB, vCC */ 5056 FETCH(r0, 1) @ r0<- CCBB 5057 mov r9, rINST, lsr #8 @ r9<- AA 5058 mov r3, r0, lsr #8 @ r3<- CC 5059 and r2, r0, #255 @ r2<- BB 5060 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5061 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5062 flds s1, [r3] @ s1<- vCC 5063 flds s0, [r2] @ s0<- vBB 5064 5065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5066 fmuls s2, s0, s1 @ s2<- op 5067 GET_INST_OPCODE(ip) @ extract opcode from rINST 5068 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5069 fsts s2, [r9] @ vAA<- s2 5070 GOTO_OPCODE(ip) @ jump to next instruction 5071 5072 5073/* ------------------------------ */ 5074 .balign 64 5075.L_OP_DIV_FLOAT: /* 0xa9 */ 5076/* File: arm-vfp/OP_DIV_FLOAT.S */ 5077/* File: arm-vfp/fbinop.S */ 5078 /* 5079 * Generic 32-bit floating-point operation. Provide an "instr" line that 5080 * specifies an instruction that performs "s2 = s0 op s1". Because we 5081 * use the "softfp" ABI, this must be an instruction, not a function call. 5082 * 5083 * For: add-float, sub-float, mul-float, div-float 5084 */ 5085 /* floatop vAA, vBB, vCC */ 5086 FETCH(r0, 1) @ r0<- CCBB 5087 mov r9, rINST, lsr #8 @ r9<- AA 5088 mov r3, r0, lsr #8 @ r3<- CC 5089 and r2, r0, #255 @ r2<- BB 5090 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5091 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5092 flds s1, [r3] @ s1<- vCC 5093 flds s0, [r2] @ s0<- vBB 5094 5095 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5096 fdivs s2, s0, s1 @ s2<- op 5097 GET_INST_OPCODE(ip) @ extract opcode from rINST 5098 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5099 fsts s2, [r9] @ vAA<- s2 5100 GOTO_OPCODE(ip) @ jump to next instruction 5101 5102 5103/* ------------------------------ */ 5104 .balign 64 5105.L_OP_REM_FLOAT: /* 0xaa */ 5106/* File: armv5te/OP_REM_FLOAT.S */ 5107/* EABI doesn't define a float remainder function, but libm does */ 5108/* File: armv5te/binop.S */ 5109 /* 5110 * Generic 32-bit binary operation. Provide an "instr" line that 5111 * specifies an instruction that performs "result = r0 op r1". 5112 * This could be an ARM instruction or a function call. (If the result 5113 * comes back in a register other than r0, you can override "result".) 5114 * 5115 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5116 * vCC (r1). Useful for integer division and modulus. Note that we 5117 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5118 * handles it correctly. 5119 * 5120 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5121 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5122 * mul-float, div-float, rem-float 5123 */ 5124 /* binop vAA, vBB, vCC */ 5125 FETCH(r0, 1) @ r0<- CCBB 5126 mov r9, rINST, lsr #8 @ r9<- AA 5127 mov r3, r0, lsr #8 @ r3<- CC 5128 and r2, r0, #255 @ r2<- BB 5129 GET_VREG(r1, r3) @ r1<- vCC 5130 GET_VREG(r0, r2) @ r0<- vBB 5131 .if 0 5132 cmp r1, #0 @ is second operand zero? 5133 beq common_errDivideByZero 5134 .endif 5135 5136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5137 @ optional op; may set condition codes 5138 bl fmodf @ r0<- op, r0-r3 changed 5139 GET_INST_OPCODE(ip) @ extract opcode from rINST 5140 SET_VREG(r0, r9) @ vAA<- r0 5141 GOTO_OPCODE(ip) @ jump to next instruction 5142 /* 11-14 instructions */ 5143 5144 5145 5146/* ------------------------------ */ 5147 .balign 64 5148.L_OP_ADD_DOUBLE: /* 0xab */ 5149/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5150/* File: arm-vfp/fbinopWide.S */ 5151 /* 5152 * Generic 64-bit double-precision floating point binary operation. 5153 * Provide an "instr" line that specifies an instruction that performs 5154 * "d2 = d0 op d1". 5155 * 5156 * for: add-double, sub-double, mul-double, div-double 5157 */ 5158 /* doubleop vAA, vBB, vCC */ 5159 FETCH(r0, 1) @ r0<- CCBB 5160 mov r9, rINST, lsr #8 @ r9<- AA 5161 mov r3, r0, lsr #8 @ r3<- CC 5162 and r2, r0, #255 @ r2<- BB 5163 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5164 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5165 fldd d1, [r3] @ d1<- vCC 5166 fldd d0, [r2] @ d0<- vBB 5167 5168 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5169 faddd d2, d0, d1 @ s2<- op 5170 GET_INST_OPCODE(ip) @ extract opcode from rINST 5171 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5172 fstd d2, [r9] @ vAA<- d2 5173 GOTO_OPCODE(ip) @ jump to next instruction 5174 5175 5176/* ------------------------------ */ 5177 .balign 64 5178.L_OP_SUB_DOUBLE: /* 0xac */ 5179/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5180/* File: arm-vfp/fbinopWide.S */ 5181 /* 5182 * Generic 64-bit double-precision floating point binary operation. 5183 * Provide an "instr" line that specifies an instruction that performs 5184 * "d2 = d0 op d1". 5185 * 5186 * for: add-double, sub-double, mul-double, div-double 5187 */ 5188 /* doubleop vAA, vBB, vCC */ 5189 FETCH(r0, 1) @ r0<- CCBB 5190 mov r9, rINST, lsr #8 @ r9<- AA 5191 mov r3, r0, lsr #8 @ r3<- CC 5192 and r2, r0, #255 @ r2<- BB 5193 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5194 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5195 fldd d1, [r3] @ d1<- vCC 5196 fldd d0, [r2] @ d0<- vBB 5197 5198 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5199 fsubd d2, d0, d1 @ s2<- op 5200 GET_INST_OPCODE(ip) @ extract opcode from rINST 5201 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5202 fstd d2, [r9] @ vAA<- d2 5203 GOTO_OPCODE(ip) @ jump to next instruction 5204 5205 5206/* ------------------------------ */ 5207 .balign 64 5208.L_OP_MUL_DOUBLE: /* 0xad */ 5209/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5210/* File: arm-vfp/fbinopWide.S */ 5211 /* 5212 * Generic 64-bit double-precision floating point binary operation. 5213 * Provide an "instr" line that specifies an instruction that performs 5214 * "d2 = d0 op d1". 5215 * 5216 * for: add-double, sub-double, mul-double, div-double 5217 */ 5218 /* doubleop vAA, vBB, vCC */ 5219 FETCH(r0, 1) @ r0<- CCBB 5220 mov r9, rINST, lsr #8 @ r9<- AA 5221 mov r3, r0, lsr #8 @ r3<- CC 5222 and r2, r0, #255 @ r2<- BB 5223 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5224 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5225 fldd d1, [r3] @ d1<- vCC 5226 fldd d0, [r2] @ d0<- vBB 5227 5228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5229 fmuld d2, d0, d1 @ s2<- op 5230 GET_INST_OPCODE(ip) @ extract opcode from rINST 5231 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5232 fstd d2, [r9] @ vAA<- d2 5233 GOTO_OPCODE(ip) @ jump to next instruction 5234 5235 5236/* ------------------------------ */ 5237 .balign 64 5238.L_OP_DIV_DOUBLE: /* 0xae */ 5239/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5240/* File: arm-vfp/fbinopWide.S */ 5241 /* 5242 * Generic 64-bit double-precision floating point binary operation. 5243 * Provide an "instr" line that specifies an instruction that performs 5244 * "d2 = d0 op d1". 5245 * 5246 * for: add-double, sub-double, mul-double, div-double 5247 */ 5248 /* doubleop vAA, vBB, vCC */ 5249 FETCH(r0, 1) @ r0<- CCBB 5250 mov r9, rINST, lsr #8 @ r9<- AA 5251 mov r3, r0, lsr #8 @ r3<- CC 5252 and r2, r0, #255 @ r2<- BB 5253 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5254 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5255 fldd d1, [r3] @ d1<- vCC 5256 fldd d0, [r2] @ d0<- vBB 5257 5258 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5259 fdivd d2, d0, d1 @ s2<- op 5260 GET_INST_OPCODE(ip) @ extract opcode from rINST 5261 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5262 fstd d2, [r9] @ vAA<- d2 5263 GOTO_OPCODE(ip) @ jump to next instruction 5264 5265 5266/* ------------------------------ */ 5267 .balign 64 5268.L_OP_REM_DOUBLE: /* 0xaf */ 5269/* File: armv5te/OP_REM_DOUBLE.S */ 5270/* EABI doesn't define a double remainder function, but libm does */ 5271/* File: armv5te/binopWide.S */ 5272 /* 5273 * Generic 64-bit binary operation. Provide an "instr" line that 5274 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5275 * This could be an ARM instruction or a function call. (If the result 5276 * comes back in a register other than r0, you can override "result".) 5277 * 5278 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5279 * vCC (r1). Useful for integer division and modulus. 5280 * 5281 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5282 * xor-long, add-double, sub-double, mul-double, div-double, 5283 * rem-double 5284 * 5285 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5286 */ 5287 /* binop vAA, vBB, vCC */ 5288 FETCH(r0, 1) @ r0<- CCBB 5289 mov r9, rINST, lsr #8 @ r9<- AA 5290 and r2, r0, #255 @ r2<- BB 5291 mov r3, r0, lsr #8 @ r3<- CC 5292 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5293 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5294 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5295 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5296 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5297 .if 0 5298 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5299 beq common_errDivideByZero 5300 .endif 5301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5302 5303 @ optional op; may set condition codes 5304 bl fmod @ result<- op, r0-r3 changed 5305 GET_INST_OPCODE(ip) @ extract opcode from rINST 5306 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5307 GOTO_OPCODE(ip) @ jump to next instruction 5308 /* 14-17 instructions */ 5309 5310 5311 5312/* ------------------------------ */ 5313 .balign 64 5314.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5315/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5316/* File: armv5te/binop2addr.S */ 5317 /* 5318 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5319 * that specifies an instruction that performs "result = r0 op r1". 5320 * This could be an ARM instruction or a function call. (If the result 5321 * comes back in a register other than r0, you can override "result".) 5322 * 5323 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5324 * vCC (r1). Useful for integer division and modulus. 5325 * 5326 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5327 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5328 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5329 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5330 */ 5331 /* binop/2addr vA, vB */ 5332 mov r9, rINST, lsr #8 @ r9<- A+ 5333 mov r3, rINST, lsr #12 @ r3<- B 5334 and r9, r9, #15 5335 GET_VREG(r1, r3) @ r1<- vB 5336 GET_VREG(r0, r9) @ r0<- vA 5337 .if 0 5338 cmp r1, #0 @ is second operand zero? 5339 beq common_errDivideByZero 5340 .endif 5341 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5342 5343 @ optional op; may set condition codes 5344 add r0, r0, r1 @ r0<- op, r0-r3 changed 5345 GET_INST_OPCODE(ip) @ extract opcode from rINST 5346 SET_VREG(r0, r9) @ vAA<- r0 5347 GOTO_OPCODE(ip) @ jump to next instruction 5348 /* 10-13 instructions */ 5349 5350 5351 5352/* ------------------------------ */ 5353 .balign 64 5354.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5355/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5356/* File: armv5te/binop2addr.S */ 5357 /* 5358 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5359 * that specifies an instruction that performs "result = r0 op r1". 5360 * This could be an ARM instruction or a function call. (If the result 5361 * comes back in a register other than r0, you can override "result".) 5362 * 5363 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5364 * vCC (r1). Useful for integer division and modulus. 5365 * 5366 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5367 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5368 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5369 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5370 */ 5371 /* binop/2addr vA, vB */ 5372 mov r9, rINST, lsr #8 @ r9<- A+ 5373 mov r3, rINST, lsr #12 @ r3<- B 5374 and r9, r9, #15 5375 GET_VREG(r1, r3) @ r1<- vB 5376 GET_VREG(r0, r9) @ r0<- vA 5377 .if 0 5378 cmp r1, #0 @ is second operand zero? 5379 beq common_errDivideByZero 5380 .endif 5381 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5382 5383 @ optional op; may set condition codes 5384 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5385 GET_INST_OPCODE(ip) @ extract opcode from rINST 5386 SET_VREG(r0, r9) @ vAA<- r0 5387 GOTO_OPCODE(ip) @ jump to next instruction 5388 /* 10-13 instructions */ 5389 5390 5391 5392/* ------------------------------ */ 5393 .balign 64 5394.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5395/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5396/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5397/* File: armv5te/binop2addr.S */ 5398 /* 5399 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5400 * that specifies an instruction that performs "result = r0 op r1". 5401 * This could be an ARM instruction or a function call. (If the result 5402 * comes back in a register other than r0, you can override "result".) 5403 * 5404 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5405 * vCC (r1). Useful for integer division and modulus. 5406 * 5407 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5408 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5409 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5410 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5411 */ 5412 /* binop/2addr vA, vB */ 5413 mov r9, rINST, lsr #8 @ r9<- A+ 5414 mov r3, rINST, lsr #12 @ r3<- B 5415 and r9, r9, #15 5416 GET_VREG(r1, r3) @ r1<- vB 5417 GET_VREG(r0, r9) @ r0<- vA 5418 .if 0 5419 cmp r1, #0 @ is second operand zero? 5420 beq common_errDivideByZero 5421 .endif 5422 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5423 5424 @ optional op; may set condition codes 5425 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5426 GET_INST_OPCODE(ip) @ extract opcode from rINST 5427 SET_VREG(r0, r9) @ vAA<- r0 5428 GOTO_OPCODE(ip) @ jump to next instruction 5429 /* 10-13 instructions */ 5430 5431 5432 5433/* ------------------------------ */ 5434 .balign 64 5435.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5436/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5437/* File: armv5te/binop2addr.S */ 5438 /* 5439 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5440 * that specifies an instruction that performs "result = r0 op r1". 5441 * This could be an ARM instruction or a function call. (If the result 5442 * comes back in a register other than r0, you can override "result".) 5443 * 5444 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5445 * vCC (r1). Useful for integer division and modulus. 5446 * 5447 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5448 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5449 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5450 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5451 */ 5452 /* binop/2addr vA, vB */ 5453 mov r9, rINST, lsr #8 @ r9<- A+ 5454 mov r3, rINST, lsr #12 @ r3<- B 5455 and r9, r9, #15 5456 GET_VREG(r1, r3) @ r1<- vB 5457 GET_VREG(r0, r9) @ r0<- vA 5458 .if 1 5459 cmp r1, #0 @ is second operand zero? 5460 beq common_errDivideByZero 5461 .endif 5462 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5463 5464 @ optional op; may set condition codes 5465 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5466 GET_INST_OPCODE(ip) @ extract opcode from rINST 5467 SET_VREG(r0, r9) @ vAA<- r0 5468 GOTO_OPCODE(ip) @ jump to next instruction 5469 /* 10-13 instructions */ 5470 5471 5472 5473/* ------------------------------ */ 5474 .balign 64 5475.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5476/* File: armv5te/OP_REM_INT_2ADDR.S */ 5477/* idivmod returns quotient in r0 and remainder in r1 */ 5478/* File: armv5te/binop2addr.S */ 5479 /* 5480 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5481 * that specifies an instruction that performs "result = r0 op r1". 5482 * This could be an ARM instruction or a function call. (If the result 5483 * comes back in a register other than r0, you can override "result".) 5484 * 5485 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5486 * vCC (r1). Useful for integer division and modulus. 5487 * 5488 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5489 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5490 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5491 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5492 */ 5493 /* binop/2addr vA, vB */ 5494 mov r9, rINST, lsr #8 @ r9<- A+ 5495 mov r3, rINST, lsr #12 @ r3<- B 5496 and r9, r9, #15 5497 GET_VREG(r1, r3) @ r1<- vB 5498 GET_VREG(r0, r9) @ r0<- vA 5499 .if 1 5500 cmp r1, #0 @ is second operand zero? 5501 beq common_errDivideByZero 5502 .endif 5503 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5504 5505 @ optional op; may set condition codes 5506 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5507 GET_INST_OPCODE(ip) @ extract opcode from rINST 5508 SET_VREG(r1, r9) @ vAA<- r1 5509 GOTO_OPCODE(ip) @ jump to next instruction 5510 /* 10-13 instructions */ 5511 5512 5513 5514/* ------------------------------ */ 5515 .balign 64 5516.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5517/* File: armv5te/OP_AND_INT_2ADDR.S */ 5518/* File: armv5te/binop2addr.S */ 5519 /* 5520 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5521 * that specifies an instruction that performs "result = r0 op r1". 5522 * This could be an ARM instruction or a function call. (If the result 5523 * comes back in a register other than r0, you can override "result".) 5524 * 5525 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5526 * vCC (r1). Useful for integer division and modulus. 5527 * 5528 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5529 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5530 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5531 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5532 */ 5533 /* binop/2addr vA, vB */ 5534 mov r9, rINST, lsr #8 @ r9<- A+ 5535 mov r3, rINST, lsr #12 @ r3<- B 5536 and r9, r9, #15 5537 GET_VREG(r1, r3) @ r1<- vB 5538 GET_VREG(r0, r9) @ r0<- vA 5539 .if 0 5540 cmp r1, #0 @ is second operand zero? 5541 beq common_errDivideByZero 5542 .endif 5543 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5544 5545 @ optional op; may set condition codes 5546 and r0, r0, r1 @ r0<- op, r0-r3 changed 5547 GET_INST_OPCODE(ip) @ extract opcode from rINST 5548 SET_VREG(r0, r9) @ vAA<- r0 5549 GOTO_OPCODE(ip) @ jump to next instruction 5550 /* 10-13 instructions */ 5551 5552 5553 5554/* ------------------------------ */ 5555 .balign 64 5556.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5557/* File: armv5te/OP_OR_INT_2ADDR.S */ 5558/* File: armv5te/binop2addr.S */ 5559 /* 5560 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5561 * that specifies an instruction that performs "result = r0 op r1". 5562 * This could be an ARM instruction or a function call. (If the result 5563 * comes back in a register other than r0, you can override "result".) 5564 * 5565 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5566 * vCC (r1). Useful for integer division and modulus. 5567 * 5568 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5569 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5570 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5571 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5572 */ 5573 /* binop/2addr vA, vB */ 5574 mov r9, rINST, lsr #8 @ r9<- A+ 5575 mov r3, rINST, lsr #12 @ r3<- B 5576 and r9, r9, #15 5577 GET_VREG(r1, r3) @ r1<- vB 5578 GET_VREG(r0, r9) @ r0<- vA 5579 .if 0 5580 cmp r1, #0 @ is second operand zero? 5581 beq common_errDivideByZero 5582 .endif 5583 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5584 5585 @ optional op; may set condition codes 5586 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5587 GET_INST_OPCODE(ip) @ extract opcode from rINST 5588 SET_VREG(r0, r9) @ vAA<- r0 5589 GOTO_OPCODE(ip) @ jump to next instruction 5590 /* 10-13 instructions */ 5591 5592 5593 5594/* ------------------------------ */ 5595 .balign 64 5596.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5597/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5598/* File: armv5te/binop2addr.S */ 5599 /* 5600 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5601 * that specifies an instruction that performs "result = r0 op r1". 5602 * This could be an ARM instruction or a function call. (If the result 5603 * comes back in a register other than r0, you can override "result".) 5604 * 5605 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5606 * vCC (r1). Useful for integer division and modulus. 5607 * 5608 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5609 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5610 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5611 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5612 */ 5613 /* binop/2addr vA, vB */ 5614 mov r9, rINST, lsr #8 @ r9<- A+ 5615 mov r3, rINST, lsr #12 @ r3<- B 5616 and r9, r9, #15 5617 GET_VREG(r1, r3) @ r1<- vB 5618 GET_VREG(r0, r9) @ r0<- vA 5619 .if 0 5620 cmp r1, #0 @ is second operand zero? 5621 beq common_errDivideByZero 5622 .endif 5623 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5624 5625 @ optional op; may set condition codes 5626 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5627 GET_INST_OPCODE(ip) @ extract opcode from rINST 5628 SET_VREG(r0, r9) @ vAA<- r0 5629 GOTO_OPCODE(ip) @ jump to next instruction 5630 /* 10-13 instructions */ 5631 5632 5633 5634/* ------------------------------ */ 5635 .balign 64 5636.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5637/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5638/* File: armv5te/binop2addr.S */ 5639 /* 5640 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5641 * that specifies an instruction that performs "result = r0 op r1". 5642 * This could be an ARM instruction or a function call. (If the result 5643 * comes back in a register other than r0, you can override "result".) 5644 * 5645 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5646 * vCC (r1). Useful for integer division and modulus. 5647 * 5648 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5649 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5650 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5651 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5652 */ 5653 /* binop/2addr vA, vB */ 5654 mov r9, rINST, lsr #8 @ r9<- A+ 5655 mov r3, rINST, lsr #12 @ r3<- B 5656 and r9, r9, #15 5657 GET_VREG(r1, r3) @ r1<- vB 5658 GET_VREG(r0, r9) @ r0<- vA 5659 .if 0 5660 cmp r1, #0 @ is second operand zero? 5661 beq common_errDivideByZero 5662 .endif 5663 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5664 5665 and r1, r1, #31 @ optional op; may set condition codes 5666 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5667 GET_INST_OPCODE(ip) @ extract opcode from rINST 5668 SET_VREG(r0, r9) @ vAA<- r0 5669 GOTO_OPCODE(ip) @ jump to next instruction 5670 /* 10-13 instructions */ 5671 5672 5673 5674/* ------------------------------ */ 5675 .balign 64 5676.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5677/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5678/* File: armv5te/binop2addr.S */ 5679 /* 5680 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5681 * that specifies an instruction that performs "result = r0 op r1". 5682 * This could be an ARM instruction or a function call. (If the result 5683 * comes back in a register other than r0, you can override "result".) 5684 * 5685 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5686 * vCC (r1). Useful for integer division and modulus. 5687 * 5688 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5689 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5690 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5691 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5692 */ 5693 /* binop/2addr vA, vB */ 5694 mov r9, rINST, lsr #8 @ r9<- A+ 5695 mov r3, rINST, lsr #12 @ r3<- B 5696 and r9, r9, #15 5697 GET_VREG(r1, r3) @ r1<- vB 5698 GET_VREG(r0, r9) @ r0<- vA 5699 .if 0 5700 cmp r1, #0 @ is second operand zero? 5701 beq common_errDivideByZero 5702 .endif 5703 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5704 5705 and r1, r1, #31 @ optional op; may set condition codes 5706 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5707 GET_INST_OPCODE(ip) @ extract opcode from rINST 5708 SET_VREG(r0, r9) @ vAA<- r0 5709 GOTO_OPCODE(ip) @ jump to next instruction 5710 /* 10-13 instructions */ 5711 5712 5713 5714/* ------------------------------ */ 5715 .balign 64 5716.L_OP_USHR_INT_2ADDR: /* 0xba */ 5717/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5718/* File: armv5te/binop2addr.S */ 5719 /* 5720 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5721 * that specifies an instruction that performs "result = r0 op r1". 5722 * This could be an ARM instruction or a function call. (If the result 5723 * comes back in a register other than r0, you can override "result".) 5724 * 5725 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5726 * vCC (r1). Useful for integer division and modulus. 5727 * 5728 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5729 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5730 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5731 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5732 */ 5733 /* binop/2addr vA, vB */ 5734 mov r9, rINST, lsr #8 @ r9<- A+ 5735 mov r3, rINST, lsr #12 @ r3<- B 5736 and r9, r9, #15 5737 GET_VREG(r1, r3) @ r1<- vB 5738 GET_VREG(r0, r9) @ r0<- vA 5739 .if 0 5740 cmp r1, #0 @ is second operand zero? 5741 beq common_errDivideByZero 5742 .endif 5743 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5744 5745 and r1, r1, #31 @ optional op; may set condition codes 5746 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5747 GET_INST_OPCODE(ip) @ extract opcode from rINST 5748 SET_VREG(r0, r9) @ vAA<- r0 5749 GOTO_OPCODE(ip) @ jump to next instruction 5750 /* 10-13 instructions */ 5751 5752 5753 5754/* ------------------------------ */ 5755 .balign 64 5756.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5757/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5758/* File: armv5te/binopWide2addr.S */ 5759 /* 5760 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5761 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5762 * This could be an ARM instruction or a function call. (If the result 5763 * comes back in a register other than r0, you can override "result".) 5764 * 5765 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5766 * vCC (r1). Useful for integer division and modulus. 5767 * 5768 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5769 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5770 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5771 * rem-double/2addr 5772 */ 5773 /* binop/2addr vA, vB */ 5774 mov r9, rINST, lsr #8 @ r9<- A+ 5775 mov r1, rINST, lsr #12 @ r1<- B 5776 and r9, r9, #15 5777 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5778 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5779 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5780 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5781 .if 0 5782 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5783 beq common_errDivideByZero 5784 .endif 5785 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5786 5787 adds r0, r0, r2 @ optional op; may set condition codes 5788 adc r1, r1, r3 @ result<- op, r0-r3 changed 5789 GET_INST_OPCODE(ip) @ extract opcode from rINST 5790 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5791 GOTO_OPCODE(ip) @ jump to next instruction 5792 /* 12-15 instructions */ 5793 5794 5795 5796/* ------------------------------ */ 5797 .balign 64 5798.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5799/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5800/* File: armv5te/binopWide2addr.S */ 5801 /* 5802 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5803 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5804 * This could be an ARM instruction or a function call. (If the result 5805 * comes back in a register other than r0, you can override "result".) 5806 * 5807 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5808 * vCC (r1). Useful for integer division and modulus. 5809 * 5810 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5811 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5812 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5813 * rem-double/2addr 5814 */ 5815 /* binop/2addr vA, vB */ 5816 mov r9, rINST, lsr #8 @ r9<- A+ 5817 mov r1, rINST, lsr #12 @ r1<- B 5818 and r9, r9, #15 5819 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5820 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5821 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5822 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5823 .if 0 5824 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5825 beq common_errDivideByZero 5826 .endif 5827 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5828 5829 subs r0, r0, r2 @ optional op; may set condition codes 5830 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5831 GET_INST_OPCODE(ip) @ extract opcode from rINST 5832 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5833 GOTO_OPCODE(ip) @ jump to next instruction 5834 /* 12-15 instructions */ 5835 5836 5837 5838/* ------------------------------ */ 5839 .balign 64 5840.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5841/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5842 /* 5843 * Signed 64-bit integer multiply, "/2addr" version. 5844 * 5845 * See OP_MUL_LONG for an explanation. 5846 * 5847 * We get a little tight on registers, so to avoid looking up &fp[A] 5848 * again we stuff it into rINST. 5849 */ 5850 /* mul-long/2addr vA, vB */ 5851 mov r9, rINST, lsr #8 @ r9<- A+ 5852 mov r1, rINST, lsr #12 @ r1<- B 5853 and r9, r9, #15 5854 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5855 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5856 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5857 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5858 mul ip, r2, r1 @ ip<- ZxW 5859 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5860 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5861 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5862 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5863 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5864 GET_INST_OPCODE(ip) @ extract opcode from rINST 5865 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5866 GOTO_OPCODE(ip) @ jump to next instruction 5867 5868 5869/* ------------------------------ */ 5870 .balign 64 5871.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5872/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5873/* File: armv5te/binopWide2addr.S */ 5874 /* 5875 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5876 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5877 * This could be an ARM instruction or a function call. (If the result 5878 * comes back in a register other than r0, you can override "result".) 5879 * 5880 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5881 * vCC (r1). Useful for integer division and modulus. 5882 * 5883 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5884 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5885 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5886 * rem-double/2addr 5887 */ 5888 /* binop/2addr vA, vB */ 5889 mov r9, rINST, lsr #8 @ r9<- A+ 5890 mov r1, rINST, lsr #12 @ r1<- B 5891 and r9, r9, #15 5892 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5893 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5894 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5895 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5896 .if 1 5897 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5898 beq common_errDivideByZero 5899 .endif 5900 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5901 5902 @ optional op; may set condition codes 5903 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5904 GET_INST_OPCODE(ip) @ extract opcode from rINST 5905 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5906 GOTO_OPCODE(ip) @ jump to next instruction 5907 /* 12-15 instructions */ 5908 5909 5910 5911/* ------------------------------ */ 5912 .balign 64 5913.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5914/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5915/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5916/* File: armv5te/binopWide2addr.S */ 5917 /* 5918 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5919 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5920 * This could be an ARM instruction or a function call. (If the result 5921 * comes back in a register other than r0, you can override "result".) 5922 * 5923 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5924 * vCC (r1). Useful for integer division and modulus. 5925 * 5926 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5927 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5928 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5929 * rem-double/2addr 5930 */ 5931 /* binop/2addr vA, vB */ 5932 mov r9, rINST, lsr #8 @ r9<- A+ 5933 mov r1, rINST, lsr #12 @ r1<- B 5934 and r9, r9, #15 5935 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5936 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5937 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5938 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5939 .if 1 5940 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5941 beq common_errDivideByZero 5942 .endif 5943 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5944 5945 @ optional op; may set condition codes 5946 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5947 GET_INST_OPCODE(ip) @ extract opcode from rINST 5948 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5949 GOTO_OPCODE(ip) @ jump to next instruction 5950 /* 12-15 instructions */ 5951 5952 5953 5954/* ------------------------------ */ 5955 .balign 64 5956.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5957/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5958/* File: armv5te/binopWide2addr.S */ 5959 /* 5960 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5961 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5962 * This could be an ARM instruction or a function call. (If the result 5963 * comes back in a register other than r0, you can override "result".) 5964 * 5965 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5966 * vCC (r1). Useful for integer division and modulus. 5967 * 5968 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5969 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5970 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5971 * rem-double/2addr 5972 */ 5973 /* binop/2addr vA, vB */ 5974 mov r9, rINST, lsr #8 @ r9<- A+ 5975 mov r1, rINST, lsr #12 @ r1<- B 5976 and r9, r9, #15 5977 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5978 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5979 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5980 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5981 .if 0 5982 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5983 beq common_errDivideByZero 5984 .endif 5985 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5986 5987 and r0, r0, r2 @ optional op; may set condition codes 5988 and r1, r1, r3 @ result<- op, r0-r3 changed 5989 GET_INST_OPCODE(ip) @ extract opcode from rINST 5990 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5991 GOTO_OPCODE(ip) @ jump to next instruction 5992 /* 12-15 instructions */ 5993 5994 5995 5996/* ------------------------------ */ 5997 .balign 64 5998.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5999/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6000/* File: armv5te/binopWide2addr.S */ 6001 /* 6002 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6003 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6004 * This could be an ARM instruction or a function call. (If the result 6005 * comes back in a register other than r0, you can override "result".) 6006 * 6007 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6008 * vCC (r1). Useful for integer division and modulus. 6009 * 6010 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6011 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6012 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6013 * rem-double/2addr 6014 */ 6015 /* binop/2addr vA, vB */ 6016 mov r9, rINST, lsr #8 @ r9<- A+ 6017 mov r1, rINST, lsr #12 @ r1<- B 6018 and r9, r9, #15 6019 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6020 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6021 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6022 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6023 .if 0 6024 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6025 beq common_errDivideByZero 6026 .endif 6027 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6028 6029 orr r0, r0, r2 @ optional op; may set condition codes 6030 orr r1, r1, r3 @ result<- op, r0-r3 changed 6031 GET_INST_OPCODE(ip) @ extract opcode from rINST 6032 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6033 GOTO_OPCODE(ip) @ jump to next instruction 6034 /* 12-15 instructions */ 6035 6036 6037 6038/* ------------------------------ */ 6039 .balign 64 6040.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6041/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6042/* File: armv5te/binopWide2addr.S */ 6043 /* 6044 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6045 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6046 * This could be an ARM instruction or a function call. (If the result 6047 * comes back in a register other than r0, you can override "result".) 6048 * 6049 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6050 * vCC (r1). Useful for integer division and modulus. 6051 * 6052 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6053 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6054 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6055 * rem-double/2addr 6056 */ 6057 /* binop/2addr vA, vB */ 6058 mov r9, rINST, lsr #8 @ r9<- A+ 6059 mov r1, rINST, lsr #12 @ r1<- B 6060 and r9, r9, #15 6061 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6062 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6063 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6064 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6065 .if 0 6066 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6067 beq common_errDivideByZero 6068 .endif 6069 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6070 6071 eor r0, r0, r2 @ optional op; may set condition codes 6072 eor r1, r1, r3 @ result<- op, r0-r3 changed 6073 GET_INST_OPCODE(ip) @ extract opcode from rINST 6074 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6075 GOTO_OPCODE(ip) @ jump to next instruction 6076 /* 12-15 instructions */ 6077 6078 6079 6080/* ------------------------------ */ 6081 .balign 64 6082.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6083/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6084 /* 6085 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6086 * 32-bit shift distance. 6087 */ 6088 /* shl-long/2addr vA, vB */ 6089 mov r9, rINST, lsr #8 @ r9<- A+ 6090 mov r3, rINST, lsr #12 @ r3<- B 6091 and r9, r9, #15 6092 GET_VREG(r2, r3) @ r2<- vB 6093 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6094 and r2, r2, #63 @ r2<- r2 & 0x3f 6095 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6096 6097 mov r1, r1, asl r2 @ r1<- r1 << r2 6098 rsb r3, r2, #32 @ r3<- 32 - r2 6099 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6100 subs ip, r2, #32 @ ip<- r2 - 32 6101 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6102 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6103 mov r0, r0, asl r2 @ r0<- r0 << r2 6104 b .LOP_SHL_LONG_2ADDR_finish 6105 6106/* ------------------------------ */ 6107 .balign 64 6108.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6109/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6110 /* 6111 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6112 * 32-bit shift distance. 6113 */ 6114 /* shr-long/2addr vA, vB */ 6115 mov r9, rINST, lsr #8 @ r9<- A+ 6116 mov r3, rINST, lsr #12 @ r3<- B 6117 and r9, r9, #15 6118 GET_VREG(r2, r3) @ r2<- vB 6119 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6120 and r2, r2, #63 @ r2<- r2 & 0x3f 6121 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6122 6123 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6124 rsb r3, r2, #32 @ r3<- 32 - r2 6125 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6126 subs ip, r2, #32 @ ip<- r2 - 32 6127 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6128 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6129 mov r1, r1, asr r2 @ r1<- r1 >> r2 6130 b .LOP_SHR_LONG_2ADDR_finish 6131 6132/* ------------------------------ */ 6133 .balign 64 6134.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6135/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6136 /* 6137 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6138 * 32-bit shift distance. 6139 */ 6140 /* ushr-long/2addr vA, vB */ 6141 mov r9, rINST, lsr #8 @ r9<- A+ 6142 mov r3, rINST, lsr #12 @ r3<- B 6143 and r9, r9, #15 6144 GET_VREG(r2, r3) @ r2<- vB 6145 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6146 and r2, r2, #63 @ r2<- r2 & 0x3f 6147 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6148 6149 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6150 rsb r3, r2, #32 @ r3<- 32 - r2 6151 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6152 subs ip, r2, #32 @ ip<- r2 - 32 6153 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6154 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6155 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6156 b .LOP_USHR_LONG_2ADDR_finish 6157 6158/* ------------------------------ */ 6159 .balign 64 6160.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6161/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6162/* File: arm-vfp/fbinop2addr.S */ 6163 /* 6164 * Generic 32-bit floating point "/2addr" binary operation. Provide 6165 * an "instr" line that specifies an instruction that performs 6166 * "s2 = s0 op s1". 6167 * 6168 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6169 */ 6170 /* binop/2addr vA, vB */ 6171 mov r3, rINST, lsr #12 @ r3<- B 6172 mov r9, rINST, lsr #8 @ r9<- A+ 6173 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6174 and r9, r9, #15 @ r9<- A 6175 flds s1, [r3] @ s1<- vB 6176 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6177 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6178 flds s0, [r9] @ s0<- vA 6179 6180 fadds s2, s0, s1 @ s2<- op 6181 GET_INST_OPCODE(ip) @ extract opcode from rINST 6182 fsts s2, [r9] @ vAA<- s2 6183 GOTO_OPCODE(ip) @ jump to next instruction 6184 6185 6186/* ------------------------------ */ 6187 .balign 64 6188.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6189/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6190/* File: arm-vfp/fbinop2addr.S */ 6191 /* 6192 * Generic 32-bit floating point "/2addr" binary operation. Provide 6193 * an "instr" line that specifies an instruction that performs 6194 * "s2 = s0 op s1". 6195 * 6196 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6197 */ 6198 /* binop/2addr vA, vB */ 6199 mov r3, rINST, lsr #12 @ r3<- B 6200 mov r9, rINST, lsr #8 @ r9<- A+ 6201 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6202 and r9, r9, #15 @ r9<- A 6203 flds s1, [r3] @ s1<- vB 6204 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6205 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6206 flds s0, [r9] @ s0<- vA 6207 6208 fsubs s2, s0, s1 @ s2<- op 6209 GET_INST_OPCODE(ip) @ extract opcode from rINST 6210 fsts s2, [r9] @ vAA<- s2 6211 GOTO_OPCODE(ip) @ jump to next instruction 6212 6213 6214/* ------------------------------ */ 6215 .balign 64 6216.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6217/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6218/* File: arm-vfp/fbinop2addr.S */ 6219 /* 6220 * Generic 32-bit floating point "/2addr" binary operation. Provide 6221 * an "instr" line that specifies an instruction that performs 6222 * "s2 = s0 op s1". 6223 * 6224 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6225 */ 6226 /* binop/2addr vA, vB */ 6227 mov r3, rINST, lsr #12 @ r3<- B 6228 mov r9, rINST, lsr #8 @ r9<- A+ 6229 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6230 and r9, r9, #15 @ r9<- A 6231 flds s1, [r3] @ s1<- vB 6232 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6233 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6234 flds s0, [r9] @ s0<- vA 6235 6236 fmuls s2, s0, s1 @ s2<- op 6237 GET_INST_OPCODE(ip) @ extract opcode from rINST 6238 fsts s2, [r9] @ vAA<- s2 6239 GOTO_OPCODE(ip) @ jump to next instruction 6240 6241 6242/* ------------------------------ */ 6243 .balign 64 6244.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6245/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6246/* File: arm-vfp/fbinop2addr.S */ 6247 /* 6248 * Generic 32-bit floating point "/2addr" binary operation. Provide 6249 * an "instr" line that specifies an instruction that performs 6250 * "s2 = s0 op s1". 6251 * 6252 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6253 */ 6254 /* binop/2addr vA, vB */ 6255 mov r3, rINST, lsr #12 @ r3<- B 6256 mov r9, rINST, lsr #8 @ r9<- A+ 6257 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6258 and r9, r9, #15 @ r9<- A 6259 flds s1, [r3] @ s1<- vB 6260 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6261 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6262 flds s0, [r9] @ s0<- vA 6263 6264 fdivs s2, s0, s1 @ s2<- op 6265 GET_INST_OPCODE(ip) @ extract opcode from rINST 6266 fsts s2, [r9] @ vAA<- s2 6267 GOTO_OPCODE(ip) @ jump to next instruction 6268 6269 6270/* ------------------------------ */ 6271 .balign 64 6272.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6273/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6274/* EABI doesn't define a float remainder function, but libm does */ 6275/* File: armv5te/binop2addr.S */ 6276 /* 6277 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6278 * that specifies an instruction that performs "result = r0 op r1". 6279 * This could be an ARM instruction or a function call. (If the result 6280 * comes back in a register other than r0, you can override "result".) 6281 * 6282 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6283 * vCC (r1). Useful for integer division and modulus. 6284 * 6285 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6286 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6287 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6288 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6289 */ 6290 /* binop/2addr vA, vB */ 6291 mov r9, rINST, lsr #8 @ r9<- A+ 6292 mov r3, rINST, lsr #12 @ r3<- B 6293 and r9, r9, #15 6294 GET_VREG(r1, r3) @ r1<- vB 6295 GET_VREG(r0, r9) @ r0<- vA 6296 .if 0 6297 cmp r1, #0 @ is second operand zero? 6298 beq common_errDivideByZero 6299 .endif 6300 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6301 6302 @ optional op; may set condition codes 6303 bl fmodf @ r0<- op, r0-r3 changed 6304 GET_INST_OPCODE(ip) @ extract opcode from rINST 6305 SET_VREG(r0, r9) @ vAA<- r0 6306 GOTO_OPCODE(ip) @ jump to next instruction 6307 /* 10-13 instructions */ 6308 6309 6310 6311/* ------------------------------ */ 6312 .balign 64 6313.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6314/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6315/* File: arm-vfp/fbinopWide2addr.S */ 6316 /* 6317 * Generic 64-bit floating point "/2addr" binary operation. Provide 6318 * an "instr" line that specifies an instruction that performs 6319 * "d2 = d0 op d1". 6320 * 6321 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6322 * div-double/2addr 6323 */ 6324 /* binop/2addr vA, vB */ 6325 mov r3, rINST, lsr #12 @ r3<- B 6326 mov r9, rINST, lsr #8 @ r9<- A+ 6327 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6328 and r9, r9, #15 @ r9<- A 6329 fldd d1, [r3] @ d1<- vB 6330 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6331 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6332 fldd d0, [r9] @ d0<- vA 6333 6334 faddd d2, d0, d1 @ d2<- op 6335 GET_INST_OPCODE(ip) @ extract opcode from rINST 6336 fstd d2, [r9] @ vAA<- d2 6337 GOTO_OPCODE(ip) @ jump to next instruction 6338 6339 6340/* ------------------------------ */ 6341 .balign 64 6342.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6343/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6344/* File: arm-vfp/fbinopWide2addr.S */ 6345 /* 6346 * Generic 64-bit floating point "/2addr" binary operation. Provide 6347 * an "instr" line that specifies an instruction that performs 6348 * "d2 = d0 op d1". 6349 * 6350 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6351 * div-double/2addr 6352 */ 6353 /* binop/2addr vA, vB */ 6354 mov r3, rINST, lsr #12 @ r3<- B 6355 mov r9, rINST, lsr #8 @ r9<- A+ 6356 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6357 and r9, r9, #15 @ r9<- A 6358 fldd d1, [r3] @ d1<- vB 6359 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6360 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6361 fldd d0, [r9] @ d0<- vA 6362 6363 fsubd d2, d0, d1 @ d2<- op 6364 GET_INST_OPCODE(ip) @ extract opcode from rINST 6365 fstd d2, [r9] @ vAA<- d2 6366 GOTO_OPCODE(ip) @ jump to next instruction 6367 6368 6369/* ------------------------------ */ 6370 .balign 64 6371.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6372/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6373/* File: arm-vfp/fbinopWide2addr.S */ 6374 /* 6375 * Generic 64-bit floating point "/2addr" binary operation. Provide 6376 * an "instr" line that specifies an instruction that performs 6377 * "d2 = d0 op d1". 6378 * 6379 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6380 * div-double/2addr 6381 */ 6382 /* binop/2addr vA, vB */ 6383 mov r3, rINST, lsr #12 @ r3<- B 6384 mov r9, rINST, lsr #8 @ r9<- A+ 6385 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6386 and r9, r9, #15 @ r9<- A 6387 fldd d1, [r3] @ d1<- vB 6388 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6389 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6390 fldd d0, [r9] @ d0<- vA 6391 6392 fmuld d2, d0, d1 @ d2<- op 6393 GET_INST_OPCODE(ip) @ extract opcode from rINST 6394 fstd d2, [r9] @ vAA<- d2 6395 GOTO_OPCODE(ip) @ jump to next instruction 6396 6397 6398/* ------------------------------ */ 6399 .balign 64 6400.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6401/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6402/* File: arm-vfp/fbinopWide2addr.S */ 6403 /* 6404 * Generic 64-bit floating point "/2addr" binary operation. Provide 6405 * an "instr" line that specifies an instruction that performs 6406 * "d2 = d0 op d1". 6407 * 6408 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6409 * div-double/2addr 6410 */ 6411 /* binop/2addr vA, vB */ 6412 mov r3, rINST, lsr #12 @ r3<- B 6413 mov r9, rINST, lsr #8 @ r9<- A+ 6414 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6415 and r9, r9, #15 @ r9<- A 6416 fldd d1, [r3] @ d1<- vB 6417 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6418 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6419 fldd d0, [r9] @ d0<- vA 6420 6421 fdivd d2, d0, d1 @ d2<- op 6422 GET_INST_OPCODE(ip) @ extract opcode from rINST 6423 fstd d2, [r9] @ vAA<- d2 6424 GOTO_OPCODE(ip) @ jump to next instruction 6425 6426 6427/* ------------------------------ */ 6428 .balign 64 6429.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6430/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6431/* EABI doesn't define a double remainder function, but libm does */ 6432/* File: armv5te/binopWide2addr.S */ 6433 /* 6434 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6435 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6436 * This could be an ARM instruction or a function call. (If the result 6437 * comes back in a register other than r0, you can override "result".) 6438 * 6439 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6440 * vCC (r1). Useful for integer division and modulus. 6441 * 6442 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6443 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6444 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6445 * rem-double/2addr 6446 */ 6447 /* binop/2addr vA, vB */ 6448 mov r9, rINST, lsr #8 @ r9<- A+ 6449 mov r1, rINST, lsr #12 @ r1<- B 6450 and r9, r9, #15 6451 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6452 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6453 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6454 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6455 .if 0 6456 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6457 beq common_errDivideByZero 6458 .endif 6459 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6460 6461 @ optional op; may set condition codes 6462 bl fmod @ result<- op, r0-r3 changed 6463 GET_INST_OPCODE(ip) @ extract opcode from rINST 6464 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6465 GOTO_OPCODE(ip) @ jump to next instruction 6466 /* 12-15 instructions */ 6467 6468 6469 6470/* ------------------------------ */ 6471 .balign 64 6472.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6473/* File: armv5te/OP_ADD_INT_LIT16.S */ 6474/* File: armv5te/binopLit16.S */ 6475 /* 6476 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6477 * that specifies an instruction that performs "result = r0 op r1". 6478 * This could be an ARM instruction or a function call. (If the result 6479 * comes back in a register other than r0, you can override "result".) 6480 * 6481 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6482 * vCC (r1). Useful for integer division and modulus. 6483 * 6484 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6485 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6486 */ 6487 /* binop/lit16 vA, vB, #+CCCC */ 6488 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6489 mov r2, rINST, lsr #12 @ r2<- B 6490 mov r9, rINST, lsr #8 @ r9<- A+ 6491 GET_VREG(r0, r2) @ r0<- vB 6492 and r9, r9, #15 6493 .if 0 6494 cmp r1, #0 @ is second operand zero? 6495 beq common_errDivideByZero 6496 .endif 6497 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6498 6499 add r0, r0, r1 @ r0<- op, r0-r3 changed 6500 GET_INST_OPCODE(ip) @ extract opcode from rINST 6501 SET_VREG(r0, r9) @ vAA<- r0 6502 GOTO_OPCODE(ip) @ jump to next instruction 6503 /* 10-13 instructions */ 6504 6505 6506 6507/* ------------------------------ */ 6508 .balign 64 6509.L_OP_RSUB_INT: /* 0xd1 */ 6510/* File: armv5te/OP_RSUB_INT.S */ 6511/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6512/* File: armv5te/binopLit16.S */ 6513 /* 6514 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6515 * that specifies an instruction that performs "result = r0 op r1". 6516 * This could be an ARM instruction or a function call. (If the result 6517 * comes back in a register other than r0, you can override "result".) 6518 * 6519 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6520 * vCC (r1). Useful for integer division and modulus. 6521 * 6522 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6523 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6524 */ 6525 /* binop/lit16 vA, vB, #+CCCC */ 6526 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6527 mov r2, rINST, lsr #12 @ r2<- B 6528 mov r9, rINST, lsr #8 @ r9<- A+ 6529 GET_VREG(r0, r2) @ r0<- vB 6530 and r9, r9, #15 6531 .if 0 6532 cmp r1, #0 @ is second operand zero? 6533 beq common_errDivideByZero 6534 .endif 6535 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6536 6537 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6538 GET_INST_OPCODE(ip) @ extract opcode from rINST 6539 SET_VREG(r0, r9) @ vAA<- r0 6540 GOTO_OPCODE(ip) @ jump to next instruction 6541 /* 10-13 instructions */ 6542 6543 6544 6545/* ------------------------------ */ 6546 .balign 64 6547.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6548/* File: armv5te/OP_MUL_INT_LIT16.S */ 6549/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6550/* File: armv5te/binopLit16.S */ 6551 /* 6552 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6553 * that specifies an instruction that performs "result = r0 op r1". 6554 * This could be an ARM instruction or a function call. (If the result 6555 * comes back in a register other than r0, you can override "result".) 6556 * 6557 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6558 * vCC (r1). Useful for integer division and modulus. 6559 * 6560 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6561 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6562 */ 6563 /* binop/lit16 vA, vB, #+CCCC */ 6564 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6565 mov r2, rINST, lsr #12 @ r2<- B 6566 mov r9, rINST, lsr #8 @ r9<- A+ 6567 GET_VREG(r0, r2) @ r0<- vB 6568 and r9, r9, #15 6569 .if 0 6570 cmp r1, #0 @ is second operand zero? 6571 beq common_errDivideByZero 6572 .endif 6573 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6574 6575 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6576 GET_INST_OPCODE(ip) @ extract opcode from rINST 6577 SET_VREG(r0, r9) @ vAA<- r0 6578 GOTO_OPCODE(ip) @ jump to next instruction 6579 /* 10-13 instructions */ 6580 6581 6582 6583/* ------------------------------ */ 6584 .balign 64 6585.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6586/* File: armv5te/OP_DIV_INT_LIT16.S */ 6587/* File: armv5te/binopLit16.S */ 6588 /* 6589 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6590 * that specifies an instruction that performs "result = r0 op r1". 6591 * This could be an ARM instruction or a function call. (If the result 6592 * comes back in a register other than r0, you can override "result".) 6593 * 6594 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6595 * vCC (r1). Useful for integer division and modulus. 6596 * 6597 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6598 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6599 */ 6600 /* binop/lit16 vA, vB, #+CCCC */ 6601 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6602 mov r2, rINST, lsr #12 @ r2<- B 6603 mov r9, rINST, lsr #8 @ r9<- A+ 6604 GET_VREG(r0, r2) @ r0<- vB 6605 and r9, r9, #15 6606 .if 1 6607 cmp r1, #0 @ is second operand zero? 6608 beq common_errDivideByZero 6609 .endif 6610 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6611 6612 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6613 GET_INST_OPCODE(ip) @ extract opcode from rINST 6614 SET_VREG(r0, r9) @ vAA<- r0 6615 GOTO_OPCODE(ip) @ jump to next instruction 6616 /* 10-13 instructions */ 6617 6618 6619 6620/* ------------------------------ */ 6621 .balign 64 6622.L_OP_REM_INT_LIT16: /* 0xd4 */ 6623/* File: armv5te/OP_REM_INT_LIT16.S */ 6624/* idivmod returns quotient in r0 and remainder in r1 */ 6625/* File: armv5te/binopLit16.S */ 6626 /* 6627 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6628 * that specifies an instruction that performs "result = r0 op r1". 6629 * This could be an ARM instruction or a function call. (If the result 6630 * comes back in a register other than r0, you can override "result".) 6631 * 6632 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6633 * vCC (r1). Useful for integer division and modulus. 6634 * 6635 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6636 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6637 */ 6638 /* binop/lit16 vA, vB, #+CCCC */ 6639 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6640 mov r2, rINST, lsr #12 @ r2<- B 6641 mov r9, rINST, lsr #8 @ r9<- A+ 6642 GET_VREG(r0, r2) @ r0<- vB 6643 and r9, r9, #15 6644 .if 1 6645 cmp r1, #0 @ is second operand zero? 6646 beq common_errDivideByZero 6647 .endif 6648 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6649 6650 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6651 GET_INST_OPCODE(ip) @ extract opcode from rINST 6652 SET_VREG(r1, r9) @ vAA<- r1 6653 GOTO_OPCODE(ip) @ jump to next instruction 6654 /* 10-13 instructions */ 6655 6656 6657 6658/* ------------------------------ */ 6659 .balign 64 6660.L_OP_AND_INT_LIT16: /* 0xd5 */ 6661/* File: armv5te/OP_AND_INT_LIT16.S */ 6662/* File: armv5te/binopLit16.S */ 6663 /* 6664 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6665 * that specifies an instruction that performs "result = r0 op r1". 6666 * This could be an ARM instruction or a function call. (If the result 6667 * comes back in a register other than r0, you can override "result".) 6668 * 6669 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6670 * vCC (r1). Useful for integer division and modulus. 6671 * 6672 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6673 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6674 */ 6675 /* binop/lit16 vA, vB, #+CCCC */ 6676 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6677 mov r2, rINST, lsr #12 @ r2<- B 6678 mov r9, rINST, lsr #8 @ r9<- A+ 6679 GET_VREG(r0, r2) @ r0<- vB 6680 and r9, r9, #15 6681 .if 0 6682 cmp r1, #0 @ is second operand zero? 6683 beq common_errDivideByZero 6684 .endif 6685 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6686 6687 and r0, r0, r1 @ r0<- op, r0-r3 changed 6688 GET_INST_OPCODE(ip) @ extract opcode from rINST 6689 SET_VREG(r0, r9) @ vAA<- r0 6690 GOTO_OPCODE(ip) @ jump to next instruction 6691 /* 10-13 instructions */ 6692 6693 6694 6695/* ------------------------------ */ 6696 .balign 64 6697.L_OP_OR_INT_LIT16: /* 0xd6 */ 6698/* File: armv5te/OP_OR_INT_LIT16.S */ 6699/* File: armv5te/binopLit16.S */ 6700 /* 6701 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6702 * that specifies an instruction that performs "result = r0 op r1". 6703 * This could be an ARM instruction or a function call. (If the result 6704 * comes back in a register other than r0, you can override "result".) 6705 * 6706 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6707 * vCC (r1). Useful for integer division and modulus. 6708 * 6709 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6710 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6711 */ 6712 /* binop/lit16 vA, vB, #+CCCC */ 6713 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6714 mov r2, rINST, lsr #12 @ r2<- B 6715 mov r9, rINST, lsr #8 @ r9<- A+ 6716 GET_VREG(r0, r2) @ r0<- vB 6717 and r9, r9, #15 6718 .if 0 6719 cmp r1, #0 @ is second operand zero? 6720 beq common_errDivideByZero 6721 .endif 6722 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6723 6724 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6725 GET_INST_OPCODE(ip) @ extract opcode from rINST 6726 SET_VREG(r0, r9) @ vAA<- r0 6727 GOTO_OPCODE(ip) @ jump to next instruction 6728 /* 10-13 instructions */ 6729 6730 6731 6732/* ------------------------------ */ 6733 .balign 64 6734.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6735/* File: armv5te/OP_XOR_INT_LIT16.S */ 6736/* File: armv5te/binopLit16.S */ 6737 /* 6738 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6739 * that specifies an instruction that performs "result = r0 op r1". 6740 * This could be an ARM instruction or a function call. (If the result 6741 * comes back in a register other than r0, you can override "result".) 6742 * 6743 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6744 * vCC (r1). Useful for integer division and modulus. 6745 * 6746 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6747 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6748 */ 6749 /* binop/lit16 vA, vB, #+CCCC */ 6750 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6751 mov r2, rINST, lsr #12 @ r2<- B 6752 mov r9, rINST, lsr #8 @ r9<- A+ 6753 GET_VREG(r0, r2) @ r0<- vB 6754 and r9, r9, #15 6755 .if 0 6756 cmp r1, #0 @ is second operand zero? 6757 beq common_errDivideByZero 6758 .endif 6759 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6760 6761 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6762 GET_INST_OPCODE(ip) @ extract opcode from rINST 6763 SET_VREG(r0, r9) @ vAA<- r0 6764 GOTO_OPCODE(ip) @ jump to next instruction 6765 /* 10-13 instructions */ 6766 6767 6768 6769/* ------------------------------ */ 6770 .balign 64 6771.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6772/* File: armv5te/OP_ADD_INT_LIT8.S */ 6773/* File: armv5te/binopLit8.S */ 6774 /* 6775 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6776 * that specifies an instruction that performs "result = r0 op r1". 6777 * This could be an ARM instruction or a function call. (If the result 6778 * comes back in a register other than r0, you can override "result".) 6779 * 6780 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6781 * vCC (r1). Useful for integer division and modulus. 6782 * 6783 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6784 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6785 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6786 */ 6787 /* binop/lit8 vAA, vBB, #+CC */ 6788 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6789 mov r9, rINST, lsr #8 @ r9<- AA 6790 and r2, r3, #255 @ r2<- BB 6791 GET_VREG(r0, r2) @ r0<- vBB 6792 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6793 .if 0 6794 @cmp r1, #0 @ is second operand zero? 6795 beq common_errDivideByZero 6796 .endif 6797 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6798 6799 @ optional op; may set condition codes 6800 add r0, r0, r1 @ r0<- op, r0-r3 changed 6801 GET_INST_OPCODE(ip) @ extract opcode from rINST 6802 SET_VREG(r0, r9) @ vAA<- r0 6803 GOTO_OPCODE(ip) @ jump to next instruction 6804 /* 10-12 instructions */ 6805 6806 6807 6808/* ------------------------------ */ 6809 .balign 64 6810.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6811/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6812/* File: armv5te/binopLit8.S */ 6813 /* 6814 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6815 * that specifies an instruction that performs "result = r0 op r1". 6816 * This could be an ARM instruction or a function call. (If the result 6817 * comes back in a register other than r0, you can override "result".) 6818 * 6819 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6820 * vCC (r1). Useful for integer division and modulus. 6821 * 6822 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6823 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6824 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6825 */ 6826 /* binop/lit8 vAA, vBB, #+CC */ 6827 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6828 mov r9, rINST, lsr #8 @ r9<- AA 6829 and r2, r3, #255 @ r2<- BB 6830 GET_VREG(r0, r2) @ r0<- vBB 6831 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6832 .if 0 6833 @cmp r1, #0 @ is second operand zero? 6834 beq common_errDivideByZero 6835 .endif 6836 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6837 6838 @ optional op; may set condition codes 6839 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6840 GET_INST_OPCODE(ip) @ extract opcode from rINST 6841 SET_VREG(r0, r9) @ vAA<- r0 6842 GOTO_OPCODE(ip) @ jump to next instruction 6843 /* 10-12 instructions */ 6844 6845 6846 6847/* ------------------------------ */ 6848 .balign 64 6849.L_OP_MUL_INT_LIT8: /* 0xda */ 6850/* File: armv5te/OP_MUL_INT_LIT8.S */ 6851/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6852/* File: armv5te/binopLit8.S */ 6853 /* 6854 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6855 * that specifies an instruction that performs "result = r0 op r1". 6856 * This could be an ARM instruction or a function call. (If the result 6857 * comes back in a register other than r0, you can override "result".) 6858 * 6859 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6860 * vCC (r1). Useful for integer division and modulus. 6861 * 6862 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6863 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6864 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6865 */ 6866 /* binop/lit8 vAA, vBB, #+CC */ 6867 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6868 mov r9, rINST, lsr #8 @ r9<- AA 6869 and r2, r3, #255 @ r2<- BB 6870 GET_VREG(r0, r2) @ r0<- vBB 6871 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6872 .if 0 6873 @cmp r1, #0 @ is second operand zero? 6874 beq common_errDivideByZero 6875 .endif 6876 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6877 6878 @ optional op; may set condition codes 6879 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6880 GET_INST_OPCODE(ip) @ extract opcode from rINST 6881 SET_VREG(r0, r9) @ vAA<- r0 6882 GOTO_OPCODE(ip) @ jump to next instruction 6883 /* 10-12 instructions */ 6884 6885 6886 6887/* ------------------------------ */ 6888 .balign 64 6889.L_OP_DIV_INT_LIT8: /* 0xdb */ 6890/* File: armv5te/OP_DIV_INT_LIT8.S */ 6891/* File: armv5te/binopLit8.S */ 6892 /* 6893 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6894 * that specifies an instruction that performs "result = r0 op r1". 6895 * This could be an ARM instruction or a function call. (If the result 6896 * comes back in a register other than r0, you can override "result".) 6897 * 6898 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6899 * vCC (r1). Useful for integer division and modulus. 6900 * 6901 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6902 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6903 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6904 */ 6905 /* binop/lit8 vAA, vBB, #+CC */ 6906 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6907 mov r9, rINST, lsr #8 @ r9<- AA 6908 and r2, r3, #255 @ r2<- BB 6909 GET_VREG(r0, r2) @ r0<- vBB 6910 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6911 .if 1 6912 @cmp r1, #0 @ is second operand zero? 6913 beq common_errDivideByZero 6914 .endif 6915 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6916 6917 @ optional op; may set condition codes 6918 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6919 GET_INST_OPCODE(ip) @ extract opcode from rINST 6920 SET_VREG(r0, r9) @ vAA<- r0 6921 GOTO_OPCODE(ip) @ jump to next instruction 6922 /* 10-12 instructions */ 6923 6924 6925 6926/* ------------------------------ */ 6927 .balign 64 6928.L_OP_REM_INT_LIT8: /* 0xdc */ 6929/* File: armv5te/OP_REM_INT_LIT8.S */ 6930/* idivmod returns quotient in r0 and remainder in r1 */ 6931/* File: armv5te/binopLit8.S */ 6932 /* 6933 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6934 * that specifies an instruction that performs "result = r0 op r1". 6935 * This could be an ARM instruction or a function call. (If the result 6936 * comes back in a register other than r0, you can override "result".) 6937 * 6938 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6939 * vCC (r1). Useful for integer division and modulus. 6940 * 6941 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6942 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6943 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6944 */ 6945 /* binop/lit8 vAA, vBB, #+CC */ 6946 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6947 mov r9, rINST, lsr #8 @ r9<- AA 6948 and r2, r3, #255 @ r2<- BB 6949 GET_VREG(r0, r2) @ r0<- vBB 6950 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6951 .if 1 6952 @cmp r1, #0 @ is second operand zero? 6953 beq common_errDivideByZero 6954 .endif 6955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6956 6957 @ optional op; may set condition codes 6958 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6959 GET_INST_OPCODE(ip) @ extract opcode from rINST 6960 SET_VREG(r1, r9) @ vAA<- r1 6961 GOTO_OPCODE(ip) @ jump to next instruction 6962 /* 10-12 instructions */ 6963 6964 6965 6966/* ------------------------------ */ 6967 .balign 64 6968.L_OP_AND_INT_LIT8: /* 0xdd */ 6969/* File: armv5te/OP_AND_INT_LIT8.S */ 6970/* File: armv5te/binopLit8.S */ 6971 /* 6972 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6973 * that specifies an instruction that performs "result = r0 op r1". 6974 * This could be an ARM instruction or a function call. (If the result 6975 * comes back in a register other than r0, you can override "result".) 6976 * 6977 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6978 * vCC (r1). Useful for integer division and modulus. 6979 * 6980 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6981 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6982 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6983 */ 6984 /* binop/lit8 vAA, vBB, #+CC */ 6985 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6986 mov r9, rINST, lsr #8 @ r9<- AA 6987 and r2, r3, #255 @ r2<- BB 6988 GET_VREG(r0, r2) @ r0<- vBB 6989 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6990 .if 0 6991 @cmp r1, #0 @ is second operand zero? 6992 beq common_errDivideByZero 6993 .endif 6994 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6995 6996 @ optional op; may set condition codes 6997 and r0, r0, r1 @ r0<- op, r0-r3 changed 6998 GET_INST_OPCODE(ip) @ extract opcode from rINST 6999 SET_VREG(r0, r9) @ vAA<- r0 7000 GOTO_OPCODE(ip) @ jump to next instruction 7001 /* 10-12 instructions */ 7002 7003 7004 7005/* ------------------------------ */ 7006 .balign 64 7007.L_OP_OR_INT_LIT8: /* 0xde */ 7008/* File: armv5te/OP_OR_INT_LIT8.S */ 7009/* File: armv5te/binopLit8.S */ 7010 /* 7011 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7012 * that specifies an instruction that performs "result = r0 op r1". 7013 * This could be an ARM instruction or a function call. (If the result 7014 * comes back in a register other than r0, you can override "result".) 7015 * 7016 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7017 * vCC (r1). Useful for integer division and modulus. 7018 * 7019 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7020 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7021 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7022 */ 7023 /* binop/lit8 vAA, vBB, #+CC */ 7024 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7025 mov r9, rINST, lsr #8 @ r9<- AA 7026 and r2, r3, #255 @ r2<- BB 7027 GET_VREG(r0, r2) @ r0<- vBB 7028 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7029 .if 0 7030 @cmp r1, #0 @ is second operand zero? 7031 beq common_errDivideByZero 7032 .endif 7033 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7034 7035 @ optional op; may set condition codes 7036 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7037 GET_INST_OPCODE(ip) @ extract opcode from rINST 7038 SET_VREG(r0, r9) @ vAA<- r0 7039 GOTO_OPCODE(ip) @ jump to next instruction 7040 /* 10-12 instructions */ 7041 7042 7043 7044/* ------------------------------ */ 7045 .balign 64 7046.L_OP_XOR_INT_LIT8: /* 0xdf */ 7047/* File: armv5te/OP_XOR_INT_LIT8.S */ 7048/* File: armv5te/binopLit8.S */ 7049 /* 7050 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7051 * that specifies an instruction that performs "result = r0 op r1". 7052 * This could be an ARM instruction or a function call. (If the result 7053 * comes back in a register other than r0, you can override "result".) 7054 * 7055 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7056 * vCC (r1). Useful for integer division and modulus. 7057 * 7058 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7059 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7060 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7061 */ 7062 /* binop/lit8 vAA, vBB, #+CC */ 7063 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7064 mov r9, rINST, lsr #8 @ r9<- AA 7065 and r2, r3, #255 @ r2<- BB 7066 GET_VREG(r0, r2) @ r0<- vBB 7067 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7068 .if 0 7069 @cmp r1, #0 @ is second operand zero? 7070 beq common_errDivideByZero 7071 .endif 7072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7073 7074 @ optional op; may set condition codes 7075 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7076 GET_INST_OPCODE(ip) @ extract opcode from rINST 7077 SET_VREG(r0, r9) @ vAA<- r0 7078 GOTO_OPCODE(ip) @ jump to next instruction 7079 /* 10-12 instructions */ 7080 7081 7082 7083/* ------------------------------ */ 7084 .balign 64 7085.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7086/* File: armv5te/OP_SHL_INT_LIT8.S */ 7087/* File: armv5te/binopLit8.S */ 7088 /* 7089 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7090 * that specifies an instruction that performs "result = r0 op r1". 7091 * This could be an ARM instruction or a function call. (If the result 7092 * comes back in a register other than r0, you can override "result".) 7093 * 7094 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7095 * vCC (r1). Useful for integer division and modulus. 7096 * 7097 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7098 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7099 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7100 */ 7101 /* binop/lit8 vAA, vBB, #+CC */ 7102 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7103 mov r9, rINST, lsr #8 @ r9<- AA 7104 and r2, r3, #255 @ r2<- BB 7105 GET_VREG(r0, r2) @ r0<- vBB 7106 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7107 .if 0 7108 @cmp r1, #0 @ is second operand zero? 7109 beq common_errDivideByZero 7110 .endif 7111 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7112 7113 and r1, r1, #31 @ optional op; may set condition codes 7114 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7115 GET_INST_OPCODE(ip) @ extract opcode from rINST 7116 SET_VREG(r0, r9) @ vAA<- r0 7117 GOTO_OPCODE(ip) @ jump to next instruction 7118 /* 10-12 instructions */ 7119 7120 7121 7122/* ------------------------------ */ 7123 .balign 64 7124.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7125/* File: armv5te/OP_SHR_INT_LIT8.S */ 7126/* File: armv5te/binopLit8.S */ 7127 /* 7128 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7129 * that specifies an instruction that performs "result = r0 op r1". 7130 * This could be an ARM instruction or a function call. (If the result 7131 * comes back in a register other than r0, you can override "result".) 7132 * 7133 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7134 * vCC (r1). Useful for integer division and modulus. 7135 * 7136 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7137 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7138 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7139 */ 7140 /* binop/lit8 vAA, vBB, #+CC */ 7141 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7142 mov r9, rINST, lsr #8 @ r9<- AA 7143 and r2, r3, #255 @ r2<- BB 7144 GET_VREG(r0, r2) @ r0<- vBB 7145 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7146 .if 0 7147 @cmp r1, #0 @ is second operand zero? 7148 beq common_errDivideByZero 7149 .endif 7150 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7151 7152 and r1, r1, #31 @ optional op; may set condition codes 7153 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7154 GET_INST_OPCODE(ip) @ extract opcode from rINST 7155 SET_VREG(r0, r9) @ vAA<- r0 7156 GOTO_OPCODE(ip) @ jump to next instruction 7157 /* 10-12 instructions */ 7158 7159 7160 7161/* ------------------------------ */ 7162 .balign 64 7163.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7164/* File: armv5te/OP_USHR_INT_LIT8.S */ 7165/* File: armv5te/binopLit8.S */ 7166 /* 7167 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7168 * that specifies an instruction that performs "result = r0 op r1". 7169 * This could be an ARM instruction or a function call. (If the result 7170 * comes back in a register other than r0, you can override "result".) 7171 * 7172 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7173 * vCC (r1). Useful for integer division and modulus. 7174 * 7175 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7176 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7177 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7178 */ 7179 /* binop/lit8 vAA, vBB, #+CC */ 7180 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7181 mov r9, rINST, lsr #8 @ r9<- AA 7182 and r2, r3, #255 @ r2<- BB 7183 GET_VREG(r0, r2) @ r0<- vBB 7184 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7185 .if 0 7186 @cmp r1, #0 @ is second operand zero? 7187 beq common_errDivideByZero 7188 .endif 7189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7190 7191 and r1, r1, #31 @ optional op; may set condition codes 7192 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7193 GET_INST_OPCODE(ip) @ extract opcode from rINST 7194 SET_VREG(r0, r9) @ vAA<- r0 7195 GOTO_OPCODE(ip) @ jump to next instruction 7196 /* 10-12 instructions */ 7197 7198 7199 7200/* ------------------------------ */ 7201 .balign 64 7202.L_OP_UNUSED_E3: /* 0xe3 */ 7203/* File: armv5te/OP_UNUSED_E3.S */ 7204/* File: armv5te/unused.S */ 7205 bl common_abort 7206 7207 7208 7209/* ------------------------------ */ 7210 .balign 64 7211.L_OP_UNUSED_E4: /* 0xe4 */ 7212/* File: armv5te/OP_UNUSED_E4.S */ 7213/* File: armv5te/unused.S */ 7214 bl common_abort 7215 7216 7217 7218/* ------------------------------ */ 7219 .balign 64 7220.L_OP_UNUSED_E5: /* 0xe5 */ 7221/* File: armv5te/OP_UNUSED_E5.S */ 7222/* File: armv5te/unused.S */ 7223 bl common_abort 7224 7225 7226 7227/* ------------------------------ */ 7228 .balign 64 7229.L_OP_UNUSED_E6: /* 0xe6 */ 7230/* File: armv5te/OP_UNUSED_E6.S */ 7231/* File: armv5te/unused.S */ 7232 bl common_abort 7233 7234 7235 7236/* ------------------------------ */ 7237 .balign 64 7238.L_OP_UNUSED_E7: /* 0xe7 */ 7239/* File: armv5te/OP_UNUSED_E7.S */ 7240/* File: armv5te/unused.S */ 7241 bl common_abort 7242 7243 7244 7245/* ------------------------------ */ 7246 .balign 64 7247.L_OP_UNUSED_E8: /* 0xe8 */ 7248/* File: armv5te/OP_UNUSED_E8.S */ 7249/* File: armv5te/unused.S */ 7250 bl common_abort 7251 7252 7253 7254/* ------------------------------ */ 7255 .balign 64 7256.L_OP_UNUSED_E9: /* 0xe9 */ 7257/* File: armv5te/OP_UNUSED_E9.S */ 7258/* File: armv5te/unused.S */ 7259 bl common_abort 7260 7261 7262 7263/* ------------------------------ */ 7264 .balign 64 7265.L_OP_UNUSED_EA: /* 0xea */ 7266/* File: armv5te/OP_UNUSED_EA.S */ 7267/* File: armv5te/unused.S */ 7268 bl common_abort 7269 7270 7271 7272/* ------------------------------ */ 7273 .balign 64 7274.L_OP_UNUSED_EB: /* 0xeb */ 7275/* File: armv5te/OP_UNUSED_EB.S */ 7276/* File: armv5te/unused.S */ 7277 bl common_abort 7278 7279 7280 7281/* ------------------------------ */ 7282 .balign 64 7283.L_OP_BREAKPOINT: /* 0xec */ 7284/* File: armv5te/OP_BREAKPOINT.S */ 7285/* File: armv5te/unused.S */ 7286 bl common_abort 7287 7288 7289 7290/* ------------------------------ */ 7291 .balign 64 7292.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7293/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7294 /* 7295 * Handle a throw-verification-error instruction. This throws an 7296 * exception for an error discovered during verification. The 7297 * exception is indicated by AA, with some detail provided by BBBB. 7298 */ 7299 /* op AA, ref@BBBB */ 7300 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7301 FETCH(r2, 1) @ r2<- BBBB 7302 EXPORT_PC() @ export the PC 7303 mov r1, rINST, lsr #8 @ r1<- AA 7304 bl dvmThrowVerificationError @ always throws 7305 b common_exceptionThrown @ handle exception 7306 7307 7308/* ------------------------------ */ 7309 .balign 64 7310.L_OP_EXECUTE_INLINE: /* 0xee */ 7311/* File: armv5te/OP_EXECUTE_INLINE.S */ 7312 /* 7313 * Execute a "native inline" instruction. 7314 * 7315 * We need to call an InlineOp4Func: 7316 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7317 * 7318 * The first four args are in r0-r3, pointer to return value storage 7319 * is on the stack. The function's return value is a flag that tells 7320 * us if an exception was thrown. 7321 */ 7322 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7323 FETCH(r10, 1) @ r10<- BBBB 7324 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7325 EXPORT_PC() @ can throw 7326 sub sp, sp, #8 @ make room for arg, +64 bit align 7327 mov r0, rINST, lsr #12 @ r0<- B 7328 str r1, [sp] @ push &glue->retval 7329 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7330 add sp, sp, #8 @ pop stack 7331 cmp r0, #0 @ test boolean result of inline 7332 beq common_exceptionThrown @ returned false, handle exception 7333 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7334 GET_INST_OPCODE(ip) @ extract opcode from rINST 7335 GOTO_OPCODE(ip) @ jump to next instruction 7336 7337/* ------------------------------ */ 7338 .balign 64 7339.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7340/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7341 /* 7342 * Execute a "native inline" instruction, using "/range" semantics. 7343 * Same idea as execute-inline, but we get the args differently. 7344 * 7345 * We need to call an InlineOp4Func: 7346 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7347 * 7348 * The first four args are in r0-r3, pointer to return value storage 7349 * is on the stack. The function's return value is a flag that tells 7350 * us if an exception was thrown. 7351 */ 7352 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7353 FETCH(r10, 1) @ r10<- BBBB 7354 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7355 EXPORT_PC() @ can throw 7356 sub sp, sp, #8 @ make room for arg, +64 bit align 7357 mov r0, rINST, lsr #8 @ r0<- AA 7358 str r1, [sp] @ push &glue->retval 7359 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7360 add sp, sp, #8 @ pop stack 7361 cmp r0, #0 @ test boolean result of inline 7362 beq common_exceptionThrown @ returned false, handle exception 7363 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7364 GET_INST_OPCODE(ip) @ extract opcode from rINST 7365 GOTO_OPCODE(ip) @ jump to next instruction 7366 7367/* ------------------------------ */ 7368 .balign 64 7369.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7370/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7371 /* 7372 * invoke-direct-empty is a no-op in a "standard" interpreter. 7373 */ 7374 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7375 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7376 GOTO_OPCODE(ip) @ execute it 7377 7378/* ------------------------------ */ 7379 .balign 64 7380.L_OP_UNUSED_F1: /* 0xf1 */ 7381/* File: armv5te/OP_UNUSED_F1.S */ 7382/* File: armv5te/unused.S */ 7383 bl common_abort 7384 7385 7386 7387/* ------------------------------ */ 7388 .balign 64 7389.L_OP_IGET_QUICK: /* 0xf2 */ 7390/* File: armv5te/OP_IGET_QUICK.S */ 7391 /* For: iget-quick, iget-object-quick */ 7392 /* op vA, vB, offset@CCCC */ 7393 mov r2, rINST, lsr #12 @ r2<- B 7394 GET_VREG(r3, r2) @ r3<- object we're operating on 7395 FETCH(r1, 1) @ r1<- field byte offset 7396 cmp r3, #0 @ check object for null 7397 mov r2, rINST, lsr #8 @ r2<- A(+) 7398 beq common_errNullObject @ object was null 7399 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7401 and r2, r2, #15 7402 GET_INST_OPCODE(ip) @ extract opcode from rINST 7403 SET_VREG(r0, r2) @ fp[A]<- r0 7404 GOTO_OPCODE(ip) @ jump to next instruction 7405 7406 7407/* ------------------------------ */ 7408 .balign 64 7409.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7410/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7411 /* iget-wide-quick vA, vB, offset@CCCC */ 7412 mov r2, rINST, lsr #12 @ r2<- B 7413 GET_VREG(r3, r2) @ r3<- object we're operating on 7414 FETCH(r1, 1) @ r1<- field byte offset 7415 cmp r3, #0 @ check object for null 7416 mov r2, rINST, lsr #8 @ r2<- A(+) 7417 beq common_errNullObject @ object was null 7418 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7419 and r2, r2, #15 7420 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7421 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7422 GET_INST_OPCODE(ip) @ extract opcode from rINST 7423 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7424 GOTO_OPCODE(ip) @ jump to next instruction 7425 7426 7427/* ------------------------------ */ 7428 .balign 64 7429.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7430/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7431/* File: armv5te/OP_IGET_QUICK.S */ 7432 /* For: iget-quick, iget-object-quick */ 7433 /* op vA, vB, offset@CCCC */ 7434 mov r2, rINST, lsr #12 @ r2<- B 7435 GET_VREG(r3, r2) @ r3<- object we're operating on 7436 FETCH(r1, 1) @ r1<- field byte offset 7437 cmp r3, #0 @ check object for null 7438 mov r2, rINST, lsr #8 @ r2<- A(+) 7439 beq common_errNullObject @ object was null 7440 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7441 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7442 and r2, r2, #15 7443 GET_INST_OPCODE(ip) @ extract opcode from rINST 7444 SET_VREG(r0, r2) @ fp[A]<- r0 7445 GOTO_OPCODE(ip) @ jump to next instruction 7446 7447 7448 7449/* ------------------------------ */ 7450 .balign 64 7451.L_OP_IPUT_QUICK: /* 0xf5 */ 7452/* File: armv5te/OP_IPUT_QUICK.S */ 7453 /* For: iput-quick, iput-object-quick */ 7454 /* op vA, vB, offset@CCCC */ 7455 mov r2, rINST, lsr #12 @ r2<- B 7456 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7457 FETCH(r1, 1) @ r1<- field byte offset 7458 cmp r3, #0 @ check object for null 7459 mov r2, rINST, lsr #8 @ r2<- A(+) 7460 beq common_errNullObject @ object was null 7461 and r2, r2, #15 7462 GET_VREG(r0, r2) @ r0<- fp[A] 7463 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7464 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7465 GET_INST_OPCODE(ip) @ extract opcode from rINST 7466 GOTO_OPCODE(ip) @ jump to next instruction 7467 7468 7469/* ------------------------------ */ 7470 .balign 64 7471.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7472/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7473 /* iput-wide-quick vA, vB, offset@CCCC */ 7474 mov r0, rINST, lsr #8 @ r0<- A(+) 7475 mov r1, rINST, lsr #12 @ r1<- B 7476 and r0, r0, #15 7477 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7478 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7479 cmp r2, #0 @ check object for null 7480 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7481 beq common_errNullObject @ object was null 7482 FETCH(r3, 1) @ r3<- field byte offset 7483 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7484 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7485 GET_INST_OPCODE(ip) @ extract opcode from rINST 7486 GOTO_OPCODE(ip) @ jump to next instruction 7487 7488 7489/* ------------------------------ */ 7490 .balign 64 7491.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7492/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7493/* File: armv5te/OP_IPUT_QUICK.S */ 7494 /* For: iput-quick, iput-object-quick */ 7495 /* op vA, vB, offset@CCCC */ 7496 mov r2, rINST, lsr #12 @ r2<- B 7497 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7498 FETCH(r1, 1) @ r1<- field byte offset 7499 cmp r3, #0 @ check object for null 7500 mov r2, rINST, lsr #8 @ r2<- A(+) 7501 beq common_errNullObject @ object was null 7502 and r2, r2, #15 7503 GET_VREG(r0, r2) @ r0<- fp[A] 7504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7505 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7506 GET_INST_OPCODE(ip) @ extract opcode from rINST 7507 GOTO_OPCODE(ip) @ jump to next instruction 7508 7509 7510 7511/* ------------------------------ */ 7512 .balign 64 7513.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7514/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7515 /* 7516 * Handle an optimized virtual method call. 7517 * 7518 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7519 */ 7520 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7521 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7522 FETCH(r3, 2) @ r3<- FEDC or CCCC 7523 FETCH(r1, 1) @ r1<- BBBB 7524 .if (!0) 7525 and r3, r3, #15 @ r3<- C (or stays CCCC) 7526 .endif 7527 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7528 cmp r2, #0 @ is "this" null? 7529 beq common_errNullObject @ null "this", throw exception 7530 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7531 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7532 EXPORT_PC() @ invoke must export 7533 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7534 bl common_invokeMethodNoRange @ continue on 7535 7536/* ------------------------------ */ 7537 .balign 64 7538.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7539/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7540/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7541 /* 7542 * Handle an optimized virtual method call. 7543 * 7544 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7545 */ 7546 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7547 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7548 FETCH(r3, 2) @ r3<- FEDC or CCCC 7549 FETCH(r1, 1) @ r1<- BBBB 7550 .if (!1) 7551 and r3, r3, #15 @ r3<- C (or stays CCCC) 7552 .endif 7553 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7554 cmp r2, #0 @ is "this" null? 7555 beq common_errNullObject @ null "this", throw exception 7556 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7557 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7558 EXPORT_PC() @ invoke must export 7559 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7560 bl common_invokeMethodRange @ continue on 7561 7562 7563/* ------------------------------ */ 7564 .balign 64 7565.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7566/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7567 /* 7568 * Handle an optimized "super" method call. 7569 * 7570 * for: [opt] invoke-super-quick, invoke-super-quick/range 7571 */ 7572 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7573 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7574 FETCH(r10, 2) @ r10<- GFED or CCCC 7575 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7576 .if (!0) 7577 and r10, r10, #15 @ r10<- D (or stays CCCC) 7578 .endif 7579 FETCH(r1, 1) @ r1<- BBBB 7580 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7581 EXPORT_PC() @ must export for invoke 7582 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7583 GET_VREG(r3, r10) @ r3<- "this" 7584 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7585 cmp r3, #0 @ null "this" ref? 7586 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7587 beq common_errNullObject @ "this" is null, throw exception 7588 bl common_invokeMethodNoRange @ continue on 7589 7590 7591/* ------------------------------ */ 7592 .balign 64 7593.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7594/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7595/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7596 /* 7597 * Handle an optimized "super" method call. 7598 * 7599 * for: [opt] invoke-super-quick, invoke-super-quick/range 7600 */ 7601 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7602 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7603 FETCH(r10, 2) @ r10<- GFED or CCCC 7604 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7605 .if (!1) 7606 and r10, r10, #15 @ r10<- D (or stays CCCC) 7607 .endif 7608 FETCH(r1, 1) @ r1<- BBBB 7609 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7610 EXPORT_PC() @ must export for invoke 7611 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7612 GET_VREG(r3, r10) @ r3<- "this" 7613 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7614 cmp r3, #0 @ null "this" ref? 7615 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7616 beq common_errNullObject @ "this" is null, throw exception 7617 bl common_invokeMethodRange @ continue on 7618 7619 7620 7621/* ------------------------------ */ 7622 .balign 64 7623.L_OP_UNUSED_FC: /* 0xfc */ 7624/* File: armv5te/OP_UNUSED_FC.S */ 7625/* File: armv5te/unused.S */ 7626 bl common_abort 7627 7628 7629 7630/* ------------------------------ */ 7631 .balign 64 7632.L_OP_UNUSED_FD: /* 0xfd */ 7633/* File: armv5te/OP_UNUSED_FD.S */ 7634/* File: armv5te/unused.S */ 7635 bl common_abort 7636 7637 7638 7639/* ------------------------------ */ 7640 .balign 64 7641.L_OP_UNUSED_FE: /* 0xfe */ 7642/* File: armv5te/OP_UNUSED_FE.S */ 7643/* File: armv5te/unused.S */ 7644 bl common_abort 7645 7646 7647 7648/* ------------------------------ */ 7649 .balign 64 7650.L_OP_UNUSED_FF: /* 0xff */ 7651/* File: armv5te/OP_UNUSED_FF.S */ 7652/* File: armv5te/unused.S */ 7653 bl common_abort 7654 7655 7656 7657 7658 .balign 64 7659 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7660 .global dvmAsmInstructionEnd 7661dvmAsmInstructionEnd: 7662 7663/* 7664 * =========================================================================== 7665 * Sister implementations 7666 * =========================================================================== 7667 */ 7668 .global dvmAsmSisterStart 7669 .type dvmAsmSisterStart, %function 7670 .text 7671 .balign 4 7672dvmAsmSisterStart: 7673 7674/* continuation for OP_CONST_STRING */ 7675 7676 /* 7677 * Continuation if the String has not yet been resolved. 7678 * r1: BBBB (String ref) 7679 * r9: target register 7680 */ 7681.LOP_CONST_STRING_resolve: 7682 EXPORT_PC() 7683 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7684 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7685 bl dvmResolveString @ r0<- String reference 7686 cmp r0, #0 @ failed? 7687 beq common_exceptionThrown @ yup, handle the exception 7688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7689 GET_INST_OPCODE(ip) @ extract opcode from rINST 7690 SET_VREG(r0, r9) @ vAA<- r0 7691 GOTO_OPCODE(ip) @ jump to next instruction 7692 7693 7694/* continuation for OP_CONST_STRING_JUMBO */ 7695 7696 /* 7697 * Continuation if the String has not yet been resolved. 7698 * r1: BBBBBBBB (String ref) 7699 * r9: target register 7700 */ 7701.LOP_CONST_STRING_JUMBO_resolve: 7702 EXPORT_PC() 7703 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7704 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7705 bl dvmResolveString @ r0<- String reference 7706 cmp r0, #0 @ failed? 7707 beq common_exceptionThrown @ yup, handle the exception 7708 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7709 GET_INST_OPCODE(ip) @ extract opcode from rINST 7710 SET_VREG(r0, r9) @ vAA<- r0 7711 GOTO_OPCODE(ip) @ jump to next instruction 7712 7713 7714/* continuation for OP_CONST_CLASS */ 7715 7716 /* 7717 * Continuation if the Class has not yet been resolved. 7718 * r1: BBBB (Class ref) 7719 * r9: target register 7720 */ 7721.LOP_CONST_CLASS_resolve: 7722 EXPORT_PC() 7723 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7724 mov r2, #1 @ r2<- true 7725 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7726 bl dvmResolveClass @ r0<- Class reference 7727 cmp r0, #0 @ failed? 7728 beq common_exceptionThrown @ yup, handle the exception 7729 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7730 GET_INST_OPCODE(ip) @ extract opcode from rINST 7731 SET_VREG(r0, r9) @ vAA<- r0 7732 GOTO_OPCODE(ip) @ jump to next instruction 7733 7734 7735/* continuation for OP_CHECK_CAST */ 7736 7737 /* 7738 * Trivial test failed, need to perform full check. This is common. 7739 * r0 holds obj->clazz 7740 * r1 holds class resolved from BBBB 7741 * r9 holds object 7742 */ 7743.LOP_CHECK_CAST_fullcheck: 7744 bl dvmInstanceofNonTrivial @ r0<- boolean result 7745 cmp r0, #0 @ failed? 7746 bne .LOP_CHECK_CAST_okay @ no, success 7747 7748 @ A cast has failed. We need to throw a ClassCastException with the 7749 @ class of the object that failed to be cast. 7750 EXPORT_PC() @ about to throw 7751 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7752 ldr r0, .LstrClassCastExceptionPtr 7753 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7754 bl dvmThrowExceptionWithClassMessage 7755 b common_exceptionThrown 7756 7757 /* 7758 * Resolution required. This is the least-likely path. 7759 * 7760 * r2 holds BBBB 7761 * r9 holds object 7762 */ 7763.LOP_CHECK_CAST_resolve: 7764 EXPORT_PC() @ resolve() could throw 7765 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7766 mov r1, r2 @ r1<- BBBB 7767 mov r2, #0 @ r2<- false 7768 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7769 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7770 cmp r0, #0 @ got null? 7771 beq common_exceptionThrown @ yes, handle exception 7772 mov r1, r0 @ r1<- class resolved from BBB 7773 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7774 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7775 7776.LstrClassCastExceptionPtr: 7777 .word .LstrClassCastException 7778 7779 7780/* continuation for OP_INSTANCE_OF */ 7781 7782 /* 7783 * Trivial test failed, need to perform full check. This is common. 7784 * r0 holds obj->clazz 7785 * r1 holds class resolved from BBBB 7786 * r9 holds A 7787 */ 7788.LOP_INSTANCE_OF_fullcheck: 7789 bl dvmInstanceofNonTrivial @ r0<- boolean result 7790 @ fall through to OP_INSTANCE_OF_store 7791 7792 /* 7793 * r0 holds boolean result 7794 * r9 holds A 7795 */ 7796.LOP_INSTANCE_OF_store: 7797 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7798 SET_VREG(r0, r9) @ vA<- r0 7799 GET_INST_OPCODE(ip) @ extract opcode from rINST 7800 GOTO_OPCODE(ip) @ jump to next instruction 7801 7802 /* 7803 * Trivial test succeeded, save and bail. 7804 * r9 holds A 7805 */ 7806.LOP_INSTANCE_OF_trivial: 7807 mov r0, #1 @ indicate success 7808 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7810 SET_VREG(r0, r9) @ vA<- r0 7811 GET_INST_OPCODE(ip) @ extract opcode from rINST 7812 GOTO_OPCODE(ip) @ jump to next instruction 7813 7814 /* 7815 * Resolution required. This is the least-likely path. 7816 * 7817 * r3 holds BBBB 7818 * r9 holds A 7819 */ 7820.LOP_INSTANCE_OF_resolve: 7821 EXPORT_PC() @ resolve() could throw 7822 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7823 mov r1, r3 @ r1<- BBBB 7824 mov r2, #1 @ r2<- true 7825 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7826 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7827 cmp r0, #0 @ got null? 7828 beq common_exceptionThrown @ yes, handle exception 7829 mov r1, r0 @ r1<- class resolved from BBB 7830 mov r3, rINST, lsr #12 @ r3<- B 7831 GET_VREG(r0, r3) @ r0<- vB (object) 7832 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7833 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7834 7835 7836/* continuation for OP_NEW_INSTANCE */ 7837 7838 .balign 32 @ minimize cache lines 7839.LOP_NEW_INSTANCE_finish: @ r0=new object 7840 mov r3, rINST, lsr #8 @ r3<- AA 7841 cmp r0, #0 @ failed? 7842 beq common_exceptionThrown @ yes, handle the exception 7843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7844 GET_INST_OPCODE(ip) @ extract opcode from rINST 7845 SET_VREG(r0, r3) @ vAA<- r0 7846 GOTO_OPCODE(ip) @ jump to next instruction 7847 7848 /* 7849 * Class initialization required. 7850 * 7851 * r0 holds class object 7852 */ 7853.LOP_NEW_INSTANCE_needinit: 7854 mov r9, r0 @ save r0 7855 bl dvmInitClass @ initialize class 7856 cmp r0, #0 @ check boolean result 7857 mov r0, r9 @ restore r0 7858 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7859 b common_exceptionThrown @ failed, deal with init exception 7860 7861 /* 7862 * Resolution required. This is the least-likely path. 7863 * 7864 * r1 holds BBBB 7865 */ 7866.LOP_NEW_INSTANCE_resolve: 7867 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7868 mov r2, #0 @ r2<- false 7869 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7870 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7871 cmp r0, #0 @ got null? 7872 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7873 b common_exceptionThrown @ yes, handle exception 7874 7875.LstrInstantiationErrorPtr: 7876 .word .LstrInstantiationError 7877 7878 7879/* continuation for OP_NEW_ARRAY */ 7880 7881 7882 /* 7883 * Resolve class. (This is an uncommon case.) 7884 * 7885 * r1 holds array length 7886 * r2 holds class ref CCCC 7887 */ 7888.LOP_NEW_ARRAY_resolve: 7889 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7890 mov r9, r1 @ r9<- length (save) 7891 mov r1, r2 @ r1<- CCCC 7892 mov r2, #0 @ r2<- false 7893 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7894 bl dvmResolveClass @ r0<- call(clazz, ref) 7895 cmp r0, #0 @ got null? 7896 mov r1, r9 @ r1<- length (restore) 7897 beq common_exceptionThrown @ yes, handle exception 7898 @ fall through to OP_NEW_ARRAY_finish 7899 7900 /* 7901 * Finish allocation. 7902 * 7903 * r0 holds class 7904 * r1 holds array length 7905 */ 7906.LOP_NEW_ARRAY_finish: 7907 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7908 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7909 cmp r0, #0 @ failed? 7910 mov r2, rINST, lsr #8 @ r2<- A+ 7911 beq common_exceptionThrown @ yes, handle the exception 7912 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7913 and r2, r2, #15 @ r2<- A 7914 GET_INST_OPCODE(ip) @ extract opcode from rINST 7915 SET_VREG(r0, r2) @ vA<- r0 7916 GOTO_OPCODE(ip) @ jump to next instruction 7917 7918 7919/* continuation for OP_FILLED_NEW_ARRAY */ 7920 7921 /* 7922 * On entry: 7923 * r0 holds array class 7924 * r10 holds AA or BA 7925 */ 7926.LOP_FILLED_NEW_ARRAY_continue: 7927 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7928 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7929 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7930 .if 0 7931 mov r1, r10 @ r1<- AA (length) 7932 .else 7933 mov r1, r10, lsr #4 @ r1<- B (length) 7934 .endif 7935 cmp r3, #'I' @ array of ints? 7936 cmpne r3, #'L' @ array of objects? 7937 cmpne r3, #'[' @ array of arrays? 7938 mov r9, r1 @ save length in r9 7939 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7940 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7941 cmp r0, #0 @ null return? 7942 beq common_exceptionThrown @ alloc failed, handle exception 7943 7944 FETCH(r1, 2) @ r1<- FEDC or CCCC 7945 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7946 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7947 subs r9, r9, #1 @ length--, check for neg 7948 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7949 bmi 2f @ was zero, bail 7950 7951 @ copy values from registers into the array 7952 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7953 .if 0 7954 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79551: ldr r3, [r2], #4 @ r3<- *r2++ 7956 subs r9, r9, #1 @ count-- 7957 str r3, [r0], #4 @ *contents++ = vX 7958 bpl 1b 7959 @ continue at 2 7960 .else 7961 cmp r9, #4 @ length was initially 5? 7962 and r2, r10, #15 @ r2<- A 7963 bne 1f @ <= 4 args, branch 7964 GET_VREG(r3, r2) @ r3<- vA 7965 sub r9, r9, #1 @ count-- 7966 str r3, [r0, #16] @ contents[4] = vA 79671: and r2, r1, #15 @ r2<- F/E/D/C 7968 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7969 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7970 subs r9, r9, #1 @ count-- 7971 str r3, [r0], #4 @ *contents++ = vX 7972 bpl 1b 7973 @ continue at 2 7974 .endif 7975 79762: 7977 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7978 GOTO_OPCODE(ip) @ execute it 7979 7980 /* 7981 * Throw an exception indicating that we have not implemented this 7982 * mode of filled-new-array. 7983 */ 7984.LOP_FILLED_NEW_ARRAY_notimpl: 7985 ldr r0, .L_strInternalError 7986 ldr r1, .L_strFilledNewArrayNotImpl 7987 bl dvmThrowException 7988 b common_exceptionThrown 7989 7990 .if (!0) @ define in one or the other, not both 7991.L_strFilledNewArrayNotImpl: 7992 .word .LstrFilledNewArrayNotImpl 7993.L_strInternalError: 7994 .word .LstrInternalError 7995 .endif 7996 7997 7998/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7999 8000 /* 8001 * On entry: 8002 * r0 holds array class 8003 * r10 holds AA or BA 8004 */ 8005.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8006 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8007 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8008 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8009 .if 1 8010 mov r1, r10 @ r1<- AA (length) 8011 .else 8012 mov r1, r10, lsr #4 @ r1<- B (length) 8013 .endif 8014 cmp r3, #'I' @ array of ints? 8015 cmpne r3, #'L' @ array of objects? 8016 cmpne r3, #'[' @ array of arrays? 8017 mov r9, r1 @ save length in r9 8018 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8019 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8020 cmp r0, #0 @ null return? 8021 beq common_exceptionThrown @ alloc failed, handle exception 8022 8023 FETCH(r1, 2) @ r1<- FEDC or CCCC 8024 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8025 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8026 subs r9, r9, #1 @ length--, check for neg 8027 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8028 bmi 2f @ was zero, bail 8029 8030 @ copy values from registers into the array 8031 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8032 .if 1 8033 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80341: ldr r3, [r2], #4 @ r3<- *r2++ 8035 subs r9, r9, #1 @ count-- 8036 str r3, [r0], #4 @ *contents++ = vX 8037 bpl 1b 8038 @ continue at 2 8039 .else 8040 cmp r9, #4 @ length was initially 5? 8041 and r2, r10, #15 @ r2<- A 8042 bne 1f @ <= 4 args, branch 8043 GET_VREG(r3, r2) @ r3<- vA 8044 sub r9, r9, #1 @ count-- 8045 str r3, [r0, #16] @ contents[4] = vA 80461: and r2, r1, #15 @ r2<- F/E/D/C 8047 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8048 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8049 subs r9, r9, #1 @ count-- 8050 str r3, [r0], #4 @ *contents++ = vX 8051 bpl 1b 8052 @ continue at 2 8053 .endif 8054 80552: 8056 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8057 GOTO_OPCODE(ip) @ execute it 8058 8059 /* 8060 * Throw an exception indicating that we have not implemented this 8061 * mode of filled-new-array. 8062 */ 8063.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8064 ldr r0, .L_strInternalError 8065 ldr r1, .L_strFilledNewArrayNotImpl 8066 bl dvmThrowException 8067 b common_exceptionThrown 8068 8069 .if (!1) @ define in one or the other, not both 8070.L_strFilledNewArrayNotImpl: 8071 .word .LstrFilledNewArrayNotImpl 8072.L_strInternalError: 8073 .word .LstrInternalError 8074 .endif 8075 8076 8077/* continuation for OP_CMPL_FLOAT */ 8078.LOP_CMPL_FLOAT_finish: 8079 SET_VREG(r0, r9) @ vAA<- r0 8080 GOTO_OPCODE(ip) @ jump to next instruction 8081 8082 8083/* continuation for OP_CMPG_FLOAT */ 8084.LOP_CMPG_FLOAT_finish: 8085 SET_VREG(r0, r9) @ vAA<- r0 8086 GOTO_OPCODE(ip) @ jump to next instruction 8087 8088 8089/* continuation for OP_CMPL_DOUBLE */ 8090.LOP_CMPL_DOUBLE_finish: 8091 SET_VREG(r0, r9) @ vAA<- r0 8092 GOTO_OPCODE(ip) @ jump to next instruction 8093 8094 8095/* continuation for OP_CMPG_DOUBLE */ 8096.LOP_CMPG_DOUBLE_finish: 8097 SET_VREG(r0, r9) @ vAA<- r0 8098 GOTO_OPCODE(ip) @ jump to next instruction 8099 8100 8101/* continuation for OP_CMP_LONG */ 8102 8103.LOP_CMP_LONG_less: 8104 mvn r1, #0 @ r1<- -1 8105 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8106 @ instead, we just replicate the tail end. 8107 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8108 SET_VREG(r1, r9) @ vAA<- r1 8109 GET_INST_OPCODE(ip) @ extract opcode from rINST 8110 GOTO_OPCODE(ip) @ jump to next instruction 8111 8112.LOP_CMP_LONG_greater: 8113 mov r1, #1 @ r1<- 1 8114 @ fall through to _finish 8115 8116.LOP_CMP_LONG_finish: 8117 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8118 SET_VREG(r1, r9) @ vAA<- r1 8119 GET_INST_OPCODE(ip) @ extract opcode from rINST 8120 GOTO_OPCODE(ip) @ jump to next instruction 8121 8122 8123/* continuation for OP_AGET_WIDE */ 8124 8125.LOP_AGET_WIDE_finish: 8126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8127 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8128 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8129 GET_INST_OPCODE(ip) @ extract opcode from rINST 8130 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8131 GOTO_OPCODE(ip) @ jump to next instruction 8132 8133 8134/* continuation for OP_APUT_WIDE */ 8135 8136.LOP_APUT_WIDE_finish: 8137 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8138 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8139 GET_INST_OPCODE(ip) @ extract opcode from rINST 8140 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8141 GOTO_OPCODE(ip) @ jump to next instruction 8142 8143 8144/* continuation for OP_APUT_OBJECT */ 8145 /* 8146 * On entry: 8147 * r1 = vBB (arrayObj) 8148 * r9 = vAA (obj) 8149 * r10 = offset into array (vBB + vCC * width) 8150 */ 8151.LOP_APUT_OBJECT_finish: 8152 cmp r9, #0 @ storing null reference? 8153 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8154 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8155 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8156 bl dvmCanPutArrayElement @ test object type vs. array type 8157 cmp r0, #0 @ okay? 8158 beq common_errArrayStore @ no 8159.LOP_APUT_OBJECT_skip_check: 8160 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8161 GET_INST_OPCODE(ip) @ extract opcode from rINST 8162 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8163 GOTO_OPCODE(ip) @ jump to next instruction 8164 8165 8166/* continuation for OP_IGET */ 8167 8168 /* 8169 * Currently: 8170 * r0 holds resolved field 8171 * r9 holds object 8172 */ 8173.LOP_IGET_finish: 8174 @bl common_squeak0 8175 cmp r9, #0 @ check object for null 8176 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8177 beq common_errNullObject @ object was null 8178 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8179 mov r2, rINST, lsr #8 @ r2<- A+ 8180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8181 and r2, r2, #15 @ r2<- A 8182 GET_INST_OPCODE(ip) @ extract opcode from rINST 8183 SET_VREG(r0, r2) @ fp[A]<- r0 8184 GOTO_OPCODE(ip) @ jump to next instruction 8185 8186 8187/* continuation for OP_IGET_WIDE */ 8188 8189 /* 8190 * Currently: 8191 * r0 holds resolved field 8192 * r9 holds object 8193 */ 8194.LOP_IGET_WIDE_finish: 8195 cmp r9, #0 @ check object for null 8196 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8197 beq common_errNullObject @ object was null 8198 mov r2, rINST, lsr #8 @ r2<- A+ 8199 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8200 and r2, r2, #15 @ r2<- A 8201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8202 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8203 GET_INST_OPCODE(ip) @ extract opcode from rINST 8204 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8205 GOTO_OPCODE(ip) @ jump to next instruction 8206 8207 8208/* continuation for OP_IGET_OBJECT */ 8209 8210 /* 8211 * Currently: 8212 * r0 holds resolved field 8213 * r9 holds object 8214 */ 8215.LOP_IGET_OBJECT_finish: 8216 @bl common_squeak0 8217 cmp r9, #0 @ check object for null 8218 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8219 beq common_errNullObject @ object was null 8220 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8221 mov r2, rINST, lsr #8 @ r2<- A+ 8222 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8223 and r2, r2, #15 @ r2<- A 8224 GET_INST_OPCODE(ip) @ extract opcode from rINST 8225 SET_VREG(r0, r2) @ fp[A]<- r0 8226 GOTO_OPCODE(ip) @ jump to next instruction 8227 8228 8229/* continuation for OP_IGET_BOOLEAN */ 8230 8231 /* 8232 * Currently: 8233 * r0 holds resolved field 8234 * r9 holds object 8235 */ 8236.LOP_IGET_BOOLEAN_finish: 8237 @bl common_squeak1 8238 cmp r9, #0 @ check object for null 8239 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8240 beq common_errNullObject @ object was null 8241 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8242 mov r2, rINST, lsr #8 @ r2<- A+ 8243 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8244 and r2, r2, #15 @ r2<- A 8245 GET_INST_OPCODE(ip) @ extract opcode from rINST 8246 SET_VREG(r0, r2) @ fp[A]<- r0 8247 GOTO_OPCODE(ip) @ jump to next instruction 8248 8249 8250/* continuation for OP_IGET_BYTE */ 8251 8252 /* 8253 * Currently: 8254 * r0 holds resolved field 8255 * r9 holds object 8256 */ 8257.LOP_IGET_BYTE_finish: 8258 @bl common_squeak2 8259 cmp r9, #0 @ check object for null 8260 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8261 beq common_errNullObject @ object was null 8262 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8263 mov r2, rINST, lsr #8 @ r2<- A+ 8264 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8265 and r2, r2, #15 @ r2<- A 8266 GET_INST_OPCODE(ip) @ extract opcode from rINST 8267 SET_VREG(r0, r2) @ fp[A]<- r0 8268 GOTO_OPCODE(ip) @ jump to next instruction 8269 8270 8271/* continuation for OP_IGET_CHAR */ 8272 8273 /* 8274 * Currently: 8275 * r0 holds resolved field 8276 * r9 holds object 8277 */ 8278.LOP_IGET_CHAR_finish: 8279 @bl common_squeak3 8280 cmp r9, #0 @ check object for null 8281 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8282 beq common_errNullObject @ object was null 8283 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8284 mov r2, rINST, lsr #8 @ r2<- A+ 8285 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8286 and r2, r2, #15 @ r2<- A 8287 GET_INST_OPCODE(ip) @ extract opcode from rINST 8288 SET_VREG(r0, r2) @ fp[A]<- r0 8289 GOTO_OPCODE(ip) @ jump to next instruction 8290 8291 8292/* continuation for OP_IGET_SHORT */ 8293 8294 /* 8295 * Currently: 8296 * r0 holds resolved field 8297 * r9 holds object 8298 */ 8299.LOP_IGET_SHORT_finish: 8300 @bl common_squeak4 8301 cmp r9, #0 @ check object for null 8302 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8303 beq common_errNullObject @ object was null 8304 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8305 mov r2, rINST, lsr #8 @ r2<- A+ 8306 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8307 and r2, r2, #15 @ r2<- A 8308 GET_INST_OPCODE(ip) @ extract opcode from rINST 8309 SET_VREG(r0, r2) @ fp[A]<- r0 8310 GOTO_OPCODE(ip) @ jump to next instruction 8311 8312 8313/* continuation for OP_IPUT */ 8314 8315 /* 8316 * Currently: 8317 * r0 holds resolved field 8318 * r9 holds object 8319 */ 8320.LOP_IPUT_finish: 8321 @bl common_squeak0 8322 mov r1, rINST, lsr #8 @ r1<- A+ 8323 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8324 and r1, r1, #15 @ r1<- A 8325 cmp r9, #0 @ check object for null 8326 GET_VREG(r0, r1) @ r0<- fp[A] 8327 beq common_errNullObject @ object was null 8328 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8329 GET_INST_OPCODE(ip) @ extract opcode from rINST 8330 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8331 GOTO_OPCODE(ip) @ jump to next instruction 8332 8333 8334/* continuation for OP_IPUT_WIDE */ 8335 8336 /* 8337 * Currently: 8338 * r0 holds resolved field 8339 * r9 holds object 8340 */ 8341.LOP_IPUT_WIDE_finish: 8342 mov r2, rINST, lsr #8 @ r2<- A+ 8343 cmp r9, #0 @ check object for null 8344 and r2, r2, #15 @ r2<- A 8345 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8346 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8347 beq common_errNullObject @ object was null 8348 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8349 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8350 GET_INST_OPCODE(ip) @ extract opcode from rINST 8351 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8352 GOTO_OPCODE(ip) @ jump to next instruction 8353 8354 8355/* continuation for OP_IPUT_OBJECT */ 8356 8357 /* 8358 * Currently: 8359 * r0 holds resolved field 8360 * r9 holds object 8361 */ 8362.LOP_IPUT_OBJECT_finish: 8363 @bl common_squeak0 8364 mov r1, rINST, lsr #8 @ r1<- A+ 8365 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8366 and r1, r1, #15 @ r1<- A 8367 cmp r9, #0 @ check object for null 8368 GET_VREG(r0, r1) @ r0<- fp[A] 8369 beq common_errNullObject @ object was null 8370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8371 GET_INST_OPCODE(ip) @ extract opcode from rINST 8372 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8373 GOTO_OPCODE(ip) @ jump to next instruction 8374 8375 8376/* continuation for OP_IPUT_BOOLEAN */ 8377 8378 /* 8379 * Currently: 8380 * r0 holds resolved field 8381 * r9 holds object 8382 */ 8383.LOP_IPUT_BOOLEAN_finish: 8384 @bl common_squeak1 8385 mov r1, rINST, lsr #8 @ r1<- A+ 8386 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8387 and r1, r1, #15 @ r1<- A 8388 cmp r9, #0 @ check object for null 8389 GET_VREG(r0, r1) @ r0<- fp[A] 8390 beq common_errNullObject @ object was null 8391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8392 GET_INST_OPCODE(ip) @ extract opcode from rINST 8393 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8394 GOTO_OPCODE(ip) @ jump to next instruction 8395 8396 8397/* continuation for OP_IPUT_BYTE */ 8398 8399 /* 8400 * Currently: 8401 * r0 holds resolved field 8402 * r9 holds object 8403 */ 8404.LOP_IPUT_BYTE_finish: 8405 @bl common_squeak2 8406 mov r1, rINST, lsr #8 @ r1<- A+ 8407 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8408 and r1, r1, #15 @ r1<- A 8409 cmp r9, #0 @ check object for null 8410 GET_VREG(r0, r1) @ r0<- fp[A] 8411 beq common_errNullObject @ object was null 8412 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8413 GET_INST_OPCODE(ip) @ extract opcode from rINST 8414 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8415 GOTO_OPCODE(ip) @ jump to next instruction 8416 8417 8418/* continuation for OP_IPUT_CHAR */ 8419 8420 /* 8421 * Currently: 8422 * r0 holds resolved field 8423 * r9 holds object 8424 */ 8425.LOP_IPUT_CHAR_finish: 8426 @bl common_squeak3 8427 mov r1, rINST, lsr #8 @ r1<- A+ 8428 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8429 and r1, r1, #15 @ r1<- A 8430 cmp r9, #0 @ check object for null 8431 GET_VREG(r0, r1) @ r0<- fp[A] 8432 beq common_errNullObject @ object was null 8433 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8434 GET_INST_OPCODE(ip) @ extract opcode from rINST 8435 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8436 GOTO_OPCODE(ip) @ jump to next instruction 8437 8438 8439/* continuation for OP_IPUT_SHORT */ 8440 8441 /* 8442 * Currently: 8443 * r0 holds resolved field 8444 * r9 holds object 8445 */ 8446.LOP_IPUT_SHORT_finish: 8447 @bl common_squeak4 8448 mov r1, rINST, lsr #8 @ r1<- A+ 8449 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8450 and r1, r1, #15 @ r1<- A 8451 cmp r9, #0 @ check object for null 8452 GET_VREG(r0, r1) @ r0<- fp[A] 8453 beq common_errNullObject @ object was null 8454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8455 GET_INST_OPCODE(ip) @ extract opcode from rINST 8456 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8457 GOTO_OPCODE(ip) @ jump to next instruction 8458 8459 8460/* continuation for OP_SGET */ 8461 8462 /* 8463 * Continuation if the field has not yet been resolved. 8464 * r1: BBBB field ref 8465 */ 8466.LOP_SGET_resolve: 8467 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8468 EXPORT_PC() @ resolve() could throw, so export now 8469 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8470 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8471 cmp r0, #0 @ success? 8472 bne .LOP_SGET_finish @ yes, finish 8473 b common_exceptionThrown @ no, handle exception 8474 8475 8476/* continuation for OP_SGET_WIDE */ 8477 8478 /* 8479 * Continuation if the field has not yet been resolved. 8480 * r1: BBBB field ref 8481 */ 8482.LOP_SGET_WIDE_resolve: 8483 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8484 EXPORT_PC() @ resolve() could throw, so export now 8485 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8486 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8487 cmp r0, #0 @ success? 8488 bne .LOP_SGET_WIDE_finish @ yes, finish 8489 b common_exceptionThrown @ no, handle exception 8490 8491 8492/* continuation for OP_SGET_OBJECT */ 8493 8494 /* 8495 * Continuation if the field has not yet been resolved. 8496 * r1: BBBB field ref 8497 */ 8498.LOP_SGET_OBJECT_resolve: 8499 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8500 EXPORT_PC() @ resolve() could throw, so export now 8501 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8502 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8503 cmp r0, #0 @ success? 8504 bne .LOP_SGET_OBJECT_finish @ yes, finish 8505 b common_exceptionThrown @ no, handle exception 8506 8507 8508/* continuation for OP_SGET_BOOLEAN */ 8509 8510 /* 8511 * Continuation if the field has not yet been resolved. 8512 * r1: BBBB field ref 8513 */ 8514.LOP_SGET_BOOLEAN_resolve: 8515 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8516 EXPORT_PC() @ resolve() could throw, so export now 8517 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8518 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8519 cmp r0, #0 @ success? 8520 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8521 b common_exceptionThrown @ no, handle exception 8522 8523 8524/* continuation for OP_SGET_BYTE */ 8525 8526 /* 8527 * Continuation if the field has not yet been resolved. 8528 * r1: BBBB field ref 8529 */ 8530.LOP_SGET_BYTE_resolve: 8531 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8532 EXPORT_PC() @ resolve() could throw, so export now 8533 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8534 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8535 cmp r0, #0 @ success? 8536 bne .LOP_SGET_BYTE_finish @ yes, finish 8537 b common_exceptionThrown @ no, handle exception 8538 8539 8540/* continuation for OP_SGET_CHAR */ 8541 8542 /* 8543 * Continuation if the field has not yet been resolved. 8544 * r1: BBBB field ref 8545 */ 8546.LOP_SGET_CHAR_resolve: 8547 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8548 EXPORT_PC() @ resolve() could throw, so export now 8549 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8550 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8551 cmp r0, #0 @ success? 8552 bne .LOP_SGET_CHAR_finish @ yes, finish 8553 b common_exceptionThrown @ no, handle exception 8554 8555 8556/* continuation for OP_SGET_SHORT */ 8557 8558 /* 8559 * Continuation if the field has not yet been resolved. 8560 * r1: BBBB field ref 8561 */ 8562.LOP_SGET_SHORT_resolve: 8563 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8564 EXPORT_PC() @ resolve() could throw, so export now 8565 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8566 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8567 cmp r0, #0 @ success? 8568 bne .LOP_SGET_SHORT_finish @ yes, finish 8569 b common_exceptionThrown @ no, handle exception 8570 8571 8572/* continuation for OP_SPUT */ 8573 8574 /* 8575 * Continuation if the field has not yet been resolved. 8576 * r1: BBBB field ref 8577 */ 8578.LOP_SPUT_resolve: 8579 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8580 EXPORT_PC() @ resolve() could throw, so export now 8581 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8582 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8583 cmp r0, #0 @ success? 8584 bne .LOP_SPUT_finish @ yes, finish 8585 b common_exceptionThrown @ no, handle exception 8586 8587 8588/* continuation for OP_SPUT_WIDE */ 8589 8590 /* 8591 * Continuation if the field has not yet been resolved. 8592 * r1: BBBB field ref 8593 * r9: &fp[AA] 8594 */ 8595.LOP_SPUT_WIDE_resolve: 8596 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8597 EXPORT_PC() @ resolve() could throw, so export now 8598 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8599 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8600 cmp r0, #0 @ success? 8601 bne .LOP_SPUT_WIDE_finish @ yes, finish 8602 b common_exceptionThrown @ no, handle exception 8603 8604 8605/* continuation for OP_SPUT_OBJECT */ 8606 8607 /* 8608 * Continuation if the field has not yet been resolved. 8609 * r1: BBBB field ref 8610 */ 8611.LOP_SPUT_OBJECT_resolve: 8612 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8613 EXPORT_PC() @ resolve() could throw, so export now 8614 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8615 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8616 cmp r0, #0 @ success? 8617 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8618 b common_exceptionThrown @ no, handle exception 8619 8620 8621/* continuation for OP_SPUT_BOOLEAN */ 8622 8623 /* 8624 * Continuation if the field has not yet been resolved. 8625 * r1: BBBB field ref 8626 */ 8627.LOP_SPUT_BOOLEAN_resolve: 8628 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8629 EXPORT_PC() @ resolve() could throw, so export now 8630 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8631 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8632 cmp r0, #0 @ success? 8633 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8634 b common_exceptionThrown @ no, handle exception 8635 8636 8637/* continuation for OP_SPUT_BYTE */ 8638 8639 /* 8640 * Continuation if the field has not yet been resolved. 8641 * r1: BBBB field ref 8642 */ 8643.LOP_SPUT_BYTE_resolve: 8644 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8645 EXPORT_PC() @ resolve() could throw, so export now 8646 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8647 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8648 cmp r0, #0 @ success? 8649 bne .LOP_SPUT_BYTE_finish @ yes, finish 8650 b common_exceptionThrown @ no, handle exception 8651 8652 8653/* continuation for OP_SPUT_CHAR */ 8654 8655 /* 8656 * Continuation if the field has not yet been resolved. 8657 * r1: BBBB field ref 8658 */ 8659.LOP_SPUT_CHAR_resolve: 8660 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8661 EXPORT_PC() @ resolve() could throw, so export now 8662 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8663 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8664 cmp r0, #0 @ success? 8665 bne .LOP_SPUT_CHAR_finish @ yes, finish 8666 b common_exceptionThrown @ no, handle exception 8667 8668 8669/* continuation for OP_SPUT_SHORT */ 8670 8671 /* 8672 * Continuation if the field has not yet been resolved. 8673 * r1: BBBB field ref 8674 */ 8675.LOP_SPUT_SHORT_resolve: 8676 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8677 EXPORT_PC() @ resolve() could throw, so export now 8678 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8679 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8680 cmp r0, #0 @ success? 8681 bne .LOP_SPUT_SHORT_finish @ yes, finish 8682 b common_exceptionThrown @ no, handle exception 8683 8684 8685/* continuation for OP_INVOKE_VIRTUAL */ 8686 8687 /* 8688 * At this point: 8689 * r0 = resolved base method 8690 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8691 */ 8692.LOP_INVOKE_VIRTUAL_continue: 8693 GET_VREG(r1, r10) @ r1<- "this" ptr 8694 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8695 cmp r1, #0 @ is "this" null? 8696 beq common_errNullObject @ null "this", throw exception 8697 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8698 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8699 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8700 bl common_invokeMethodNoRange @ continue on 8701 8702 8703/* continuation for OP_INVOKE_SUPER */ 8704 8705 /* 8706 * At this point: 8707 * r0 = resolved base method 8708 * r9 = method->clazz 8709 */ 8710.LOP_INVOKE_SUPER_continue: 8711 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8712 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8713 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8714 EXPORT_PC() @ must export for invoke 8715 cmp r2, r3 @ compare (methodIndex, vtableCount) 8716 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8717 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8718 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8719 bl common_invokeMethodNoRange @ continue on 8720 8721.LOP_INVOKE_SUPER_resolve: 8722 mov r0, r9 @ r0<- method->clazz 8723 mov r2, #METHOD_VIRTUAL @ resolver method type 8724 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8725 cmp r0, #0 @ got null? 8726 bne .LOP_INVOKE_SUPER_continue @ no, continue 8727 b common_exceptionThrown @ yes, handle exception 8728 8729 /* 8730 * Throw a NoSuchMethodError with the method name as the message. 8731 * r0 = resolved base method 8732 */ 8733.LOP_INVOKE_SUPER_nsm: 8734 ldr r1, [r0, #offMethod_name] @ r1<- method name 8735 b common_errNoSuchMethod 8736 8737 8738/* continuation for OP_INVOKE_DIRECT */ 8739 8740 /* 8741 * On entry: 8742 * r1 = reference (BBBB or CCCC) 8743 * r10 = "this" register 8744 */ 8745.LOP_INVOKE_DIRECT_resolve: 8746 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8747 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8748 mov r2, #METHOD_DIRECT @ resolver method type 8749 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8750 cmp r0, #0 @ got null? 8751 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8752 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8753 b common_exceptionThrown @ yes, handle exception 8754 8755 8756/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8757 8758 /* 8759 * At this point: 8760 * r0 = resolved base method 8761 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8762 */ 8763.LOP_INVOKE_VIRTUAL_RANGE_continue: 8764 GET_VREG(r1, r10) @ r1<- "this" ptr 8765 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8766 cmp r1, #0 @ is "this" null? 8767 beq common_errNullObject @ null "this", throw exception 8768 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8769 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8770 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8771 bl common_invokeMethodRange @ continue on 8772 8773 8774/* continuation for OP_INVOKE_SUPER_RANGE */ 8775 8776 /* 8777 * At this point: 8778 * r0 = resolved base method 8779 * r9 = method->clazz 8780 */ 8781.LOP_INVOKE_SUPER_RANGE_continue: 8782 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8783 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8784 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8785 EXPORT_PC() @ must export for invoke 8786 cmp r2, r3 @ compare (methodIndex, vtableCount) 8787 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8788 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8789 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8790 bl common_invokeMethodRange @ continue on 8791 8792.LOP_INVOKE_SUPER_RANGE_resolve: 8793 mov r0, r9 @ r0<- method->clazz 8794 mov r2, #METHOD_VIRTUAL @ resolver method type 8795 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8796 cmp r0, #0 @ got null? 8797 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8798 b common_exceptionThrown @ yes, handle exception 8799 8800 /* 8801 * Throw a NoSuchMethodError with the method name as the message. 8802 * r0 = resolved base method 8803 */ 8804.LOP_INVOKE_SUPER_RANGE_nsm: 8805 ldr r1, [r0, #offMethod_name] @ r1<- method name 8806 b common_errNoSuchMethod 8807 8808 8809/* continuation for OP_INVOKE_DIRECT_RANGE */ 8810 8811 /* 8812 * On entry: 8813 * r1 = reference (BBBB or CCCC) 8814 * r10 = "this" register 8815 */ 8816.LOP_INVOKE_DIRECT_RANGE_resolve: 8817 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8818 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8819 mov r2, #METHOD_DIRECT @ resolver method type 8820 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8821 cmp r0, #0 @ got null? 8822 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8823 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8824 b common_exceptionThrown @ yes, handle exception 8825 8826 8827/* continuation for OP_FLOAT_TO_LONG */ 8828/* 8829 * Convert the float in r0 to a long in r0/r1. 8830 * 8831 * We have to clip values to long min/max per the specification. The 8832 * expected common case is a "reasonable" value that converts directly 8833 * to modest integer. The EABI convert function isn't doing this for us. 8834 */ 8835f2l_doconv: 8836 stmfd sp!, {r4, lr} 8837 mov r1, #0x5f000000 @ (float)maxlong 8838 mov r4, r0 8839 bl __aeabi_fcmpge @ is arg >= maxlong? 8840 cmp r0, #0 @ nonzero == yes 8841 mvnne r0, #0 @ return maxlong (7fffffff) 8842 mvnne r1, #0x80000000 8843 ldmnefd sp!, {r4, pc} 8844 8845 mov r0, r4 @ recover arg 8846 mov r1, #0xdf000000 @ (float)minlong 8847 bl __aeabi_fcmple @ is arg <= minlong? 8848 cmp r0, #0 @ nonzero == yes 8849 movne r0, #0 @ return minlong (80000000) 8850 movne r1, #0x80000000 8851 ldmnefd sp!, {r4, pc} 8852 8853 mov r0, r4 @ recover arg 8854 mov r1, r4 8855 bl __aeabi_fcmpeq @ is arg == self? 8856 cmp r0, #0 @ zero == no 8857 moveq r1, #0 @ return zero for NaN 8858 ldmeqfd sp!, {r4, pc} 8859 8860 mov r0, r4 @ recover arg 8861 bl __aeabi_f2lz @ convert float to long 8862 ldmfd sp!, {r4, pc} 8863 8864 8865/* continuation for OP_DOUBLE_TO_LONG */ 8866/* 8867 * Convert the double in r0/r1 to a long in r0/r1. 8868 * 8869 * We have to clip values to long min/max per the specification. The 8870 * expected common case is a "reasonable" value that converts directly 8871 * to modest integer. The EABI convert function isn't doing this for us. 8872 */ 8873d2l_doconv: 8874 stmfd sp!, {r4, r5, lr} @ save regs 8875 mov r3, #0x43000000 @ maxlong, as a double (high word) 8876 add r3, #0x00e00000 @ 0x43e00000 8877 mov r2, #0 @ maxlong, as a double (low word) 8878 sub sp, sp, #4 @ align for EABI 8879 mov r4, r0 @ save a copy of r0 8880 mov r5, r1 @ and r1 8881 bl __aeabi_dcmpge @ is arg >= maxlong? 8882 cmp r0, #0 @ nonzero == yes 8883 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8884 mvnne r1, #0x80000000 8885 bne 1f 8886 8887 mov r0, r4 @ recover arg 8888 mov r1, r5 8889 mov r3, #0xc3000000 @ minlong, as a double (high word) 8890 add r3, #0x00e00000 @ 0xc3e00000 8891 mov r2, #0 @ minlong, as a double (low word) 8892 bl __aeabi_dcmple @ is arg <= minlong? 8893 cmp r0, #0 @ nonzero == yes 8894 movne r0, #0 @ return minlong (8000000000000000) 8895 movne r1, #0x80000000 8896 bne 1f 8897 8898 mov r0, r4 @ recover arg 8899 mov r1, r5 8900 mov r2, r4 @ compare against self 8901 mov r3, r5 8902 bl __aeabi_dcmpeq @ is arg == self? 8903 cmp r0, #0 @ zero == no 8904 moveq r1, #0 @ return zero for NaN 8905 beq 1f 8906 8907 mov r0, r4 @ recover arg 8908 mov r1, r5 8909 bl __aeabi_d2lz @ convert double to long 8910 89111: 8912 add sp, sp, #4 8913 ldmfd sp!, {r4, r5, pc} 8914 8915 8916/* continuation for OP_MUL_LONG */ 8917 8918.LOP_MUL_LONG_finish: 8919 GET_INST_OPCODE(ip) @ extract opcode from rINST 8920 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8921 GOTO_OPCODE(ip) @ jump to next instruction 8922 8923 8924/* continuation for OP_SHL_LONG */ 8925 8926.LOP_SHL_LONG_finish: 8927 mov r0, r0, asl r2 @ r0<- r0 << r2 8928 GET_INST_OPCODE(ip) @ extract opcode from rINST 8929 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8930 GOTO_OPCODE(ip) @ jump to next instruction 8931 8932 8933/* continuation for OP_SHR_LONG */ 8934 8935.LOP_SHR_LONG_finish: 8936 mov r1, r1, asr r2 @ r1<- r1 >> r2 8937 GET_INST_OPCODE(ip) @ extract opcode from rINST 8938 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8939 GOTO_OPCODE(ip) @ jump to next instruction 8940 8941 8942/* continuation for OP_USHR_LONG */ 8943 8944.LOP_USHR_LONG_finish: 8945 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8946 GET_INST_OPCODE(ip) @ extract opcode from rINST 8947 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8948 GOTO_OPCODE(ip) @ jump to next instruction 8949 8950 8951/* continuation for OP_SHL_LONG_2ADDR */ 8952 8953.LOP_SHL_LONG_2ADDR_finish: 8954 GET_INST_OPCODE(ip) @ extract opcode from rINST 8955 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8956 GOTO_OPCODE(ip) @ jump to next instruction 8957 8958 8959/* continuation for OP_SHR_LONG_2ADDR */ 8960 8961.LOP_SHR_LONG_2ADDR_finish: 8962 GET_INST_OPCODE(ip) @ extract opcode from rINST 8963 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8964 GOTO_OPCODE(ip) @ jump to next instruction 8965 8966 8967/* continuation for OP_USHR_LONG_2ADDR */ 8968 8969.LOP_USHR_LONG_2ADDR_finish: 8970 GET_INST_OPCODE(ip) @ extract opcode from rINST 8971 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8972 GOTO_OPCODE(ip) @ jump to next instruction 8973 8974 8975/* continuation for OP_EXECUTE_INLINE */ 8976 8977 /* 8978 * Extract args, call function. 8979 * r0 = #of args (0-4) 8980 * r10 = call index 8981 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8982 * 8983 * Other ideas: 8984 * - Use a jump table from the main piece to jump directly into the 8985 * AND/LDR pairs. Costs a data load, saves a branch. 8986 * - Have five separate pieces that do the loading, so we can work the 8987 * interleave a little better. Increases code size. 8988 */ 8989.LOP_EXECUTE_INLINE_continue: 8990 rsb r0, r0, #4 @ r0<- 4-r0 8991 FETCH(r9, 2) @ r9<- FEDC 8992 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8993 bl common_abort @ (skipped due to ARM prefetch) 89944: and ip, r9, #0xf000 @ isolate F 8995 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89963: and ip, r9, #0x0f00 @ isolate E 8997 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 89982: and ip, r9, #0x00f0 @ isolate D 8999 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 90001: and ip, r9, #0x000f @ isolate C 9001 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 90020: 9003 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9004 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9005 @ (not reached) 9006 9007.LOP_EXECUTE_INLINE_table: 9008 .word gDvmInlineOpsTable 9009 9010 9011/* continuation for OP_EXECUTE_INLINE_RANGE */ 9012 9013 /* 9014 * Extract args, call function. 9015 * r0 = #of args (0-4) 9016 * r10 = call index 9017 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9018 */ 9019.LOP_EXECUTE_INLINE_RANGE_continue: 9020 rsb r0, r0, #4 @ r0<- 4-r0 9021 FETCH(r9, 2) @ r9<- CCCC 9022 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9023 bl common_abort @ (skipped due to ARM prefetch) 90244: add ip, r9, #3 @ base+3 9025 GET_VREG(r3, ip) @ r3<- vBase[3] 90263: add ip, r9, #2 @ base+2 9027 GET_VREG(r2, ip) @ r2<- vBase[2] 90282: add ip, r9, #1 @ base+1 9029 GET_VREG(r1, ip) @ r1<- vBase[1] 90301: add ip, r9, #0 @ (nop) 9031 GET_VREG(r0, ip) @ r0<- vBase[0] 90320: 9033 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9034 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9035 @ (not reached) 9036 9037.LOP_EXECUTE_INLINE_RANGE_table: 9038 .word gDvmInlineOpsTable 9039 9040 9041 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9042 .global dvmAsmSisterEnd 9043dvmAsmSisterEnd: 9044 9045/* File: armv5te/footer.S */ 9046 9047/* 9048 * =========================================================================== 9049 * Common subroutines and data 9050 * =========================================================================== 9051 */ 9052 9053 9054 9055 .text 9056 .align 2 9057 9058#if defined(WITH_JIT) 9059#if defined(WITH_SELF_VERIFICATION) 9060 .global dvmJitToInterpPunt 9061dvmJitToInterpPunt: 9062 mov r2,#kSVSPunt @ r2<- interpreter entry point 9063 b dvmJitSelfVerificationEnd @ doesn't return 9064 9065 .global dvmJitToInterpSingleStep 9066dvmJitToInterpSingleStep: 9067 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9068 b dvmJitSelfVerificationEnd @ doesn't return 9069 9070 .global dvmJitToTraceSelect 9071dvmJitToTraceSelect: 9072 ldr r0,[lr, #-1] @ pass our target PC 9073 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9074 b dvmJitSelfVerificationEnd @ doesn't return 9075 9076 .global dvmJitToBackwardBranch 9077dvmJitToBackwardBranch: 9078 ldr r0,[lr, #-1] @ pass our target PC 9079 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9080 b dvmJitSelfVerificationEnd @ doesn't return 9081 9082 .global dvmJitToInterpNormal 9083dvmJitToInterpNormal: 9084 ldr r0,[lr, #-1] @ pass our target PC 9085 mov r2,#kSVSNormal @ r2<- interpreter entry point 9086 b dvmJitSelfVerificationEnd @ doesn't return 9087 9088 .global dvmJitToInterpNoChain 9089dvmJitToInterpNoChain: 9090 mov r0,rPC @ pass our target PC 9091 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9092 b dvmJitSelfVerificationEnd @ doesn't return 9093#else 9094/* 9095 * Return from the translation cache to the interpreter when the compiler is 9096 * having issues translating/executing a Dalvik instruction. We have to skip 9097 * the code cache lookup otherwise it is possible to indefinitely bouce 9098 * between the interpreter and the code cache if the instruction that fails 9099 * to be compiled happens to be at a trace start. 9100 */ 9101 .global dvmJitToInterpPunt 9102dvmJitToInterpPunt: 9103 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9104 mov rPC, r0 9105#ifdef EXIT_STATS 9106 mov r0,lr 9107 bl dvmBumpPunt; 9108#endif 9109 EXPORT_PC() 9110 mov r0, #0 9111 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9112 adrl rIBASE, dvmAsmInstructionStart 9113 FETCH_INST() 9114 GET_INST_OPCODE(ip) 9115 GOTO_OPCODE(ip) 9116 9117/* 9118 * Return to the interpreter to handle a single instruction. 9119 * On entry: 9120 * r0 <= PC 9121 * r1 <= PC of resume instruction 9122 * lr <= resume point in translation 9123 */ 9124 .global dvmJitToInterpSingleStep 9125dvmJitToInterpSingleStep: 9126 str lr,[rGLUE,#offGlue_jitResume] 9127 str r1,[rGLUE,#offGlue_jitResumePC] 9128 mov r1,#kInterpEntryInstr 9129 @ enum is 4 byte in aapcs-EABI 9130 str r1, [rGLUE, #offGlue_entryPoint] 9131 mov rPC,r0 9132 EXPORT_PC() 9133 9134 adrl rIBASE, dvmAsmInstructionStart 9135 mov r2,#kJitSingleStep @ Ask for single step and then revert 9136 str r2,[rGLUE,#offGlue_jitState] 9137 mov r1,#1 @ set changeInterp to bail to debug interp 9138 b common_gotoBail 9139 9140 9141/* 9142 * Return from the translation cache and immediately request 9143 * a translation for the exit target. Commonly used following 9144 * invokes. 9145 */ 9146 .global dvmJitToTraceSelect 9147dvmJitToTraceSelect: 9148 ldr rPC,[lr, #-1] @ get our target PC 9149 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9150 add rINST,lr,#-5 @ save start of chain branch 9151 mov r0,rPC 9152 bl dvmJitGetCodeAddr @ Is there a translation? 9153 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9154 cmp r0,#0 9155 beq 2f 9156 mov r1,rINST 9157 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9158 mov r1, rPC @ arg1 of translation may need this 9159 mov lr, #0 @ in case target is HANDLER_INTERPRET 9160 cmp r0,#0 @ successful chain? 9161 bxne r0 @ continue native execution 9162 b toInterpreter @ didn't chain - resume with interpreter 9163 9164/* No translation, so request one if profiling isn't disabled*/ 91652: 9166 adrl rIBASE, dvmAsmInstructionStart 9167 GET_JIT_PROF_TABLE(r0) 9168 FETCH_INST() 9169 cmp r0, #0 9170 bne common_selectTrace 9171 GET_INST_OPCODE(ip) 9172 GOTO_OPCODE(ip) 9173 9174/* 9175 * Return from the translation cache to the interpreter. 9176 * The return was done with a BLX from thumb mode, and 9177 * the following 32-bit word contains the target rPC value. 9178 * Note that lr (r14) will have its low-order bit set to denote 9179 * its thumb-mode origin. 9180 * 9181 * We'll need to stash our lr origin away, recover the new 9182 * target and then check to see if there is a translation available 9183 * for our new target. If so, we do a translation chain and 9184 * go back to native execution. Otherwise, it's back to the 9185 * interpreter (after treating this entry as a potential 9186 * trace start). 9187 */ 9188 .global dvmJitToInterpNormal 9189dvmJitToInterpNormal: 9190 ldr rPC,[lr, #-1] @ get our target PC 9191 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9192 add rINST,lr,#-5 @ save start of chain branch 9193#ifdef EXIT_STATS 9194 bl dvmBumpNormal 9195#endif 9196 mov r0,rPC 9197 bl dvmJitGetCodeAddr @ Is there a translation? 9198 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9199 cmp r0,#0 9200 beq toInterpreter @ go if not, otherwise do chain 9201 mov r1,rINST 9202 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9203 mov r1, rPC @ arg1 of translation may need this 9204 mov lr, #0 @ in case target is HANDLER_INTERPRET 9205 cmp r0,#0 @ successful chain? 9206 bxne r0 @ continue native execution 9207 b toInterpreter @ didn't chain - resume with interpreter 9208 9209/* 9210 * Return from the translation cache to the interpreter to do method invocation. 9211 * Check if translation exists for the callee, but don't chain to it. 9212 */ 9213 .global dvmJitToInterpNoChain 9214dvmJitToInterpNoChain: 9215#ifdef EXIT_STATS 9216 bl dvmBumpNoChain 9217#endif 9218 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9219 mov r0,rPC 9220 bl dvmJitGetCodeAddr @ Is there a translation? 9221 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9222 mov r1, rPC @ arg1 of translation may need this 9223 mov lr, #0 @ in case target is HANDLER_INTERPRET 9224 cmp r0,#0 9225 bxne r0 @ continue native execution if so 9226#endif 9227 9228/* 9229 * No translation, restore interpreter regs and start interpreting. 9230 * rGLUE & rFP were preserved in the translated code, and rPC has 9231 * already been restored by the time we get here. We'll need to set 9232 * up rIBASE & rINST, and load the address of the JitTable into r0. 9233 */ 9234toInterpreter: 9235 EXPORT_PC() 9236 adrl rIBASE, dvmAsmInstructionStart 9237 FETCH_INST() 9238 GET_JIT_PROF_TABLE(r0) 9239 @ NOTE: intended fallthrough 9240/* 9241 * Common code to update potential trace start counter, and initiate 9242 * a trace-build if appropriate. On entry, rPC should point to the 9243 * next instruction to execute, and rINST should be already loaded with 9244 * the next opcode word, and r0 holds a pointer to the jit profile 9245 * table (pJitProfTable). 9246 */ 9247common_testUpdateProfile: 9248 cmp r0,#0 9249 GET_INST_OPCODE(ip) 9250 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9251 9252common_updateProfile: 9253 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9254 lsl r3,r3,#21 @ shift out excess 2047 9255 ldrb r1,[r0,r3,lsr #21] @ get counter 9256 GET_INST_OPCODE(ip) 9257 subs r1,r1,#1 @ decrement counter 9258 strb r1,[r0,r3,lsr #21] @ and store it 9259 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9260 9261/* 9262 * Here, we switch to the debug interpreter to request 9263 * trace selection. First, though, check to see if there 9264 * is already a native translation in place (and, if so, 9265 * jump to it now). 9266 */ 9267 GET_JIT_THRESHOLD(r1) 9268 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9269 strb r1,[r0,r3,lsr #21] @ reset counter 9270 EXPORT_PC() 9271 mov r0,rPC 9272 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9273 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9274 mov r1, rPC @ arg1 of translation may need this 9275 mov lr, #0 @ in case target is HANDLER_INTERPRET 9276 cmp r0,#0 9277#if !defined(WITH_SELF_VERIFICATION) 9278 bxne r0 @ jump to the translation 9279#else 9280 beq common_selectTrace 9281 /* 9282 * At this point, we have a target translation. However, if 9283 * that translation is actually the interpret-only pseudo-translation 9284 * we want to treat it the same as no translation. 9285 */ 9286 mov r10, r0 @ save target 9287 bl dvmCompilerGetInterpretTemplate 9288 cmp r0, r10 @ special case? 9289 bne dvmJitSelfVerificationStart @ set up self verification 9290 GET_INST_OPCODE(ip) 9291 GOTO_OPCODE(ip) 9292 /* no return */ 9293#endif 9294 9295common_selectTrace: 9296 mov r2,#kJitTSelectRequest @ ask for trace selection 9297 str r2,[rGLUE,#offGlue_jitState] 9298 mov r2,#kInterpEntryInstr @ normal entry reason 9299 str r2,[rGLUE,#offGlue_entryPoint] 9300 mov r1,#1 @ set changeInterp 9301 b common_gotoBail 9302 9303#if defined(WITH_SELF_VERIFICATION) 9304/* 9305 * Save PC and registers to shadow memory for self verification mode 9306 * before jumping to native translation. 9307 * On entry, r10 contains the address of the target translation. 9308 */ 9309dvmJitSelfVerificationStart: 9310 mov r0,rPC @ r0<- program counter 9311 mov r1,rFP @ r1<- frame pointer 9312 mov r2,rGLUE @ r2<- InterpState pointer 9313 mov r3,r10 @ r3<- target translation 9314 bl dvmSelfVerificationSaveState @ save registers to shadow space 9315 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9316 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9317 bx r10 @ jump to the translation 9318 9319/* 9320 * Restore PC, registers, and interpState to original values 9321 * before jumping back to the interpreter. 9322 */ 9323dvmJitSelfVerificationEnd: 9324 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9325 mov r1, #0 9326 str r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9327 mov r1,rFP @ pass ending fp 9328 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9329 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9330 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9331 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9332 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9333 cmp r1,#0 @ check for punt condition 9334 beq 1f 9335 mov r2,#kJitSelfVerification @ ask for self verification 9336 str r2,[rGLUE,#offGlue_jitState] 9337 mov r2,#kInterpEntryInstr @ normal entry reason 9338 str r2,[rGLUE,#offGlue_entryPoint] 9339 mov r1,#1 @ set changeInterp 9340 b common_gotoBail 9341 93421: @ exit to interpreter without check 9343 EXPORT_PC() 9344 adrl rIBASE, dvmAsmInstructionStart 9345 FETCH_INST() 9346 GET_INST_OPCODE(ip) 9347 GOTO_OPCODE(ip) 9348#endif 9349 9350#endif 9351 9352/* 9353 * Common code when a backward branch is taken. 9354 * 9355 * On entry: 9356 * r9 is PC adjustment *in bytes* 9357 */ 9358common_backwardBranch: 9359 mov r0, #kInterpEntryInstr 9360 bl common_periodicChecks 9361#if defined(WITH_JIT) 9362 GET_JIT_PROF_TABLE(r0) 9363 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9364 cmp r0,#0 9365 bne common_updateProfile 9366 GET_INST_OPCODE(ip) 9367 GOTO_OPCODE(ip) 9368#else 9369 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9370 GET_INST_OPCODE(ip) @ extract opcode from rINST 9371 GOTO_OPCODE(ip) @ jump to next instruction 9372#endif 9373 9374 9375/* 9376 * Need to see if the thread needs to be suspended or debugger/profiler 9377 * activity has begun. 9378 * 9379 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9380 * have to do the second ldr. 9381 * 9382 * TODO: reduce this so we're just checking a single location. 9383 * 9384 * On entry: 9385 * r0 is reentry type, e.g. kInterpEntryInstr 9386 * r9 is trampoline PC adjustment *in bytes* 9387 */ 9388common_periodicChecks: 9389 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9390 9391 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9392 str r0, [rGLUE, #offGlue_entryPoint] 9393 9394#if defined(WITH_DEBUGGER) 9395 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9396#endif 9397#if defined(WITH_PROFILER) 9398 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9399#endif 9400 9401 ldr r3, [r3] @ r3<- suspendCount (int) 9402 9403#if defined(WITH_DEBUGGER) 9404 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9405#endif 9406#if defined (WITH_PROFILER) 9407 ldr r2, [r2] @ r2<- activeProfilers (int) 9408#endif 9409 9410 cmp r3, #0 @ suspend pending? 9411 bne 2f @ yes, do full suspension check 9412 9413#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9414# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9415 orrs r1, r1, r2 @ r1<- r1 | r2 9416 cmp r1, #0 @ debugger attached or profiler started? 9417# elif defined(WITH_DEBUGGER) 9418 cmp r1, #0 @ debugger attached? 9419# elif defined(WITH_PROFILER) 9420 cmp r2, #0 @ profiler started? 9421# endif 9422 bne 3f @ debugger/profiler, switch interp 9423#endif 9424 9425 bx lr @ nothing to do, return 9426 94272: @ check suspend 9428#if defined(WITH_JIT) 9429 /* 9430 * Refresh the Jit's cached copy of profile table pointer. This pointer 9431 * doubles as the Jit's on/off switch. 9432 */ 9433 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable 9434 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9435 ldr r3, [r3] @ r10 <- pJitProfTable 9436 EXPORT_PC() @ need for precise GC 9437 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9438#else 9439 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9440 EXPORT_PC() @ need for precise GC 9441#endif 9442 b dvmCheckSuspendPending @ suspend if necessary, then return 9443 94443: @ debugger/profiler enabled, bail out 9445 add rPC, rPC, r9 @ update rPC 9446 mov r1, #1 @ "want switch" = true 9447 b common_gotoBail 9448 9449 9450/* 9451 * The equivalent of "goto bail", this calls through the "bail handler". 9452 * 9453 * State registers will be saved to the "glue" area before bailing. 9454 * 9455 * On entry: 9456 * r1 is "bool changeInterp", indicating if we want to switch to the 9457 * other interpreter or just bail all the way out 9458 */ 9459common_gotoBail: 9460 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9461 mov r0, rGLUE @ r0<- glue ptr 9462 b dvmMterpStdBail @ call(glue, changeInterp) 9463 9464 @add r1, r1, #1 @ using (boolean+1) 9465 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9466 @bl _longjmp @ does not return 9467 @bl common_abort 9468 9469 9470/* 9471 * Common code for method invocation with range. 9472 * 9473 * On entry: 9474 * r0 is "Method* methodToCall", the method we're trying to call 9475 */ 9476common_invokeMethodRange: 9477.LinvokeNewRange: 9478 @ prepare to copy args to "outs" area of current frame 9479 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9480 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9481 beq .LinvokeArgsDone @ if no args, skip the rest 9482 FETCH(r1, 2) @ r1<- CCCC 9483 9484 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9485 @ (very few methods have > 10 args; could unroll for common cases) 9486 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9487 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9488 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94891: ldr r1, [r3], #4 @ val = *fp++ 9490 subs r2, r2, #1 @ count-- 9491 str r1, [r10], #4 @ *outs++ = val 9492 bne 1b @ ...while count != 0 9493 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9494 b .LinvokeArgsDone 9495 9496/* 9497 * Common code for method invocation without range. 9498 * 9499 * On entry: 9500 * r0 is "Method* methodToCall", the method we're trying to call 9501 */ 9502common_invokeMethodNoRange: 9503.LinvokeNewNoRange: 9504 @ prepare to copy args to "outs" area of current frame 9505 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9506 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9507 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9508 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9509 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9510 beq .LinvokeArgsDone 9511 9512 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9513.LinvokeNonRange: 9514 rsb r2, r2, #5 @ r2<- 5-r2 9515 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9516 bl common_abort @ (skipped due to ARM prefetch) 95175: and ip, rINST, #0x0f00 @ isolate A 9518 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9519 mov r0, r0 @ nop 9520 str r2, [r10, #-4]! @ *--outs = vA 95214: and ip, r1, #0xf000 @ isolate G 9522 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9523 mov r0, r0 @ nop 9524 str r2, [r10, #-4]! @ *--outs = vG 95253: and ip, r1, #0x0f00 @ isolate F 9526 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9527 mov r0, r0 @ nop 9528 str r2, [r10, #-4]! @ *--outs = vF 95292: and ip, r1, #0x00f0 @ isolate E 9530 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9531 mov r0, r0 @ nop 9532 str r2, [r10, #-4]! @ *--outs = vE 95331: and ip, r1, #0x000f @ isolate D 9534 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9535 mov r0, r0 @ nop 9536 str r2, [r10, #-4]! @ *--outs = vD 95370: @ fall through to .LinvokeArgsDone 9538 9539.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9540 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9541 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9542 @ find space for the new stack frame, check for overflow 9543 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9544 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9545 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9546@ bl common_dumpRegs 9547 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9548 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9549 cmp r3, r9 @ bottom < interpStackEnd? 9550 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9551 blt .LstackOverflow @ yes, this frame will overflow stack 9552 9553 @ set up newSaveArea 9554#ifdef EASY_GDB 9555 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9556 str ip, [r10, #offStackSaveArea_prevSave] 9557#endif 9558 str rFP, [r10, #offStackSaveArea_prevFrame] 9559 str rPC, [r10, #offStackSaveArea_savedPc] 9560#if defined(WITH_JIT) 9561 mov r9, #0 9562 str r9, [r10, #offStackSaveArea_returnAddr] 9563#endif 9564 str r0, [r10, #offStackSaveArea_method] 9565 tst r3, #ACC_NATIVE 9566 bne .LinvokeNative 9567 9568 /* 9569 stmfd sp!, {r0-r3} 9570 bl common_printNewline 9571 mov r0, rFP 9572 mov r1, #0 9573 bl dvmDumpFp 9574 ldmfd sp!, {r0-r3} 9575 stmfd sp!, {r0-r3} 9576 mov r0, r1 9577 mov r1, r10 9578 bl dvmDumpFp 9579 bl common_printNewline 9580 ldmfd sp!, {r0-r3} 9581 */ 9582 9583 ldrh r9, [r2] @ r9 <- load INST from new PC 9584 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9585 mov rPC, r2 @ publish new rPC 9586 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9587 9588 @ Update "glue" values for the new method 9589 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9590 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9591 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9592#if defined(WITH_JIT) 9593 GET_JIT_PROF_TABLE(r0) 9594 mov rFP, r1 @ fp = newFp 9595 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9596 mov rINST, r9 @ publish new rINST 9597 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9598 cmp r0,#0 9599 bne common_updateProfile 9600 GOTO_OPCODE(ip) @ jump to next instruction 9601#else 9602 mov rFP, r1 @ fp = newFp 9603 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9604 mov rINST, r9 @ publish new rINST 9605 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9606 GOTO_OPCODE(ip) @ jump to next instruction 9607#endif 9608 9609.LinvokeNative: 9610 @ Prep for the native call 9611 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9612 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9613 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9614 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9615 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9616 mov r9, r3 @ r9<- glue->self (preserve) 9617 9618 mov r2, r0 @ r2<- methodToCall 9619 mov r0, r1 @ r0<- newFp (points to args) 9620 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9621 9622#ifdef ASSIST_DEBUGGER 9623 /* insert fake function header to help gdb find the stack frame */ 9624 b .Lskip 9625 .type dalvik_mterp, %function 9626dalvik_mterp: 9627 .fnstart 9628 MTERP_ENTRY1 9629 MTERP_ENTRY2 9630.Lskip: 9631#endif 9632 9633 @mov lr, pc @ set return addr 9634 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9635 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9636 9637#if defined(WITH_JIT) 9638 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9639#endif 9640 9641 @ native return; r9=self, r10=newSaveArea 9642 @ equivalent to dvmPopJniLocals 9643 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9644 ldr r1, [r9, #offThread_exception] @ check for exception 9645#if defined(WITH_JIT) 9646 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9647#endif 9648 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9649 cmp r1, #0 @ null? 9650 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9651#if defined(WITH_JIT) 9652 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9653#endif 9654 bne common_exceptionThrown @ no, handle exception 9655 9656 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9657 GET_INST_OPCODE(ip) @ extract opcode from rINST 9658 GOTO_OPCODE(ip) @ jump to next instruction 9659 9660.LstackOverflow: @ r0=methodToCall 9661 mov r1, r0 @ r1<- methodToCall 9662 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9663 bl dvmHandleStackOverflow 9664 b common_exceptionThrown 9665#ifdef ASSIST_DEBUGGER 9666 .fnend 9667#endif 9668 9669 9670 /* 9671 * Common code for method invocation, calling through "glue code". 9672 * 9673 * TODO: now that we have range and non-range invoke handlers, this 9674 * needs to be split into two. Maybe just create entry points 9675 * that set r9 and jump here? 9676 * 9677 * On entry: 9678 * r0 is "Method* methodToCall", the method we're trying to call 9679 * r9 is "bool methodCallRange", indicating if this is a /range variant 9680 */ 9681 .if 0 9682.LinvokeOld: 9683 sub sp, sp, #8 @ space for args + pad 9684 FETCH(ip, 2) @ ip<- FEDC or CCCC 9685 mov r2, r0 @ A2<- methodToCall 9686 mov r0, rGLUE @ A0<- glue 9687 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9688 mov r1, r9 @ A1<- methodCallRange 9689 mov r3, rINST, lsr #8 @ A3<- AA 9690 str ip, [sp, #0] @ A4<- ip 9691 bl dvmMterp_invokeMethod @ call the C invokeMethod 9692 add sp, sp, #8 @ remove arg area 9693 b common_resumeAfterGlueCall @ continue to next instruction 9694 .endif 9695 9696 9697 9698/* 9699 * Common code for handling a return instruction. 9700 * 9701 * This does not return. 9702 */ 9703common_returnFromMethod: 9704.LreturnNew: 9705 mov r0, #kInterpEntryReturn 9706 mov r9, #0 9707 bl common_periodicChecks 9708 9709 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9710 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9711 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9712 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9713 @ r2<- method we're returning to 9714 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9715 cmp r2, #0 @ is this a break frame? 9716 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9717 mov r1, #0 @ "want switch" = false 9718 beq common_gotoBail @ break frame, bail out completely 9719 9720 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9721 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9722 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9723 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9724#if defined(WITH_JIT) 9725 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 9726 GET_JIT_PROF_TABLE(r0) 9727 mov rPC, r9 @ publish new rPC 9728 str r1, [rGLUE, #offGlue_methodClassDex] 9729 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 9730 cmp r10, #0 @ caller is compiled code 9731 blxne r10 9732 GET_INST_OPCODE(ip) @ extract opcode from rINST 9733 cmp r0,#0 9734 bne common_updateProfile 9735 GOTO_OPCODE(ip) @ jump to next instruction 9736#else 9737 GET_INST_OPCODE(ip) @ extract opcode from rINST 9738 mov rPC, r9 @ publish new rPC 9739 str r1, [rGLUE, #offGlue_methodClassDex] 9740 GOTO_OPCODE(ip) @ jump to next instruction 9741#endif 9742 9743 /* 9744 * Return handling, calls through "glue code". 9745 */ 9746 .if 0 9747.LreturnOld: 9748 SAVE_PC_FP_TO_GLUE() @ export state 9749 mov r0, rGLUE @ arg to function 9750 bl dvmMterp_returnFromMethod 9751 b common_resumeAfterGlueCall 9752 .endif 9753 9754 9755/* 9756 * Somebody has thrown an exception. Handle it. 9757 * 9758 * If the exception processing code returns to us (instead of falling 9759 * out of the interpreter), continue with whatever the next instruction 9760 * now happens to be. 9761 * 9762 * This does not return. 9763 */ 9764 .global dvmMterpCommonExceptionThrown 9765dvmMterpCommonExceptionThrown: 9766common_exceptionThrown: 9767.LexceptionNew: 9768 mov r0, #kInterpEntryThrow 9769 mov r9, #0 9770 bl common_periodicChecks 9771 9772#if defined(WITH_JIT) 9773 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9774 str r2,[rGLUE,#offGlue_jitState] 9775#endif 9776 9777 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9778 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9779 mov r1, r10 @ r1<- self 9780 mov r0, r9 @ r0<- exception 9781 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9782 mov r3, #0 @ r3<- NULL 9783 str r3, [r10, #offThread_exception] @ self->exception = NULL 9784 9785 /* set up args and a local for "&fp" */ 9786 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9787 str rFP, [sp, #-4]! @ *--sp = fp 9788 mov ip, sp @ ip<- &fp 9789 mov r3, #0 @ r3<- false 9790 str ip, [sp, #-4]! @ *--sp = &fp 9791 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9792 mov r0, r10 @ r0<- self 9793 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9794 mov r2, r9 @ r2<- exception 9795 sub r1, rPC, r1 @ r1<- pc - method->insns 9796 mov r1, r1, asr #1 @ r1<- offset in code units 9797 9798 /* call, r0 gets catchRelPc (a code-unit offset) */ 9799 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9800 9801 /* fix earlier stack overflow if necessary; may trash rFP */ 9802 ldrb r1, [r10, #offThread_stackOverflowed] 9803 cmp r1, #0 @ did we overflow earlier? 9804 beq 1f @ no, skip ahead 9805 mov rFP, r0 @ save relPc result in rFP 9806 mov r0, r10 @ r0<- self 9807 mov r1, r9 @ r1<- exception 9808 bl dvmCleanupStackOverflow @ call(self) 9809 mov r0, rFP @ restore result 98101: 9811 9812 /* update frame pointer and check result from dvmFindCatchBlock */ 9813 ldr rFP, [sp, #4] @ retrieve the updated rFP 9814 cmp r0, #0 @ is catchRelPc < 0? 9815 add sp, sp, #8 @ restore stack 9816 bmi .LnotCaughtLocally 9817 9818 /* adjust locals to match self->curFrame and updated PC */ 9819 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9820 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9821 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9822 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9823 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9824 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9825 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9826 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9827 9828 /* release the tracked alloc on the exception */ 9829 mov r0, r9 @ r0<- exception 9830 mov r1, r10 @ r1<- self 9831 bl dvmReleaseTrackedAlloc @ release the exception 9832 9833 /* restore the exception if the handler wants it */ 9834 FETCH_INST() @ load rINST from rPC 9835 GET_INST_OPCODE(ip) @ extract opcode from rINST 9836 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9837 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9838 GOTO_OPCODE(ip) @ jump to next instruction 9839 9840.LnotCaughtLocally: @ r9=exception, r10=self 9841 /* fix stack overflow if necessary */ 9842 ldrb r1, [r10, #offThread_stackOverflowed] 9843 cmp r1, #0 @ did we overflow earlier? 9844 movne r0, r10 @ if yes: r0<- self 9845 movne r1, r9 @ if yes: r1<- exception 9846 blne dvmCleanupStackOverflow @ if yes: call(self) 9847 9848 @ may want to show "not caught locally" debug messages here 9849#if DVM_SHOW_EXCEPTION >= 2 9850 /* call __android_log_print(prio, tag, format, ...) */ 9851 /* "Exception %s from %s:%d not caught locally" */ 9852 @ dvmLineNumFromPC(method, pc - method->insns) 9853 ldr r0, [rGLUE, #offGlue_method] 9854 ldr r1, [r0, #offMethod_insns] 9855 sub r1, rPC, r1 9856 asr r1, r1, #1 9857 bl dvmLineNumFromPC 9858 str r0, [sp, #-4]! 9859 @ dvmGetMethodSourceFile(method) 9860 ldr r0, [rGLUE, #offGlue_method] 9861 bl dvmGetMethodSourceFile 9862 str r0, [sp, #-4]! 9863 @ exception->clazz->descriptor 9864 ldr r3, [r9, #offObject_clazz] 9865 ldr r3, [r3, #offClassObject_descriptor] 9866 @ 9867 ldr r2, strExceptionNotCaughtLocally 9868 ldr r1, strLogTag 9869 mov r0, #3 @ LOG_DEBUG 9870 bl __android_log_print 9871#endif 9872 str r9, [r10, #offThread_exception] @ restore exception 9873 mov r0, r9 @ r0<- exception 9874 mov r1, r10 @ r1<- self 9875 bl dvmReleaseTrackedAlloc @ release the exception 9876 mov r1, #0 @ "want switch" = false 9877 b common_gotoBail @ bail out 9878 9879 9880 /* 9881 * Exception handling, calls through "glue code". 9882 */ 9883 .if 0 9884.LexceptionOld: 9885 SAVE_PC_FP_TO_GLUE() @ export state 9886 mov r0, rGLUE @ arg to function 9887 bl dvmMterp_exceptionThrown 9888 b common_resumeAfterGlueCall 9889 .endif 9890 9891 9892/* 9893 * After returning from a "glued" function, pull out the updated 9894 * values and start executing at the next instruction. 9895 */ 9896common_resumeAfterGlueCall: 9897 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9898 FETCH_INST() @ load rINST from rPC 9899 GET_INST_OPCODE(ip) @ extract opcode from rINST 9900 GOTO_OPCODE(ip) @ jump to next instruction 9901 9902/* 9903 * Invalid array index. 9904 */ 9905common_errArrayIndex: 9906 EXPORT_PC() 9907 ldr r0, strArrayIndexException 9908 mov r1, #0 9909 bl dvmThrowException 9910 b common_exceptionThrown 9911 9912/* 9913 * Invalid array value. 9914 */ 9915common_errArrayStore: 9916 EXPORT_PC() 9917 ldr r0, strArrayStoreException 9918 mov r1, #0 9919 bl dvmThrowException 9920 b common_exceptionThrown 9921 9922/* 9923 * Integer divide or mod by zero. 9924 */ 9925common_errDivideByZero: 9926 EXPORT_PC() 9927 ldr r0, strArithmeticException 9928 ldr r1, strDivideByZero 9929 bl dvmThrowException 9930 b common_exceptionThrown 9931 9932/* 9933 * Attempt to allocate an array with a negative size. 9934 */ 9935common_errNegativeArraySize: 9936 EXPORT_PC() 9937 ldr r0, strNegativeArraySizeException 9938 mov r1, #0 9939 bl dvmThrowException 9940 b common_exceptionThrown 9941 9942/* 9943 * Invocation of a non-existent method. 9944 */ 9945common_errNoSuchMethod: 9946 EXPORT_PC() 9947 ldr r0, strNoSuchMethodError 9948 mov r1, #0 9949 bl dvmThrowException 9950 b common_exceptionThrown 9951 9952/* 9953 * We encountered a null object when we weren't expecting one. We 9954 * export the PC, throw a NullPointerException, and goto the exception 9955 * processing code. 9956 */ 9957common_errNullObject: 9958 EXPORT_PC() 9959 ldr r0, strNullPointerException 9960 mov r1, #0 9961 bl dvmThrowException 9962 b common_exceptionThrown 9963 9964/* 9965 * For debugging, cause an immediate fault. The source address will 9966 * be in lr (use a bl instruction to jump here). 9967 */ 9968common_abort: 9969 ldr pc, .LdeadFood 9970.LdeadFood: 9971 .word 0xdeadf00d 9972 9973/* 9974 * Spit out a "we were here", preserving all registers. (The attempt 9975 * to save ip won't work, but we need to save an even number of 9976 * registers for EABI 64-bit stack alignment.) 9977 */ 9978 .macro SQUEAK num 9979common_squeak\num: 9980 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9981 ldr r0, strSqueak 9982 mov r1, #\num 9983 bl printf 9984 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9985 bx lr 9986 .endm 9987 9988 SQUEAK 0 9989 SQUEAK 1 9990 SQUEAK 2 9991 SQUEAK 3 9992 SQUEAK 4 9993 SQUEAK 5 9994 9995/* 9996 * Spit out the number in r0, preserving registers. 9997 */ 9998common_printNum: 9999 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10000 mov r1, r0 10001 ldr r0, strSqueak 10002 bl printf 10003 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10004 bx lr 10005 10006/* 10007 * Print a newline, preserving registers. 10008 */ 10009common_printNewline: 10010 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10011 ldr r0, strNewline 10012 bl printf 10013 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10014 bx lr 10015 10016 /* 10017 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10018 */ 10019common_printHex: 10020 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10021 mov r1, r0 10022 ldr r0, strPrintHex 10023 bl printf 10024 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10025 bx lr 10026 10027/* 10028 * Print the 64-bit quantity in r0-r1, preserving registers. 10029 */ 10030common_printLong: 10031 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10032 mov r3, r1 10033 mov r2, r0 10034 ldr r0, strPrintLong 10035 bl printf 10036 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10037 bx lr 10038 10039/* 10040 * Print full method info. Pass the Method* in r0. Preserves regs. 10041 */ 10042common_printMethod: 10043 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10044 bl dvmMterpPrintMethod 10045 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10046 bx lr 10047 10048/* 10049 * Call a C helper function that dumps regs and possibly some 10050 * additional info. Requires the C function to be compiled in. 10051 */ 10052 .if 0 10053common_dumpRegs: 10054 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10055 bl dvmMterpDumpArmRegs 10056 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10057 bx lr 10058 .endif 10059 10060#if 0 10061/* 10062 * Experiment on VFP mode. 10063 * 10064 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10065 * 10066 * Updates the bits specified by "mask", setting them to the values in "val". 10067 */ 10068setFPSCR: 10069 and r0, r0, r1 @ make sure no stray bits are set 10070 fmrx r2, fpscr @ get VFP reg 10071 mvn r1, r1 @ bit-invert mask 10072 and r2, r2, r1 @ clear masked bits 10073 orr r2, r2, r0 @ set specified bits 10074 fmxr fpscr, r2 @ set VFP reg 10075 mov r0, r2 @ return new value 10076 bx lr 10077 10078 .align 2 10079 .global dvmConfigureFP 10080 .type dvmConfigureFP, %function 10081dvmConfigureFP: 10082 stmfd sp!, {ip, lr} 10083 /* 0x03000000 sets DN/FZ */ 10084 /* 0x00009f00 clears the six exception enable flags */ 10085 bl common_squeak0 10086 mov r0, #0x03000000 @ r0<- 0x03000000 10087 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10088 bl setFPSCR 10089 ldmfd sp!, {ip, pc} 10090#endif 10091 10092 10093/* 10094 * String references, must be close to the code that uses them. 10095 */ 10096 .align 2 10097strArithmeticException: 10098 .word .LstrArithmeticException 10099strArrayIndexException: 10100 .word .LstrArrayIndexException 10101strArrayStoreException: 10102 .word .LstrArrayStoreException 10103strDivideByZero: 10104 .word .LstrDivideByZero 10105strNegativeArraySizeException: 10106 .word .LstrNegativeArraySizeException 10107strNoSuchMethodError: 10108 .word .LstrNoSuchMethodError 10109strNullPointerException: 10110 .word .LstrNullPointerException 10111 10112strLogTag: 10113 .word .LstrLogTag 10114strExceptionNotCaughtLocally: 10115 .word .LstrExceptionNotCaughtLocally 10116 10117strNewline: 10118 .word .LstrNewline 10119strSqueak: 10120 .word .LstrSqueak 10121strPrintHex: 10122 .word .LstrPrintHex 10123strPrintLong: 10124 .word .LstrPrintLong 10125 10126/* 10127 * Zero-terminated ASCII string data. 10128 * 10129 * On ARM we have two choices: do like gcc does, and LDR from a .word 10130 * with the address, or use an ADR pseudo-op to get the address 10131 * directly. ADR saves 4 bytes and an indirection, but it's using a 10132 * PC-relative addressing mode and hence has a limited range, which 10133 * makes it not work well with mergeable string sections. 10134 */ 10135 .section .rodata.str1.4,"aMS",%progbits,1 10136 10137.LstrBadEntryPoint: 10138 .asciz "Bad entry point %d\n" 10139.LstrArithmeticException: 10140 .asciz "Ljava/lang/ArithmeticException;" 10141.LstrArrayIndexException: 10142 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10143.LstrArrayStoreException: 10144 .asciz "Ljava/lang/ArrayStoreException;" 10145.LstrClassCastException: 10146 .asciz "Ljava/lang/ClassCastException;" 10147.LstrDivideByZero: 10148 .asciz "divide by zero" 10149.LstrFilledNewArrayNotImpl: 10150 .asciz "filled-new-array only implemented for objects and 'int'" 10151.LstrInternalError: 10152 .asciz "Ljava/lang/InternalError;" 10153.LstrInstantiationError: 10154 .asciz "Ljava/lang/InstantiationError;" 10155.LstrNegativeArraySizeException: 10156 .asciz "Ljava/lang/NegativeArraySizeException;" 10157.LstrNoSuchMethodError: 10158 .asciz "Ljava/lang/NoSuchMethodError;" 10159.LstrNullPointerException: 10160 .asciz "Ljava/lang/NullPointerException;" 10161 10162.LstrLogTag: 10163 .asciz "mterp" 10164.LstrExceptionNotCaughtLocally: 10165 .asciz "Exception %s from %s:%d not caught locally\n" 10166 10167.LstrNewline: 10168 .asciz "\n" 10169.LstrSqueak: 10170 .asciz "<%d>" 10171.LstrPrintHex: 10172 .asciz "<0x%x>" 10173.LstrPrintLong: 10174 .asciz "<%lld>" 10175 10176 10177