InterpAsm-armv5te-vfp.S revision d726991ba52466cde88e37aba4de2395b62477fa
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_ENABLED(_reg) ldr _reg,[rGLUE,#offGlue_jitEnabled] 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205 206/* File: armv5te/platform.S */ 207/* 208 * =========================================================================== 209 * CPU-version-specific defines 210 * =========================================================================== 211 */ 212 213/* 214 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 215 * one-way branch. 216 * 217 * May modify IP. Does not modify LR. 218 */ 219.macro LDR_PC source 220 ldr pc, \source 221.endm 222 223/* 224 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 225 * Jump to subroutine. 226 * 227 * May modify IP and LR. 228 */ 229.macro LDR_PC_LR source 230 mov lr, pc 231 ldr pc, \source 232.endm 233 234/* 235 * Macro for "LDMFD SP!, {...regs...,PC}". 236 * 237 * May modify IP and LR. 238 */ 239.macro LDMFD_PC regs 240 ldmfd sp!, {\regs,pc} 241.endm 242 243 244/* File: armv5te/entry.S */ 245/* 246 * Copyright (C) 2008 The Android Open Source Project 247 * 248 * Licensed under the Apache License, Version 2.0 (the "License"); 249 * you may not use this file except in compliance with the License. 250 * You may obtain a copy of the License at 251 * 252 * http://www.apache.org/licenses/LICENSE-2.0 253 * 254 * Unless required by applicable law or agreed to in writing, software 255 * distributed under the License is distributed on an "AS IS" BASIS, 256 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 257 * See the License for the specific language governing permissions and 258 * limitations under the License. 259 */ 260/* 261 * Interpreter entry point. 262 */ 263 264/* 265 * We don't have formal stack frames, so gdb scans upward in the code 266 * to find the start of the function (a label with the %function type), 267 * and then looks at the next few instructions to figure out what 268 * got pushed onto the stack. From this it figures out how to restore 269 * the registers, including PC, for the previous stack frame. If gdb 270 * sees a non-function label, it stops scanning, so either we need to 271 * have nothing but assembler-local labels between the entry point and 272 * the break, or we need to fake it out. 273 * 274 * When this is defined, we add some stuff to make gdb less confused. 275 */ 276#define ASSIST_DEBUGGER 1 277 278 .text 279 .align 2 280 .global dvmMterpStdRun 281 .type dvmMterpStdRun, %function 282 283/* 284 * On entry: 285 * r0 MterpGlue* glue 286 * 287 * This function returns a boolean "changeInterp" value. The return comes 288 * via a call to dvmMterpStdBail(). 289 */ 290dvmMterpStdRun: 291#define MTERP_ENTRY1 \ 292 .save {r4-r10,fp,lr}; \ 293 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 294#define MTERP_ENTRY2 \ 295 .pad #4; \ 296 sub sp, sp, #4 @ align 64 297 298 .fnstart 299 MTERP_ENTRY1 300 MTERP_ENTRY2 301 302 /* save stack pointer, add magic word for debuggerd */ 303 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 304 305 /* set up "named" registers, figure out entry point */ 306 mov rGLUE, r0 @ set rGLUE 307 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 308 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 309 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 310 cmp r1, #kInterpEntryInstr @ usual case? 311 bne .Lnot_instr @ no, handle it 312 313#if defined(WITH_JIT) 314.Lno_singleStep: 315 /* Entry is always a possible trace start */ 316 GET_JIT_PROF_TABLE(r0) 317 FETCH_INST() 318 cmp r0,#0 319 bne common_updateProfile 320 GET_INST_OPCODE(ip) 321 GOTO_OPCODE(ip) 322#else 323 /* start executing the instruction at rPC */ 324 FETCH_INST() @ load rINST from rPC 325 GET_INST_OPCODE(ip) @ extract opcode from rINST 326 GOTO_OPCODE(ip) @ jump to next instruction 327#endif 328 329.Lnot_instr: 330 cmp r1, #kInterpEntryReturn @ were we returning from a method? 331 beq common_returnFromMethod 332 333.Lnot_return: 334 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 335 beq common_exceptionThrown 336 337#if defined(WITH_JIT) 338.Lnot_throw: 339 ldr r0,[rGLUE, #offGlue_jitResume] 340 ldr r2,[rGLUE, #offGlue_jitResumePC] 341 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 342 bne .Lbad_arg 343 cmp rPC,r2 344 bne .Lno_singleStep @ must have branched, don't resume 345 mov r1, #kInterpEntryInstr 346 strb r1, [rGLUE, #offGlue_entryPoint] 347 ldr rINST, .LdvmCompilerTemplate 348 bx r0 @ re-enter the translation 349.LdvmCompilerTemplate: 350 .word dvmCompilerTemplateStart 351#endif 352 353.Lbad_arg: 354 ldr r0, strBadEntryPoint 355 @ r1 holds value of entryPoint 356 bl printf 357 bl dvmAbort 358 .fnend 359 360 361 .global dvmMterpStdBail 362 .type dvmMterpStdBail, %function 363 364/* 365 * Restore the stack pointer and PC from the save point established on entry. 366 * This is essentially the same as a longjmp, but should be cheaper. The 367 * last instruction causes us to return to whoever called dvmMterpStdRun. 368 * 369 * We pushed some registers on the stack in dvmMterpStdRun, then saved 370 * SP and LR. Here we restore SP, restore the registers, and then restore 371 * LR to PC. 372 * 373 * On entry: 374 * r0 MterpGlue* glue 375 * r1 bool changeInterp 376 */ 377dvmMterpStdBail: 378 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 379 mov r0, r1 @ return the changeInterp value 380 add sp, sp, #4 @ un-align 64 381 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 382 383 384/* 385 * String references. 386 */ 387strBadEntryPoint: 388 .word .LstrBadEntryPoint 389 390 391 392 .global dvmAsmInstructionStart 393 .type dvmAsmInstructionStart, %function 394dvmAsmInstructionStart = .L_OP_NOP 395 .text 396 397/* ------------------------------ */ 398 .balign 64 399.L_OP_NOP: /* 0x00 */ 400/* File: armv5te/OP_NOP.S */ 401 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 402 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 403 GOTO_OPCODE(ip) @ execute it 404 405#ifdef ASSIST_DEBUGGER 406 /* insert fake function header to help gdb find the stack frame */ 407 .type dalvik_inst, %function 408dalvik_inst: 409 .fnstart 410 MTERP_ENTRY1 411 MTERP_ENTRY2 412 .fnend 413#endif 414 415 416/* ------------------------------ */ 417 .balign 64 418.L_OP_MOVE: /* 0x01 */ 419/* File: armv5te/OP_MOVE.S */ 420 /* for move, move-object, long-to-int */ 421 /* op vA, vB */ 422 mov r1, rINST, lsr #12 @ r1<- B from 15:12 423 mov r0, rINST, lsr #8 @ r0<- A from 11:8 424 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 425 GET_VREG(r2, r1) @ r2<- fp[B] 426 and r0, r0, #15 427 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 428 SET_VREG(r2, r0) @ fp[A]<- r2 429 GOTO_OPCODE(ip) @ execute next instruction 430 431 432/* ------------------------------ */ 433 .balign 64 434.L_OP_MOVE_FROM16: /* 0x02 */ 435/* File: armv5te/OP_MOVE_FROM16.S */ 436 /* for: move/from16, move-object/from16 */ 437 /* op vAA, vBBBB */ 438 FETCH(r1, 1) @ r1<- BBBB 439 mov r0, rINST, lsr #8 @ r0<- AA 440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 441 GET_VREG(r2, r1) @ r2<- fp[BBBB] 442 GET_INST_OPCODE(ip) @ extract opcode from rINST 443 SET_VREG(r2, r0) @ fp[AA]<- r2 444 GOTO_OPCODE(ip) @ jump to next instruction 445 446 447/* ------------------------------ */ 448 .balign 64 449.L_OP_MOVE_16: /* 0x03 */ 450/* File: armv5te/OP_MOVE_16.S */ 451 /* for: move/16, move-object/16 */ 452 /* op vAAAA, vBBBB */ 453 FETCH(r1, 2) @ r1<- BBBB 454 FETCH(r0, 1) @ r0<- AAAA 455 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 456 GET_VREG(r2, r1) @ r2<- fp[BBBB] 457 GET_INST_OPCODE(ip) @ extract opcode from rINST 458 SET_VREG(r2, r0) @ fp[AAAA]<- r2 459 GOTO_OPCODE(ip) @ jump to next instruction 460 461 462/* ------------------------------ */ 463 .balign 64 464.L_OP_MOVE_WIDE: /* 0x04 */ 465/* File: armv5te/OP_MOVE_WIDE.S */ 466 /* move-wide vA, vB */ 467 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 468 mov r2, rINST, lsr #8 @ r2<- A(+) 469 mov r3, rINST, lsr #12 @ r3<- B 470 and r2, r2, #15 471 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 472 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 473 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 474 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 475 GET_INST_OPCODE(ip) @ extract opcode from rINST 476 stmia r2, {r0-r1} @ fp[A]<- r0/r1 477 GOTO_OPCODE(ip) @ jump to next instruction 478 479 480/* ------------------------------ */ 481 .balign 64 482.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 483/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 484 /* move-wide/from16 vAA, vBBBB */ 485 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 486 FETCH(r3, 1) @ r3<- BBBB 487 mov r2, rINST, lsr #8 @ r2<- AA 488 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 489 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 490 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 491 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 492 GET_INST_OPCODE(ip) @ extract opcode from rINST 493 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 494 GOTO_OPCODE(ip) @ jump to next instruction 495 496 497/* ------------------------------ */ 498 .balign 64 499.L_OP_MOVE_WIDE_16: /* 0x06 */ 500/* File: armv5te/OP_MOVE_WIDE_16.S */ 501 /* move-wide/16 vAAAA, vBBBB */ 502 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 503 FETCH(r3, 2) @ r3<- BBBB 504 FETCH(r2, 1) @ r2<- AAAA 505 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 506 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 507 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 508 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 509 GET_INST_OPCODE(ip) @ extract opcode from rINST 510 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 511 GOTO_OPCODE(ip) @ jump to next instruction 512 513 514/* ------------------------------ */ 515 .balign 64 516.L_OP_MOVE_OBJECT: /* 0x07 */ 517/* File: armv5te/OP_MOVE_OBJECT.S */ 518/* File: armv5te/OP_MOVE.S */ 519 /* for move, move-object, long-to-int */ 520 /* op vA, vB */ 521 mov r1, rINST, lsr #12 @ r1<- B from 15:12 522 mov r0, rINST, lsr #8 @ r0<- A from 11:8 523 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 524 GET_VREG(r2, r1) @ r2<- fp[B] 525 and r0, r0, #15 526 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 527 SET_VREG(r2, r0) @ fp[A]<- r2 528 GOTO_OPCODE(ip) @ execute next instruction 529 530 531 532/* ------------------------------ */ 533 .balign 64 534.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 535/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 536/* File: armv5te/OP_MOVE_FROM16.S */ 537 /* for: move/from16, move-object/from16 */ 538 /* op vAA, vBBBB */ 539 FETCH(r1, 1) @ r1<- BBBB 540 mov r0, rINST, lsr #8 @ r0<- AA 541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 542 GET_VREG(r2, r1) @ r2<- fp[BBBB] 543 GET_INST_OPCODE(ip) @ extract opcode from rINST 544 SET_VREG(r2, r0) @ fp[AA]<- r2 545 GOTO_OPCODE(ip) @ jump to next instruction 546 547 548 549/* ------------------------------ */ 550 .balign 64 551.L_OP_MOVE_OBJECT_16: /* 0x09 */ 552/* File: armv5te/OP_MOVE_OBJECT_16.S */ 553/* File: armv5te/OP_MOVE_16.S */ 554 /* for: move/16, move-object/16 */ 555 /* op vAAAA, vBBBB */ 556 FETCH(r1, 2) @ r1<- BBBB 557 FETCH(r0, 1) @ r0<- AAAA 558 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 559 GET_VREG(r2, r1) @ r2<- fp[BBBB] 560 GET_INST_OPCODE(ip) @ extract opcode from rINST 561 SET_VREG(r2, r0) @ fp[AAAA]<- r2 562 GOTO_OPCODE(ip) @ jump to next instruction 563 564 565 566/* ------------------------------ */ 567 .balign 64 568.L_OP_MOVE_RESULT: /* 0x0a */ 569/* File: armv5te/OP_MOVE_RESULT.S */ 570 /* for: move-result, move-result-object */ 571 /* op vAA */ 572 mov r2, rINST, lsr #8 @ r2<- AA 573 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 574 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 575 GET_INST_OPCODE(ip) @ extract opcode from rINST 576 SET_VREG(r0, r2) @ fp[AA]<- r0 577 GOTO_OPCODE(ip) @ jump to next instruction 578 579 580/* ------------------------------ */ 581 .balign 64 582.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 583/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 584 /* move-result-wide vAA */ 585 mov r2, rINST, lsr #8 @ r2<- AA 586 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 587 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 588 ldmia r3, {r0-r1} @ r0/r1<- retval.j 589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 590 GET_INST_OPCODE(ip) @ extract opcode from rINST 591 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 592 GOTO_OPCODE(ip) @ jump to next instruction 593 594 595/* ------------------------------ */ 596 .balign 64 597.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 598/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 599/* File: armv5te/OP_MOVE_RESULT.S */ 600 /* for: move-result, move-result-object */ 601 /* op vAA */ 602 mov r2, rINST, lsr #8 @ r2<- AA 603 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 604 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 605 GET_INST_OPCODE(ip) @ extract opcode from rINST 606 SET_VREG(r0, r2) @ fp[AA]<- r0 607 GOTO_OPCODE(ip) @ jump to next instruction 608 609 610 611/* ------------------------------ */ 612 .balign 64 613.L_OP_MOVE_EXCEPTION: /* 0x0d */ 614/* File: armv5te/OP_MOVE_EXCEPTION.S */ 615 /* move-exception vAA */ 616 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 617 mov r2, rINST, lsr #8 @ r2<- AA 618 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 619 mov r1, #0 @ r1<- 0 620 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 621 SET_VREG(r3, r2) @ fp[AA]<- exception obj 622 GET_INST_OPCODE(ip) @ extract opcode from rINST 623 str r1, [r0, #offThread_exception] @ dvmClearException bypass 624 GOTO_OPCODE(ip) @ jump to next instruction 625 626 627/* ------------------------------ */ 628 .balign 64 629.L_OP_RETURN_VOID: /* 0x0e */ 630/* File: armv5te/OP_RETURN_VOID.S */ 631 b common_returnFromMethod 632 633 634/* ------------------------------ */ 635 .balign 64 636.L_OP_RETURN: /* 0x0f */ 637/* File: armv5te/OP_RETURN.S */ 638 /* 639 * Return a 32-bit value. Copies the return value into the "glue" 640 * structure, then jumps to the return handler. 641 * 642 * for: return, return-object 643 */ 644 /* op vAA */ 645 mov r2, rINST, lsr #8 @ r2<- AA 646 GET_VREG(r0, r2) @ r0<- vAA 647 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 648 b common_returnFromMethod 649 650 651/* ------------------------------ */ 652 .balign 64 653.L_OP_RETURN_WIDE: /* 0x10 */ 654/* File: armv5te/OP_RETURN_WIDE.S */ 655 /* 656 * Return a 64-bit value. Copies the return value into the "glue" 657 * structure, then jumps to the return handler. 658 */ 659 /* return-wide vAA */ 660 mov r2, rINST, lsr #8 @ r2<- AA 661 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 662 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 663 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 664 stmia r3, {r0-r1} @ retval<- r0/r1 665 b common_returnFromMethod 666 667 668/* ------------------------------ */ 669 .balign 64 670.L_OP_RETURN_OBJECT: /* 0x11 */ 671/* File: armv5te/OP_RETURN_OBJECT.S */ 672/* File: armv5te/OP_RETURN.S */ 673 /* 674 * Return a 32-bit value. Copies the return value into the "glue" 675 * structure, then jumps to the return handler. 676 * 677 * for: return, return-object 678 */ 679 /* op vAA */ 680 mov r2, rINST, lsr #8 @ r2<- AA 681 GET_VREG(r0, r2) @ r0<- vAA 682 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 683 b common_returnFromMethod 684 685 686 687/* ------------------------------ */ 688 .balign 64 689.L_OP_CONST_4: /* 0x12 */ 690/* File: armv5te/OP_CONST_4.S */ 691 /* const/4 vA, #+B */ 692 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 693 mov r0, rINST, lsr #8 @ r0<- A+ 694 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 695 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 696 and r0, r0, #15 697 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 698 SET_VREG(r1, r0) @ fp[A]<- r1 699 GOTO_OPCODE(ip) @ execute next instruction 700 701 702/* ------------------------------ */ 703 .balign 64 704.L_OP_CONST_16: /* 0x13 */ 705/* File: armv5te/OP_CONST_16.S */ 706 /* const/16 vAA, #+BBBB */ 707 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 708 mov r3, rINST, lsr #8 @ r3<- AA 709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 710 SET_VREG(r0, r3) @ vAA<- r0 711 GET_INST_OPCODE(ip) @ extract opcode from rINST 712 GOTO_OPCODE(ip) @ jump to next instruction 713 714 715/* ------------------------------ */ 716 .balign 64 717.L_OP_CONST: /* 0x14 */ 718/* File: armv5te/OP_CONST.S */ 719 /* const vAA, #+BBBBbbbb */ 720 mov r3, rINST, lsr #8 @ r3<- AA 721 FETCH(r0, 1) @ r0<- bbbb (low) 722 FETCH(r1, 2) @ r1<- BBBB (high) 723 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 724 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 725 GET_INST_OPCODE(ip) @ extract opcode from rINST 726 SET_VREG(r0, r3) @ vAA<- r0 727 GOTO_OPCODE(ip) @ jump to next instruction 728 729 730/* ------------------------------ */ 731 .balign 64 732.L_OP_CONST_HIGH16: /* 0x15 */ 733/* File: armv5te/OP_CONST_HIGH16.S */ 734 /* const/high16 vAA, #+BBBB0000 */ 735 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 736 mov r3, rINST, lsr #8 @ r3<- AA 737 mov r0, r0, lsl #16 @ r0<- BBBB0000 738 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 739 SET_VREG(r0, r3) @ vAA<- r0 740 GET_INST_OPCODE(ip) @ extract opcode from rINST 741 GOTO_OPCODE(ip) @ jump to next instruction 742 743 744/* ------------------------------ */ 745 .balign 64 746.L_OP_CONST_WIDE_16: /* 0x16 */ 747/* File: armv5te/OP_CONST_WIDE_16.S */ 748 /* const-wide/16 vAA, #+BBBB */ 749 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 750 mov r3, rINST, lsr #8 @ r3<- AA 751 mov r1, r0, asr #31 @ r1<- ssssssss 752 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 753 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 754 GET_INST_OPCODE(ip) @ extract opcode from rINST 755 stmia r3, {r0-r1} @ vAA<- r0/r1 756 GOTO_OPCODE(ip) @ jump to next instruction 757 758 759/* ------------------------------ */ 760 .balign 64 761.L_OP_CONST_WIDE_32: /* 0x17 */ 762/* File: armv5te/OP_CONST_WIDE_32.S */ 763 /* const-wide/32 vAA, #+BBBBbbbb */ 764 FETCH(r0, 1) @ r0<- 0000bbbb (low) 765 mov r3, rINST, lsr #8 @ r3<- AA 766 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 767 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 768 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 769 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 770 mov r1, r0, asr #31 @ r1<- ssssssss 771 GET_INST_OPCODE(ip) @ extract opcode from rINST 772 stmia r3, {r0-r1} @ vAA<- r0/r1 773 GOTO_OPCODE(ip) @ jump to next instruction 774 775 776/* ------------------------------ */ 777 .balign 64 778.L_OP_CONST_WIDE: /* 0x18 */ 779/* File: armv5te/OP_CONST_WIDE.S */ 780 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 781 FETCH(r0, 1) @ r0<- bbbb (low) 782 FETCH(r1, 2) @ r1<- BBBB (low middle) 783 FETCH(r2, 3) @ r2<- hhhh (high middle) 784 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 785 FETCH(r3, 4) @ r3<- HHHH (high) 786 mov r9, rINST, lsr #8 @ r9<- AA 787 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 788 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 789 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 790 GET_INST_OPCODE(ip) @ extract opcode from rINST 791 stmia r9, {r0-r1} @ vAA<- r0/r1 792 GOTO_OPCODE(ip) @ jump to next instruction 793 794 795/* ------------------------------ */ 796 .balign 64 797.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 798/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 799 /* const-wide/high16 vAA, #+BBBB000000000000 */ 800 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 801 mov r3, rINST, lsr #8 @ r3<- AA 802 mov r0, #0 @ r0<- 00000000 803 mov r1, r1, lsl #16 @ r1<- BBBB0000 804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 805 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 806 GET_INST_OPCODE(ip) @ extract opcode from rINST 807 stmia r3, {r0-r1} @ vAA<- r0/r1 808 GOTO_OPCODE(ip) @ jump to next instruction 809 810 811/* ------------------------------ */ 812 .balign 64 813.L_OP_CONST_STRING: /* 0x1a */ 814/* File: armv5te/OP_CONST_STRING.S */ 815 /* const/string vAA, String@BBBB */ 816 FETCH(r1, 1) @ r1<- BBBB 817 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 818 mov r9, rINST, lsr #8 @ r9<- AA 819 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 820 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 821 cmp r0, #0 @ not yet resolved? 822 beq .LOP_CONST_STRING_resolve 823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 824 GET_INST_OPCODE(ip) @ extract opcode from rINST 825 SET_VREG(r0, r9) @ vAA<- r0 826 GOTO_OPCODE(ip) @ jump to next instruction 827 828/* ------------------------------ */ 829 .balign 64 830.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 831/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 832 /* const/string vAA, String@BBBBBBBB */ 833 FETCH(r0, 1) @ r0<- bbbb (low) 834 FETCH(r1, 2) @ r1<- BBBB (high) 835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 836 mov r9, rINST, lsr #8 @ r9<- AA 837 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 838 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 839 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 840 cmp r0, #0 841 beq .LOP_CONST_STRING_JUMBO_resolve 842 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 843 GET_INST_OPCODE(ip) @ extract opcode from rINST 844 SET_VREG(r0, r9) @ vAA<- r0 845 GOTO_OPCODE(ip) @ jump to next instruction 846 847/* ------------------------------ */ 848 .balign 64 849.L_OP_CONST_CLASS: /* 0x1c */ 850/* File: armv5te/OP_CONST_CLASS.S */ 851 /* const/class vAA, Class@BBBB */ 852 FETCH(r1, 1) @ r1<- BBBB 853 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 854 mov r9, rINST, lsr #8 @ r9<- AA 855 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 856 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 857 cmp r0, #0 @ not yet resolved? 858 beq .LOP_CONST_CLASS_resolve 859 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 860 GET_INST_OPCODE(ip) @ extract opcode from rINST 861 SET_VREG(r0, r9) @ vAA<- r0 862 GOTO_OPCODE(ip) @ jump to next instruction 863 864/* ------------------------------ */ 865 .balign 64 866.L_OP_MONITOR_ENTER: /* 0x1d */ 867/* File: armv5te/OP_MONITOR_ENTER.S */ 868 /* 869 * Synchronize on an object. 870 */ 871 /* monitor-enter vAA */ 872 mov r2, rINST, lsr #8 @ r2<- AA 873 GET_VREG(r1, r2) @ r1<- vAA (object) 874 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 875 cmp r1, #0 @ null object? 876 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 877 beq common_errNullObject @ null object, throw an exception 878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 879 bl dvmLockObject @ call(self, obj) 880#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 881 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 882 ldr r1, [r0, #offThread_exception] @ check for exception 883 cmp r1, #0 884 bne common_exceptionThrown @ exception raised, bail out 885#endif 886 GET_INST_OPCODE(ip) @ extract opcode from rINST 887 GOTO_OPCODE(ip) @ jump to next instruction 888 889 890/* ------------------------------ */ 891 .balign 64 892.L_OP_MONITOR_EXIT: /* 0x1e */ 893/* File: armv5te/OP_MONITOR_EXIT.S */ 894 /* 895 * Unlock an object. 896 * 897 * Exceptions that occur when unlocking a monitor need to appear as 898 * if they happened at the following instruction. See the Dalvik 899 * instruction spec. 900 */ 901 /* monitor-exit vAA */ 902 mov r2, rINST, lsr #8 @ r2<- AA 903 EXPORT_PC() @ before fetch: export the PC 904 GET_VREG(r1, r2) @ r1<- vAA (object) 905 cmp r1, #0 @ null object? 906 beq common_errNullObject @ yes 907 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 908 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 909 cmp r0, #0 @ failed? 910 beq common_exceptionThrown @ yes, exception is pending 911 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 912 GET_INST_OPCODE(ip) @ extract opcode from rINST 913 GOTO_OPCODE(ip) @ jump to next instruction 914 915 916/* ------------------------------ */ 917 .balign 64 918.L_OP_CHECK_CAST: /* 0x1f */ 919/* File: armv5te/OP_CHECK_CAST.S */ 920 /* 921 * Check to see if a cast from one class to another is allowed. 922 */ 923 /* check-cast vAA, class@BBBB */ 924 mov r3, rINST, lsr #8 @ r3<- AA 925 FETCH(r2, 1) @ r2<- BBBB 926 GET_VREG(r9, r3) @ r9<- object 927 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 928 cmp r9, #0 @ is object null? 929 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 930 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 931 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 932 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 933 cmp r1, #0 @ have we resolved this before? 934 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 935.LOP_CHECK_CAST_resolved: 936 cmp r0, r1 @ same class (trivial success)? 937 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 938.LOP_CHECK_CAST_okay: 939 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 940 GET_INST_OPCODE(ip) @ extract opcode from rINST 941 GOTO_OPCODE(ip) @ jump to next instruction 942 943/* ------------------------------ */ 944 .balign 64 945.L_OP_INSTANCE_OF: /* 0x20 */ 946/* File: armv5te/OP_INSTANCE_OF.S */ 947 /* 948 * Check to see if an object reference is an instance of a class. 949 * 950 * Most common situation is a non-null object, being compared against 951 * an already-resolved class. 952 */ 953 /* instance-of vA, vB, class@CCCC */ 954 mov r3, rINST, lsr #12 @ r3<- B 955 mov r9, rINST, lsr #8 @ r9<- A+ 956 GET_VREG(r0, r3) @ r0<- vB (object) 957 and r9, r9, #15 @ r9<- A 958 cmp r0, #0 @ is object null? 959 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 960 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 961 FETCH(r3, 1) @ r3<- CCCC 962 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 963 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 964 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 965 cmp r1, #0 @ have we resolved this before? 966 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 967.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 968 cmp r0, r1 @ same class (trivial success)? 969 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 970 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 971 972/* ------------------------------ */ 973 .balign 64 974.L_OP_ARRAY_LENGTH: /* 0x21 */ 975/* File: armv5te/OP_ARRAY_LENGTH.S */ 976 /* 977 * Return the length of an array. 978 */ 979 mov r1, rINST, lsr #12 @ r1<- B 980 mov r2, rINST, lsr #8 @ r2<- A+ 981 GET_VREG(r0, r1) @ r0<- vB (object ref) 982 and r2, r2, #15 @ r2<- A 983 cmp r0, #0 @ is object null? 984 beq common_errNullObject @ yup, fail 985 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 986 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 987 GET_INST_OPCODE(ip) @ extract opcode from rINST 988 SET_VREG(r3, r2) @ vB<- length 989 GOTO_OPCODE(ip) @ jump to next instruction 990 991 992/* ------------------------------ */ 993 .balign 64 994.L_OP_NEW_INSTANCE: /* 0x22 */ 995/* File: armv5te/OP_NEW_INSTANCE.S */ 996 /* 997 * Create a new instance of a class. 998 */ 999 /* new-instance vAA, class@BBBB */ 1000 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1001 FETCH(r1, 1) @ r1<- BBBB 1002 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1003 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1004 EXPORT_PC() @ req'd for init, resolve, alloc 1005 cmp r0, #0 @ already resolved? 1006 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1007.LOP_NEW_INSTANCE_resolved: @ r0=class 1008 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1009 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1010 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1011.LOP_NEW_INSTANCE_initialized: @ r0=class 1012 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1013 bl dvmAllocObject @ r0<- new object 1014 b .LOP_NEW_INSTANCE_finish @ continue 1015 1016/* ------------------------------ */ 1017 .balign 64 1018.L_OP_NEW_ARRAY: /* 0x23 */ 1019/* File: armv5te/OP_NEW_ARRAY.S */ 1020 /* 1021 * Allocate an array of objects, specified with the array class 1022 * and a count. 1023 * 1024 * The verifier guarantees that this is an array class, so we don't 1025 * check for it here. 1026 */ 1027 /* new-array vA, vB, class@CCCC */ 1028 mov r0, rINST, lsr #12 @ r0<- B 1029 FETCH(r2, 1) @ r2<- CCCC 1030 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1031 GET_VREG(r1, r0) @ r1<- vB (array length) 1032 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1033 cmp r1, #0 @ check length 1034 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1035 bmi common_errNegativeArraySize @ negative length, bail 1036 cmp r0, #0 @ already resolved? 1037 EXPORT_PC() @ req'd for resolve, alloc 1038 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1039 b .LOP_NEW_ARRAY_resolve @ do resolve now 1040 1041/* ------------------------------ */ 1042 .balign 64 1043.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1044/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1045 /* 1046 * Create a new array with elements filled from registers. 1047 * 1048 * for: filled-new-array, filled-new-array/range 1049 */ 1050 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1051 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1052 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1053 FETCH(r1, 1) @ r1<- BBBB 1054 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1055 EXPORT_PC() @ need for resolve and alloc 1056 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1057 mov r10, rINST, lsr #8 @ r10<- AA or BA 1058 cmp r0, #0 @ already resolved? 1059 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10608: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1061 mov r2, #0 @ r2<- false 1062 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1063 bl dvmResolveClass @ r0<- call(clazz, ref) 1064 cmp r0, #0 @ got null? 1065 beq common_exceptionThrown @ yes, handle exception 1066 b .LOP_FILLED_NEW_ARRAY_continue 1067 1068/* ------------------------------ */ 1069 .balign 64 1070.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1071/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1072/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1073 /* 1074 * Create a new array with elements filled from registers. 1075 * 1076 * for: filled-new-array, filled-new-array/range 1077 */ 1078 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1079 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1080 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1081 FETCH(r1, 1) @ r1<- BBBB 1082 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1083 EXPORT_PC() @ need for resolve and alloc 1084 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1085 mov r10, rINST, lsr #8 @ r10<- AA or BA 1086 cmp r0, #0 @ already resolved? 1087 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10888: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1089 mov r2, #0 @ r2<- false 1090 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1091 bl dvmResolveClass @ r0<- call(clazz, ref) 1092 cmp r0, #0 @ got null? 1093 beq common_exceptionThrown @ yes, handle exception 1094 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1095 1096 1097/* ------------------------------ */ 1098 .balign 64 1099.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1100/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1101 /* fill-array-data vAA, +BBBBBBBB */ 1102 FETCH(r0, 1) @ r0<- bbbb (lo) 1103 FETCH(r1, 2) @ r1<- BBBB (hi) 1104 mov r3, rINST, lsr #8 @ r3<- AA 1105 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1106 GET_VREG(r0, r3) @ r0<- vAA (array object) 1107 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1108 EXPORT_PC(); 1109 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1110 cmp r0, #0 @ 0 means an exception is thrown 1111 beq common_exceptionThrown @ has exception 1112 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1113 GET_INST_OPCODE(ip) @ extract opcode from rINST 1114 GOTO_OPCODE(ip) @ jump to next instruction 1115 1116/* ------------------------------ */ 1117 .balign 64 1118.L_OP_THROW: /* 0x27 */ 1119/* File: armv5te/OP_THROW.S */ 1120 /* 1121 * Throw an exception object in the current thread. 1122 */ 1123 /* throw vAA */ 1124 mov r2, rINST, lsr #8 @ r2<- AA 1125 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1126 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1127 cmp r1, #0 @ null object? 1128 beq common_errNullObject @ yes, throw an NPE instead 1129 @ bypass dvmSetException, just store it 1130 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1131 b common_exceptionThrown 1132 1133 1134/* ------------------------------ */ 1135 .balign 64 1136.L_OP_GOTO: /* 0x28 */ 1137/* File: armv5te/OP_GOTO.S */ 1138 /* 1139 * Unconditional branch, 8-bit offset. 1140 * 1141 * The branch distance is a signed code-unit offset, which we need to 1142 * double to get a byte offset. 1143 */ 1144 /* goto +AA */ 1145 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1146 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1147 mov r9, r9, lsl #1 @ r9<- byte offset 1148 bmi common_backwardBranch @ backward branch, do periodic checks 1149#if defined(WITH_JIT) 1150 GET_JIT_PROF_TABLE(r0) 1151 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1152 cmp r0,#0 1153 bne common_updateProfile 1154 GET_INST_OPCODE(ip) @ extract opcode from rINST 1155 GOTO_OPCODE(ip) @ jump to next instruction 1156#else 1157 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1158 GET_INST_OPCODE(ip) @ extract opcode from rINST 1159 GOTO_OPCODE(ip) @ jump to next instruction 1160#endif 1161 1162/* ------------------------------ */ 1163 .balign 64 1164.L_OP_GOTO_16: /* 0x29 */ 1165/* File: armv5te/OP_GOTO_16.S */ 1166 /* 1167 * Unconditional branch, 16-bit offset. 1168 * 1169 * The branch distance is a signed code-unit offset, which we need to 1170 * double to get a byte offset. 1171 */ 1172 /* goto/16 +AAAA */ 1173 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1174 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1175 bmi common_backwardBranch @ backward branch, do periodic checks 1176#if defined(WITH_JIT) 1177 GET_JIT_PROF_TABLE(r0) 1178 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1179 cmp r0,#0 1180 bne common_updateProfile 1181 GET_INST_OPCODE(ip) @ extract opcode from rINST 1182 GOTO_OPCODE(ip) @ jump to next instruction 1183#else 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 GET_INST_OPCODE(ip) @ extract opcode from rINST 1186 GOTO_OPCODE(ip) @ jump to next instruction 1187#endif 1188 1189 1190/* ------------------------------ */ 1191 .balign 64 1192.L_OP_GOTO_32: /* 0x2a */ 1193/* File: armv5te/OP_GOTO_32.S */ 1194 /* 1195 * Unconditional branch, 32-bit offset. 1196 * 1197 * The branch distance is a signed code-unit offset, which we need to 1198 * double to get a byte offset. 1199 * 1200 * Unlike most opcodes, this one is allowed to branch to itself, so 1201 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1202 * instruction doesn't affect the V flag, so we need to clear it 1203 * explicitly. 1204 */ 1205 /* goto/32 +AAAAAAAA */ 1206 FETCH(r0, 1) @ r0<- aaaa (lo) 1207 FETCH(r1, 2) @ r1<- AAAA (hi) 1208 cmp ip, ip @ (clear V flag during stall) 1209 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1210 mov r9, r0, asl #1 @ r9<- byte offset 1211 ble common_backwardBranch @ backward branch, do periodic checks 1212#if defined(WITH_JIT) 1213 GET_JIT_PROF_TABLE(r0) 1214 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1215 cmp r0,#0 1216 bne common_updateProfile 1217 GET_INST_OPCODE(ip) @ extract opcode from rINST 1218 GOTO_OPCODE(ip) @ jump to next instruction 1219#else 1220 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1221 GET_INST_OPCODE(ip) @ extract opcode from rINST 1222 GOTO_OPCODE(ip) @ jump to next instruction 1223#endif 1224 1225/* ------------------------------ */ 1226 .balign 64 1227.L_OP_PACKED_SWITCH: /* 0x2b */ 1228/* File: armv5te/OP_PACKED_SWITCH.S */ 1229 /* 1230 * Handle a packed-switch or sparse-switch instruction. In both cases 1231 * we decode it and hand it off to a helper function. 1232 * 1233 * We don't really expect backward branches in a switch statement, but 1234 * they're perfectly legal, so we check for them here. 1235 * 1236 * for: packed-switch, sparse-switch 1237 */ 1238 /* op vAA, +BBBB */ 1239 FETCH(r0, 1) @ r0<- bbbb (lo) 1240 FETCH(r1, 2) @ r1<- BBBB (hi) 1241 mov r3, rINST, lsr #8 @ r3<- AA 1242 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1243 GET_VREG(r1, r3) @ r1<- vAA 1244 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1245 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1246 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1247 bmi common_backwardBranch @ backward branch, do periodic checks 1248 beq common_backwardBranch @ (want to use BLE but V is unknown) 1249#if defined(WITH_JIT) 1250 GET_JIT_PROF_TABLE(r0) 1251 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1252 cmp r0,#0 1253 bne common_updateProfile 1254 GET_INST_OPCODE(ip) @ extract opcode from rINST 1255 GOTO_OPCODE(ip) @ jump to next instruction 1256#else 1257 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1258 GET_INST_OPCODE(ip) @ extract opcode from rINST 1259 GOTO_OPCODE(ip) @ jump to next instruction 1260#endif 1261 1262 1263/* ------------------------------ */ 1264 .balign 64 1265.L_OP_SPARSE_SWITCH: /* 0x2c */ 1266/* File: armv5te/OP_SPARSE_SWITCH.S */ 1267/* File: armv5te/OP_PACKED_SWITCH.S */ 1268 /* 1269 * Handle a packed-switch or sparse-switch instruction. In both cases 1270 * we decode it and hand it off to a helper function. 1271 * 1272 * We don't really expect backward branches in a switch statement, but 1273 * they're perfectly legal, so we check for them here. 1274 * 1275 * for: packed-switch, sparse-switch 1276 */ 1277 /* op vAA, +BBBB */ 1278 FETCH(r0, 1) @ r0<- bbbb (lo) 1279 FETCH(r1, 2) @ r1<- BBBB (hi) 1280 mov r3, rINST, lsr #8 @ r3<- AA 1281 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1282 GET_VREG(r1, r3) @ r1<- vAA 1283 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1284 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1285 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1286 bmi common_backwardBranch @ backward branch, do periodic checks 1287 beq common_backwardBranch @ (want to use BLE but V is unknown) 1288#if defined(WITH_JIT) 1289 GET_JIT_PROF_TABLE(r0) 1290 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1291 cmp r0,#0 1292 bne common_updateProfile 1293 GET_INST_OPCODE(ip) @ extract opcode from rINST 1294 GOTO_OPCODE(ip) @ jump to next instruction 1295#else 1296 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1297 GET_INST_OPCODE(ip) @ extract opcode from rINST 1298 GOTO_OPCODE(ip) @ jump to next instruction 1299#endif 1300 1301 1302 1303/* ------------------------------ */ 1304 .balign 64 1305.L_OP_CMPL_FLOAT: /* 0x2d */ 1306/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1307 /* 1308 * Compare two floating-point values. Puts 0, 1, or -1 into the 1309 * destination register based on the results of the comparison. 1310 * 1311 * int compare(x, y) { 1312 * if (x == y) { 1313 * return 0; 1314 * } else if (x > y) { 1315 * return 1; 1316 * } else if (x < y) { 1317 * return -1; 1318 * } else { 1319 * return -1; 1320 * } 1321 * } 1322 */ 1323 /* op vAA, vBB, vCC */ 1324 FETCH(r0, 1) @ r0<- CCBB 1325 mov r9, rINST, lsr #8 @ r9<- AA 1326 and r2, r0, #255 @ r2<- BB 1327 mov r3, r0, lsr #8 @ r3<- CC 1328 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1329 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1330 flds s0, [r2] @ s0<- vBB 1331 flds s1, [r3] @ s1<- vCC 1332 fcmpes s0, s1 @ compare (vBB, vCC) 1333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1334 mvn r0, #0 @ r0<- -1 (default) 1335 GET_INST_OPCODE(ip) @ extract opcode from rINST 1336 fmstat @ export status flags 1337 movgt r0, #1 @ (greater than) r1<- 1 1338 moveq r0, #0 @ (equal) r1<- 0 1339 b .LOP_CMPL_FLOAT_finish @ argh 1340 1341 1342/* ------------------------------ */ 1343 .balign 64 1344.L_OP_CMPG_FLOAT: /* 0x2e */ 1345/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1346 /* 1347 * Compare two floating-point values. Puts 0, 1, or -1 into the 1348 * destination register based on the results of the comparison. 1349 * 1350 * int compare(x, y) { 1351 * if (x == y) { 1352 * return 0; 1353 * } else if (x < y) { 1354 * return -1; 1355 * } else if (x > y) { 1356 * return 1; 1357 * } else { 1358 * return 1; 1359 * } 1360 * } 1361 */ 1362 /* op vAA, vBB, vCC */ 1363 FETCH(r0, 1) @ r0<- CCBB 1364 mov r9, rINST, lsr #8 @ r9<- AA 1365 and r2, r0, #255 @ r2<- BB 1366 mov r3, r0, lsr #8 @ r3<- CC 1367 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1368 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1369 flds s0, [r2] @ s0<- vBB 1370 flds s1, [r3] @ s1<- vCC 1371 fcmpes s0, s1 @ compare (vBB, vCC) 1372 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1373 mov r0, #1 @ r0<- 1 (default) 1374 GET_INST_OPCODE(ip) @ extract opcode from rINST 1375 fmstat @ export status flags 1376 mvnmi r0, #0 @ (less than) r1<- -1 1377 moveq r0, #0 @ (equal) r1<- 0 1378 b .LOP_CMPG_FLOAT_finish @ argh 1379 1380 1381/* ------------------------------ */ 1382 .balign 64 1383.L_OP_CMPL_DOUBLE: /* 0x2f */ 1384/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1385 /* 1386 * Compare two floating-point values. Puts 0, 1, or -1 into the 1387 * destination register based on the results of the comparison. 1388 * 1389 * int compare(x, y) { 1390 * if (x == y) { 1391 * return 0; 1392 * } else if (x > y) { 1393 * return 1; 1394 * } else if (x < y) { 1395 * return -1; 1396 * } else { 1397 * return -1; 1398 * } 1399 * } 1400 */ 1401 /* op vAA, vBB, vCC */ 1402 FETCH(r0, 1) @ r0<- CCBB 1403 mov r9, rINST, lsr #8 @ r9<- AA 1404 and r2, r0, #255 @ r2<- BB 1405 mov r3, r0, lsr #8 @ r3<- CC 1406 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1407 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1408 fldd d0, [r2] @ d0<- vBB 1409 fldd d1, [r3] @ d1<- vCC 1410 fcmped d0, d1 @ compare (vBB, vCC) 1411 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1412 mvn r0, #0 @ r0<- -1 (default) 1413 GET_INST_OPCODE(ip) @ extract opcode from rINST 1414 fmstat @ export status flags 1415 movgt r0, #1 @ (greater than) r1<- 1 1416 moveq r0, #0 @ (equal) r1<- 0 1417 b .LOP_CMPL_DOUBLE_finish @ argh 1418 1419 1420/* ------------------------------ */ 1421 .balign 64 1422.L_OP_CMPG_DOUBLE: /* 0x30 */ 1423/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1424 /* 1425 * Compare two floating-point values. Puts 0, 1, or -1 into the 1426 * destination register based on the results of the comparison. 1427 * 1428 * int compare(x, y) { 1429 * if (x == y) { 1430 * return 0; 1431 * } else if (x < y) { 1432 * return -1; 1433 * } else if (x > y) { 1434 * return 1; 1435 * } else { 1436 * return 1; 1437 * } 1438 * } 1439 */ 1440 /* op vAA, vBB, vCC */ 1441 FETCH(r0, 1) @ r0<- CCBB 1442 mov r9, rINST, lsr #8 @ r9<- AA 1443 and r2, r0, #255 @ r2<- BB 1444 mov r3, r0, lsr #8 @ r3<- CC 1445 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1446 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1447 fldd d0, [r2] @ d0<- vBB 1448 fldd d1, [r3] @ d1<- vCC 1449 fcmped d0, d1 @ compare (vBB, vCC) 1450 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1451 mov r0, #1 @ r0<- 1 (default) 1452 GET_INST_OPCODE(ip) @ extract opcode from rINST 1453 fmstat @ export status flags 1454 mvnmi r0, #0 @ (less than) r1<- -1 1455 moveq r0, #0 @ (equal) r1<- 0 1456 b .LOP_CMPG_DOUBLE_finish @ argh 1457 1458 1459/* ------------------------------ */ 1460 .balign 64 1461.L_OP_CMP_LONG: /* 0x31 */ 1462/* File: armv5te/OP_CMP_LONG.S */ 1463 /* 1464 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1465 * register based on the results of the comparison. 1466 * 1467 * We load the full values with LDM, but in practice many values could 1468 * be resolved by only looking at the high word. This could be made 1469 * faster or slower by splitting the LDM into a pair of LDRs. 1470 * 1471 * If we just wanted to set condition flags, we could do this: 1472 * subs ip, r0, r2 1473 * sbcs ip, r1, r3 1474 * subeqs ip, r0, r2 1475 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1476 * integer value, which we can do with 2 conditional mov/mvn instructions 1477 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1478 * us a constant 5-cycle path plus a branch at the end to the 1479 * instruction epilogue code. The multi-compare approach below needs 1480 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1481 * in the worst case (the 64-bit values are equal). 1482 */ 1483 /* cmp-long vAA, vBB, vCC */ 1484 FETCH(r0, 1) @ r0<- CCBB 1485 mov r9, rINST, lsr #8 @ r9<- AA 1486 and r2, r0, #255 @ r2<- BB 1487 mov r3, r0, lsr #8 @ r3<- CC 1488 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1489 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1490 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1491 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1492 cmp r1, r3 @ compare (vBB+1, vCC+1) 1493 blt .LOP_CMP_LONG_less @ signed compare on high part 1494 bgt .LOP_CMP_LONG_greater 1495 subs r1, r0, r2 @ r1<- r0 - r2 1496 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1497 bne .LOP_CMP_LONG_less 1498 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1499 1500/* ------------------------------ */ 1501 .balign 64 1502.L_OP_IF_EQ: /* 0x32 */ 1503/* File: armv5te/OP_IF_EQ.S */ 1504/* File: armv5te/bincmp.S */ 1505 /* 1506 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1507 * fragment that specifies the *reverse* comparison to perform, e.g. 1508 * for "if-le" you would use "gt". 1509 * 1510 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1511 */ 1512 /* if-cmp vA, vB, +CCCC */ 1513 mov r0, rINST, lsr #8 @ r0<- A+ 1514 mov r1, rINST, lsr #12 @ r1<- B 1515 and r0, r0, #15 1516 GET_VREG(r3, r1) @ r3<- vB 1517 GET_VREG(r2, r0) @ r2<- vA 1518 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1519 cmp r2, r3 @ compare (vA, vB) 1520 bne 1f @ branch to 1 if comparison failed 1521 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1522 movs r9, r9, asl #1 @ convert to bytes, check sign 1523 bmi common_backwardBranch @ yes, do periodic checks 15241: 1525#if defined(WITH_JIT) 1526 GET_JIT_PROF_TABLE(r0) 1527 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1528 b common_testUpdateProfile 1529#else 1530 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1531 GET_INST_OPCODE(ip) @ extract opcode from rINST 1532 GOTO_OPCODE(ip) @ jump to next instruction 1533#endif 1534 1535 1536 1537/* ------------------------------ */ 1538 .balign 64 1539.L_OP_IF_NE: /* 0x33 */ 1540/* File: armv5te/OP_IF_NE.S */ 1541/* File: armv5te/bincmp.S */ 1542 /* 1543 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1544 * fragment that specifies the *reverse* comparison to perform, e.g. 1545 * for "if-le" you would use "gt". 1546 * 1547 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1548 */ 1549 /* if-cmp vA, vB, +CCCC */ 1550 mov r0, rINST, lsr #8 @ r0<- A+ 1551 mov r1, rINST, lsr #12 @ r1<- B 1552 and r0, r0, #15 1553 GET_VREG(r3, r1) @ r3<- vB 1554 GET_VREG(r2, r0) @ r2<- vA 1555 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1556 cmp r2, r3 @ compare (vA, vB) 1557 beq 1f @ branch to 1 if comparison failed 1558 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1559 movs r9, r9, asl #1 @ convert to bytes, check sign 1560 bmi common_backwardBranch @ yes, do periodic checks 15611: 1562#if defined(WITH_JIT) 1563 GET_JIT_PROF_TABLE(r0) 1564 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1565 b common_testUpdateProfile 1566#else 1567 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1568 GET_INST_OPCODE(ip) @ extract opcode from rINST 1569 GOTO_OPCODE(ip) @ jump to next instruction 1570#endif 1571 1572 1573 1574/* ------------------------------ */ 1575 .balign 64 1576.L_OP_IF_LT: /* 0x34 */ 1577/* File: armv5te/OP_IF_LT.S */ 1578/* File: armv5te/bincmp.S */ 1579 /* 1580 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1581 * fragment that specifies the *reverse* comparison to perform, e.g. 1582 * for "if-le" you would use "gt". 1583 * 1584 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1585 */ 1586 /* if-cmp vA, vB, +CCCC */ 1587 mov r0, rINST, lsr #8 @ r0<- A+ 1588 mov r1, rINST, lsr #12 @ r1<- B 1589 and r0, r0, #15 1590 GET_VREG(r3, r1) @ r3<- vB 1591 GET_VREG(r2, r0) @ r2<- vA 1592 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1593 cmp r2, r3 @ compare (vA, vB) 1594 bge 1f @ branch to 1 if comparison failed 1595 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1596 movs r9, r9, asl #1 @ convert to bytes, check sign 1597 bmi common_backwardBranch @ yes, do periodic checks 15981: 1599#if defined(WITH_JIT) 1600 GET_JIT_PROF_TABLE(r0) 1601 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1602 b common_testUpdateProfile 1603#else 1604 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1605 GET_INST_OPCODE(ip) @ extract opcode from rINST 1606 GOTO_OPCODE(ip) @ jump to next instruction 1607#endif 1608 1609 1610 1611/* ------------------------------ */ 1612 .balign 64 1613.L_OP_IF_GE: /* 0x35 */ 1614/* File: armv5te/OP_IF_GE.S */ 1615/* File: armv5te/bincmp.S */ 1616 /* 1617 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1618 * fragment that specifies the *reverse* comparison to perform, e.g. 1619 * for "if-le" you would use "gt". 1620 * 1621 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1622 */ 1623 /* if-cmp vA, vB, +CCCC */ 1624 mov r0, rINST, lsr #8 @ r0<- A+ 1625 mov r1, rINST, lsr #12 @ r1<- B 1626 and r0, r0, #15 1627 GET_VREG(r3, r1) @ r3<- vB 1628 GET_VREG(r2, r0) @ r2<- vA 1629 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1630 cmp r2, r3 @ compare (vA, vB) 1631 blt 1f @ branch to 1 if comparison failed 1632 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1633 movs r9, r9, asl #1 @ convert to bytes, check sign 1634 bmi common_backwardBranch @ yes, do periodic checks 16351: 1636#if defined(WITH_JIT) 1637 GET_JIT_PROF_TABLE(r0) 1638 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1639 b common_testUpdateProfile 1640#else 1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1642 GET_INST_OPCODE(ip) @ extract opcode from rINST 1643 GOTO_OPCODE(ip) @ jump to next instruction 1644#endif 1645 1646 1647 1648/* ------------------------------ */ 1649 .balign 64 1650.L_OP_IF_GT: /* 0x36 */ 1651/* File: armv5te/OP_IF_GT.S */ 1652/* File: armv5te/bincmp.S */ 1653 /* 1654 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1655 * fragment that specifies the *reverse* comparison to perform, e.g. 1656 * for "if-le" you would use "gt". 1657 * 1658 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1659 */ 1660 /* if-cmp vA, vB, +CCCC */ 1661 mov r0, rINST, lsr #8 @ r0<- A+ 1662 mov r1, rINST, lsr #12 @ r1<- B 1663 and r0, r0, #15 1664 GET_VREG(r3, r1) @ r3<- vB 1665 GET_VREG(r2, r0) @ r2<- vA 1666 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1667 cmp r2, r3 @ compare (vA, vB) 1668 ble 1f @ branch to 1 if comparison failed 1669 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1670 movs r9, r9, asl #1 @ convert to bytes, check sign 1671 bmi common_backwardBranch @ yes, do periodic checks 16721: 1673#if defined(WITH_JIT) 1674 GET_JIT_PROF_TABLE(r0) 1675 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1676 b common_testUpdateProfile 1677#else 1678 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1679 GET_INST_OPCODE(ip) @ extract opcode from rINST 1680 GOTO_OPCODE(ip) @ jump to next instruction 1681#endif 1682 1683 1684 1685/* ------------------------------ */ 1686 .balign 64 1687.L_OP_IF_LE: /* 0x37 */ 1688/* File: armv5te/OP_IF_LE.S */ 1689/* File: armv5te/bincmp.S */ 1690 /* 1691 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1692 * fragment that specifies the *reverse* comparison to perform, e.g. 1693 * for "if-le" you would use "gt". 1694 * 1695 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1696 */ 1697 /* if-cmp vA, vB, +CCCC */ 1698 mov r0, rINST, lsr #8 @ r0<- A+ 1699 mov r1, rINST, lsr #12 @ r1<- B 1700 and r0, r0, #15 1701 GET_VREG(r3, r1) @ r3<- vB 1702 GET_VREG(r2, r0) @ r2<- vA 1703 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1704 cmp r2, r3 @ compare (vA, vB) 1705 bgt 1f @ branch to 1 if comparison failed 1706 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1707 movs r9, r9, asl #1 @ convert to bytes, check sign 1708 bmi common_backwardBranch @ yes, do periodic checks 17091: 1710#if defined(WITH_JIT) 1711 GET_JIT_PROF_TABLE(r0) 1712 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1713 b common_testUpdateProfile 1714#else 1715 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1716 GET_INST_OPCODE(ip) @ extract opcode from rINST 1717 GOTO_OPCODE(ip) @ jump to next instruction 1718#endif 1719 1720 1721 1722/* ------------------------------ */ 1723 .balign 64 1724.L_OP_IF_EQZ: /* 0x38 */ 1725/* File: armv5te/OP_IF_EQZ.S */ 1726/* File: armv5te/zcmp.S */ 1727 /* 1728 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1729 * fragment that specifies the *reverse* comparison to perform, e.g. 1730 * for "if-le" you would use "gt". 1731 * 1732 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1733 */ 1734 /* if-cmp vAA, +BBBB */ 1735 mov r0, rINST, lsr #8 @ r0<- AA 1736 GET_VREG(r2, r0) @ r2<- vAA 1737 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1738 cmp r2, #0 @ compare (vA, 0) 1739 bne 1f @ branch to 1 if comparison failed 1740 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1741 movs r9, r9, asl #1 @ convert to bytes, check sign 1742 bmi common_backwardBranch @ backward branch, do periodic checks 17431: 1744#if defined(WITH_JIT) 1745 GET_JIT_PROF_TABLE(r0) 1746 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1747 cmp r0,#0 1748 bne common_updateProfile 1749 GET_INST_OPCODE(ip) @ extract opcode from rINST 1750 GOTO_OPCODE(ip) @ jump to next instruction 1751#else 1752 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1753 GET_INST_OPCODE(ip) @ extract opcode from rINST 1754 GOTO_OPCODE(ip) @ jump to next instruction 1755#endif 1756 1757 1758 1759/* ------------------------------ */ 1760 .balign 64 1761.L_OP_IF_NEZ: /* 0x39 */ 1762/* File: armv5te/OP_IF_NEZ.S */ 1763/* File: armv5te/zcmp.S */ 1764 /* 1765 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1766 * fragment that specifies the *reverse* comparison to perform, e.g. 1767 * for "if-le" you would use "gt". 1768 * 1769 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1770 */ 1771 /* if-cmp vAA, +BBBB */ 1772 mov r0, rINST, lsr #8 @ r0<- AA 1773 GET_VREG(r2, r0) @ r2<- vAA 1774 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1775 cmp r2, #0 @ compare (vA, 0) 1776 beq 1f @ branch to 1 if comparison failed 1777 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1778 movs r9, r9, asl #1 @ convert to bytes, check sign 1779 bmi common_backwardBranch @ backward branch, do periodic checks 17801: 1781#if defined(WITH_JIT) 1782 GET_JIT_PROF_TABLE(r0) 1783 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1784 cmp r0,#0 1785 bne common_updateProfile 1786 GET_INST_OPCODE(ip) @ extract opcode from rINST 1787 GOTO_OPCODE(ip) @ jump to next instruction 1788#else 1789 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1790 GET_INST_OPCODE(ip) @ extract opcode from rINST 1791 GOTO_OPCODE(ip) @ jump to next instruction 1792#endif 1793 1794 1795 1796/* ------------------------------ */ 1797 .balign 64 1798.L_OP_IF_LTZ: /* 0x3a */ 1799/* File: armv5te/OP_IF_LTZ.S */ 1800/* File: armv5te/zcmp.S */ 1801 /* 1802 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1803 * fragment that specifies the *reverse* comparison to perform, e.g. 1804 * for "if-le" you would use "gt". 1805 * 1806 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1807 */ 1808 /* if-cmp vAA, +BBBB */ 1809 mov r0, rINST, lsr #8 @ r0<- AA 1810 GET_VREG(r2, r0) @ r2<- vAA 1811 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1812 cmp r2, #0 @ compare (vA, 0) 1813 bge 1f @ branch to 1 if comparison failed 1814 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1815 movs r9, r9, asl #1 @ convert to bytes, check sign 1816 bmi common_backwardBranch @ backward branch, do periodic checks 18171: 1818#if defined(WITH_JIT) 1819 GET_JIT_PROF_TABLE(r0) 1820 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1821 cmp r0,#0 1822 bne common_updateProfile 1823 GET_INST_OPCODE(ip) @ extract opcode from rINST 1824 GOTO_OPCODE(ip) @ jump to next instruction 1825#else 1826 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1827 GET_INST_OPCODE(ip) @ extract opcode from rINST 1828 GOTO_OPCODE(ip) @ jump to next instruction 1829#endif 1830 1831 1832 1833/* ------------------------------ */ 1834 .balign 64 1835.L_OP_IF_GEZ: /* 0x3b */ 1836/* File: armv5te/OP_IF_GEZ.S */ 1837/* File: armv5te/zcmp.S */ 1838 /* 1839 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1840 * fragment that specifies the *reverse* comparison to perform, e.g. 1841 * for "if-le" you would use "gt". 1842 * 1843 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1844 */ 1845 /* if-cmp vAA, +BBBB */ 1846 mov r0, rINST, lsr #8 @ r0<- AA 1847 GET_VREG(r2, r0) @ r2<- vAA 1848 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1849 cmp r2, #0 @ compare (vA, 0) 1850 blt 1f @ branch to 1 if comparison failed 1851 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1852 movs r9, r9, asl #1 @ convert to bytes, check sign 1853 bmi common_backwardBranch @ backward branch, do periodic checks 18541: 1855#if defined(WITH_JIT) 1856 GET_JIT_PROF_TABLE(r0) 1857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1858 cmp r0,#0 1859 bne common_updateProfile 1860 GET_INST_OPCODE(ip) @ extract opcode from rINST 1861 GOTO_OPCODE(ip) @ jump to next instruction 1862#else 1863 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1864 GET_INST_OPCODE(ip) @ extract opcode from rINST 1865 GOTO_OPCODE(ip) @ jump to next instruction 1866#endif 1867 1868 1869 1870/* ------------------------------ */ 1871 .balign 64 1872.L_OP_IF_GTZ: /* 0x3c */ 1873/* File: armv5te/OP_IF_GTZ.S */ 1874/* File: armv5te/zcmp.S */ 1875 /* 1876 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1877 * fragment that specifies the *reverse* comparison to perform, e.g. 1878 * for "if-le" you would use "gt". 1879 * 1880 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1881 */ 1882 /* if-cmp vAA, +BBBB */ 1883 mov r0, rINST, lsr #8 @ r0<- AA 1884 GET_VREG(r2, r0) @ r2<- vAA 1885 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1886 cmp r2, #0 @ compare (vA, 0) 1887 ble 1f @ branch to 1 if comparison failed 1888 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1889 movs r9, r9, asl #1 @ convert to bytes, check sign 1890 bmi common_backwardBranch @ backward branch, do periodic checks 18911: 1892#if defined(WITH_JIT) 1893 GET_JIT_PROF_TABLE(r0) 1894 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1895 cmp r0,#0 1896 bne common_updateProfile 1897 GET_INST_OPCODE(ip) @ extract opcode from rINST 1898 GOTO_OPCODE(ip) @ jump to next instruction 1899#else 1900 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1901 GET_INST_OPCODE(ip) @ extract opcode from rINST 1902 GOTO_OPCODE(ip) @ jump to next instruction 1903#endif 1904 1905 1906 1907/* ------------------------------ */ 1908 .balign 64 1909.L_OP_IF_LEZ: /* 0x3d */ 1910/* File: armv5te/OP_IF_LEZ.S */ 1911/* File: armv5te/zcmp.S */ 1912 /* 1913 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1914 * fragment that specifies the *reverse* comparison to perform, e.g. 1915 * for "if-le" you would use "gt". 1916 * 1917 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1918 */ 1919 /* if-cmp vAA, +BBBB */ 1920 mov r0, rINST, lsr #8 @ r0<- AA 1921 GET_VREG(r2, r0) @ r2<- vAA 1922 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1923 cmp r2, #0 @ compare (vA, 0) 1924 bgt 1f @ branch to 1 if comparison failed 1925 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1926 movs r9, r9, asl #1 @ convert to bytes, check sign 1927 bmi common_backwardBranch @ backward branch, do periodic checks 19281: 1929#if defined(WITH_JIT) 1930 GET_JIT_PROF_TABLE(r0) 1931 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1932 cmp r0,#0 1933 bne common_updateProfile 1934 GET_INST_OPCODE(ip) @ extract opcode from rINST 1935 GOTO_OPCODE(ip) @ jump to next instruction 1936#else 1937 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1938 GET_INST_OPCODE(ip) @ extract opcode from rINST 1939 GOTO_OPCODE(ip) @ jump to next instruction 1940#endif 1941 1942 1943 1944/* ------------------------------ */ 1945 .balign 64 1946.L_OP_UNUSED_3E: /* 0x3e */ 1947/* File: armv5te/OP_UNUSED_3E.S */ 1948/* File: armv5te/unused.S */ 1949 bl common_abort 1950 1951 1952 1953/* ------------------------------ */ 1954 .balign 64 1955.L_OP_UNUSED_3F: /* 0x3f */ 1956/* File: armv5te/OP_UNUSED_3F.S */ 1957/* File: armv5te/unused.S */ 1958 bl common_abort 1959 1960 1961 1962/* ------------------------------ */ 1963 .balign 64 1964.L_OP_UNUSED_40: /* 0x40 */ 1965/* File: armv5te/OP_UNUSED_40.S */ 1966/* File: armv5te/unused.S */ 1967 bl common_abort 1968 1969 1970 1971/* ------------------------------ */ 1972 .balign 64 1973.L_OP_UNUSED_41: /* 0x41 */ 1974/* File: armv5te/OP_UNUSED_41.S */ 1975/* File: armv5te/unused.S */ 1976 bl common_abort 1977 1978 1979 1980/* ------------------------------ */ 1981 .balign 64 1982.L_OP_UNUSED_42: /* 0x42 */ 1983/* File: armv5te/OP_UNUSED_42.S */ 1984/* File: armv5te/unused.S */ 1985 bl common_abort 1986 1987 1988 1989/* ------------------------------ */ 1990 .balign 64 1991.L_OP_UNUSED_43: /* 0x43 */ 1992/* File: armv5te/OP_UNUSED_43.S */ 1993/* File: armv5te/unused.S */ 1994 bl common_abort 1995 1996 1997 1998/* ------------------------------ */ 1999 .balign 64 2000.L_OP_AGET: /* 0x44 */ 2001/* File: armv5te/OP_AGET.S */ 2002 /* 2003 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2004 * 2005 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2006 * instructions. We use a pair of FETCH_Bs instead. 2007 * 2008 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2009 */ 2010 /* op vAA, vBB, vCC */ 2011 FETCH_B(r2, 1, 0) @ r2<- BB 2012 mov r9, rINST, lsr #8 @ r9<- AA 2013 FETCH_B(r3, 1, 1) @ r3<- CC 2014 GET_VREG(r0, r2) @ r0<- vBB (array object) 2015 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2016 cmp r0, #0 @ null array object? 2017 beq common_errNullObject @ yes, bail 2018 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2019 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2020 cmp r1, r3 @ compare unsigned index, length 2021 bcs common_errArrayIndex @ index >= length, bail 2022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2023 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2024 GET_INST_OPCODE(ip) @ extract opcode from rINST 2025 SET_VREG(r2, r9) @ vAA<- r2 2026 GOTO_OPCODE(ip) @ jump to next instruction 2027 2028 2029/* ------------------------------ */ 2030 .balign 64 2031.L_OP_AGET_WIDE: /* 0x45 */ 2032/* File: armv5te/OP_AGET_WIDE.S */ 2033 /* 2034 * Array get, 64 bits. vAA <- vBB[vCC]. 2035 * 2036 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2037 */ 2038 /* aget-wide vAA, vBB, vCC */ 2039 FETCH(r0, 1) @ r0<- CCBB 2040 mov r9, rINST, lsr #8 @ r9<- AA 2041 and r2, r0, #255 @ r2<- BB 2042 mov r3, r0, lsr #8 @ r3<- CC 2043 GET_VREG(r0, r2) @ r0<- vBB (array object) 2044 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2045 cmp r0, #0 @ null array object? 2046 beq common_errNullObject @ yes, bail 2047 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2048 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2049 cmp r1, r3 @ compare unsigned index, length 2050 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2051 b common_errArrayIndex @ index >= length, bail 2052 @ May want to swap the order of these two branches depending on how the 2053 @ branch prediction (if any) handles conditional forward branches vs. 2054 @ unconditional forward branches. 2055 2056/* ------------------------------ */ 2057 .balign 64 2058.L_OP_AGET_OBJECT: /* 0x46 */ 2059/* File: armv5te/OP_AGET_OBJECT.S */ 2060/* File: armv5te/OP_AGET.S */ 2061 /* 2062 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2063 * 2064 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2065 * instructions. We use a pair of FETCH_Bs instead. 2066 * 2067 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2068 */ 2069 /* op vAA, vBB, vCC */ 2070 FETCH_B(r2, 1, 0) @ r2<- BB 2071 mov r9, rINST, lsr #8 @ r9<- AA 2072 FETCH_B(r3, 1, 1) @ r3<- CC 2073 GET_VREG(r0, r2) @ r0<- vBB (array object) 2074 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2075 cmp r0, #0 @ null array object? 2076 beq common_errNullObject @ yes, bail 2077 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2078 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2079 cmp r1, r3 @ compare unsigned index, length 2080 bcs common_errArrayIndex @ index >= length, bail 2081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2082 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2083 GET_INST_OPCODE(ip) @ extract opcode from rINST 2084 SET_VREG(r2, r9) @ vAA<- r2 2085 GOTO_OPCODE(ip) @ jump to next instruction 2086 2087 2088 2089/* ------------------------------ */ 2090 .balign 64 2091.L_OP_AGET_BOOLEAN: /* 0x47 */ 2092/* File: armv5te/OP_AGET_BOOLEAN.S */ 2093/* File: armv5te/OP_AGET.S */ 2094 /* 2095 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2096 * 2097 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2098 * instructions. We use a pair of FETCH_Bs instead. 2099 * 2100 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2101 */ 2102 /* op vAA, vBB, vCC */ 2103 FETCH_B(r2, 1, 0) @ r2<- BB 2104 mov r9, rINST, lsr #8 @ r9<- AA 2105 FETCH_B(r3, 1, 1) @ r3<- CC 2106 GET_VREG(r0, r2) @ r0<- vBB (array object) 2107 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2108 cmp r0, #0 @ null array object? 2109 beq common_errNullObject @ yes, bail 2110 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2111 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2112 cmp r1, r3 @ compare unsigned index, length 2113 bcs common_errArrayIndex @ index >= length, bail 2114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2115 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2116 GET_INST_OPCODE(ip) @ extract opcode from rINST 2117 SET_VREG(r2, r9) @ vAA<- r2 2118 GOTO_OPCODE(ip) @ jump to next instruction 2119 2120 2121 2122/* ------------------------------ */ 2123 .balign 64 2124.L_OP_AGET_BYTE: /* 0x48 */ 2125/* File: armv5te/OP_AGET_BYTE.S */ 2126/* File: armv5te/OP_AGET.S */ 2127 /* 2128 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2129 * 2130 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2131 * instructions. We use a pair of FETCH_Bs instead. 2132 * 2133 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2134 */ 2135 /* op vAA, vBB, vCC */ 2136 FETCH_B(r2, 1, 0) @ r2<- BB 2137 mov r9, rINST, lsr #8 @ r9<- AA 2138 FETCH_B(r3, 1, 1) @ r3<- CC 2139 GET_VREG(r0, r2) @ r0<- vBB (array object) 2140 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2141 cmp r0, #0 @ null array object? 2142 beq common_errNullObject @ yes, bail 2143 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2144 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2145 cmp r1, r3 @ compare unsigned index, length 2146 bcs common_errArrayIndex @ index >= length, bail 2147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2148 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2149 GET_INST_OPCODE(ip) @ extract opcode from rINST 2150 SET_VREG(r2, r9) @ vAA<- r2 2151 GOTO_OPCODE(ip) @ jump to next instruction 2152 2153 2154 2155/* ------------------------------ */ 2156 .balign 64 2157.L_OP_AGET_CHAR: /* 0x49 */ 2158/* File: armv5te/OP_AGET_CHAR.S */ 2159/* File: armv5te/OP_AGET.S */ 2160 /* 2161 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2162 * 2163 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2164 * instructions. We use a pair of FETCH_Bs instead. 2165 * 2166 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2167 */ 2168 /* op vAA, vBB, vCC */ 2169 FETCH_B(r2, 1, 0) @ r2<- BB 2170 mov r9, rINST, lsr #8 @ r9<- AA 2171 FETCH_B(r3, 1, 1) @ r3<- CC 2172 GET_VREG(r0, r2) @ r0<- vBB (array object) 2173 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2174 cmp r0, #0 @ null array object? 2175 beq common_errNullObject @ yes, bail 2176 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2177 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2178 cmp r1, r3 @ compare unsigned index, length 2179 bcs common_errArrayIndex @ index >= length, bail 2180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2181 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2182 GET_INST_OPCODE(ip) @ extract opcode from rINST 2183 SET_VREG(r2, r9) @ vAA<- r2 2184 GOTO_OPCODE(ip) @ jump to next instruction 2185 2186 2187 2188/* ------------------------------ */ 2189 .balign 64 2190.L_OP_AGET_SHORT: /* 0x4a */ 2191/* File: armv5te/OP_AGET_SHORT.S */ 2192/* File: armv5te/OP_AGET.S */ 2193 /* 2194 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2195 * 2196 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2197 * instructions. We use a pair of FETCH_Bs instead. 2198 * 2199 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2200 */ 2201 /* op vAA, vBB, vCC */ 2202 FETCH_B(r2, 1, 0) @ r2<- BB 2203 mov r9, rINST, lsr #8 @ r9<- AA 2204 FETCH_B(r3, 1, 1) @ r3<- CC 2205 GET_VREG(r0, r2) @ r0<- vBB (array object) 2206 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2207 cmp r0, #0 @ null array object? 2208 beq common_errNullObject @ yes, bail 2209 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2210 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2211 cmp r1, r3 @ compare unsigned index, length 2212 bcs common_errArrayIndex @ index >= length, bail 2213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2214 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2215 GET_INST_OPCODE(ip) @ extract opcode from rINST 2216 SET_VREG(r2, r9) @ vAA<- r2 2217 GOTO_OPCODE(ip) @ jump to next instruction 2218 2219 2220 2221/* ------------------------------ */ 2222 .balign 64 2223.L_OP_APUT: /* 0x4b */ 2224/* File: armv5te/OP_APUT.S */ 2225 /* 2226 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2227 * 2228 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2229 * instructions. We use a pair of FETCH_Bs instead. 2230 * 2231 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2232 */ 2233 /* op vAA, vBB, vCC */ 2234 FETCH_B(r2, 1, 0) @ r2<- BB 2235 mov r9, rINST, lsr #8 @ r9<- AA 2236 FETCH_B(r3, 1, 1) @ r3<- CC 2237 GET_VREG(r0, r2) @ r0<- vBB (array object) 2238 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2239 cmp r0, #0 @ null array object? 2240 beq common_errNullObject @ yes, bail 2241 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2242 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2243 cmp r1, r3 @ compare unsigned index, length 2244 bcs common_errArrayIndex @ index >= length, bail 2245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2246 GET_VREG(r2, r9) @ r2<- vAA 2247 GET_INST_OPCODE(ip) @ extract opcode from rINST 2248 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2249 GOTO_OPCODE(ip) @ jump to next instruction 2250 2251 2252/* ------------------------------ */ 2253 .balign 64 2254.L_OP_APUT_WIDE: /* 0x4c */ 2255/* File: armv5te/OP_APUT_WIDE.S */ 2256 /* 2257 * Array put, 64 bits. vBB[vCC] <- vAA. 2258 * 2259 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2260 */ 2261 /* aput-wide vAA, vBB, vCC */ 2262 FETCH(r0, 1) @ r0<- CCBB 2263 mov r9, rINST, lsr #8 @ r9<- AA 2264 and r2, r0, #255 @ r2<- BB 2265 mov r3, r0, lsr #8 @ r3<- CC 2266 GET_VREG(r0, r2) @ r0<- vBB (array object) 2267 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2268 cmp r0, #0 @ null array object? 2269 beq common_errNullObject @ yes, bail 2270 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2271 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2272 cmp r1, r3 @ compare unsigned index, length 2273 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2274 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2275 b common_errArrayIndex @ index >= length, bail 2276 @ May want to swap the order of these two branches depending on how the 2277 @ branch prediction (if any) handles conditional forward branches vs. 2278 @ unconditional forward branches. 2279 2280/* ------------------------------ */ 2281 .balign 64 2282.L_OP_APUT_OBJECT: /* 0x4d */ 2283/* File: armv5te/OP_APUT_OBJECT.S */ 2284 /* 2285 * Store an object into an array. vBB[vCC] <- vAA. 2286 * 2287 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2288 * instructions. We use a pair of FETCH_Bs instead. 2289 */ 2290 /* op vAA, vBB, vCC */ 2291 FETCH(r0, 1) @ r0<- CCBB 2292 mov r9, rINST, lsr #8 @ r9<- AA 2293 and r2, r0, #255 @ r2<- BB 2294 mov r3, r0, lsr #8 @ r3<- CC 2295 GET_VREG(r1, r2) @ r1<- vBB (array object) 2296 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2297 cmp r1, #0 @ null array object? 2298 GET_VREG(r9, r9) @ r9<- vAA 2299 beq common_errNullObject @ yes, bail 2300 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2301 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2302 cmp r0, r3 @ compare unsigned index, length 2303 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2304 b common_errArrayIndex @ index >= length, bail 2305 2306 2307/* ------------------------------ */ 2308 .balign 64 2309.L_OP_APUT_BOOLEAN: /* 0x4e */ 2310/* File: armv5te/OP_APUT_BOOLEAN.S */ 2311/* File: armv5te/OP_APUT.S */ 2312 /* 2313 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2314 * 2315 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2316 * instructions. We use a pair of FETCH_Bs instead. 2317 * 2318 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2319 */ 2320 /* op vAA, vBB, vCC */ 2321 FETCH_B(r2, 1, 0) @ r2<- BB 2322 mov r9, rINST, lsr #8 @ r9<- AA 2323 FETCH_B(r3, 1, 1) @ r3<- CC 2324 GET_VREG(r0, r2) @ r0<- vBB (array object) 2325 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2326 cmp r0, #0 @ null array object? 2327 beq common_errNullObject @ yes, bail 2328 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2329 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2330 cmp r1, r3 @ compare unsigned index, length 2331 bcs common_errArrayIndex @ index >= length, bail 2332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2333 GET_VREG(r2, r9) @ r2<- vAA 2334 GET_INST_OPCODE(ip) @ extract opcode from rINST 2335 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2336 GOTO_OPCODE(ip) @ jump to next instruction 2337 2338 2339 2340/* ------------------------------ */ 2341 .balign 64 2342.L_OP_APUT_BYTE: /* 0x4f */ 2343/* File: armv5te/OP_APUT_BYTE.S */ 2344/* File: armv5te/OP_APUT.S */ 2345 /* 2346 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2347 * 2348 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2349 * instructions. We use a pair of FETCH_Bs instead. 2350 * 2351 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2352 */ 2353 /* op vAA, vBB, vCC */ 2354 FETCH_B(r2, 1, 0) @ r2<- BB 2355 mov r9, rINST, lsr #8 @ r9<- AA 2356 FETCH_B(r3, 1, 1) @ r3<- CC 2357 GET_VREG(r0, r2) @ r0<- vBB (array object) 2358 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2359 cmp r0, #0 @ null array object? 2360 beq common_errNullObject @ yes, bail 2361 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2362 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2363 cmp r1, r3 @ compare unsigned index, length 2364 bcs common_errArrayIndex @ index >= length, bail 2365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2366 GET_VREG(r2, r9) @ r2<- vAA 2367 GET_INST_OPCODE(ip) @ extract opcode from rINST 2368 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2369 GOTO_OPCODE(ip) @ jump to next instruction 2370 2371 2372 2373/* ------------------------------ */ 2374 .balign 64 2375.L_OP_APUT_CHAR: /* 0x50 */ 2376/* File: armv5te/OP_APUT_CHAR.S */ 2377/* File: armv5te/OP_APUT.S */ 2378 /* 2379 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2380 * 2381 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2382 * instructions. We use a pair of FETCH_Bs instead. 2383 * 2384 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2385 */ 2386 /* op vAA, vBB, vCC */ 2387 FETCH_B(r2, 1, 0) @ r2<- BB 2388 mov r9, rINST, lsr #8 @ r9<- AA 2389 FETCH_B(r3, 1, 1) @ r3<- CC 2390 GET_VREG(r0, r2) @ r0<- vBB (array object) 2391 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2392 cmp r0, #0 @ null array object? 2393 beq common_errNullObject @ yes, bail 2394 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2395 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2396 cmp r1, r3 @ compare unsigned index, length 2397 bcs common_errArrayIndex @ index >= length, bail 2398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2399 GET_VREG(r2, r9) @ r2<- vAA 2400 GET_INST_OPCODE(ip) @ extract opcode from rINST 2401 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2402 GOTO_OPCODE(ip) @ jump to next instruction 2403 2404 2405 2406/* ------------------------------ */ 2407 .balign 64 2408.L_OP_APUT_SHORT: /* 0x51 */ 2409/* File: armv5te/OP_APUT_SHORT.S */ 2410/* File: armv5te/OP_APUT.S */ 2411 /* 2412 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2413 * 2414 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2415 * instructions. We use a pair of FETCH_Bs instead. 2416 * 2417 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2418 */ 2419 /* op vAA, vBB, vCC */ 2420 FETCH_B(r2, 1, 0) @ r2<- BB 2421 mov r9, rINST, lsr #8 @ r9<- AA 2422 FETCH_B(r3, 1, 1) @ r3<- CC 2423 GET_VREG(r0, r2) @ r0<- vBB (array object) 2424 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2425 cmp r0, #0 @ null array object? 2426 beq common_errNullObject @ yes, bail 2427 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2428 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2429 cmp r1, r3 @ compare unsigned index, length 2430 bcs common_errArrayIndex @ index >= length, bail 2431 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2432 GET_VREG(r2, r9) @ r2<- vAA 2433 GET_INST_OPCODE(ip) @ extract opcode from rINST 2434 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2435 GOTO_OPCODE(ip) @ jump to next instruction 2436 2437 2438 2439/* ------------------------------ */ 2440 .balign 64 2441.L_OP_IGET: /* 0x52 */ 2442/* File: armv5te/OP_IGET.S */ 2443 /* 2444 * General 32-bit instance field get. 2445 * 2446 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2447 */ 2448 /* op vA, vB, field@CCCC */ 2449 mov r0, rINST, lsr #12 @ r0<- B 2450 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2451 FETCH(r1, 1) @ r1<- field ref CCCC 2452 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2453 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2454 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2455 cmp r0, #0 @ is resolved entry null? 2456 bne .LOP_IGET_finish @ no, already resolved 24578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2458 EXPORT_PC() @ resolve() could throw 2459 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2460 bl dvmResolveInstField @ r0<- resolved InstField ptr 2461 cmp r0, #0 2462 bne .LOP_IGET_finish 2463 b common_exceptionThrown 2464 2465/* ------------------------------ */ 2466 .balign 64 2467.L_OP_IGET_WIDE: /* 0x53 */ 2468/* File: armv5te/OP_IGET_WIDE.S */ 2469 /* 2470 * Wide 32-bit instance field get. 2471 */ 2472 /* iget-wide vA, vB, field@CCCC */ 2473 mov r0, rINST, lsr #12 @ r0<- B 2474 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2475 FETCH(r1, 1) @ r1<- field ref CCCC 2476 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2477 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2478 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2479 cmp r0, #0 @ is resolved entry null? 2480 bne .LOP_IGET_WIDE_finish @ no, already resolved 24818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2482 EXPORT_PC() @ resolve() could throw 2483 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2484 bl dvmResolveInstField @ r0<- resolved InstField ptr 2485 cmp r0, #0 2486 bne .LOP_IGET_WIDE_finish 2487 b common_exceptionThrown 2488 2489/* ------------------------------ */ 2490 .balign 64 2491.L_OP_IGET_OBJECT: /* 0x54 */ 2492/* File: armv5te/OP_IGET_OBJECT.S */ 2493/* File: armv5te/OP_IGET.S */ 2494 /* 2495 * General 32-bit instance field get. 2496 * 2497 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2498 */ 2499 /* op vA, vB, field@CCCC */ 2500 mov r0, rINST, lsr #12 @ r0<- B 2501 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2502 FETCH(r1, 1) @ r1<- field ref CCCC 2503 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2504 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2505 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2506 cmp r0, #0 @ is resolved entry null? 2507 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25088: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2509 EXPORT_PC() @ resolve() could throw 2510 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2511 bl dvmResolveInstField @ r0<- resolved InstField ptr 2512 cmp r0, #0 2513 bne .LOP_IGET_OBJECT_finish 2514 b common_exceptionThrown 2515 2516 2517/* ------------------------------ */ 2518 .balign 64 2519.L_OP_IGET_BOOLEAN: /* 0x55 */ 2520/* File: armv5te/OP_IGET_BOOLEAN.S */ 2521@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2522/* File: armv5te/OP_IGET.S */ 2523 /* 2524 * General 32-bit instance field get. 2525 * 2526 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2527 */ 2528 /* op vA, vB, field@CCCC */ 2529 mov r0, rINST, lsr #12 @ r0<- B 2530 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2531 FETCH(r1, 1) @ r1<- field ref CCCC 2532 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2533 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2534 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2535 cmp r0, #0 @ is resolved entry null? 2536 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25378: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2538 EXPORT_PC() @ resolve() could throw 2539 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2540 bl dvmResolveInstField @ r0<- resolved InstField ptr 2541 cmp r0, #0 2542 bne .LOP_IGET_BOOLEAN_finish 2543 b common_exceptionThrown 2544 2545 2546/* ------------------------------ */ 2547 .balign 64 2548.L_OP_IGET_BYTE: /* 0x56 */ 2549/* File: armv5te/OP_IGET_BYTE.S */ 2550@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2551/* File: armv5te/OP_IGET.S */ 2552 /* 2553 * General 32-bit instance field get. 2554 * 2555 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2556 */ 2557 /* op vA, vB, field@CCCC */ 2558 mov r0, rINST, lsr #12 @ r0<- B 2559 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2560 FETCH(r1, 1) @ r1<- field ref CCCC 2561 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2562 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2563 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2564 cmp r0, #0 @ is resolved entry null? 2565 bne .LOP_IGET_BYTE_finish @ no, already resolved 25668: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2567 EXPORT_PC() @ resolve() could throw 2568 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2569 bl dvmResolveInstField @ r0<- resolved InstField ptr 2570 cmp r0, #0 2571 bne .LOP_IGET_BYTE_finish 2572 b common_exceptionThrown 2573 2574 2575/* ------------------------------ */ 2576 .balign 64 2577.L_OP_IGET_CHAR: /* 0x57 */ 2578/* File: armv5te/OP_IGET_CHAR.S */ 2579@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2580/* File: armv5te/OP_IGET.S */ 2581 /* 2582 * General 32-bit instance field get. 2583 * 2584 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2585 */ 2586 /* op vA, vB, field@CCCC */ 2587 mov r0, rINST, lsr #12 @ r0<- B 2588 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2589 FETCH(r1, 1) @ r1<- field ref CCCC 2590 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2591 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2592 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2593 cmp r0, #0 @ is resolved entry null? 2594 bne .LOP_IGET_CHAR_finish @ no, already resolved 25958: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2596 EXPORT_PC() @ resolve() could throw 2597 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2598 bl dvmResolveInstField @ r0<- resolved InstField ptr 2599 cmp r0, #0 2600 bne .LOP_IGET_CHAR_finish 2601 b common_exceptionThrown 2602 2603 2604/* ------------------------------ */ 2605 .balign 64 2606.L_OP_IGET_SHORT: /* 0x58 */ 2607/* File: armv5te/OP_IGET_SHORT.S */ 2608@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2609/* File: armv5te/OP_IGET.S */ 2610 /* 2611 * General 32-bit instance field get. 2612 * 2613 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2614 */ 2615 /* op vA, vB, field@CCCC */ 2616 mov r0, rINST, lsr #12 @ r0<- B 2617 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2618 FETCH(r1, 1) @ r1<- field ref CCCC 2619 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2620 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2621 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2622 cmp r0, #0 @ is resolved entry null? 2623 bne .LOP_IGET_SHORT_finish @ no, already resolved 26248: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2625 EXPORT_PC() @ resolve() could throw 2626 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2627 bl dvmResolveInstField @ r0<- resolved InstField ptr 2628 cmp r0, #0 2629 bne .LOP_IGET_SHORT_finish 2630 b common_exceptionThrown 2631 2632 2633/* ------------------------------ */ 2634 .balign 64 2635.L_OP_IPUT: /* 0x59 */ 2636/* File: armv5te/OP_IPUT.S */ 2637 /* 2638 * General 32-bit instance field put. 2639 * 2640 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2641 */ 2642 /* op vA, vB, field@CCCC */ 2643 mov r0, rINST, lsr #12 @ r0<- B 2644 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2645 FETCH(r1, 1) @ r1<- field ref CCCC 2646 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2647 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2648 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2649 cmp r0, #0 @ is resolved entry null? 2650 bne .LOP_IPUT_finish @ no, already resolved 26518: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2652 EXPORT_PC() @ resolve() could throw 2653 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2654 bl dvmResolveInstField @ r0<- resolved InstField ptr 2655 cmp r0, #0 @ success? 2656 bne .LOP_IPUT_finish @ yes, finish up 2657 b common_exceptionThrown 2658 2659/* ------------------------------ */ 2660 .balign 64 2661.L_OP_IPUT_WIDE: /* 0x5a */ 2662/* File: armv5te/OP_IPUT_WIDE.S */ 2663 /* iput-wide vA, vB, field@CCCC */ 2664 mov r0, rINST, lsr #12 @ r0<- B 2665 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2666 FETCH(r1, 1) @ r1<- field ref CCCC 2667 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2668 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2669 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2670 cmp r0, #0 @ is resolved entry null? 2671 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2673 EXPORT_PC() @ resolve() could throw 2674 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2675 bl dvmResolveInstField @ r0<- resolved InstField ptr 2676 cmp r0, #0 @ success? 2677 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2678 b common_exceptionThrown 2679 2680/* ------------------------------ */ 2681 .balign 64 2682.L_OP_IPUT_OBJECT: /* 0x5b */ 2683/* File: armv5te/OP_IPUT_OBJECT.S */ 2684/* File: armv5te/OP_IPUT.S */ 2685 /* 2686 * General 32-bit instance field put. 2687 * 2688 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2689 */ 2690 /* op vA, vB, field@CCCC */ 2691 mov r0, rINST, lsr #12 @ r0<- B 2692 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2693 FETCH(r1, 1) @ r1<- field ref CCCC 2694 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2695 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2696 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2697 cmp r0, #0 @ is resolved entry null? 2698 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26998: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2700 EXPORT_PC() @ resolve() could throw 2701 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2702 bl dvmResolveInstField @ r0<- resolved InstField ptr 2703 cmp r0, #0 @ success? 2704 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2705 b common_exceptionThrown 2706 2707 2708/* ------------------------------ */ 2709 .balign 64 2710.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2711/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2712@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2713/* File: armv5te/OP_IPUT.S */ 2714 /* 2715 * General 32-bit instance field put. 2716 * 2717 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2718 */ 2719 /* op vA, vB, field@CCCC */ 2720 mov r0, rINST, lsr #12 @ r0<- B 2721 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2722 FETCH(r1, 1) @ r1<- field ref CCCC 2723 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2724 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2725 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2726 cmp r0, #0 @ is resolved entry null? 2727 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27288: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2729 EXPORT_PC() @ resolve() could throw 2730 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2731 bl dvmResolveInstField @ r0<- resolved InstField ptr 2732 cmp r0, #0 @ success? 2733 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2734 b common_exceptionThrown 2735 2736 2737/* ------------------------------ */ 2738 .balign 64 2739.L_OP_IPUT_BYTE: /* 0x5d */ 2740/* File: armv5te/OP_IPUT_BYTE.S */ 2741@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2742/* File: armv5te/OP_IPUT.S */ 2743 /* 2744 * General 32-bit instance field put. 2745 * 2746 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2747 */ 2748 /* op vA, vB, field@CCCC */ 2749 mov r0, rINST, lsr #12 @ r0<- B 2750 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2751 FETCH(r1, 1) @ r1<- field ref CCCC 2752 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2753 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2754 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2755 cmp r0, #0 @ is resolved entry null? 2756 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2758 EXPORT_PC() @ resolve() could throw 2759 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2760 bl dvmResolveInstField @ r0<- resolved InstField ptr 2761 cmp r0, #0 @ success? 2762 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2763 b common_exceptionThrown 2764 2765 2766/* ------------------------------ */ 2767 .balign 64 2768.L_OP_IPUT_CHAR: /* 0x5e */ 2769/* File: armv5te/OP_IPUT_CHAR.S */ 2770@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2771/* File: armv5te/OP_IPUT.S */ 2772 /* 2773 * General 32-bit instance field put. 2774 * 2775 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2776 */ 2777 /* op vA, vB, field@CCCC */ 2778 mov r0, rINST, lsr #12 @ r0<- B 2779 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2780 FETCH(r1, 1) @ r1<- field ref CCCC 2781 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2782 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2783 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2784 cmp r0, #0 @ is resolved entry null? 2785 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2787 EXPORT_PC() @ resolve() could throw 2788 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2789 bl dvmResolveInstField @ r0<- resolved InstField ptr 2790 cmp r0, #0 @ success? 2791 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2792 b common_exceptionThrown 2793 2794 2795/* ------------------------------ */ 2796 .balign 64 2797.L_OP_IPUT_SHORT: /* 0x5f */ 2798/* File: armv5te/OP_IPUT_SHORT.S */ 2799@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2800/* File: armv5te/OP_IPUT.S */ 2801 /* 2802 * General 32-bit instance field put. 2803 * 2804 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2805 */ 2806 /* op vA, vB, field@CCCC */ 2807 mov r0, rINST, lsr #12 @ r0<- B 2808 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2809 FETCH(r1, 1) @ r1<- field ref CCCC 2810 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2811 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2812 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2813 cmp r0, #0 @ is resolved entry null? 2814 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28158: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2816 EXPORT_PC() @ resolve() could throw 2817 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2818 bl dvmResolveInstField @ r0<- resolved InstField ptr 2819 cmp r0, #0 @ success? 2820 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2821 b common_exceptionThrown 2822 2823 2824/* ------------------------------ */ 2825 .balign 64 2826.L_OP_SGET: /* 0x60 */ 2827/* File: armv5te/OP_SGET.S */ 2828 /* 2829 * General 32-bit SGET handler. 2830 * 2831 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2832 */ 2833 /* op vAA, field@BBBB */ 2834 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2835 FETCH(r1, 1) @ r1<- field ref BBBB 2836 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2837 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2838 cmp r0, #0 @ is resolved entry null? 2839 beq .LOP_SGET_resolve @ yes, do resolve 2840.LOP_SGET_finish: @ field ptr in r0 2841 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2842 mov r2, rINST, lsr #8 @ r2<- AA 2843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2844 SET_VREG(r1, r2) @ fp[AA]<- r1 2845 GET_INST_OPCODE(ip) @ extract opcode from rINST 2846 GOTO_OPCODE(ip) @ jump to next instruction 2847 2848/* ------------------------------ */ 2849 .balign 64 2850.L_OP_SGET_WIDE: /* 0x61 */ 2851/* File: armv5te/OP_SGET_WIDE.S */ 2852 /* 2853 * 64-bit SGET handler. 2854 */ 2855 /* sget-wide vAA, field@BBBB */ 2856 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2857 FETCH(r1, 1) @ r1<- field ref BBBB 2858 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2859 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2860 cmp r0, #0 @ is resolved entry null? 2861 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2862.LOP_SGET_WIDE_finish: 2863 mov r1, rINST, lsr #8 @ r1<- AA 2864 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2865 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2866 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2867 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2868 GET_INST_OPCODE(ip) @ extract opcode from rINST 2869 GOTO_OPCODE(ip) @ jump to next instruction 2870 2871/* ------------------------------ */ 2872 .balign 64 2873.L_OP_SGET_OBJECT: /* 0x62 */ 2874/* File: armv5te/OP_SGET_OBJECT.S */ 2875/* File: armv5te/OP_SGET.S */ 2876 /* 2877 * General 32-bit SGET handler. 2878 * 2879 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2880 */ 2881 /* op vAA, field@BBBB */ 2882 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2883 FETCH(r1, 1) @ r1<- field ref BBBB 2884 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2885 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2886 cmp r0, #0 @ is resolved entry null? 2887 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2888.LOP_SGET_OBJECT_finish: @ field ptr in r0 2889 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2890 mov r2, rINST, lsr #8 @ r2<- AA 2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2892 SET_VREG(r1, r2) @ fp[AA]<- r1 2893 GET_INST_OPCODE(ip) @ extract opcode from rINST 2894 GOTO_OPCODE(ip) @ jump to next instruction 2895 2896 2897/* ------------------------------ */ 2898 .balign 64 2899.L_OP_SGET_BOOLEAN: /* 0x63 */ 2900/* File: armv5te/OP_SGET_BOOLEAN.S */ 2901/* File: armv5te/OP_SGET.S */ 2902 /* 2903 * General 32-bit SGET handler. 2904 * 2905 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2906 */ 2907 /* op vAA, field@BBBB */ 2908 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2909 FETCH(r1, 1) @ r1<- field ref BBBB 2910 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2911 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2912 cmp r0, #0 @ is resolved entry null? 2913 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2914.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2915 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2916 mov r2, rINST, lsr #8 @ r2<- AA 2917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2918 SET_VREG(r1, r2) @ fp[AA]<- r1 2919 GET_INST_OPCODE(ip) @ extract opcode from rINST 2920 GOTO_OPCODE(ip) @ jump to next instruction 2921 2922 2923/* ------------------------------ */ 2924 .balign 64 2925.L_OP_SGET_BYTE: /* 0x64 */ 2926/* File: armv5te/OP_SGET_BYTE.S */ 2927/* File: armv5te/OP_SGET.S */ 2928 /* 2929 * General 32-bit SGET handler. 2930 * 2931 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2932 */ 2933 /* op vAA, field@BBBB */ 2934 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2935 FETCH(r1, 1) @ r1<- field ref BBBB 2936 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2937 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2938 cmp r0, #0 @ is resolved entry null? 2939 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2940.LOP_SGET_BYTE_finish: @ field ptr in r0 2941 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2942 mov r2, rINST, lsr #8 @ r2<- AA 2943 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2944 SET_VREG(r1, r2) @ fp[AA]<- r1 2945 GET_INST_OPCODE(ip) @ extract opcode from rINST 2946 GOTO_OPCODE(ip) @ jump to next instruction 2947 2948 2949/* ------------------------------ */ 2950 .balign 64 2951.L_OP_SGET_CHAR: /* 0x65 */ 2952/* File: armv5te/OP_SGET_CHAR.S */ 2953/* File: armv5te/OP_SGET.S */ 2954 /* 2955 * General 32-bit SGET handler. 2956 * 2957 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2958 */ 2959 /* op vAA, field@BBBB */ 2960 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2961 FETCH(r1, 1) @ r1<- field ref BBBB 2962 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2963 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2964 cmp r0, #0 @ is resolved entry null? 2965 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2966.LOP_SGET_CHAR_finish: @ field ptr in r0 2967 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2968 mov r2, rINST, lsr #8 @ r2<- AA 2969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2970 SET_VREG(r1, r2) @ fp[AA]<- r1 2971 GET_INST_OPCODE(ip) @ extract opcode from rINST 2972 GOTO_OPCODE(ip) @ jump to next instruction 2973 2974 2975/* ------------------------------ */ 2976 .balign 64 2977.L_OP_SGET_SHORT: /* 0x66 */ 2978/* File: armv5te/OP_SGET_SHORT.S */ 2979/* File: armv5te/OP_SGET.S */ 2980 /* 2981 * General 32-bit SGET handler. 2982 * 2983 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2984 */ 2985 /* op vAA, field@BBBB */ 2986 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2987 FETCH(r1, 1) @ r1<- field ref BBBB 2988 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2989 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2990 cmp r0, #0 @ is resolved entry null? 2991 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2992.LOP_SGET_SHORT_finish: @ field ptr in r0 2993 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2994 mov r2, rINST, lsr #8 @ r2<- AA 2995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2996 SET_VREG(r1, r2) @ fp[AA]<- r1 2997 GET_INST_OPCODE(ip) @ extract opcode from rINST 2998 GOTO_OPCODE(ip) @ jump to next instruction 2999 3000 3001/* ------------------------------ */ 3002 .balign 64 3003.L_OP_SPUT: /* 0x67 */ 3004/* File: armv5te/OP_SPUT.S */ 3005 /* 3006 * General 32-bit SPUT handler. 3007 * 3008 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3009 */ 3010 /* op vAA, field@BBBB */ 3011 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3012 FETCH(r1, 1) @ r1<- field ref BBBB 3013 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3014 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3015 cmp r0, #0 @ is resolved entry null? 3016 beq .LOP_SPUT_resolve @ yes, do resolve 3017.LOP_SPUT_finish: @ field ptr in r0 3018 mov r2, rINST, lsr #8 @ r2<- AA 3019 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3020 GET_VREG(r1, r2) @ r1<- fp[AA] 3021 GET_INST_OPCODE(ip) @ extract opcode from rINST 3022 str r1, [r0, #offStaticField_value] @ field<- vAA 3023 GOTO_OPCODE(ip) @ jump to next instruction 3024 3025/* ------------------------------ */ 3026 .balign 64 3027.L_OP_SPUT_WIDE: /* 0x68 */ 3028/* File: armv5te/OP_SPUT_WIDE.S */ 3029 /* 3030 * 64-bit SPUT handler. 3031 */ 3032 /* sput-wide vAA, field@BBBB */ 3033 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3034 FETCH(r1, 1) @ r1<- field ref BBBB 3035 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3036 mov r9, rINST, lsr #8 @ r9<- AA 3037 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3038 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3039 cmp r0, #0 @ is resolved entry null? 3040 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3041.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3042 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3043 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3044 GET_INST_OPCODE(ip) @ extract opcode from rINST 3045 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3046 GOTO_OPCODE(ip) @ jump to next instruction 3047 3048/* ------------------------------ */ 3049 .balign 64 3050.L_OP_SPUT_OBJECT: /* 0x69 */ 3051/* File: armv5te/OP_SPUT_OBJECT.S */ 3052/* File: armv5te/OP_SPUT.S */ 3053 /* 3054 * General 32-bit SPUT handler. 3055 * 3056 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3057 */ 3058 /* op vAA, field@BBBB */ 3059 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3060 FETCH(r1, 1) @ r1<- field ref BBBB 3061 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3062 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3063 cmp r0, #0 @ is resolved entry null? 3064 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3065.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3066 mov r2, rINST, lsr #8 @ r2<- AA 3067 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3068 GET_VREG(r1, r2) @ r1<- fp[AA] 3069 GET_INST_OPCODE(ip) @ extract opcode from rINST 3070 str r1, [r0, #offStaticField_value] @ field<- vAA 3071 GOTO_OPCODE(ip) @ jump to next instruction 3072 3073 3074/* ------------------------------ */ 3075 .balign 64 3076.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3077/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3078/* File: armv5te/OP_SPUT.S */ 3079 /* 3080 * General 32-bit SPUT handler. 3081 * 3082 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3083 */ 3084 /* op vAA, field@BBBB */ 3085 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3086 FETCH(r1, 1) @ r1<- field ref BBBB 3087 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3088 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3089 cmp r0, #0 @ is resolved entry null? 3090 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3091.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3092 mov r2, rINST, lsr #8 @ r2<- AA 3093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3094 GET_VREG(r1, r2) @ r1<- fp[AA] 3095 GET_INST_OPCODE(ip) @ extract opcode from rINST 3096 str r1, [r0, #offStaticField_value] @ field<- vAA 3097 GOTO_OPCODE(ip) @ jump to next instruction 3098 3099 3100/* ------------------------------ */ 3101 .balign 64 3102.L_OP_SPUT_BYTE: /* 0x6b */ 3103/* File: armv5te/OP_SPUT_BYTE.S */ 3104/* File: armv5te/OP_SPUT.S */ 3105 /* 3106 * General 32-bit SPUT handler. 3107 * 3108 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3109 */ 3110 /* op vAA, field@BBBB */ 3111 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3112 FETCH(r1, 1) @ r1<- field ref BBBB 3113 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3114 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3115 cmp r0, #0 @ is resolved entry null? 3116 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3117.LOP_SPUT_BYTE_finish: @ field ptr in r0 3118 mov r2, rINST, lsr #8 @ r2<- AA 3119 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3120 GET_VREG(r1, r2) @ r1<- fp[AA] 3121 GET_INST_OPCODE(ip) @ extract opcode from rINST 3122 str r1, [r0, #offStaticField_value] @ field<- vAA 3123 GOTO_OPCODE(ip) @ jump to next instruction 3124 3125 3126/* ------------------------------ */ 3127 .balign 64 3128.L_OP_SPUT_CHAR: /* 0x6c */ 3129/* File: armv5te/OP_SPUT_CHAR.S */ 3130/* File: armv5te/OP_SPUT.S */ 3131 /* 3132 * General 32-bit SPUT handler. 3133 * 3134 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3135 */ 3136 /* op vAA, field@BBBB */ 3137 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3138 FETCH(r1, 1) @ r1<- field ref BBBB 3139 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3140 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3141 cmp r0, #0 @ is resolved entry null? 3142 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3143.LOP_SPUT_CHAR_finish: @ field ptr in r0 3144 mov r2, rINST, lsr #8 @ r2<- AA 3145 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3146 GET_VREG(r1, r2) @ r1<- fp[AA] 3147 GET_INST_OPCODE(ip) @ extract opcode from rINST 3148 str r1, [r0, #offStaticField_value] @ field<- vAA 3149 GOTO_OPCODE(ip) @ jump to next instruction 3150 3151 3152/* ------------------------------ */ 3153 .balign 64 3154.L_OP_SPUT_SHORT: /* 0x6d */ 3155/* File: armv5te/OP_SPUT_SHORT.S */ 3156/* File: armv5te/OP_SPUT.S */ 3157 /* 3158 * General 32-bit SPUT handler. 3159 * 3160 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3161 */ 3162 /* op vAA, field@BBBB */ 3163 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3164 FETCH(r1, 1) @ r1<- field ref BBBB 3165 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3166 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3167 cmp r0, #0 @ is resolved entry null? 3168 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3169.LOP_SPUT_SHORT_finish: @ field ptr in r0 3170 mov r2, rINST, lsr #8 @ r2<- AA 3171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3172 GET_VREG(r1, r2) @ r1<- fp[AA] 3173 GET_INST_OPCODE(ip) @ extract opcode from rINST 3174 str r1, [r0, #offStaticField_value] @ field<- vAA 3175 GOTO_OPCODE(ip) @ jump to next instruction 3176 3177 3178/* ------------------------------ */ 3179 .balign 64 3180.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3181/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3182 /* 3183 * Handle a virtual method call. 3184 * 3185 * for: invoke-virtual, invoke-virtual/range 3186 */ 3187 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3188 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3189 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3190 FETCH(r1, 1) @ r1<- BBBB 3191 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3192 FETCH(r10, 2) @ r10<- GFED or CCCC 3193 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3194 .if (!0) 3195 and r10, r10, #15 @ r10<- D (or stays CCCC) 3196 .endif 3197 cmp r0, #0 @ already resolved? 3198 EXPORT_PC() @ must export for invoke 3199 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3200 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3201 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3202 mov r2, #METHOD_VIRTUAL @ resolver method type 3203 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3204 cmp r0, #0 @ got null? 3205 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3206 b common_exceptionThrown @ yes, handle exception 3207 3208/* ------------------------------ */ 3209 .balign 64 3210.L_OP_INVOKE_SUPER: /* 0x6f */ 3211/* File: armv5te/OP_INVOKE_SUPER.S */ 3212 /* 3213 * Handle a "super" method call. 3214 * 3215 * for: invoke-super, invoke-super/range 3216 */ 3217 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3218 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3219 FETCH(r10, 2) @ r10<- GFED or CCCC 3220 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3221 .if (!0) 3222 and r10, r10, #15 @ r10<- D (or stays CCCC) 3223 .endif 3224 FETCH(r1, 1) @ r1<- BBBB 3225 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3226 GET_VREG(r2, r10) @ r2<- "this" ptr 3227 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3228 cmp r2, #0 @ null "this"? 3229 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3230 beq common_errNullObject @ null "this", throw exception 3231 cmp r0, #0 @ already resolved? 3232 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3233 EXPORT_PC() @ must export for invoke 3234 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3235 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3236 3237/* ------------------------------ */ 3238 .balign 64 3239.L_OP_INVOKE_DIRECT: /* 0x70 */ 3240/* File: armv5te/OP_INVOKE_DIRECT.S */ 3241 /* 3242 * Handle a direct method call. 3243 * 3244 * (We could defer the "is 'this' pointer null" test to the common 3245 * method invocation code, and use a flag to indicate that static 3246 * calls don't count. If we do this as part of copying the arguments 3247 * out we could avoiding loading the first arg twice.) 3248 * 3249 * for: invoke-direct, invoke-direct/range 3250 */ 3251 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3252 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3253 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3254 FETCH(r1, 1) @ r1<- BBBB 3255 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3256 FETCH(r10, 2) @ r10<- GFED or CCCC 3257 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3258 .if (!0) 3259 and r10, r10, #15 @ r10<- D (or stays CCCC) 3260 .endif 3261 cmp r0, #0 @ already resolved? 3262 EXPORT_PC() @ must export for invoke 3263 GET_VREG(r2, r10) @ r2<- "this" ptr 3264 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3265.LOP_INVOKE_DIRECT_finish: 3266 cmp r2, #0 @ null "this" ref? 3267 bne common_invokeMethodNoRange @ no, continue on 3268 b common_errNullObject @ yes, throw exception 3269 3270/* ------------------------------ */ 3271 .balign 64 3272.L_OP_INVOKE_STATIC: /* 0x71 */ 3273/* File: armv5te/OP_INVOKE_STATIC.S */ 3274 /* 3275 * Handle a static method call. 3276 * 3277 * for: invoke-static, invoke-static/range 3278 */ 3279 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3280 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3281 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3282 FETCH(r1, 1) @ r1<- BBBB 3283 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3284 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3285 cmp r0, #0 @ already resolved? 3286 EXPORT_PC() @ must export for invoke 3287 bne common_invokeMethodNoRange @ yes, continue on 32880: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3289 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3290 mov r2, #METHOD_STATIC @ resolver method type 3291 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3292 cmp r0, #0 @ got null? 3293 bne common_invokeMethodNoRange @ no, continue 3294 b common_exceptionThrown @ yes, handle exception 3295 3296 3297/* ------------------------------ */ 3298 .balign 64 3299.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3300/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3301 /* 3302 * Handle an interface method call. 3303 * 3304 * for: invoke-interface, invoke-interface/range 3305 */ 3306 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3307 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3308 FETCH(r2, 2) @ r2<- FEDC or CCCC 3309 FETCH(r1, 1) @ r1<- BBBB 3310 .if (!0) 3311 and r2, r2, #15 @ r2<- C (or stays CCCC) 3312 .endif 3313 EXPORT_PC() @ must export for invoke 3314 GET_VREG(r0, r2) @ r0<- first arg ("this") 3315 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3316 cmp r0, #0 @ null obj? 3317 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3318 beq common_errNullObject @ yes, fail 3319 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3320 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3321 cmp r0, #0 @ failed? 3322 beq common_exceptionThrown @ yes, handle exception 3323 b common_invokeMethodNoRange @ jump to common handler 3324 3325 3326/* ------------------------------ */ 3327 .balign 64 3328.L_OP_UNUSED_73: /* 0x73 */ 3329/* File: armv5te/OP_UNUSED_73.S */ 3330/* File: armv5te/unused.S */ 3331 bl common_abort 3332 3333 3334 3335/* ------------------------------ */ 3336 .balign 64 3337.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3338/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3339/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3340 /* 3341 * Handle a virtual method call. 3342 * 3343 * for: invoke-virtual, invoke-virtual/range 3344 */ 3345 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3346 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3347 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3348 FETCH(r1, 1) @ r1<- BBBB 3349 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3350 FETCH(r10, 2) @ r10<- GFED or CCCC 3351 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3352 .if (!1) 3353 and r10, r10, #15 @ r10<- D (or stays CCCC) 3354 .endif 3355 cmp r0, #0 @ already resolved? 3356 EXPORT_PC() @ must export for invoke 3357 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3358 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3359 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3360 mov r2, #METHOD_VIRTUAL @ resolver method type 3361 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3362 cmp r0, #0 @ got null? 3363 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3364 b common_exceptionThrown @ yes, handle exception 3365 3366 3367/* ------------------------------ */ 3368 .balign 64 3369.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3370/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3371/* File: armv5te/OP_INVOKE_SUPER.S */ 3372 /* 3373 * Handle a "super" method call. 3374 * 3375 * for: invoke-super, invoke-super/range 3376 */ 3377 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3378 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3379 FETCH(r10, 2) @ r10<- GFED or CCCC 3380 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3381 .if (!1) 3382 and r10, r10, #15 @ r10<- D (or stays CCCC) 3383 .endif 3384 FETCH(r1, 1) @ r1<- BBBB 3385 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3386 GET_VREG(r2, r10) @ r2<- "this" ptr 3387 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3388 cmp r2, #0 @ null "this"? 3389 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3390 beq common_errNullObject @ null "this", throw exception 3391 cmp r0, #0 @ already resolved? 3392 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3393 EXPORT_PC() @ must export for invoke 3394 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3395 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3396 3397 3398/* ------------------------------ */ 3399 .balign 64 3400.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3401/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3402/* File: armv5te/OP_INVOKE_DIRECT.S */ 3403 /* 3404 * Handle a direct method call. 3405 * 3406 * (We could defer the "is 'this' pointer null" test to the common 3407 * method invocation code, and use a flag to indicate that static 3408 * calls don't count. If we do this as part of copying the arguments 3409 * out we could avoiding loading the first arg twice.) 3410 * 3411 * for: invoke-direct, invoke-direct/range 3412 */ 3413 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3414 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3415 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3416 FETCH(r1, 1) @ r1<- BBBB 3417 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3418 FETCH(r10, 2) @ r10<- GFED or CCCC 3419 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3420 .if (!1) 3421 and r10, r10, #15 @ r10<- D (or stays CCCC) 3422 .endif 3423 cmp r0, #0 @ already resolved? 3424 EXPORT_PC() @ must export for invoke 3425 GET_VREG(r2, r10) @ r2<- "this" ptr 3426 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3427.LOP_INVOKE_DIRECT_RANGE_finish: 3428 cmp r2, #0 @ null "this" ref? 3429 bne common_invokeMethodRange @ no, continue on 3430 b common_errNullObject @ yes, throw exception 3431 3432 3433/* ------------------------------ */ 3434 .balign 64 3435.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3436/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3437/* File: armv5te/OP_INVOKE_STATIC.S */ 3438 /* 3439 * Handle a static method call. 3440 * 3441 * for: invoke-static, invoke-static/range 3442 */ 3443 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3444 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3445 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3446 FETCH(r1, 1) @ r1<- BBBB 3447 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3448 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3449 cmp r0, #0 @ already resolved? 3450 EXPORT_PC() @ must export for invoke 3451 bne common_invokeMethodRange @ yes, continue on 34520: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3453 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3454 mov r2, #METHOD_STATIC @ resolver method type 3455 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3456 cmp r0, #0 @ got null? 3457 bne common_invokeMethodRange @ no, continue 3458 b common_exceptionThrown @ yes, handle exception 3459 3460 3461 3462/* ------------------------------ */ 3463 .balign 64 3464.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3465/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3466/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3467 /* 3468 * Handle an interface method call. 3469 * 3470 * for: invoke-interface, invoke-interface/range 3471 */ 3472 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3473 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3474 FETCH(r2, 2) @ r2<- FEDC or CCCC 3475 FETCH(r1, 1) @ r1<- BBBB 3476 .if (!1) 3477 and r2, r2, #15 @ r2<- C (or stays CCCC) 3478 .endif 3479 EXPORT_PC() @ must export for invoke 3480 GET_VREG(r0, r2) @ r0<- first arg ("this") 3481 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3482 cmp r0, #0 @ null obj? 3483 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3484 beq common_errNullObject @ yes, fail 3485 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3486 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3487 cmp r0, #0 @ failed? 3488 beq common_exceptionThrown @ yes, handle exception 3489 b common_invokeMethodRange @ jump to common handler 3490 3491 3492 3493/* ------------------------------ */ 3494 .balign 64 3495.L_OP_UNUSED_79: /* 0x79 */ 3496/* File: armv5te/OP_UNUSED_79.S */ 3497/* File: armv5te/unused.S */ 3498 bl common_abort 3499 3500 3501 3502/* ------------------------------ */ 3503 .balign 64 3504.L_OP_UNUSED_7A: /* 0x7a */ 3505/* File: armv5te/OP_UNUSED_7A.S */ 3506/* File: armv5te/unused.S */ 3507 bl common_abort 3508 3509 3510 3511/* ------------------------------ */ 3512 .balign 64 3513.L_OP_NEG_INT: /* 0x7b */ 3514/* File: armv5te/OP_NEG_INT.S */ 3515/* File: armv5te/unop.S */ 3516 /* 3517 * Generic 32-bit unary operation. Provide an "instr" line that 3518 * specifies an instruction that performs "result = op r0". 3519 * This could be an ARM instruction or a function call. 3520 * 3521 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3522 * int-to-byte, int-to-char, int-to-short 3523 */ 3524 /* unop vA, vB */ 3525 mov r3, rINST, lsr #12 @ r3<- B 3526 mov r9, rINST, lsr #8 @ r9<- A+ 3527 GET_VREG(r0, r3) @ r0<- vB 3528 and r9, r9, #15 3529 @ optional op; may set condition codes 3530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3531 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3532 GET_INST_OPCODE(ip) @ extract opcode from rINST 3533 SET_VREG(r0, r9) @ vAA<- r0 3534 GOTO_OPCODE(ip) @ jump to next instruction 3535 /* 9-10 instructions */ 3536 3537 3538/* ------------------------------ */ 3539 .balign 64 3540.L_OP_NOT_INT: /* 0x7c */ 3541/* File: armv5te/OP_NOT_INT.S */ 3542/* File: armv5te/unop.S */ 3543 /* 3544 * Generic 32-bit unary operation. Provide an "instr" line that 3545 * specifies an instruction that performs "result = op r0". 3546 * This could be an ARM instruction or a function call. 3547 * 3548 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3549 * int-to-byte, int-to-char, int-to-short 3550 */ 3551 /* unop vA, vB */ 3552 mov r3, rINST, lsr #12 @ r3<- B 3553 mov r9, rINST, lsr #8 @ r9<- A+ 3554 GET_VREG(r0, r3) @ r0<- vB 3555 and r9, r9, #15 3556 @ optional op; may set condition codes 3557 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3558 mvn r0, r0 @ r0<- op, r0-r3 changed 3559 GET_INST_OPCODE(ip) @ extract opcode from rINST 3560 SET_VREG(r0, r9) @ vAA<- r0 3561 GOTO_OPCODE(ip) @ jump to next instruction 3562 /* 9-10 instructions */ 3563 3564 3565/* ------------------------------ */ 3566 .balign 64 3567.L_OP_NEG_LONG: /* 0x7d */ 3568/* File: armv5te/OP_NEG_LONG.S */ 3569/* File: armv5te/unopWide.S */ 3570 /* 3571 * Generic 64-bit unary operation. Provide an "instr" line that 3572 * specifies an instruction that performs "result = op r0/r1". 3573 * This could be an ARM instruction or a function call. 3574 * 3575 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3576 */ 3577 /* unop vA, vB */ 3578 mov r9, rINST, lsr #8 @ r9<- A+ 3579 mov r3, rINST, lsr #12 @ r3<- B 3580 and r9, r9, #15 3581 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3582 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3583 ldmia r3, {r0-r1} @ r0/r1<- vAA 3584 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3585 rsbs r0, r0, #0 @ optional op; may set condition codes 3586 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3587 GET_INST_OPCODE(ip) @ extract opcode from rINST 3588 stmia r9, {r0-r1} @ vAA<- r0/r1 3589 GOTO_OPCODE(ip) @ jump to next instruction 3590 /* 12-13 instructions */ 3591 3592 3593 3594/* ------------------------------ */ 3595 .balign 64 3596.L_OP_NOT_LONG: /* 0x7e */ 3597/* File: armv5te/OP_NOT_LONG.S */ 3598/* File: armv5te/unopWide.S */ 3599 /* 3600 * Generic 64-bit unary operation. Provide an "instr" line that 3601 * specifies an instruction that performs "result = op r0/r1". 3602 * This could be an ARM instruction or a function call. 3603 * 3604 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3605 */ 3606 /* unop vA, vB */ 3607 mov r9, rINST, lsr #8 @ r9<- A+ 3608 mov r3, rINST, lsr #12 @ r3<- B 3609 and r9, r9, #15 3610 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3611 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3612 ldmia r3, {r0-r1} @ r0/r1<- vAA 3613 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3614 mvn r0, r0 @ optional op; may set condition codes 3615 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3616 GET_INST_OPCODE(ip) @ extract opcode from rINST 3617 stmia r9, {r0-r1} @ vAA<- r0/r1 3618 GOTO_OPCODE(ip) @ jump to next instruction 3619 /* 12-13 instructions */ 3620 3621 3622 3623/* ------------------------------ */ 3624 .balign 64 3625.L_OP_NEG_FLOAT: /* 0x7f */ 3626/* File: armv5te/OP_NEG_FLOAT.S */ 3627/* File: armv5te/unop.S */ 3628 /* 3629 * Generic 32-bit unary operation. Provide an "instr" line that 3630 * specifies an instruction that performs "result = op r0". 3631 * This could be an ARM instruction or a function call. 3632 * 3633 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3634 * int-to-byte, int-to-char, int-to-short 3635 */ 3636 /* unop vA, vB */ 3637 mov r3, rINST, lsr #12 @ r3<- B 3638 mov r9, rINST, lsr #8 @ r9<- A+ 3639 GET_VREG(r0, r3) @ r0<- vB 3640 and r9, r9, #15 3641 @ optional op; may set condition codes 3642 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3643 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3644 GET_INST_OPCODE(ip) @ extract opcode from rINST 3645 SET_VREG(r0, r9) @ vAA<- r0 3646 GOTO_OPCODE(ip) @ jump to next instruction 3647 /* 9-10 instructions */ 3648 3649 3650/* ------------------------------ */ 3651 .balign 64 3652.L_OP_NEG_DOUBLE: /* 0x80 */ 3653/* File: armv5te/OP_NEG_DOUBLE.S */ 3654/* File: armv5te/unopWide.S */ 3655 /* 3656 * Generic 64-bit unary operation. Provide an "instr" line that 3657 * specifies an instruction that performs "result = op r0/r1". 3658 * This could be an ARM instruction or a function call. 3659 * 3660 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3661 */ 3662 /* unop vA, vB */ 3663 mov r9, rINST, lsr #8 @ r9<- A+ 3664 mov r3, rINST, lsr #12 @ r3<- B 3665 and r9, r9, #15 3666 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3667 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3668 ldmia r3, {r0-r1} @ r0/r1<- vAA 3669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3670 @ optional op; may set condition codes 3671 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3672 GET_INST_OPCODE(ip) @ extract opcode from rINST 3673 stmia r9, {r0-r1} @ vAA<- r0/r1 3674 GOTO_OPCODE(ip) @ jump to next instruction 3675 /* 12-13 instructions */ 3676 3677 3678 3679/* ------------------------------ */ 3680 .balign 64 3681.L_OP_INT_TO_LONG: /* 0x81 */ 3682/* File: armv5te/OP_INT_TO_LONG.S */ 3683/* File: armv5te/unopWider.S */ 3684 /* 3685 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3686 * that specifies an instruction that performs "result = op r0", where 3687 * "result" is a 64-bit quantity in r0/r1. 3688 * 3689 * For: int-to-long, int-to-double, float-to-long, float-to-double 3690 */ 3691 /* unop vA, vB */ 3692 mov r9, rINST, lsr #8 @ r9<- A+ 3693 mov r3, rINST, lsr #12 @ r3<- B 3694 and r9, r9, #15 3695 GET_VREG(r0, r3) @ r0<- vB 3696 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3697 @ optional op; may set condition codes 3698 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3699 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3700 GET_INST_OPCODE(ip) @ extract opcode from rINST 3701 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3702 GOTO_OPCODE(ip) @ jump to next instruction 3703 /* 10-11 instructions */ 3704 3705 3706/* ------------------------------ */ 3707 .balign 64 3708.L_OP_INT_TO_FLOAT: /* 0x82 */ 3709/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3710/* File: arm-vfp/funop.S */ 3711 /* 3712 * Generic 32-bit unary floating-point operation. Provide an "instr" 3713 * line that specifies an instruction that performs "s1 = op s0". 3714 * 3715 * for: int-to-float, float-to-int 3716 */ 3717 /* unop vA, vB */ 3718 mov r3, rINST, lsr #12 @ r3<- B 3719 mov r9, rINST, lsr #8 @ r9<- A+ 3720 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3721 flds s0, [r3] @ s0<- vB 3722 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3723 and r9, r9, #15 @ r9<- A 3724 fsitos s1, s0 @ s1<- op 3725 GET_INST_OPCODE(ip) @ extract opcode from rINST 3726 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3727 fsts s1, [r9] @ vA<- s1 3728 GOTO_OPCODE(ip) @ jump to next instruction 3729 3730 3731/* ------------------------------ */ 3732 .balign 64 3733.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3734/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3735/* File: arm-vfp/funopWider.S */ 3736 /* 3737 * Generic 32bit-to-64bit floating point unary operation. Provide an 3738 * "instr" line that specifies an instruction that performs "d0 = op s0". 3739 * 3740 * For: int-to-double, float-to-double 3741 */ 3742 /* unop vA, vB */ 3743 mov r3, rINST, lsr #12 @ r3<- B 3744 mov r9, rINST, lsr #8 @ r9<- A+ 3745 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3746 flds s0, [r3] @ s0<- vB 3747 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3748 and r9, r9, #15 @ r9<- A 3749 fsitod d0, s0 @ d0<- op 3750 GET_INST_OPCODE(ip) @ extract opcode from rINST 3751 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3752 fstd d0, [r9] @ vA<- d0 3753 GOTO_OPCODE(ip) @ jump to next instruction 3754 3755 3756/* ------------------------------ */ 3757 .balign 64 3758.L_OP_LONG_TO_INT: /* 0x84 */ 3759/* File: armv5te/OP_LONG_TO_INT.S */ 3760/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3761/* File: armv5te/OP_MOVE.S */ 3762 /* for move, move-object, long-to-int */ 3763 /* op vA, vB */ 3764 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3765 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3766 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3767 GET_VREG(r2, r1) @ r2<- fp[B] 3768 and r0, r0, #15 3769 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3770 SET_VREG(r2, r0) @ fp[A]<- r2 3771 GOTO_OPCODE(ip) @ execute next instruction 3772 3773 3774 3775/* ------------------------------ */ 3776 .balign 64 3777.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3778/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3779/* File: armv5te/unopNarrower.S */ 3780 /* 3781 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3782 * that specifies an instruction that performs "result = op r0/r1", where 3783 * "result" is a 32-bit quantity in r0. 3784 * 3785 * For: long-to-float, double-to-int, double-to-float 3786 * 3787 * (This would work for long-to-int, but that instruction is actually 3788 * an exact match for OP_MOVE.) 3789 */ 3790 /* unop vA, vB */ 3791 mov r3, rINST, lsr #12 @ r3<- B 3792 mov r9, rINST, lsr #8 @ r9<- A+ 3793 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3794 and r9, r9, #15 3795 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3796 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3797 @ optional op; may set condition codes 3798 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3799 GET_INST_OPCODE(ip) @ extract opcode from rINST 3800 SET_VREG(r0, r9) @ vA<- r0 3801 GOTO_OPCODE(ip) @ jump to next instruction 3802 /* 10-11 instructions */ 3803 3804 3805/* ------------------------------ */ 3806 .balign 64 3807.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3808/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3809/* File: armv5te/unopWide.S */ 3810 /* 3811 * Generic 64-bit unary operation. Provide an "instr" line that 3812 * specifies an instruction that performs "result = op r0/r1". 3813 * This could be an ARM instruction or a function call. 3814 * 3815 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3816 */ 3817 /* unop vA, vB */ 3818 mov r9, rINST, lsr #8 @ r9<- A+ 3819 mov r3, rINST, lsr #12 @ r3<- B 3820 and r9, r9, #15 3821 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3822 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3823 ldmia r3, {r0-r1} @ r0/r1<- vAA 3824 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3825 @ optional op; may set condition codes 3826 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3827 GET_INST_OPCODE(ip) @ extract opcode from rINST 3828 stmia r9, {r0-r1} @ vAA<- r0/r1 3829 GOTO_OPCODE(ip) @ jump to next instruction 3830 /* 12-13 instructions */ 3831 3832 3833 3834/* ------------------------------ */ 3835 .balign 64 3836.L_OP_FLOAT_TO_INT: /* 0x87 */ 3837/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3838/* File: arm-vfp/funop.S */ 3839 /* 3840 * Generic 32-bit unary floating-point operation. Provide an "instr" 3841 * line that specifies an instruction that performs "s1 = op s0". 3842 * 3843 * for: int-to-float, float-to-int 3844 */ 3845 /* unop vA, vB */ 3846 mov r3, rINST, lsr #12 @ r3<- B 3847 mov r9, rINST, lsr #8 @ r9<- A+ 3848 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3849 flds s0, [r3] @ s0<- vB 3850 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3851 and r9, r9, #15 @ r9<- A 3852 ftosizs s1, s0 @ s1<- op 3853 GET_INST_OPCODE(ip) @ extract opcode from rINST 3854 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3855 fsts s1, [r9] @ vA<- s1 3856 GOTO_OPCODE(ip) @ jump to next instruction 3857 3858 3859/* ------------------------------ */ 3860 .balign 64 3861.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3862/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3863@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3864/* File: armv5te/unopWider.S */ 3865 /* 3866 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3867 * that specifies an instruction that performs "result = op r0", where 3868 * "result" is a 64-bit quantity in r0/r1. 3869 * 3870 * For: int-to-long, int-to-double, float-to-long, float-to-double 3871 */ 3872 /* unop vA, vB */ 3873 mov r9, rINST, lsr #8 @ r9<- A+ 3874 mov r3, rINST, lsr #12 @ r3<- B 3875 and r9, r9, #15 3876 GET_VREG(r0, r3) @ r0<- vB 3877 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3878 @ optional op; may set condition codes 3879 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3880 bl f2l_doconv @ r0<- op, r0-r3 changed 3881 GET_INST_OPCODE(ip) @ extract opcode from rINST 3882 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3883 GOTO_OPCODE(ip) @ jump to next instruction 3884 /* 10-11 instructions */ 3885 3886 3887 3888/* ------------------------------ */ 3889 .balign 64 3890.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3891/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3892/* File: arm-vfp/funopWider.S */ 3893 /* 3894 * Generic 32bit-to-64bit floating point unary operation. Provide an 3895 * "instr" line that specifies an instruction that performs "d0 = op s0". 3896 * 3897 * For: int-to-double, float-to-double 3898 */ 3899 /* unop vA, vB */ 3900 mov r3, rINST, lsr #12 @ r3<- B 3901 mov r9, rINST, lsr #8 @ r9<- A+ 3902 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3903 flds s0, [r3] @ s0<- vB 3904 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3905 and r9, r9, #15 @ r9<- A 3906 fcvtds d0, s0 @ d0<- op 3907 GET_INST_OPCODE(ip) @ extract opcode from rINST 3908 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3909 fstd d0, [r9] @ vA<- d0 3910 GOTO_OPCODE(ip) @ jump to next instruction 3911 3912 3913/* ------------------------------ */ 3914 .balign 64 3915.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3916/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3917/* File: arm-vfp/funopNarrower.S */ 3918 /* 3919 * Generic 64bit-to-32bit unary floating point operation. Provide an 3920 * "instr" line that specifies an instruction that performs "s0 = op d0". 3921 * 3922 * For: double-to-int, double-to-float 3923 */ 3924 /* unop vA, vB */ 3925 mov r3, rINST, lsr #12 @ r3<- B 3926 mov r9, rINST, lsr #8 @ r9<- A+ 3927 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3928 fldd d0, [r3] @ d0<- vB 3929 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3930 and r9, r9, #15 @ r9<- A 3931 ftosizd s0, d0 @ s0<- op 3932 GET_INST_OPCODE(ip) @ extract opcode from rINST 3933 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3934 fsts s0, [r9] @ vA<- s0 3935 GOTO_OPCODE(ip) @ jump to next instruction 3936 3937 3938/* ------------------------------ */ 3939 .balign 64 3940.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3941/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3942@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3943/* File: armv5te/unopWide.S */ 3944 /* 3945 * Generic 64-bit unary operation. Provide an "instr" line that 3946 * specifies an instruction that performs "result = op r0/r1". 3947 * This could be an ARM instruction or a function call. 3948 * 3949 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3950 */ 3951 /* unop vA, vB */ 3952 mov r9, rINST, lsr #8 @ r9<- A+ 3953 mov r3, rINST, lsr #12 @ r3<- B 3954 and r9, r9, #15 3955 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3957 ldmia r3, {r0-r1} @ r0/r1<- vAA 3958 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3959 @ optional op; may set condition codes 3960 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3961 GET_INST_OPCODE(ip) @ extract opcode from rINST 3962 stmia r9, {r0-r1} @ vAA<- r0/r1 3963 GOTO_OPCODE(ip) @ jump to next instruction 3964 /* 12-13 instructions */ 3965 3966 3967 3968 3969/* ------------------------------ */ 3970 .balign 64 3971.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3972/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3973/* File: arm-vfp/funopNarrower.S */ 3974 /* 3975 * Generic 64bit-to-32bit unary floating point operation. Provide an 3976 * "instr" line that specifies an instruction that performs "s0 = op d0". 3977 * 3978 * For: double-to-int, double-to-float 3979 */ 3980 /* unop vA, vB */ 3981 mov r3, rINST, lsr #12 @ r3<- B 3982 mov r9, rINST, lsr #8 @ r9<- A+ 3983 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3984 fldd d0, [r3] @ d0<- vB 3985 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3986 and r9, r9, #15 @ r9<- A 3987 fcvtsd s0, d0 @ s0<- op 3988 GET_INST_OPCODE(ip) @ extract opcode from rINST 3989 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3990 fsts s0, [r9] @ vA<- s0 3991 GOTO_OPCODE(ip) @ jump to next instruction 3992 3993 3994/* ------------------------------ */ 3995 .balign 64 3996.L_OP_INT_TO_BYTE: /* 0x8d */ 3997/* File: armv5te/OP_INT_TO_BYTE.S */ 3998/* File: armv5te/unop.S */ 3999 /* 4000 * Generic 32-bit unary operation. Provide an "instr" line that 4001 * specifies an instruction that performs "result = op r0". 4002 * This could be an ARM instruction or a function call. 4003 * 4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4005 * int-to-byte, int-to-char, int-to-short 4006 */ 4007 /* unop vA, vB */ 4008 mov r3, rINST, lsr #12 @ r3<- B 4009 mov r9, rINST, lsr #8 @ r9<- A+ 4010 GET_VREG(r0, r3) @ r0<- vB 4011 and r9, r9, #15 4012 mov r0, r0, asl #24 @ optional op; may set condition codes 4013 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4014 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4015 GET_INST_OPCODE(ip) @ extract opcode from rINST 4016 SET_VREG(r0, r9) @ vAA<- r0 4017 GOTO_OPCODE(ip) @ jump to next instruction 4018 /* 9-10 instructions */ 4019 4020 4021/* ------------------------------ */ 4022 .balign 64 4023.L_OP_INT_TO_CHAR: /* 0x8e */ 4024/* File: armv5te/OP_INT_TO_CHAR.S */ 4025/* File: armv5te/unop.S */ 4026 /* 4027 * Generic 32-bit unary operation. Provide an "instr" line that 4028 * specifies an instruction that performs "result = op r0". 4029 * This could be an ARM instruction or a function call. 4030 * 4031 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4032 * int-to-byte, int-to-char, int-to-short 4033 */ 4034 /* unop vA, vB */ 4035 mov r3, rINST, lsr #12 @ r3<- B 4036 mov r9, rINST, lsr #8 @ r9<- A+ 4037 GET_VREG(r0, r3) @ r0<- vB 4038 and r9, r9, #15 4039 mov r0, r0, asl #16 @ optional op; may set condition codes 4040 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4041 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4042 GET_INST_OPCODE(ip) @ extract opcode from rINST 4043 SET_VREG(r0, r9) @ vAA<- r0 4044 GOTO_OPCODE(ip) @ jump to next instruction 4045 /* 9-10 instructions */ 4046 4047 4048/* ------------------------------ */ 4049 .balign 64 4050.L_OP_INT_TO_SHORT: /* 0x8f */ 4051/* File: armv5te/OP_INT_TO_SHORT.S */ 4052/* File: armv5te/unop.S */ 4053 /* 4054 * Generic 32-bit unary operation. Provide an "instr" line that 4055 * specifies an instruction that performs "result = op r0". 4056 * This could be an ARM instruction or a function call. 4057 * 4058 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4059 * int-to-byte, int-to-char, int-to-short 4060 */ 4061 /* unop vA, vB */ 4062 mov r3, rINST, lsr #12 @ r3<- B 4063 mov r9, rINST, lsr #8 @ r9<- A+ 4064 GET_VREG(r0, r3) @ r0<- vB 4065 and r9, r9, #15 4066 mov r0, r0, asl #16 @ optional op; may set condition codes 4067 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4068 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4069 GET_INST_OPCODE(ip) @ extract opcode from rINST 4070 SET_VREG(r0, r9) @ vAA<- r0 4071 GOTO_OPCODE(ip) @ jump to next instruction 4072 /* 9-10 instructions */ 4073 4074 4075/* ------------------------------ */ 4076 .balign 64 4077.L_OP_ADD_INT: /* 0x90 */ 4078/* File: armv5te/OP_ADD_INT.S */ 4079/* File: armv5te/binop.S */ 4080 /* 4081 * Generic 32-bit binary operation. Provide an "instr" line that 4082 * specifies an instruction that performs "result = r0 op r1". 4083 * This could be an ARM instruction or a function call. (If the result 4084 * comes back in a register other than r0, you can override "result".) 4085 * 4086 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4087 * vCC (r1). Useful for integer division and modulus. Note that we 4088 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4089 * handles it correctly. 4090 * 4091 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4092 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4093 * mul-float, div-float, rem-float 4094 */ 4095 /* binop vAA, vBB, vCC */ 4096 FETCH(r0, 1) @ r0<- CCBB 4097 mov r9, rINST, lsr #8 @ r9<- AA 4098 mov r3, r0, lsr #8 @ r3<- CC 4099 and r2, r0, #255 @ r2<- BB 4100 GET_VREG(r1, r3) @ r1<- vCC 4101 GET_VREG(r0, r2) @ r0<- vBB 4102 .if 0 4103 cmp r1, #0 @ is second operand zero? 4104 beq common_errDivideByZero 4105 .endif 4106 4107 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4108 @ optional op; may set condition codes 4109 add r0, r0, r1 @ r0<- op, r0-r3 changed 4110 GET_INST_OPCODE(ip) @ extract opcode from rINST 4111 SET_VREG(r0, r9) @ vAA<- r0 4112 GOTO_OPCODE(ip) @ jump to next instruction 4113 /* 11-14 instructions */ 4114 4115 4116 4117/* ------------------------------ */ 4118 .balign 64 4119.L_OP_SUB_INT: /* 0x91 */ 4120/* File: armv5te/OP_SUB_INT.S */ 4121/* File: armv5te/binop.S */ 4122 /* 4123 * Generic 32-bit binary operation. Provide an "instr" line that 4124 * specifies an instruction that performs "result = r0 op r1". 4125 * This could be an ARM instruction or a function call. (If the result 4126 * comes back in a register other than r0, you can override "result".) 4127 * 4128 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4129 * vCC (r1). Useful for integer division and modulus. Note that we 4130 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4131 * handles it correctly. 4132 * 4133 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4134 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4135 * mul-float, div-float, rem-float 4136 */ 4137 /* binop vAA, vBB, vCC */ 4138 FETCH(r0, 1) @ r0<- CCBB 4139 mov r9, rINST, lsr #8 @ r9<- AA 4140 mov r3, r0, lsr #8 @ r3<- CC 4141 and r2, r0, #255 @ r2<- BB 4142 GET_VREG(r1, r3) @ r1<- vCC 4143 GET_VREG(r0, r2) @ r0<- vBB 4144 .if 0 4145 cmp r1, #0 @ is second operand zero? 4146 beq common_errDivideByZero 4147 .endif 4148 4149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4150 @ optional op; may set condition codes 4151 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4152 GET_INST_OPCODE(ip) @ extract opcode from rINST 4153 SET_VREG(r0, r9) @ vAA<- r0 4154 GOTO_OPCODE(ip) @ jump to next instruction 4155 /* 11-14 instructions */ 4156 4157 4158 4159/* ------------------------------ */ 4160 .balign 64 4161.L_OP_MUL_INT: /* 0x92 */ 4162/* File: armv5te/OP_MUL_INT.S */ 4163/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4164/* File: armv5te/binop.S */ 4165 /* 4166 * Generic 32-bit binary operation. Provide an "instr" line that 4167 * specifies an instruction that performs "result = r0 op r1". 4168 * This could be an ARM instruction or a function call. (If the result 4169 * comes back in a register other than r0, you can override "result".) 4170 * 4171 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4172 * vCC (r1). Useful for integer division and modulus. Note that we 4173 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4174 * handles it correctly. 4175 * 4176 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4177 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4178 * mul-float, div-float, rem-float 4179 */ 4180 /* binop vAA, vBB, vCC */ 4181 FETCH(r0, 1) @ r0<- CCBB 4182 mov r9, rINST, lsr #8 @ r9<- AA 4183 mov r3, r0, lsr #8 @ r3<- CC 4184 and r2, r0, #255 @ r2<- BB 4185 GET_VREG(r1, r3) @ r1<- vCC 4186 GET_VREG(r0, r2) @ r0<- vBB 4187 .if 0 4188 cmp r1, #0 @ is second operand zero? 4189 beq common_errDivideByZero 4190 .endif 4191 4192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4193 @ optional op; may set condition codes 4194 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4195 GET_INST_OPCODE(ip) @ extract opcode from rINST 4196 SET_VREG(r0, r9) @ vAA<- r0 4197 GOTO_OPCODE(ip) @ jump to next instruction 4198 /* 11-14 instructions */ 4199 4200 4201 4202/* ------------------------------ */ 4203 .balign 64 4204.L_OP_DIV_INT: /* 0x93 */ 4205/* File: armv5te/OP_DIV_INT.S */ 4206/* File: armv5te/binop.S */ 4207 /* 4208 * Generic 32-bit binary operation. Provide an "instr" line that 4209 * specifies an instruction that performs "result = r0 op r1". 4210 * This could be an ARM instruction or a function call. (If the result 4211 * comes back in a register other than r0, you can override "result".) 4212 * 4213 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4214 * vCC (r1). Useful for integer division and modulus. Note that we 4215 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4216 * handles it correctly. 4217 * 4218 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4219 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4220 * mul-float, div-float, rem-float 4221 */ 4222 /* binop vAA, vBB, vCC */ 4223 FETCH(r0, 1) @ r0<- CCBB 4224 mov r9, rINST, lsr #8 @ r9<- AA 4225 mov r3, r0, lsr #8 @ r3<- CC 4226 and r2, r0, #255 @ r2<- BB 4227 GET_VREG(r1, r3) @ r1<- vCC 4228 GET_VREG(r0, r2) @ r0<- vBB 4229 .if 1 4230 cmp r1, #0 @ is second operand zero? 4231 beq common_errDivideByZero 4232 .endif 4233 4234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4235 @ optional op; may set condition codes 4236 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4237 GET_INST_OPCODE(ip) @ extract opcode from rINST 4238 SET_VREG(r0, r9) @ vAA<- r0 4239 GOTO_OPCODE(ip) @ jump to next instruction 4240 /* 11-14 instructions */ 4241 4242 4243 4244/* ------------------------------ */ 4245 .balign 64 4246.L_OP_REM_INT: /* 0x94 */ 4247/* File: armv5te/OP_REM_INT.S */ 4248/* idivmod returns quotient in r0 and remainder in r1 */ 4249/* File: armv5te/binop.S */ 4250 /* 4251 * Generic 32-bit binary operation. Provide an "instr" line that 4252 * specifies an instruction that performs "result = r0 op r1". 4253 * This could be an ARM instruction or a function call. (If the result 4254 * comes back in a register other than r0, you can override "result".) 4255 * 4256 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4257 * vCC (r1). Useful for integer division and modulus. Note that we 4258 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4259 * handles it correctly. 4260 * 4261 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4262 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4263 * mul-float, div-float, rem-float 4264 */ 4265 /* binop vAA, vBB, vCC */ 4266 FETCH(r0, 1) @ r0<- CCBB 4267 mov r9, rINST, lsr #8 @ r9<- AA 4268 mov r3, r0, lsr #8 @ r3<- CC 4269 and r2, r0, #255 @ r2<- BB 4270 GET_VREG(r1, r3) @ r1<- vCC 4271 GET_VREG(r0, r2) @ r0<- vBB 4272 .if 1 4273 cmp r1, #0 @ is second operand zero? 4274 beq common_errDivideByZero 4275 .endif 4276 4277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4278 @ optional op; may set condition codes 4279 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4280 GET_INST_OPCODE(ip) @ extract opcode from rINST 4281 SET_VREG(r1, r9) @ vAA<- r1 4282 GOTO_OPCODE(ip) @ jump to next instruction 4283 /* 11-14 instructions */ 4284 4285 4286 4287/* ------------------------------ */ 4288 .balign 64 4289.L_OP_AND_INT: /* 0x95 */ 4290/* File: armv5te/OP_AND_INT.S */ 4291/* File: armv5te/binop.S */ 4292 /* 4293 * Generic 32-bit binary operation. Provide an "instr" line that 4294 * specifies an instruction that performs "result = r0 op r1". 4295 * This could be an ARM instruction or a function call. (If the result 4296 * comes back in a register other than r0, you can override "result".) 4297 * 4298 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4299 * vCC (r1). Useful for integer division and modulus. Note that we 4300 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4301 * handles it correctly. 4302 * 4303 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4304 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4305 * mul-float, div-float, rem-float 4306 */ 4307 /* binop vAA, vBB, vCC */ 4308 FETCH(r0, 1) @ r0<- CCBB 4309 mov r9, rINST, lsr #8 @ r9<- AA 4310 mov r3, r0, lsr #8 @ r3<- CC 4311 and r2, r0, #255 @ r2<- BB 4312 GET_VREG(r1, r3) @ r1<- vCC 4313 GET_VREG(r0, r2) @ r0<- vBB 4314 .if 0 4315 cmp r1, #0 @ is second operand zero? 4316 beq common_errDivideByZero 4317 .endif 4318 4319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4320 @ optional op; may set condition codes 4321 and r0, r0, r1 @ r0<- op, r0-r3 changed 4322 GET_INST_OPCODE(ip) @ extract opcode from rINST 4323 SET_VREG(r0, r9) @ vAA<- r0 4324 GOTO_OPCODE(ip) @ jump to next instruction 4325 /* 11-14 instructions */ 4326 4327 4328 4329/* ------------------------------ */ 4330 .balign 64 4331.L_OP_OR_INT: /* 0x96 */ 4332/* File: armv5te/OP_OR_INT.S */ 4333/* File: armv5te/binop.S */ 4334 /* 4335 * Generic 32-bit binary operation. Provide an "instr" line that 4336 * specifies an instruction that performs "result = r0 op r1". 4337 * This could be an ARM instruction or a function call. (If the result 4338 * comes back in a register other than r0, you can override "result".) 4339 * 4340 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4341 * vCC (r1). Useful for integer division and modulus. Note that we 4342 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4343 * handles it correctly. 4344 * 4345 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4346 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4347 * mul-float, div-float, rem-float 4348 */ 4349 /* binop vAA, vBB, vCC */ 4350 FETCH(r0, 1) @ r0<- CCBB 4351 mov r9, rINST, lsr #8 @ r9<- AA 4352 mov r3, r0, lsr #8 @ r3<- CC 4353 and r2, r0, #255 @ r2<- BB 4354 GET_VREG(r1, r3) @ r1<- vCC 4355 GET_VREG(r0, r2) @ r0<- vBB 4356 .if 0 4357 cmp r1, #0 @ is second operand zero? 4358 beq common_errDivideByZero 4359 .endif 4360 4361 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4362 @ optional op; may set condition codes 4363 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4364 GET_INST_OPCODE(ip) @ extract opcode from rINST 4365 SET_VREG(r0, r9) @ vAA<- r0 4366 GOTO_OPCODE(ip) @ jump to next instruction 4367 /* 11-14 instructions */ 4368 4369 4370 4371/* ------------------------------ */ 4372 .balign 64 4373.L_OP_XOR_INT: /* 0x97 */ 4374/* File: armv5te/OP_XOR_INT.S */ 4375/* File: armv5te/binop.S */ 4376 /* 4377 * Generic 32-bit binary operation. Provide an "instr" line that 4378 * specifies an instruction that performs "result = r0 op r1". 4379 * This could be an ARM instruction or a function call. (If the result 4380 * comes back in a register other than r0, you can override "result".) 4381 * 4382 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4383 * vCC (r1). Useful for integer division and modulus. Note that we 4384 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4385 * handles it correctly. 4386 * 4387 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4388 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4389 * mul-float, div-float, rem-float 4390 */ 4391 /* binop vAA, vBB, vCC */ 4392 FETCH(r0, 1) @ r0<- CCBB 4393 mov r9, rINST, lsr #8 @ r9<- AA 4394 mov r3, r0, lsr #8 @ r3<- CC 4395 and r2, r0, #255 @ r2<- BB 4396 GET_VREG(r1, r3) @ r1<- vCC 4397 GET_VREG(r0, r2) @ r0<- vBB 4398 .if 0 4399 cmp r1, #0 @ is second operand zero? 4400 beq common_errDivideByZero 4401 .endif 4402 4403 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4404 @ optional op; may set condition codes 4405 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4406 GET_INST_OPCODE(ip) @ extract opcode from rINST 4407 SET_VREG(r0, r9) @ vAA<- r0 4408 GOTO_OPCODE(ip) @ jump to next instruction 4409 /* 11-14 instructions */ 4410 4411 4412 4413/* ------------------------------ */ 4414 .balign 64 4415.L_OP_SHL_INT: /* 0x98 */ 4416/* File: armv5te/OP_SHL_INT.S */ 4417/* File: armv5te/binop.S */ 4418 /* 4419 * Generic 32-bit binary operation. Provide an "instr" line that 4420 * specifies an instruction that performs "result = r0 op r1". 4421 * This could be an ARM instruction or a function call. (If the result 4422 * comes back in a register other than r0, you can override "result".) 4423 * 4424 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4425 * vCC (r1). Useful for integer division and modulus. Note that we 4426 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4427 * handles it correctly. 4428 * 4429 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4430 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4431 * mul-float, div-float, rem-float 4432 */ 4433 /* binop vAA, vBB, vCC */ 4434 FETCH(r0, 1) @ r0<- CCBB 4435 mov r9, rINST, lsr #8 @ r9<- AA 4436 mov r3, r0, lsr #8 @ r3<- CC 4437 and r2, r0, #255 @ r2<- BB 4438 GET_VREG(r1, r3) @ r1<- vCC 4439 GET_VREG(r0, r2) @ r0<- vBB 4440 .if 0 4441 cmp r1, #0 @ is second operand zero? 4442 beq common_errDivideByZero 4443 .endif 4444 4445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4446 and r1, r1, #31 @ optional op; may set condition codes 4447 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4448 GET_INST_OPCODE(ip) @ extract opcode from rINST 4449 SET_VREG(r0, r9) @ vAA<- r0 4450 GOTO_OPCODE(ip) @ jump to next instruction 4451 /* 11-14 instructions */ 4452 4453 4454 4455/* ------------------------------ */ 4456 .balign 64 4457.L_OP_SHR_INT: /* 0x99 */ 4458/* File: armv5te/OP_SHR_INT.S */ 4459/* File: armv5te/binop.S */ 4460 /* 4461 * Generic 32-bit binary operation. Provide an "instr" line that 4462 * specifies an instruction that performs "result = r0 op r1". 4463 * This could be an ARM instruction or a function call. (If the result 4464 * comes back in a register other than r0, you can override "result".) 4465 * 4466 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4467 * vCC (r1). Useful for integer division and modulus. Note that we 4468 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4469 * handles it correctly. 4470 * 4471 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4472 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4473 * mul-float, div-float, rem-float 4474 */ 4475 /* binop vAA, vBB, vCC */ 4476 FETCH(r0, 1) @ r0<- CCBB 4477 mov r9, rINST, lsr #8 @ r9<- AA 4478 mov r3, r0, lsr #8 @ r3<- CC 4479 and r2, r0, #255 @ r2<- BB 4480 GET_VREG(r1, r3) @ r1<- vCC 4481 GET_VREG(r0, r2) @ r0<- vBB 4482 .if 0 4483 cmp r1, #0 @ is second operand zero? 4484 beq common_errDivideByZero 4485 .endif 4486 4487 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4488 and r1, r1, #31 @ optional op; may set condition codes 4489 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4490 GET_INST_OPCODE(ip) @ extract opcode from rINST 4491 SET_VREG(r0, r9) @ vAA<- r0 4492 GOTO_OPCODE(ip) @ jump to next instruction 4493 /* 11-14 instructions */ 4494 4495 4496 4497/* ------------------------------ */ 4498 .balign 64 4499.L_OP_USHR_INT: /* 0x9a */ 4500/* File: armv5te/OP_USHR_INT.S */ 4501/* File: armv5te/binop.S */ 4502 /* 4503 * Generic 32-bit binary operation. Provide an "instr" line that 4504 * specifies an instruction that performs "result = r0 op r1". 4505 * This could be an ARM instruction or a function call. (If the result 4506 * comes back in a register other than r0, you can override "result".) 4507 * 4508 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4509 * vCC (r1). Useful for integer division and modulus. Note that we 4510 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4511 * handles it correctly. 4512 * 4513 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4514 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4515 * mul-float, div-float, rem-float 4516 */ 4517 /* binop vAA, vBB, vCC */ 4518 FETCH(r0, 1) @ r0<- CCBB 4519 mov r9, rINST, lsr #8 @ r9<- AA 4520 mov r3, r0, lsr #8 @ r3<- CC 4521 and r2, r0, #255 @ r2<- BB 4522 GET_VREG(r1, r3) @ r1<- vCC 4523 GET_VREG(r0, r2) @ r0<- vBB 4524 .if 0 4525 cmp r1, #0 @ is second operand zero? 4526 beq common_errDivideByZero 4527 .endif 4528 4529 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4530 and r1, r1, #31 @ optional op; may set condition codes 4531 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4532 GET_INST_OPCODE(ip) @ extract opcode from rINST 4533 SET_VREG(r0, r9) @ vAA<- r0 4534 GOTO_OPCODE(ip) @ jump to next instruction 4535 /* 11-14 instructions */ 4536 4537 4538 4539/* ------------------------------ */ 4540 .balign 64 4541.L_OP_ADD_LONG: /* 0x9b */ 4542/* File: armv5te/OP_ADD_LONG.S */ 4543/* File: armv5te/binopWide.S */ 4544 /* 4545 * Generic 64-bit binary operation. Provide an "instr" line that 4546 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4547 * This could be an ARM instruction or a function call. (If the result 4548 * comes back in a register other than r0, you can override "result".) 4549 * 4550 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4551 * vCC (r1). Useful for integer division and modulus. 4552 * 4553 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4554 * xor-long, add-double, sub-double, mul-double, div-double, 4555 * rem-double 4556 * 4557 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4558 */ 4559 /* binop vAA, vBB, vCC */ 4560 FETCH(r0, 1) @ r0<- CCBB 4561 mov r9, rINST, lsr #8 @ r9<- AA 4562 and r2, r0, #255 @ r2<- BB 4563 mov r3, r0, lsr #8 @ r3<- CC 4564 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4565 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4566 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4567 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4568 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4569 .if 0 4570 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4571 beq common_errDivideByZero 4572 .endif 4573 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4574 4575 adds r0, r0, r2 @ optional op; may set condition codes 4576 adc r1, r1, r3 @ result<- op, r0-r3 changed 4577 GET_INST_OPCODE(ip) @ extract opcode from rINST 4578 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4579 GOTO_OPCODE(ip) @ jump to next instruction 4580 /* 14-17 instructions */ 4581 4582 4583 4584/* ------------------------------ */ 4585 .balign 64 4586.L_OP_SUB_LONG: /* 0x9c */ 4587/* File: armv5te/OP_SUB_LONG.S */ 4588/* File: armv5te/binopWide.S */ 4589 /* 4590 * Generic 64-bit binary operation. Provide an "instr" line that 4591 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4592 * This could be an ARM instruction or a function call. (If the result 4593 * comes back in a register other than r0, you can override "result".) 4594 * 4595 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4596 * vCC (r1). Useful for integer division and modulus. 4597 * 4598 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4599 * xor-long, add-double, sub-double, mul-double, div-double, 4600 * rem-double 4601 * 4602 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4603 */ 4604 /* binop vAA, vBB, vCC */ 4605 FETCH(r0, 1) @ r0<- CCBB 4606 mov r9, rINST, lsr #8 @ r9<- AA 4607 and r2, r0, #255 @ r2<- BB 4608 mov r3, r0, lsr #8 @ r3<- CC 4609 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4610 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4611 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4612 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4613 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4614 .if 0 4615 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4616 beq common_errDivideByZero 4617 .endif 4618 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4619 4620 subs r0, r0, r2 @ optional op; may set condition codes 4621 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4622 GET_INST_OPCODE(ip) @ extract opcode from rINST 4623 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4624 GOTO_OPCODE(ip) @ jump to next instruction 4625 /* 14-17 instructions */ 4626 4627 4628 4629/* ------------------------------ */ 4630 .balign 64 4631.L_OP_MUL_LONG: /* 0x9d */ 4632/* File: armv5te/OP_MUL_LONG.S */ 4633 /* 4634 * Signed 64-bit integer multiply. 4635 * 4636 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4637 * WX 4638 * x YZ 4639 * -------- 4640 * ZW ZX 4641 * YW YX 4642 * 4643 * The low word of the result holds ZX, the high word holds 4644 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4645 * it doesn't fit in the low 64 bits. 4646 * 4647 * Unlike most ARM math operations, multiply instructions have 4648 * restrictions on using the same register more than once (Rd and Rm 4649 * cannot be the same). 4650 */ 4651 /* mul-long vAA, vBB, vCC */ 4652 FETCH(r0, 1) @ r0<- CCBB 4653 and r2, r0, #255 @ r2<- BB 4654 mov r3, r0, lsr #8 @ r3<- CC 4655 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4656 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4657 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4658 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4659 mul ip, r2, r1 @ ip<- ZxW 4660 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4661 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4662 mov r0, rINST, lsr #8 @ r0<- AA 4663 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4664 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4665 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4666 b .LOP_MUL_LONG_finish 4667 4668/* ------------------------------ */ 4669 .balign 64 4670.L_OP_DIV_LONG: /* 0x9e */ 4671/* File: armv5te/OP_DIV_LONG.S */ 4672/* File: armv5te/binopWide.S */ 4673 /* 4674 * Generic 64-bit binary operation. Provide an "instr" line that 4675 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4676 * This could be an ARM instruction or a function call. (If the result 4677 * comes back in a register other than r0, you can override "result".) 4678 * 4679 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4680 * vCC (r1). Useful for integer division and modulus. 4681 * 4682 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4683 * xor-long, add-double, sub-double, mul-double, div-double, 4684 * rem-double 4685 * 4686 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4687 */ 4688 /* binop vAA, vBB, vCC */ 4689 FETCH(r0, 1) @ r0<- CCBB 4690 mov r9, rINST, lsr #8 @ r9<- AA 4691 and r2, r0, #255 @ r2<- BB 4692 mov r3, r0, lsr #8 @ r3<- CC 4693 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4694 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4695 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4696 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4697 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4698 .if 1 4699 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4700 beq common_errDivideByZero 4701 .endif 4702 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4703 4704 @ optional op; may set condition codes 4705 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4706 GET_INST_OPCODE(ip) @ extract opcode from rINST 4707 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4708 GOTO_OPCODE(ip) @ jump to next instruction 4709 /* 14-17 instructions */ 4710 4711 4712 4713/* ------------------------------ */ 4714 .balign 64 4715.L_OP_REM_LONG: /* 0x9f */ 4716/* File: armv5te/OP_REM_LONG.S */ 4717/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4718/* File: armv5te/binopWide.S */ 4719 /* 4720 * Generic 64-bit binary operation. Provide an "instr" line that 4721 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4722 * This could be an ARM instruction or a function call. (If the result 4723 * comes back in a register other than r0, you can override "result".) 4724 * 4725 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4726 * vCC (r1). Useful for integer division and modulus. 4727 * 4728 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4729 * xor-long, add-double, sub-double, mul-double, div-double, 4730 * rem-double 4731 * 4732 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4733 */ 4734 /* binop vAA, vBB, vCC */ 4735 FETCH(r0, 1) @ r0<- CCBB 4736 mov r9, rINST, lsr #8 @ r9<- AA 4737 and r2, r0, #255 @ r2<- BB 4738 mov r3, r0, lsr #8 @ r3<- CC 4739 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4740 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4741 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4742 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4743 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4744 .if 1 4745 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4746 beq common_errDivideByZero 4747 .endif 4748 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4749 4750 @ optional op; may set condition codes 4751 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4752 GET_INST_OPCODE(ip) @ extract opcode from rINST 4753 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4754 GOTO_OPCODE(ip) @ jump to next instruction 4755 /* 14-17 instructions */ 4756 4757 4758 4759/* ------------------------------ */ 4760 .balign 64 4761.L_OP_AND_LONG: /* 0xa0 */ 4762/* File: armv5te/OP_AND_LONG.S */ 4763/* File: armv5te/binopWide.S */ 4764 /* 4765 * Generic 64-bit binary operation. Provide an "instr" line that 4766 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4767 * This could be an ARM instruction or a function call. (If the result 4768 * comes back in a register other than r0, you can override "result".) 4769 * 4770 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4771 * vCC (r1). Useful for integer division and modulus. 4772 * 4773 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4774 * xor-long, add-double, sub-double, mul-double, div-double, 4775 * rem-double 4776 * 4777 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4778 */ 4779 /* binop vAA, vBB, vCC */ 4780 FETCH(r0, 1) @ r0<- CCBB 4781 mov r9, rINST, lsr #8 @ r9<- AA 4782 and r2, r0, #255 @ r2<- BB 4783 mov r3, r0, lsr #8 @ r3<- CC 4784 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4785 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4786 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4787 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4788 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4789 .if 0 4790 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4791 beq common_errDivideByZero 4792 .endif 4793 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4794 4795 and r0, r0, r2 @ optional op; may set condition codes 4796 and r1, r1, r3 @ result<- op, r0-r3 changed 4797 GET_INST_OPCODE(ip) @ extract opcode from rINST 4798 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4799 GOTO_OPCODE(ip) @ jump to next instruction 4800 /* 14-17 instructions */ 4801 4802 4803 4804/* ------------------------------ */ 4805 .balign 64 4806.L_OP_OR_LONG: /* 0xa1 */ 4807/* File: armv5te/OP_OR_LONG.S */ 4808/* File: armv5te/binopWide.S */ 4809 /* 4810 * Generic 64-bit binary operation. Provide an "instr" line that 4811 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4812 * This could be an ARM instruction or a function call. (If the result 4813 * comes back in a register other than r0, you can override "result".) 4814 * 4815 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4816 * vCC (r1). Useful for integer division and modulus. 4817 * 4818 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4819 * xor-long, add-double, sub-double, mul-double, div-double, 4820 * rem-double 4821 * 4822 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4823 */ 4824 /* binop vAA, vBB, vCC */ 4825 FETCH(r0, 1) @ r0<- CCBB 4826 mov r9, rINST, lsr #8 @ r9<- AA 4827 and r2, r0, #255 @ r2<- BB 4828 mov r3, r0, lsr #8 @ r3<- CC 4829 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4830 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4831 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4832 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4833 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4834 .if 0 4835 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4836 beq common_errDivideByZero 4837 .endif 4838 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4839 4840 orr r0, r0, r2 @ optional op; may set condition codes 4841 orr r1, r1, r3 @ result<- op, r0-r3 changed 4842 GET_INST_OPCODE(ip) @ extract opcode from rINST 4843 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4844 GOTO_OPCODE(ip) @ jump to next instruction 4845 /* 14-17 instructions */ 4846 4847 4848 4849/* ------------------------------ */ 4850 .balign 64 4851.L_OP_XOR_LONG: /* 0xa2 */ 4852/* File: armv5te/OP_XOR_LONG.S */ 4853/* File: armv5te/binopWide.S */ 4854 /* 4855 * Generic 64-bit binary operation. Provide an "instr" line that 4856 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4857 * This could be an ARM instruction or a function call. (If the result 4858 * comes back in a register other than r0, you can override "result".) 4859 * 4860 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4861 * vCC (r1). Useful for integer division and modulus. 4862 * 4863 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4864 * xor-long, add-double, sub-double, mul-double, div-double, 4865 * rem-double 4866 * 4867 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4868 */ 4869 /* binop vAA, vBB, vCC */ 4870 FETCH(r0, 1) @ r0<- CCBB 4871 mov r9, rINST, lsr #8 @ r9<- AA 4872 and r2, r0, #255 @ r2<- BB 4873 mov r3, r0, lsr #8 @ r3<- CC 4874 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4875 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4876 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4877 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4878 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4879 .if 0 4880 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4881 beq common_errDivideByZero 4882 .endif 4883 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4884 4885 eor r0, r0, r2 @ optional op; may set condition codes 4886 eor r1, r1, r3 @ result<- op, r0-r3 changed 4887 GET_INST_OPCODE(ip) @ extract opcode from rINST 4888 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4889 GOTO_OPCODE(ip) @ jump to next instruction 4890 /* 14-17 instructions */ 4891 4892 4893 4894/* ------------------------------ */ 4895 .balign 64 4896.L_OP_SHL_LONG: /* 0xa3 */ 4897/* File: armv5te/OP_SHL_LONG.S */ 4898 /* 4899 * Long integer shift. This is different from the generic 32/64-bit 4900 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4901 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4902 * 6 bits of the shift distance. 4903 */ 4904 /* shl-long vAA, vBB, vCC */ 4905 FETCH(r0, 1) @ r0<- CCBB 4906 mov r9, rINST, lsr #8 @ r9<- AA 4907 and r3, r0, #255 @ r3<- BB 4908 mov r0, r0, lsr #8 @ r0<- CC 4909 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4910 GET_VREG(r2, r0) @ r2<- vCC 4911 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4912 and r2, r2, #63 @ r2<- r2 & 0x3f 4913 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4914 4915 mov r1, r1, asl r2 @ r1<- r1 << r2 4916 rsb r3, r2, #32 @ r3<- 32 - r2 4917 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4918 subs ip, r2, #32 @ ip<- r2 - 32 4919 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4920 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4921 b .LOP_SHL_LONG_finish 4922 4923/* ------------------------------ */ 4924 .balign 64 4925.L_OP_SHR_LONG: /* 0xa4 */ 4926/* File: armv5te/OP_SHR_LONG.S */ 4927 /* 4928 * Long integer shift. This is different from the generic 32/64-bit 4929 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4930 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4931 * 6 bits of the shift distance. 4932 */ 4933 /* shr-long vAA, vBB, vCC */ 4934 FETCH(r0, 1) @ r0<- CCBB 4935 mov r9, rINST, lsr #8 @ r9<- AA 4936 and r3, r0, #255 @ r3<- BB 4937 mov r0, r0, lsr #8 @ r0<- CC 4938 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4939 GET_VREG(r2, r0) @ r2<- vCC 4940 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4941 and r2, r2, #63 @ r0<- r0 & 0x3f 4942 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4943 4944 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4945 rsb r3, r2, #32 @ r3<- 32 - r2 4946 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4947 subs ip, r2, #32 @ ip<- r2 - 32 4948 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4949 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4950 b .LOP_SHR_LONG_finish 4951 4952/* ------------------------------ */ 4953 .balign 64 4954.L_OP_USHR_LONG: /* 0xa5 */ 4955/* File: armv5te/OP_USHR_LONG.S */ 4956 /* 4957 * Long integer shift. This is different from the generic 32/64-bit 4958 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4959 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4960 * 6 bits of the shift distance. 4961 */ 4962 /* ushr-long vAA, vBB, vCC */ 4963 FETCH(r0, 1) @ r0<- CCBB 4964 mov r9, rINST, lsr #8 @ r9<- AA 4965 and r3, r0, #255 @ r3<- BB 4966 mov r0, r0, lsr #8 @ r0<- CC 4967 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4968 GET_VREG(r2, r0) @ r2<- vCC 4969 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4970 and r2, r2, #63 @ r0<- r0 & 0x3f 4971 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4972 4973 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4974 rsb r3, r2, #32 @ r3<- 32 - r2 4975 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4976 subs ip, r2, #32 @ ip<- r2 - 32 4977 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4978 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4979 b .LOP_USHR_LONG_finish 4980 4981/* ------------------------------ */ 4982 .balign 64 4983.L_OP_ADD_FLOAT: /* 0xa6 */ 4984/* File: arm-vfp/OP_ADD_FLOAT.S */ 4985/* File: arm-vfp/fbinop.S */ 4986 /* 4987 * Generic 32-bit floating-point operation. Provide an "instr" line that 4988 * specifies an instruction that performs "s2 = s0 op s1". Because we 4989 * use the "softfp" ABI, this must be an instruction, not a function call. 4990 * 4991 * For: add-float, sub-float, mul-float, div-float 4992 */ 4993 /* floatop vAA, vBB, vCC */ 4994 FETCH(r0, 1) @ r0<- CCBB 4995 mov r9, rINST, lsr #8 @ r9<- AA 4996 mov r3, r0, lsr #8 @ r3<- CC 4997 and r2, r0, #255 @ r2<- BB 4998 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4999 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5000 flds s1, [r3] @ s1<- vCC 5001 flds s0, [r2] @ s0<- vBB 5002 5003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5004 fadds s2, s0, s1 @ s2<- op 5005 GET_INST_OPCODE(ip) @ extract opcode from rINST 5006 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5007 fsts s2, [r9] @ vAA<- s2 5008 GOTO_OPCODE(ip) @ jump to next instruction 5009 5010 5011/* ------------------------------ */ 5012 .balign 64 5013.L_OP_SUB_FLOAT: /* 0xa7 */ 5014/* File: arm-vfp/OP_SUB_FLOAT.S */ 5015/* File: arm-vfp/fbinop.S */ 5016 /* 5017 * Generic 32-bit floating-point operation. Provide an "instr" line that 5018 * specifies an instruction that performs "s2 = s0 op s1". Because we 5019 * use the "softfp" ABI, this must be an instruction, not a function call. 5020 * 5021 * For: add-float, sub-float, mul-float, div-float 5022 */ 5023 /* floatop vAA, vBB, vCC */ 5024 FETCH(r0, 1) @ r0<- CCBB 5025 mov r9, rINST, lsr #8 @ r9<- AA 5026 mov r3, r0, lsr #8 @ r3<- CC 5027 and r2, r0, #255 @ r2<- BB 5028 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5029 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5030 flds s1, [r3] @ s1<- vCC 5031 flds s0, [r2] @ s0<- vBB 5032 5033 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5034 fsubs s2, s0, s1 @ s2<- op 5035 GET_INST_OPCODE(ip) @ extract opcode from rINST 5036 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5037 fsts s2, [r9] @ vAA<- s2 5038 GOTO_OPCODE(ip) @ jump to next instruction 5039 5040 5041/* ------------------------------ */ 5042 .balign 64 5043.L_OP_MUL_FLOAT: /* 0xa8 */ 5044/* File: arm-vfp/OP_MUL_FLOAT.S */ 5045/* File: arm-vfp/fbinop.S */ 5046 /* 5047 * Generic 32-bit floating-point operation. Provide an "instr" line that 5048 * specifies an instruction that performs "s2 = s0 op s1". Because we 5049 * use the "softfp" ABI, this must be an instruction, not a function call. 5050 * 5051 * For: add-float, sub-float, mul-float, div-float 5052 */ 5053 /* floatop vAA, vBB, vCC */ 5054 FETCH(r0, 1) @ r0<- CCBB 5055 mov r9, rINST, lsr #8 @ r9<- AA 5056 mov r3, r0, lsr #8 @ r3<- CC 5057 and r2, r0, #255 @ r2<- BB 5058 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5059 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5060 flds s1, [r3] @ s1<- vCC 5061 flds s0, [r2] @ s0<- vBB 5062 5063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5064 fmuls s2, s0, s1 @ s2<- op 5065 GET_INST_OPCODE(ip) @ extract opcode from rINST 5066 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5067 fsts s2, [r9] @ vAA<- s2 5068 GOTO_OPCODE(ip) @ jump to next instruction 5069 5070 5071/* ------------------------------ */ 5072 .balign 64 5073.L_OP_DIV_FLOAT: /* 0xa9 */ 5074/* File: arm-vfp/OP_DIV_FLOAT.S */ 5075/* File: arm-vfp/fbinop.S */ 5076 /* 5077 * Generic 32-bit floating-point operation. Provide an "instr" line that 5078 * specifies an instruction that performs "s2 = s0 op s1". Because we 5079 * use the "softfp" ABI, this must be an instruction, not a function call. 5080 * 5081 * For: add-float, sub-float, mul-float, div-float 5082 */ 5083 /* floatop vAA, vBB, vCC */ 5084 FETCH(r0, 1) @ r0<- CCBB 5085 mov r9, rINST, lsr #8 @ r9<- AA 5086 mov r3, r0, lsr #8 @ r3<- CC 5087 and r2, r0, #255 @ r2<- BB 5088 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5089 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5090 flds s1, [r3] @ s1<- vCC 5091 flds s0, [r2] @ s0<- vBB 5092 5093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5094 fdivs s2, s0, s1 @ s2<- op 5095 GET_INST_OPCODE(ip) @ extract opcode from rINST 5096 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5097 fsts s2, [r9] @ vAA<- s2 5098 GOTO_OPCODE(ip) @ jump to next instruction 5099 5100 5101/* ------------------------------ */ 5102 .balign 64 5103.L_OP_REM_FLOAT: /* 0xaa */ 5104/* File: armv5te/OP_REM_FLOAT.S */ 5105/* EABI doesn't define a float remainder function, but libm does */ 5106/* File: armv5te/binop.S */ 5107 /* 5108 * Generic 32-bit binary operation. Provide an "instr" line that 5109 * specifies an instruction that performs "result = r0 op r1". 5110 * This could be an ARM instruction or a function call. (If the result 5111 * comes back in a register other than r0, you can override "result".) 5112 * 5113 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5114 * vCC (r1). Useful for integer division and modulus. Note that we 5115 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5116 * handles it correctly. 5117 * 5118 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5119 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5120 * mul-float, div-float, rem-float 5121 */ 5122 /* binop vAA, vBB, vCC */ 5123 FETCH(r0, 1) @ r0<- CCBB 5124 mov r9, rINST, lsr #8 @ r9<- AA 5125 mov r3, r0, lsr #8 @ r3<- CC 5126 and r2, r0, #255 @ r2<- BB 5127 GET_VREG(r1, r3) @ r1<- vCC 5128 GET_VREG(r0, r2) @ r0<- vBB 5129 .if 0 5130 cmp r1, #0 @ is second operand zero? 5131 beq common_errDivideByZero 5132 .endif 5133 5134 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5135 @ optional op; may set condition codes 5136 bl fmodf @ r0<- op, r0-r3 changed 5137 GET_INST_OPCODE(ip) @ extract opcode from rINST 5138 SET_VREG(r0, r9) @ vAA<- r0 5139 GOTO_OPCODE(ip) @ jump to next instruction 5140 /* 11-14 instructions */ 5141 5142 5143 5144/* ------------------------------ */ 5145 .balign 64 5146.L_OP_ADD_DOUBLE: /* 0xab */ 5147/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5148/* File: arm-vfp/fbinopWide.S */ 5149 /* 5150 * Generic 64-bit double-precision floating point binary operation. 5151 * Provide an "instr" line that specifies an instruction that performs 5152 * "d2 = d0 op d1". 5153 * 5154 * for: add-double, sub-double, mul-double, div-double 5155 */ 5156 /* doubleop vAA, vBB, vCC */ 5157 FETCH(r0, 1) @ r0<- CCBB 5158 mov r9, rINST, lsr #8 @ r9<- AA 5159 mov r3, r0, lsr #8 @ r3<- CC 5160 and r2, r0, #255 @ r2<- BB 5161 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5162 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5163 fldd d1, [r3] @ d1<- vCC 5164 fldd d0, [r2] @ d0<- vBB 5165 5166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5167 faddd d2, d0, d1 @ s2<- op 5168 GET_INST_OPCODE(ip) @ extract opcode from rINST 5169 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5170 fstd d2, [r9] @ vAA<- d2 5171 GOTO_OPCODE(ip) @ jump to next instruction 5172 5173 5174/* ------------------------------ */ 5175 .balign 64 5176.L_OP_SUB_DOUBLE: /* 0xac */ 5177/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5178/* File: arm-vfp/fbinopWide.S */ 5179 /* 5180 * Generic 64-bit double-precision floating point binary operation. 5181 * Provide an "instr" line that specifies an instruction that performs 5182 * "d2 = d0 op d1". 5183 * 5184 * for: add-double, sub-double, mul-double, div-double 5185 */ 5186 /* doubleop vAA, vBB, vCC */ 5187 FETCH(r0, 1) @ r0<- CCBB 5188 mov r9, rINST, lsr #8 @ r9<- AA 5189 mov r3, r0, lsr #8 @ r3<- CC 5190 and r2, r0, #255 @ r2<- BB 5191 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5192 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5193 fldd d1, [r3] @ d1<- vCC 5194 fldd d0, [r2] @ d0<- vBB 5195 5196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5197 fsubd d2, d0, d1 @ s2<- op 5198 GET_INST_OPCODE(ip) @ extract opcode from rINST 5199 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5200 fstd d2, [r9] @ vAA<- d2 5201 GOTO_OPCODE(ip) @ jump to next instruction 5202 5203 5204/* ------------------------------ */ 5205 .balign 64 5206.L_OP_MUL_DOUBLE: /* 0xad */ 5207/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5208/* File: arm-vfp/fbinopWide.S */ 5209 /* 5210 * Generic 64-bit double-precision floating point binary operation. 5211 * Provide an "instr" line that specifies an instruction that performs 5212 * "d2 = d0 op d1". 5213 * 5214 * for: add-double, sub-double, mul-double, div-double 5215 */ 5216 /* doubleop vAA, vBB, vCC */ 5217 FETCH(r0, 1) @ r0<- CCBB 5218 mov r9, rINST, lsr #8 @ r9<- AA 5219 mov r3, r0, lsr #8 @ r3<- CC 5220 and r2, r0, #255 @ r2<- BB 5221 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5222 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5223 fldd d1, [r3] @ d1<- vCC 5224 fldd d0, [r2] @ d0<- vBB 5225 5226 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5227 fmuld d2, d0, d1 @ s2<- op 5228 GET_INST_OPCODE(ip) @ extract opcode from rINST 5229 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5230 fstd d2, [r9] @ vAA<- d2 5231 GOTO_OPCODE(ip) @ jump to next instruction 5232 5233 5234/* ------------------------------ */ 5235 .balign 64 5236.L_OP_DIV_DOUBLE: /* 0xae */ 5237/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5238/* File: arm-vfp/fbinopWide.S */ 5239 /* 5240 * Generic 64-bit double-precision floating point binary operation. 5241 * Provide an "instr" line that specifies an instruction that performs 5242 * "d2 = d0 op d1". 5243 * 5244 * for: add-double, sub-double, mul-double, div-double 5245 */ 5246 /* doubleop vAA, vBB, vCC */ 5247 FETCH(r0, 1) @ r0<- CCBB 5248 mov r9, rINST, lsr #8 @ r9<- AA 5249 mov r3, r0, lsr #8 @ r3<- CC 5250 and r2, r0, #255 @ r2<- BB 5251 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5252 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5253 fldd d1, [r3] @ d1<- vCC 5254 fldd d0, [r2] @ d0<- vBB 5255 5256 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5257 fdivd d2, d0, d1 @ s2<- op 5258 GET_INST_OPCODE(ip) @ extract opcode from rINST 5259 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5260 fstd d2, [r9] @ vAA<- d2 5261 GOTO_OPCODE(ip) @ jump to next instruction 5262 5263 5264/* ------------------------------ */ 5265 .balign 64 5266.L_OP_REM_DOUBLE: /* 0xaf */ 5267/* File: armv5te/OP_REM_DOUBLE.S */ 5268/* EABI doesn't define a double remainder function, but libm does */ 5269/* File: armv5te/binopWide.S */ 5270 /* 5271 * Generic 64-bit binary operation. Provide an "instr" line that 5272 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5273 * This could be an ARM instruction or a function call. (If the result 5274 * comes back in a register other than r0, you can override "result".) 5275 * 5276 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5277 * vCC (r1). Useful for integer division and modulus. 5278 * 5279 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5280 * xor-long, add-double, sub-double, mul-double, div-double, 5281 * rem-double 5282 * 5283 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5284 */ 5285 /* binop vAA, vBB, vCC */ 5286 FETCH(r0, 1) @ r0<- CCBB 5287 mov r9, rINST, lsr #8 @ r9<- AA 5288 and r2, r0, #255 @ r2<- BB 5289 mov r3, r0, lsr #8 @ r3<- CC 5290 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5291 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5292 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5293 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5294 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5295 .if 0 5296 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5297 beq common_errDivideByZero 5298 .endif 5299 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5300 5301 @ optional op; may set condition codes 5302 bl fmod @ result<- op, r0-r3 changed 5303 GET_INST_OPCODE(ip) @ extract opcode from rINST 5304 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5305 GOTO_OPCODE(ip) @ jump to next instruction 5306 /* 14-17 instructions */ 5307 5308 5309 5310/* ------------------------------ */ 5311 .balign 64 5312.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5313/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5314/* File: armv5te/binop2addr.S */ 5315 /* 5316 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5317 * that specifies an instruction that performs "result = r0 op r1". 5318 * This could be an ARM instruction or a function call. (If the result 5319 * comes back in a register other than r0, you can override "result".) 5320 * 5321 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5322 * vCC (r1). Useful for integer division and modulus. 5323 * 5324 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5325 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5326 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5327 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5328 */ 5329 /* binop/2addr vA, vB */ 5330 mov r9, rINST, lsr #8 @ r9<- A+ 5331 mov r3, rINST, lsr #12 @ r3<- B 5332 and r9, r9, #15 5333 GET_VREG(r1, r3) @ r1<- vB 5334 GET_VREG(r0, r9) @ r0<- vA 5335 .if 0 5336 cmp r1, #0 @ is second operand zero? 5337 beq common_errDivideByZero 5338 .endif 5339 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5340 5341 @ optional op; may set condition codes 5342 add r0, r0, r1 @ r0<- op, r0-r3 changed 5343 GET_INST_OPCODE(ip) @ extract opcode from rINST 5344 SET_VREG(r0, r9) @ vAA<- r0 5345 GOTO_OPCODE(ip) @ jump to next instruction 5346 /* 10-13 instructions */ 5347 5348 5349 5350/* ------------------------------ */ 5351 .balign 64 5352.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5353/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5354/* File: armv5te/binop2addr.S */ 5355 /* 5356 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5357 * that specifies an instruction that performs "result = r0 op r1". 5358 * This could be an ARM instruction or a function call. (If the result 5359 * comes back in a register other than r0, you can override "result".) 5360 * 5361 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5362 * vCC (r1). Useful for integer division and modulus. 5363 * 5364 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5365 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5366 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5367 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5368 */ 5369 /* binop/2addr vA, vB */ 5370 mov r9, rINST, lsr #8 @ r9<- A+ 5371 mov r3, rINST, lsr #12 @ r3<- B 5372 and r9, r9, #15 5373 GET_VREG(r1, r3) @ r1<- vB 5374 GET_VREG(r0, r9) @ r0<- vA 5375 .if 0 5376 cmp r1, #0 @ is second operand zero? 5377 beq common_errDivideByZero 5378 .endif 5379 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5380 5381 @ optional op; may set condition codes 5382 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5383 GET_INST_OPCODE(ip) @ extract opcode from rINST 5384 SET_VREG(r0, r9) @ vAA<- r0 5385 GOTO_OPCODE(ip) @ jump to next instruction 5386 /* 10-13 instructions */ 5387 5388 5389 5390/* ------------------------------ */ 5391 .balign 64 5392.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5393/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5394/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5395/* File: armv5te/binop2addr.S */ 5396 /* 5397 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5398 * that specifies an instruction that performs "result = r0 op r1". 5399 * This could be an ARM instruction or a function call. (If the result 5400 * comes back in a register other than r0, you can override "result".) 5401 * 5402 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5403 * vCC (r1). Useful for integer division and modulus. 5404 * 5405 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5406 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5407 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5408 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5409 */ 5410 /* binop/2addr vA, vB */ 5411 mov r9, rINST, lsr #8 @ r9<- A+ 5412 mov r3, rINST, lsr #12 @ r3<- B 5413 and r9, r9, #15 5414 GET_VREG(r1, r3) @ r1<- vB 5415 GET_VREG(r0, r9) @ r0<- vA 5416 .if 0 5417 cmp r1, #0 @ is second operand zero? 5418 beq common_errDivideByZero 5419 .endif 5420 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5421 5422 @ optional op; may set condition codes 5423 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5424 GET_INST_OPCODE(ip) @ extract opcode from rINST 5425 SET_VREG(r0, r9) @ vAA<- r0 5426 GOTO_OPCODE(ip) @ jump to next instruction 5427 /* 10-13 instructions */ 5428 5429 5430 5431/* ------------------------------ */ 5432 .balign 64 5433.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5434/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5435/* File: armv5te/binop2addr.S */ 5436 /* 5437 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5438 * that specifies an instruction that performs "result = r0 op r1". 5439 * This could be an ARM instruction or a function call. (If the result 5440 * comes back in a register other than r0, you can override "result".) 5441 * 5442 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5443 * vCC (r1). Useful for integer division and modulus. 5444 * 5445 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5446 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5447 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5448 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5449 */ 5450 /* binop/2addr vA, vB */ 5451 mov r9, rINST, lsr #8 @ r9<- A+ 5452 mov r3, rINST, lsr #12 @ r3<- B 5453 and r9, r9, #15 5454 GET_VREG(r1, r3) @ r1<- vB 5455 GET_VREG(r0, r9) @ r0<- vA 5456 .if 1 5457 cmp r1, #0 @ is second operand zero? 5458 beq common_errDivideByZero 5459 .endif 5460 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5461 5462 @ optional op; may set condition codes 5463 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5464 GET_INST_OPCODE(ip) @ extract opcode from rINST 5465 SET_VREG(r0, r9) @ vAA<- r0 5466 GOTO_OPCODE(ip) @ jump to next instruction 5467 /* 10-13 instructions */ 5468 5469 5470 5471/* ------------------------------ */ 5472 .balign 64 5473.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5474/* File: armv5te/OP_REM_INT_2ADDR.S */ 5475/* idivmod returns quotient in r0 and remainder in r1 */ 5476/* File: armv5te/binop2addr.S */ 5477 /* 5478 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5479 * that specifies an instruction that performs "result = r0 op r1". 5480 * This could be an ARM instruction or a function call. (If the result 5481 * comes back in a register other than r0, you can override "result".) 5482 * 5483 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5484 * vCC (r1). Useful for integer division and modulus. 5485 * 5486 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5487 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5488 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5489 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5490 */ 5491 /* binop/2addr vA, vB */ 5492 mov r9, rINST, lsr #8 @ r9<- A+ 5493 mov r3, rINST, lsr #12 @ r3<- B 5494 and r9, r9, #15 5495 GET_VREG(r1, r3) @ r1<- vB 5496 GET_VREG(r0, r9) @ r0<- vA 5497 .if 1 5498 cmp r1, #0 @ is second operand zero? 5499 beq common_errDivideByZero 5500 .endif 5501 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5502 5503 @ optional op; may set condition codes 5504 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5505 GET_INST_OPCODE(ip) @ extract opcode from rINST 5506 SET_VREG(r1, r9) @ vAA<- r1 5507 GOTO_OPCODE(ip) @ jump to next instruction 5508 /* 10-13 instructions */ 5509 5510 5511 5512/* ------------------------------ */ 5513 .balign 64 5514.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5515/* File: armv5te/OP_AND_INT_2ADDR.S */ 5516/* File: armv5te/binop2addr.S */ 5517 /* 5518 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5519 * that specifies an instruction that performs "result = r0 op r1". 5520 * This could be an ARM instruction or a function call. (If the result 5521 * comes back in a register other than r0, you can override "result".) 5522 * 5523 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5524 * vCC (r1). Useful for integer division and modulus. 5525 * 5526 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5527 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5528 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5529 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5530 */ 5531 /* binop/2addr vA, vB */ 5532 mov r9, rINST, lsr #8 @ r9<- A+ 5533 mov r3, rINST, lsr #12 @ r3<- B 5534 and r9, r9, #15 5535 GET_VREG(r1, r3) @ r1<- vB 5536 GET_VREG(r0, r9) @ r0<- vA 5537 .if 0 5538 cmp r1, #0 @ is second operand zero? 5539 beq common_errDivideByZero 5540 .endif 5541 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5542 5543 @ optional op; may set condition codes 5544 and r0, r0, r1 @ r0<- op, r0-r3 changed 5545 GET_INST_OPCODE(ip) @ extract opcode from rINST 5546 SET_VREG(r0, r9) @ vAA<- r0 5547 GOTO_OPCODE(ip) @ jump to next instruction 5548 /* 10-13 instructions */ 5549 5550 5551 5552/* ------------------------------ */ 5553 .balign 64 5554.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5555/* File: armv5te/OP_OR_INT_2ADDR.S */ 5556/* File: armv5te/binop2addr.S */ 5557 /* 5558 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5559 * that specifies an instruction that performs "result = r0 op r1". 5560 * This could be an ARM instruction or a function call. (If the result 5561 * comes back in a register other than r0, you can override "result".) 5562 * 5563 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5564 * vCC (r1). Useful for integer division and modulus. 5565 * 5566 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5567 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5568 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5569 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5570 */ 5571 /* binop/2addr vA, vB */ 5572 mov r9, rINST, lsr #8 @ r9<- A+ 5573 mov r3, rINST, lsr #12 @ r3<- B 5574 and r9, r9, #15 5575 GET_VREG(r1, r3) @ r1<- vB 5576 GET_VREG(r0, r9) @ r0<- vA 5577 .if 0 5578 cmp r1, #0 @ is second operand zero? 5579 beq common_errDivideByZero 5580 .endif 5581 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5582 5583 @ optional op; may set condition codes 5584 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5585 GET_INST_OPCODE(ip) @ extract opcode from rINST 5586 SET_VREG(r0, r9) @ vAA<- r0 5587 GOTO_OPCODE(ip) @ jump to next instruction 5588 /* 10-13 instructions */ 5589 5590 5591 5592/* ------------------------------ */ 5593 .balign 64 5594.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5595/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5596/* File: armv5te/binop2addr.S */ 5597 /* 5598 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5599 * that specifies an instruction that performs "result = r0 op r1". 5600 * This could be an ARM instruction or a function call. (If the result 5601 * comes back in a register other than r0, you can override "result".) 5602 * 5603 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5604 * vCC (r1). Useful for integer division and modulus. 5605 * 5606 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5607 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5608 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5609 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5610 */ 5611 /* binop/2addr vA, vB */ 5612 mov r9, rINST, lsr #8 @ r9<- A+ 5613 mov r3, rINST, lsr #12 @ r3<- B 5614 and r9, r9, #15 5615 GET_VREG(r1, r3) @ r1<- vB 5616 GET_VREG(r0, r9) @ r0<- vA 5617 .if 0 5618 cmp r1, #0 @ is second operand zero? 5619 beq common_errDivideByZero 5620 .endif 5621 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5622 5623 @ optional op; may set condition codes 5624 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5625 GET_INST_OPCODE(ip) @ extract opcode from rINST 5626 SET_VREG(r0, r9) @ vAA<- r0 5627 GOTO_OPCODE(ip) @ jump to next instruction 5628 /* 10-13 instructions */ 5629 5630 5631 5632/* ------------------------------ */ 5633 .balign 64 5634.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5635/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5636/* File: armv5te/binop2addr.S */ 5637 /* 5638 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5639 * that specifies an instruction that performs "result = r0 op r1". 5640 * This could be an ARM instruction or a function call. (If the result 5641 * comes back in a register other than r0, you can override "result".) 5642 * 5643 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5644 * vCC (r1). Useful for integer division and modulus. 5645 * 5646 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5647 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5648 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5649 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5650 */ 5651 /* binop/2addr vA, vB */ 5652 mov r9, rINST, lsr #8 @ r9<- A+ 5653 mov r3, rINST, lsr #12 @ r3<- B 5654 and r9, r9, #15 5655 GET_VREG(r1, r3) @ r1<- vB 5656 GET_VREG(r0, r9) @ r0<- vA 5657 .if 0 5658 cmp r1, #0 @ is second operand zero? 5659 beq common_errDivideByZero 5660 .endif 5661 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5662 5663 and r1, r1, #31 @ optional op; may set condition codes 5664 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5665 GET_INST_OPCODE(ip) @ extract opcode from rINST 5666 SET_VREG(r0, r9) @ vAA<- r0 5667 GOTO_OPCODE(ip) @ jump to next instruction 5668 /* 10-13 instructions */ 5669 5670 5671 5672/* ------------------------------ */ 5673 .balign 64 5674.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5675/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5676/* File: armv5te/binop2addr.S */ 5677 /* 5678 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5679 * that specifies an instruction that performs "result = r0 op r1". 5680 * This could be an ARM instruction or a function call. (If the result 5681 * comes back in a register other than r0, you can override "result".) 5682 * 5683 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5684 * vCC (r1). Useful for integer division and modulus. 5685 * 5686 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5687 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5688 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5689 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5690 */ 5691 /* binop/2addr vA, vB */ 5692 mov r9, rINST, lsr #8 @ r9<- A+ 5693 mov r3, rINST, lsr #12 @ r3<- B 5694 and r9, r9, #15 5695 GET_VREG(r1, r3) @ r1<- vB 5696 GET_VREG(r0, r9) @ r0<- vA 5697 .if 0 5698 cmp r1, #0 @ is second operand zero? 5699 beq common_errDivideByZero 5700 .endif 5701 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5702 5703 and r1, r1, #31 @ optional op; may set condition codes 5704 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5705 GET_INST_OPCODE(ip) @ extract opcode from rINST 5706 SET_VREG(r0, r9) @ vAA<- r0 5707 GOTO_OPCODE(ip) @ jump to next instruction 5708 /* 10-13 instructions */ 5709 5710 5711 5712/* ------------------------------ */ 5713 .balign 64 5714.L_OP_USHR_INT_2ADDR: /* 0xba */ 5715/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5716/* File: armv5te/binop2addr.S */ 5717 /* 5718 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5719 * that specifies an instruction that performs "result = r0 op r1". 5720 * This could be an ARM instruction or a function call. (If the result 5721 * comes back in a register other than r0, you can override "result".) 5722 * 5723 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5724 * vCC (r1). Useful for integer division and modulus. 5725 * 5726 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5727 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5728 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5729 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5730 */ 5731 /* binop/2addr vA, vB */ 5732 mov r9, rINST, lsr #8 @ r9<- A+ 5733 mov r3, rINST, lsr #12 @ r3<- B 5734 and r9, r9, #15 5735 GET_VREG(r1, r3) @ r1<- vB 5736 GET_VREG(r0, r9) @ r0<- vA 5737 .if 0 5738 cmp r1, #0 @ is second operand zero? 5739 beq common_errDivideByZero 5740 .endif 5741 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5742 5743 and r1, r1, #31 @ optional op; may set condition codes 5744 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5745 GET_INST_OPCODE(ip) @ extract opcode from rINST 5746 SET_VREG(r0, r9) @ vAA<- r0 5747 GOTO_OPCODE(ip) @ jump to next instruction 5748 /* 10-13 instructions */ 5749 5750 5751 5752/* ------------------------------ */ 5753 .balign 64 5754.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5755/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5756/* File: armv5te/binopWide2addr.S */ 5757 /* 5758 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5759 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5760 * This could be an ARM instruction or a function call. (If the result 5761 * comes back in a register other than r0, you can override "result".) 5762 * 5763 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5764 * vCC (r1). Useful for integer division and modulus. 5765 * 5766 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5767 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5768 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5769 * rem-double/2addr 5770 */ 5771 /* binop/2addr vA, vB */ 5772 mov r9, rINST, lsr #8 @ r9<- A+ 5773 mov r1, rINST, lsr #12 @ r1<- B 5774 and r9, r9, #15 5775 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5776 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5777 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5778 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5779 .if 0 5780 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5781 beq common_errDivideByZero 5782 .endif 5783 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5784 5785 adds r0, r0, r2 @ optional op; may set condition codes 5786 adc r1, r1, r3 @ result<- op, r0-r3 changed 5787 GET_INST_OPCODE(ip) @ extract opcode from rINST 5788 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5789 GOTO_OPCODE(ip) @ jump to next instruction 5790 /* 12-15 instructions */ 5791 5792 5793 5794/* ------------------------------ */ 5795 .balign 64 5796.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5797/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5798/* File: armv5te/binopWide2addr.S */ 5799 /* 5800 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5801 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5802 * This could be an ARM instruction or a function call. (If the result 5803 * comes back in a register other than r0, you can override "result".) 5804 * 5805 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5806 * vCC (r1). Useful for integer division and modulus. 5807 * 5808 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5809 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5810 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5811 * rem-double/2addr 5812 */ 5813 /* binop/2addr vA, vB */ 5814 mov r9, rINST, lsr #8 @ r9<- A+ 5815 mov r1, rINST, lsr #12 @ r1<- B 5816 and r9, r9, #15 5817 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5818 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5819 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5820 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5821 .if 0 5822 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5823 beq common_errDivideByZero 5824 .endif 5825 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5826 5827 subs r0, r0, r2 @ optional op; may set condition codes 5828 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5829 GET_INST_OPCODE(ip) @ extract opcode from rINST 5830 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5831 GOTO_OPCODE(ip) @ jump to next instruction 5832 /* 12-15 instructions */ 5833 5834 5835 5836/* ------------------------------ */ 5837 .balign 64 5838.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5839/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5840 /* 5841 * Signed 64-bit integer multiply, "/2addr" version. 5842 * 5843 * See OP_MUL_LONG for an explanation. 5844 * 5845 * We get a little tight on registers, so to avoid looking up &fp[A] 5846 * again we stuff it into rINST. 5847 */ 5848 /* mul-long/2addr vA, vB */ 5849 mov r9, rINST, lsr #8 @ r9<- A+ 5850 mov r1, rINST, lsr #12 @ r1<- B 5851 and r9, r9, #15 5852 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5853 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5854 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5855 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5856 mul ip, r2, r1 @ ip<- ZxW 5857 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5858 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5859 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5860 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5861 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5862 GET_INST_OPCODE(ip) @ extract opcode from rINST 5863 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5864 GOTO_OPCODE(ip) @ jump to next instruction 5865 5866 5867/* ------------------------------ */ 5868 .balign 64 5869.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5870/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5871/* File: armv5te/binopWide2addr.S */ 5872 /* 5873 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5874 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5875 * This could be an ARM instruction or a function call. (If the result 5876 * comes back in a register other than r0, you can override "result".) 5877 * 5878 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5879 * vCC (r1). Useful for integer division and modulus. 5880 * 5881 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5882 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5883 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5884 * rem-double/2addr 5885 */ 5886 /* binop/2addr vA, vB */ 5887 mov r9, rINST, lsr #8 @ r9<- A+ 5888 mov r1, rINST, lsr #12 @ r1<- B 5889 and r9, r9, #15 5890 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5891 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5892 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5893 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5894 .if 1 5895 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5896 beq common_errDivideByZero 5897 .endif 5898 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5899 5900 @ optional op; may set condition codes 5901 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5902 GET_INST_OPCODE(ip) @ extract opcode from rINST 5903 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5904 GOTO_OPCODE(ip) @ jump to next instruction 5905 /* 12-15 instructions */ 5906 5907 5908 5909/* ------------------------------ */ 5910 .balign 64 5911.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5912/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5913/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5914/* File: armv5te/binopWide2addr.S */ 5915 /* 5916 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5917 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5918 * This could be an ARM instruction or a function call. (If the result 5919 * comes back in a register other than r0, you can override "result".) 5920 * 5921 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5922 * vCC (r1). Useful for integer division and modulus. 5923 * 5924 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5925 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5926 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5927 * rem-double/2addr 5928 */ 5929 /* binop/2addr vA, vB */ 5930 mov r9, rINST, lsr #8 @ r9<- A+ 5931 mov r1, rINST, lsr #12 @ r1<- B 5932 and r9, r9, #15 5933 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5934 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5935 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5936 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5937 .if 1 5938 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5939 beq common_errDivideByZero 5940 .endif 5941 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5942 5943 @ optional op; may set condition codes 5944 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5945 GET_INST_OPCODE(ip) @ extract opcode from rINST 5946 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5947 GOTO_OPCODE(ip) @ jump to next instruction 5948 /* 12-15 instructions */ 5949 5950 5951 5952/* ------------------------------ */ 5953 .balign 64 5954.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5955/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5956/* File: armv5te/binopWide2addr.S */ 5957 /* 5958 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5959 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5960 * This could be an ARM instruction or a function call. (If the result 5961 * comes back in a register other than r0, you can override "result".) 5962 * 5963 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5964 * vCC (r1). Useful for integer division and modulus. 5965 * 5966 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5967 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5968 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5969 * rem-double/2addr 5970 */ 5971 /* binop/2addr vA, vB */ 5972 mov r9, rINST, lsr #8 @ r9<- A+ 5973 mov r1, rINST, lsr #12 @ r1<- B 5974 and r9, r9, #15 5975 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5976 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5977 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5978 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5979 .if 0 5980 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5981 beq common_errDivideByZero 5982 .endif 5983 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5984 5985 and r0, r0, r2 @ optional op; may set condition codes 5986 and r1, r1, r3 @ result<- op, r0-r3 changed 5987 GET_INST_OPCODE(ip) @ extract opcode from rINST 5988 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5989 GOTO_OPCODE(ip) @ jump to next instruction 5990 /* 12-15 instructions */ 5991 5992 5993 5994/* ------------------------------ */ 5995 .balign 64 5996.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5997/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5998/* File: armv5te/binopWide2addr.S */ 5999 /* 6000 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6001 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6002 * This could be an ARM instruction or a function call. (If the result 6003 * comes back in a register other than r0, you can override "result".) 6004 * 6005 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6006 * vCC (r1). Useful for integer division and modulus. 6007 * 6008 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6009 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6010 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6011 * rem-double/2addr 6012 */ 6013 /* binop/2addr vA, vB */ 6014 mov r9, rINST, lsr #8 @ r9<- A+ 6015 mov r1, rINST, lsr #12 @ r1<- B 6016 and r9, r9, #15 6017 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6018 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6019 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6020 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6021 .if 0 6022 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6023 beq common_errDivideByZero 6024 .endif 6025 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6026 6027 orr r0, r0, r2 @ optional op; may set condition codes 6028 orr r1, r1, r3 @ result<- op, r0-r3 changed 6029 GET_INST_OPCODE(ip) @ extract opcode from rINST 6030 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6031 GOTO_OPCODE(ip) @ jump to next instruction 6032 /* 12-15 instructions */ 6033 6034 6035 6036/* ------------------------------ */ 6037 .balign 64 6038.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6039/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6040/* File: armv5te/binopWide2addr.S */ 6041 /* 6042 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6043 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6044 * This could be an ARM instruction or a function call. (If the result 6045 * comes back in a register other than r0, you can override "result".) 6046 * 6047 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6048 * vCC (r1). Useful for integer division and modulus. 6049 * 6050 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6051 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6052 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6053 * rem-double/2addr 6054 */ 6055 /* binop/2addr vA, vB */ 6056 mov r9, rINST, lsr #8 @ r9<- A+ 6057 mov r1, rINST, lsr #12 @ r1<- B 6058 and r9, r9, #15 6059 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6060 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6061 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6062 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6063 .if 0 6064 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6065 beq common_errDivideByZero 6066 .endif 6067 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6068 6069 eor r0, r0, r2 @ optional op; may set condition codes 6070 eor r1, r1, r3 @ result<- op, r0-r3 changed 6071 GET_INST_OPCODE(ip) @ extract opcode from rINST 6072 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6073 GOTO_OPCODE(ip) @ jump to next instruction 6074 /* 12-15 instructions */ 6075 6076 6077 6078/* ------------------------------ */ 6079 .balign 64 6080.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6081/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6082 /* 6083 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6084 * 32-bit shift distance. 6085 */ 6086 /* shl-long/2addr vA, vB */ 6087 mov r9, rINST, lsr #8 @ r9<- A+ 6088 mov r3, rINST, lsr #12 @ r3<- B 6089 and r9, r9, #15 6090 GET_VREG(r2, r3) @ r2<- vB 6091 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6092 and r2, r2, #63 @ r2<- r2 & 0x3f 6093 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6094 6095 mov r1, r1, asl r2 @ r1<- r1 << r2 6096 rsb r3, r2, #32 @ r3<- 32 - r2 6097 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6098 subs ip, r2, #32 @ ip<- r2 - 32 6099 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6100 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6101 mov r0, r0, asl r2 @ r0<- r0 << r2 6102 b .LOP_SHL_LONG_2ADDR_finish 6103 6104/* ------------------------------ */ 6105 .balign 64 6106.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6107/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6108 /* 6109 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6110 * 32-bit shift distance. 6111 */ 6112 /* shr-long/2addr vA, vB */ 6113 mov r9, rINST, lsr #8 @ r9<- A+ 6114 mov r3, rINST, lsr #12 @ r3<- B 6115 and r9, r9, #15 6116 GET_VREG(r2, r3) @ r2<- vB 6117 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6118 and r2, r2, #63 @ r2<- r2 & 0x3f 6119 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6120 6121 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6122 rsb r3, r2, #32 @ r3<- 32 - r2 6123 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6124 subs ip, r2, #32 @ ip<- r2 - 32 6125 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6126 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6127 mov r1, r1, asr r2 @ r1<- r1 >> r2 6128 b .LOP_SHR_LONG_2ADDR_finish 6129 6130/* ------------------------------ */ 6131 .balign 64 6132.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6133/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6134 /* 6135 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6136 * 32-bit shift distance. 6137 */ 6138 /* ushr-long/2addr vA, vB */ 6139 mov r9, rINST, lsr #8 @ r9<- A+ 6140 mov r3, rINST, lsr #12 @ r3<- B 6141 and r9, r9, #15 6142 GET_VREG(r2, r3) @ r2<- vB 6143 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6144 and r2, r2, #63 @ r2<- r2 & 0x3f 6145 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6146 6147 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6148 rsb r3, r2, #32 @ r3<- 32 - r2 6149 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6150 subs ip, r2, #32 @ ip<- r2 - 32 6151 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6152 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6153 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6154 b .LOP_USHR_LONG_2ADDR_finish 6155 6156/* ------------------------------ */ 6157 .balign 64 6158.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6159/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6160/* File: arm-vfp/fbinop2addr.S */ 6161 /* 6162 * Generic 32-bit floating point "/2addr" binary operation. Provide 6163 * an "instr" line that specifies an instruction that performs 6164 * "s2 = s0 op s1". 6165 * 6166 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6167 */ 6168 /* binop/2addr vA, vB */ 6169 mov r3, rINST, lsr #12 @ r3<- B 6170 mov r9, rINST, lsr #8 @ r9<- A+ 6171 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6172 and r9, r9, #15 @ r9<- A 6173 flds s1, [r3] @ s1<- vB 6174 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6175 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6176 flds s0, [r9] @ s0<- vA 6177 6178 fadds s2, s0, s1 @ s2<- op 6179 GET_INST_OPCODE(ip) @ extract opcode from rINST 6180 fsts s2, [r9] @ vAA<- s2 6181 GOTO_OPCODE(ip) @ jump to next instruction 6182 6183 6184/* ------------------------------ */ 6185 .balign 64 6186.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6187/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6188/* File: arm-vfp/fbinop2addr.S */ 6189 /* 6190 * Generic 32-bit floating point "/2addr" binary operation. Provide 6191 * an "instr" line that specifies an instruction that performs 6192 * "s2 = s0 op s1". 6193 * 6194 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6195 */ 6196 /* binop/2addr vA, vB */ 6197 mov r3, rINST, lsr #12 @ r3<- B 6198 mov r9, rINST, lsr #8 @ r9<- A+ 6199 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6200 and r9, r9, #15 @ r9<- A 6201 flds s1, [r3] @ s1<- vB 6202 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6203 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6204 flds s0, [r9] @ s0<- vA 6205 6206 fsubs s2, s0, s1 @ s2<- op 6207 GET_INST_OPCODE(ip) @ extract opcode from rINST 6208 fsts s2, [r9] @ vAA<- s2 6209 GOTO_OPCODE(ip) @ jump to next instruction 6210 6211 6212/* ------------------------------ */ 6213 .balign 64 6214.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6215/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6216/* File: arm-vfp/fbinop2addr.S */ 6217 /* 6218 * Generic 32-bit floating point "/2addr" binary operation. Provide 6219 * an "instr" line that specifies an instruction that performs 6220 * "s2 = s0 op s1". 6221 * 6222 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6223 */ 6224 /* binop/2addr vA, vB */ 6225 mov r3, rINST, lsr #12 @ r3<- B 6226 mov r9, rINST, lsr #8 @ r9<- A+ 6227 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6228 and r9, r9, #15 @ r9<- A 6229 flds s1, [r3] @ s1<- vB 6230 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6231 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6232 flds s0, [r9] @ s0<- vA 6233 6234 fmuls s2, s0, s1 @ s2<- op 6235 GET_INST_OPCODE(ip) @ extract opcode from rINST 6236 fsts s2, [r9] @ vAA<- s2 6237 GOTO_OPCODE(ip) @ jump to next instruction 6238 6239 6240/* ------------------------------ */ 6241 .balign 64 6242.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6243/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6244/* File: arm-vfp/fbinop2addr.S */ 6245 /* 6246 * Generic 32-bit floating point "/2addr" binary operation. Provide 6247 * an "instr" line that specifies an instruction that performs 6248 * "s2 = s0 op s1". 6249 * 6250 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6251 */ 6252 /* binop/2addr vA, vB */ 6253 mov r3, rINST, lsr #12 @ r3<- B 6254 mov r9, rINST, lsr #8 @ r9<- A+ 6255 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6256 and r9, r9, #15 @ r9<- A 6257 flds s1, [r3] @ s1<- vB 6258 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6259 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6260 flds s0, [r9] @ s0<- vA 6261 6262 fdivs s2, s0, s1 @ s2<- op 6263 GET_INST_OPCODE(ip) @ extract opcode from rINST 6264 fsts s2, [r9] @ vAA<- s2 6265 GOTO_OPCODE(ip) @ jump to next instruction 6266 6267 6268/* ------------------------------ */ 6269 .balign 64 6270.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6271/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6272/* EABI doesn't define a float remainder function, but libm does */ 6273/* File: armv5te/binop2addr.S */ 6274 /* 6275 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6276 * that specifies an instruction that performs "result = r0 op r1". 6277 * This could be an ARM instruction or a function call. (If the result 6278 * comes back in a register other than r0, you can override "result".) 6279 * 6280 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6281 * vCC (r1). Useful for integer division and modulus. 6282 * 6283 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6284 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6285 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6286 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6287 */ 6288 /* binop/2addr vA, vB */ 6289 mov r9, rINST, lsr #8 @ r9<- A+ 6290 mov r3, rINST, lsr #12 @ r3<- B 6291 and r9, r9, #15 6292 GET_VREG(r1, r3) @ r1<- vB 6293 GET_VREG(r0, r9) @ r0<- vA 6294 .if 0 6295 cmp r1, #0 @ is second operand zero? 6296 beq common_errDivideByZero 6297 .endif 6298 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6299 6300 @ optional op; may set condition codes 6301 bl fmodf @ r0<- op, r0-r3 changed 6302 GET_INST_OPCODE(ip) @ extract opcode from rINST 6303 SET_VREG(r0, r9) @ vAA<- r0 6304 GOTO_OPCODE(ip) @ jump to next instruction 6305 /* 10-13 instructions */ 6306 6307 6308 6309/* ------------------------------ */ 6310 .balign 64 6311.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6312/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6313/* File: arm-vfp/fbinopWide2addr.S */ 6314 /* 6315 * Generic 64-bit floating point "/2addr" binary operation. Provide 6316 * an "instr" line that specifies an instruction that performs 6317 * "d2 = d0 op d1". 6318 * 6319 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6320 * div-double/2addr 6321 */ 6322 /* binop/2addr vA, vB */ 6323 mov r3, rINST, lsr #12 @ r3<- B 6324 mov r9, rINST, lsr #8 @ r9<- A+ 6325 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6326 and r9, r9, #15 @ r9<- A 6327 fldd d1, [r3] @ d1<- vB 6328 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6329 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6330 fldd d0, [r9] @ d0<- vA 6331 6332 faddd d2, d0, d1 @ d2<- op 6333 GET_INST_OPCODE(ip) @ extract opcode from rINST 6334 fstd d2, [r9] @ vAA<- d2 6335 GOTO_OPCODE(ip) @ jump to next instruction 6336 6337 6338/* ------------------------------ */ 6339 .balign 64 6340.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6341/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6342/* File: arm-vfp/fbinopWide2addr.S */ 6343 /* 6344 * Generic 64-bit floating point "/2addr" binary operation. Provide 6345 * an "instr" line that specifies an instruction that performs 6346 * "d2 = d0 op d1". 6347 * 6348 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6349 * div-double/2addr 6350 */ 6351 /* binop/2addr vA, vB */ 6352 mov r3, rINST, lsr #12 @ r3<- B 6353 mov r9, rINST, lsr #8 @ r9<- A+ 6354 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6355 and r9, r9, #15 @ r9<- A 6356 fldd d1, [r3] @ d1<- vB 6357 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6358 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6359 fldd d0, [r9] @ d0<- vA 6360 6361 fsubd d2, d0, d1 @ d2<- op 6362 GET_INST_OPCODE(ip) @ extract opcode from rINST 6363 fstd d2, [r9] @ vAA<- d2 6364 GOTO_OPCODE(ip) @ jump to next instruction 6365 6366 6367/* ------------------------------ */ 6368 .balign 64 6369.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6370/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6371/* File: arm-vfp/fbinopWide2addr.S */ 6372 /* 6373 * Generic 64-bit floating point "/2addr" binary operation. Provide 6374 * an "instr" line that specifies an instruction that performs 6375 * "d2 = d0 op d1". 6376 * 6377 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6378 * div-double/2addr 6379 */ 6380 /* binop/2addr vA, vB */ 6381 mov r3, rINST, lsr #12 @ r3<- B 6382 mov r9, rINST, lsr #8 @ r9<- A+ 6383 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6384 and r9, r9, #15 @ r9<- A 6385 fldd d1, [r3] @ d1<- vB 6386 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6387 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6388 fldd d0, [r9] @ d0<- vA 6389 6390 fmuld d2, d0, d1 @ d2<- op 6391 GET_INST_OPCODE(ip) @ extract opcode from rINST 6392 fstd d2, [r9] @ vAA<- d2 6393 GOTO_OPCODE(ip) @ jump to next instruction 6394 6395 6396/* ------------------------------ */ 6397 .balign 64 6398.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6399/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6400/* File: arm-vfp/fbinopWide2addr.S */ 6401 /* 6402 * Generic 64-bit floating point "/2addr" binary operation. Provide 6403 * an "instr" line that specifies an instruction that performs 6404 * "d2 = d0 op d1". 6405 * 6406 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6407 * div-double/2addr 6408 */ 6409 /* binop/2addr vA, vB */ 6410 mov r3, rINST, lsr #12 @ r3<- B 6411 mov r9, rINST, lsr #8 @ r9<- A+ 6412 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6413 and r9, r9, #15 @ r9<- A 6414 fldd d1, [r3] @ d1<- vB 6415 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6416 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6417 fldd d0, [r9] @ d0<- vA 6418 6419 fdivd d2, d0, d1 @ d2<- op 6420 GET_INST_OPCODE(ip) @ extract opcode from rINST 6421 fstd d2, [r9] @ vAA<- d2 6422 GOTO_OPCODE(ip) @ jump to next instruction 6423 6424 6425/* ------------------------------ */ 6426 .balign 64 6427.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6428/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6429/* EABI doesn't define a double remainder function, but libm does */ 6430/* File: armv5te/binopWide2addr.S */ 6431 /* 6432 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6433 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6434 * This could be an ARM instruction or a function call. (If the result 6435 * comes back in a register other than r0, you can override "result".) 6436 * 6437 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6438 * vCC (r1). Useful for integer division and modulus. 6439 * 6440 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6441 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6442 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6443 * rem-double/2addr 6444 */ 6445 /* binop/2addr vA, vB */ 6446 mov r9, rINST, lsr #8 @ r9<- A+ 6447 mov r1, rINST, lsr #12 @ r1<- B 6448 and r9, r9, #15 6449 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6450 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6451 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6452 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6453 .if 0 6454 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6455 beq common_errDivideByZero 6456 .endif 6457 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6458 6459 @ optional op; may set condition codes 6460 bl fmod @ result<- op, r0-r3 changed 6461 GET_INST_OPCODE(ip) @ extract opcode from rINST 6462 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6463 GOTO_OPCODE(ip) @ jump to next instruction 6464 /* 12-15 instructions */ 6465 6466 6467 6468/* ------------------------------ */ 6469 .balign 64 6470.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6471/* File: armv5te/OP_ADD_INT_LIT16.S */ 6472/* File: armv5te/binopLit16.S */ 6473 /* 6474 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6475 * that specifies an instruction that performs "result = r0 op r1". 6476 * This could be an ARM instruction or a function call. (If the result 6477 * comes back in a register other than r0, you can override "result".) 6478 * 6479 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6480 * vCC (r1). Useful for integer division and modulus. 6481 * 6482 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6483 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6484 */ 6485 /* binop/lit16 vA, vB, #+CCCC */ 6486 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6487 mov r2, rINST, lsr #12 @ r2<- B 6488 mov r9, rINST, lsr #8 @ r9<- A+ 6489 GET_VREG(r0, r2) @ r0<- vB 6490 and r9, r9, #15 6491 .if 0 6492 cmp r1, #0 @ is second operand zero? 6493 beq common_errDivideByZero 6494 .endif 6495 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6496 6497 add r0, r0, r1 @ r0<- op, r0-r3 changed 6498 GET_INST_OPCODE(ip) @ extract opcode from rINST 6499 SET_VREG(r0, r9) @ vAA<- r0 6500 GOTO_OPCODE(ip) @ jump to next instruction 6501 /* 10-13 instructions */ 6502 6503 6504 6505/* ------------------------------ */ 6506 .balign 64 6507.L_OP_RSUB_INT: /* 0xd1 */ 6508/* File: armv5te/OP_RSUB_INT.S */ 6509/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6510/* File: armv5te/binopLit16.S */ 6511 /* 6512 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6513 * that specifies an instruction that performs "result = r0 op r1". 6514 * This could be an ARM instruction or a function call. (If the result 6515 * comes back in a register other than r0, you can override "result".) 6516 * 6517 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6518 * vCC (r1). Useful for integer division and modulus. 6519 * 6520 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6521 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6522 */ 6523 /* binop/lit16 vA, vB, #+CCCC */ 6524 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6525 mov r2, rINST, lsr #12 @ r2<- B 6526 mov r9, rINST, lsr #8 @ r9<- A+ 6527 GET_VREG(r0, r2) @ r0<- vB 6528 and r9, r9, #15 6529 .if 0 6530 cmp r1, #0 @ is second operand zero? 6531 beq common_errDivideByZero 6532 .endif 6533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6534 6535 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6536 GET_INST_OPCODE(ip) @ extract opcode from rINST 6537 SET_VREG(r0, r9) @ vAA<- r0 6538 GOTO_OPCODE(ip) @ jump to next instruction 6539 /* 10-13 instructions */ 6540 6541 6542 6543/* ------------------------------ */ 6544 .balign 64 6545.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6546/* File: armv5te/OP_MUL_INT_LIT16.S */ 6547/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6548/* File: armv5te/binopLit16.S */ 6549 /* 6550 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6551 * that specifies an instruction that performs "result = r0 op r1". 6552 * This could be an ARM instruction or a function call. (If the result 6553 * comes back in a register other than r0, you can override "result".) 6554 * 6555 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6556 * vCC (r1). Useful for integer division and modulus. 6557 * 6558 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6559 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6560 */ 6561 /* binop/lit16 vA, vB, #+CCCC */ 6562 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6563 mov r2, rINST, lsr #12 @ r2<- B 6564 mov r9, rINST, lsr #8 @ r9<- A+ 6565 GET_VREG(r0, r2) @ r0<- vB 6566 and r9, r9, #15 6567 .if 0 6568 cmp r1, #0 @ is second operand zero? 6569 beq common_errDivideByZero 6570 .endif 6571 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6572 6573 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6574 GET_INST_OPCODE(ip) @ extract opcode from rINST 6575 SET_VREG(r0, r9) @ vAA<- r0 6576 GOTO_OPCODE(ip) @ jump to next instruction 6577 /* 10-13 instructions */ 6578 6579 6580 6581/* ------------------------------ */ 6582 .balign 64 6583.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6584/* File: armv5te/OP_DIV_INT_LIT16.S */ 6585/* File: armv5te/binopLit16.S */ 6586 /* 6587 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6588 * that specifies an instruction that performs "result = r0 op r1". 6589 * This could be an ARM instruction or a function call. (If the result 6590 * comes back in a register other than r0, you can override "result".) 6591 * 6592 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6593 * vCC (r1). Useful for integer division and modulus. 6594 * 6595 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6596 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6597 */ 6598 /* binop/lit16 vA, vB, #+CCCC */ 6599 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6600 mov r2, rINST, lsr #12 @ r2<- B 6601 mov r9, rINST, lsr #8 @ r9<- A+ 6602 GET_VREG(r0, r2) @ r0<- vB 6603 and r9, r9, #15 6604 .if 1 6605 cmp r1, #0 @ is second operand zero? 6606 beq common_errDivideByZero 6607 .endif 6608 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6609 6610 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6611 GET_INST_OPCODE(ip) @ extract opcode from rINST 6612 SET_VREG(r0, r9) @ vAA<- r0 6613 GOTO_OPCODE(ip) @ jump to next instruction 6614 /* 10-13 instructions */ 6615 6616 6617 6618/* ------------------------------ */ 6619 .balign 64 6620.L_OP_REM_INT_LIT16: /* 0xd4 */ 6621/* File: armv5te/OP_REM_INT_LIT16.S */ 6622/* idivmod returns quotient in r0 and remainder in r1 */ 6623/* File: armv5te/binopLit16.S */ 6624 /* 6625 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6626 * that specifies an instruction that performs "result = r0 op r1". 6627 * This could be an ARM instruction or a function call. (If the result 6628 * comes back in a register other than r0, you can override "result".) 6629 * 6630 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6631 * vCC (r1). Useful for integer division and modulus. 6632 * 6633 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6634 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6635 */ 6636 /* binop/lit16 vA, vB, #+CCCC */ 6637 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6638 mov r2, rINST, lsr #12 @ r2<- B 6639 mov r9, rINST, lsr #8 @ r9<- A+ 6640 GET_VREG(r0, r2) @ r0<- vB 6641 and r9, r9, #15 6642 .if 1 6643 cmp r1, #0 @ is second operand zero? 6644 beq common_errDivideByZero 6645 .endif 6646 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6647 6648 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6649 GET_INST_OPCODE(ip) @ extract opcode from rINST 6650 SET_VREG(r1, r9) @ vAA<- r1 6651 GOTO_OPCODE(ip) @ jump to next instruction 6652 /* 10-13 instructions */ 6653 6654 6655 6656/* ------------------------------ */ 6657 .balign 64 6658.L_OP_AND_INT_LIT16: /* 0xd5 */ 6659/* File: armv5te/OP_AND_INT_LIT16.S */ 6660/* File: armv5te/binopLit16.S */ 6661 /* 6662 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6663 * that specifies an instruction that performs "result = r0 op r1". 6664 * This could be an ARM instruction or a function call. (If the result 6665 * comes back in a register other than r0, you can override "result".) 6666 * 6667 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6668 * vCC (r1). Useful for integer division and modulus. 6669 * 6670 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6671 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6672 */ 6673 /* binop/lit16 vA, vB, #+CCCC */ 6674 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6675 mov r2, rINST, lsr #12 @ r2<- B 6676 mov r9, rINST, lsr #8 @ r9<- A+ 6677 GET_VREG(r0, r2) @ r0<- vB 6678 and r9, r9, #15 6679 .if 0 6680 cmp r1, #0 @ is second operand zero? 6681 beq common_errDivideByZero 6682 .endif 6683 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6684 6685 and r0, r0, r1 @ r0<- op, r0-r3 changed 6686 GET_INST_OPCODE(ip) @ extract opcode from rINST 6687 SET_VREG(r0, r9) @ vAA<- r0 6688 GOTO_OPCODE(ip) @ jump to next instruction 6689 /* 10-13 instructions */ 6690 6691 6692 6693/* ------------------------------ */ 6694 .balign 64 6695.L_OP_OR_INT_LIT16: /* 0xd6 */ 6696/* File: armv5te/OP_OR_INT_LIT16.S */ 6697/* File: armv5te/binopLit16.S */ 6698 /* 6699 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6700 * that specifies an instruction that performs "result = r0 op r1". 6701 * This could be an ARM instruction or a function call. (If the result 6702 * comes back in a register other than r0, you can override "result".) 6703 * 6704 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6705 * vCC (r1). Useful for integer division and modulus. 6706 * 6707 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6708 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6709 */ 6710 /* binop/lit16 vA, vB, #+CCCC */ 6711 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6712 mov r2, rINST, lsr #12 @ r2<- B 6713 mov r9, rINST, lsr #8 @ r9<- A+ 6714 GET_VREG(r0, r2) @ r0<- vB 6715 and r9, r9, #15 6716 .if 0 6717 cmp r1, #0 @ is second operand zero? 6718 beq common_errDivideByZero 6719 .endif 6720 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6721 6722 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6723 GET_INST_OPCODE(ip) @ extract opcode from rINST 6724 SET_VREG(r0, r9) @ vAA<- r0 6725 GOTO_OPCODE(ip) @ jump to next instruction 6726 /* 10-13 instructions */ 6727 6728 6729 6730/* ------------------------------ */ 6731 .balign 64 6732.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6733/* File: armv5te/OP_XOR_INT_LIT16.S */ 6734/* File: armv5te/binopLit16.S */ 6735 /* 6736 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6737 * that specifies an instruction that performs "result = r0 op r1". 6738 * This could be an ARM instruction or a function call. (If the result 6739 * comes back in a register other than r0, you can override "result".) 6740 * 6741 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6742 * vCC (r1). Useful for integer division and modulus. 6743 * 6744 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6745 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6746 */ 6747 /* binop/lit16 vA, vB, #+CCCC */ 6748 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6749 mov r2, rINST, lsr #12 @ r2<- B 6750 mov r9, rINST, lsr #8 @ r9<- A+ 6751 GET_VREG(r0, r2) @ r0<- vB 6752 and r9, r9, #15 6753 .if 0 6754 cmp r1, #0 @ is second operand zero? 6755 beq common_errDivideByZero 6756 .endif 6757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6758 6759 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6760 GET_INST_OPCODE(ip) @ extract opcode from rINST 6761 SET_VREG(r0, r9) @ vAA<- r0 6762 GOTO_OPCODE(ip) @ jump to next instruction 6763 /* 10-13 instructions */ 6764 6765 6766 6767/* ------------------------------ */ 6768 .balign 64 6769.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6770/* File: armv5te/OP_ADD_INT_LIT8.S */ 6771/* File: armv5te/binopLit8.S */ 6772 /* 6773 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6774 * that specifies an instruction that performs "result = r0 op r1". 6775 * This could be an ARM instruction or a function call. (If the result 6776 * comes back in a register other than r0, you can override "result".) 6777 * 6778 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6779 * vCC (r1). Useful for integer division and modulus. 6780 * 6781 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6782 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6783 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6784 */ 6785 /* binop/lit8 vAA, vBB, #+CC */ 6786 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6787 mov r9, rINST, lsr #8 @ r9<- AA 6788 and r2, r3, #255 @ r2<- BB 6789 GET_VREG(r0, r2) @ r0<- vBB 6790 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6791 .if 0 6792 @cmp r1, #0 @ is second operand zero? 6793 beq common_errDivideByZero 6794 .endif 6795 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6796 6797 @ optional op; may set condition codes 6798 add r0, r0, r1 @ r0<- op, r0-r3 changed 6799 GET_INST_OPCODE(ip) @ extract opcode from rINST 6800 SET_VREG(r0, r9) @ vAA<- r0 6801 GOTO_OPCODE(ip) @ jump to next instruction 6802 /* 10-12 instructions */ 6803 6804 6805 6806/* ------------------------------ */ 6807 .balign 64 6808.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6809/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6810/* File: armv5te/binopLit8.S */ 6811 /* 6812 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6813 * that specifies an instruction that performs "result = r0 op r1". 6814 * This could be an ARM instruction or a function call. (If the result 6815 * comes back in a register other than r0, you can override "result".) 6816 * 6817 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6818 * vCC (r1). Useful for integer division and modulus. 6819 * 6820 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6821 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6822 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6823 */ 6824 /* binop/lit8 vAA, vBB, #+CC */ 6825 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6826 mov r9, rINST, lsr #8 @ r9<- AA 6827 and r2, r3, #255 @ r2<- BB 6828 GET_VREG(r0, r2) @ r0<- vBB 6829 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6830 .if 0 6831 @cmp r1, #0 @ is second operand zero? 6832 beq common_errDivideByZero 6833 .endif 6834 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6835 6836 @ optional op; may set condition codes 6837 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6838 GET_INST_OPCODE(ip) @ extract opcode from rINST 6839 SET_VREG(r0, r9) @ vAA<- r0 6840 GOTO_OPCODE(ip) @ jump to next instruction 6841 /* 10-12 instructions */ 6842 6843 6844 6845/* ------------------------------ */ 6846 .balign 64 6847.L_OP_MUL_INT_LIT8: /* 0xda */ 6848/* File: armv5te/OP_MUL_INT_LIT8.S */ 6849/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6850/* File: armv5te/binopLit8.S */ 6851 /* 6852 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6853 * that specifies an instruction that performs "result = r0 op r1". 6854 * This could be an ARM instruction or a function call. (If the result 6855 * comes back in a register other than r0, you can override "result".) 6856 * 6857 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6858 * vCC (r1). Useful for integer division and modulus. 6859 * 6860 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6861 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6862 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6863 */ 6864 /* binop/lit8 vAA, vBB, #+CC */ 6865 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6866 mov r9, rINST, lsr #8 @ r9<- AA 6867 and r2, r3, #255 @ r2<- BB 6868 GET_VREG(r0, r2) @ r0<- vBB 6869 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6870 .if 0 6871 @cmp r1, #0 @ is second operand zero? 6872 beq common_errDivideByZero 6873 .endif 6874 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6875 6876 @ optional op; may set condition codes 6877 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6878 GET_INST_OPCODE(ip) @ extract opcode from rINST 6879 SET_VREG(r0, r9) @ vAA<- r0 6880 GOTO_OPCODE(ip) @ jump to next instruction 6881 /* 10-12 instructions */ 6882 6883 6884 6885/* ------------------------------ */ 6886 .balign 64 6887.L_OP_DIV_INT_LIT8: /* 0xdb */ 6888/* File: armv5te/OP_DIV_INT_LIT8.S */ 6889/* File: armv5te/binopLit8.S */ 6890 /* 6891 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6892 * that specifies an instruction that performs "result = r0 op r1". 6893 * This could be an ARM instruction or a function call. (If the result 6894 * comes back in a register other than r0, you can override "result".) 6895 * 6896 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6897 * vCC (r1). Useful for integer division and modulus. 6898 * 6899 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6900 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6901 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6902 */ 6903 /* binop/lit8 vAA, vBB, #+CC */ 6904 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6905 mov r9, rINST, lsr #8 @ r9<- AA 6906 and r2, r3, #255 @ r2<- BB 6907 GET_VREG(r0, r2) @ r0<- vBB 6908 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6909 .if 1 6910 @cmp r1, #0 @ is second operand zero? 6911 beq common_errDivideByZero 6912 .endif 6913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6914 6915 @ optional op; may set condition codes 6916 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6917 GET_INST_OPCODE(ip) @ extract opcode from rINST 6918 SET_VREG(r0, r9) @ vAA<- r0 6919 GOTO_OPCODE(ip) @ jump to next instruction 6920 /* 10-12 instructions */ 6921 6922 6923 6924/* ------------------------------ */ 6925 .balign 64 6926.L_OP_REM_INT_LIT8: /* 0xdc */ 6927/* File: armv5te/OP_REM_INT_LIT8.S */ 6928/* idivmod returns quotient in r0 and remainder in r1 */ 6929/* File: armv5te/binopLit8.S */ 6930 /* 6931 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6932 * that specifies an instruction that performs "result = r0 op r1". 6933 * This could be an ARM instruction or a function call. (If the result 6934 * comes back in a register other than r0, you can override "result".) 6935 * 6936 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6937 * vCC (r1). Useful for integer division and modulus. 6938 * 6939 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6940 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6941 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6942 */ 6943 /* binop/lit8 vAA, vBB, #+CC */ 6944 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6945 mov r9, rINST, lsr #8 @ r9<- AA 6946 and r2, r3, #255 @ r2<- BB 6947 GET_VREG(r0, r2) @ r0<- vBB 6948 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6949 .if 1 6950 @cmp r1, #0 @ is second operand zero? 6951 beq common_errDivideByZero 6952 .endif 6953 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6954 6955 @ optional op; may set condition codes 6956 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6957 GET_INST_OPCODE(ip) @ extract opcode from rINST 6958 SET_VREG(r1, r9) @ vAA<- r1 6959 GOTO_OPCODE(ip) @ jump to next instruction 6960 /* 10-12 instructions */ 6961 6962 6963 6964/* ------------------------------ */ 6965 .balign 64 6966.L_OP_AND_INT_LIT8: /* 0xdd */ 6967/* File: armv5te/OP_AND_INT_LIT8.S */ 6968/* File: armv5te/binopLit8.S */ 6969 /* 6970 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6971 * that specifies an instruction that performs "result = r0 op r1". 6972 * This could be an ARM instruction or a function call. (If the result 6973 * comes back in a register other than r0, you can override "result".) 6974 * 6975 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6976 * vCC (r1). Useful for integer division and modulus. 6977 * 6978 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6979 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6980 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6981 */ 6982 /* binop/lit8 vAA, vBB, #+CC */ 6983 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6984 mov r9, rINST, lsr #8 @ r9<- AA 6985 and r2, r3, #255 @ r2<- BB 6986 GET_VREG(r0, r2) @ r0<- vBB 6987 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6988 .if 0 6989 @cmp r1, #0 @ is second operand zero? 6990 beq common_errDivideByZero 6991 .endif 6992 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6993 6994 @ optional op; may set condition codes 6995 and r0, r0, r1 @ r0<- op, r0-r3 changed 6996 GET_INST_OPCODE(ip) @ extract opcode from rINST 6997 SET_VREG(r0, r9) @ vAA<- r0 6998 GOTO_OPCODE(ip) @ jump to next instruction 6999 /* 10-12 instructions */ 7000 7001 7002 7003/* ------------------------------ */ 7004 .balign 64 7005.L_OP_OR_INT_LIT8: /* 0xde */ 7006/* File: armv5te/OP_OR_INT_LIT8.S */ 7007/* File: armv5te/binopLit8.S */ 7008 /* 7009 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7010 * that specifies an instruction that performs "result = r0 op r1". 7011 * This could be an ARM instruction or a function call. (If the result 7012 * comes back in a register other than r0, you can override "result".) 7013 * 7014 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7015 * vCC (r1). Useful for integer division and modulus. 7016 * 7017 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7018 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7019 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7020 */ 7021 /* binop/lit8 vAA, vBB, #+CC */ 7022 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7023 mov r9, rINST, lsr #8 @ r9<- AA 7024 and r2, r3, #255 @ r2<- BB 7025 GET_VREG(r0, r2) @ r0<- vBB 7026 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7027 .if 0 7028 @cmp r1, #0 @ is second operand zero? 7029 beq common_errDivideByZero 7030 .endif 7031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7032 7033 @ optional op; may set condition codes 7034 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7035 GET_INST_OPCODE(ip) @ extract opcode from rINST 7036 SET_VREG(r0, r9) @ vAA<- r0 7037 GOTO_OPCODE(ip) @ jump to next instruction 7038 /* 10-12 instructions */ 7039 7040 7041 7042/* ------------------------------ */ 7043 .balign 64 7044.L_OP_XOR_INT_LIT8: /* 0xdf */ 7045/* File: armv5te/OP_XOR_INT_LIT8.S */ 7046/* File: armv5te/binopLit8.S */ 7047 /* 7048 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7049 * that specifies an instruction that performs "result = r0 op r1". 7050 * This could be an ARM instruction or a function call. (If the result 7051 * comes back in a register other than r0, you can override "result".) 7052 * 7053 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7054 * vCC (r1). Useful for integer division and modulus. 7055 * 7056 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7057 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7058 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7059 */ 7060 /* binop/lit8 vAA, vBB, #+CC */ 7061 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7062 mov r9, rINST, lsr #8 @ r9<- AA 7063 and r2, r3, #255 @ r2<- BB 7064 GET_VREG(r0, r2) @ r0<- vBB 7065 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7066 .if 0 7067 @cmp r1, #0 @ is second operand zero? 7068 beq common_errDivideByZero 7069 .endif 7070 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7071 7072 @ optional op; may set condition codes 7073 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7074 GET_INST_OPCODE(ip) @ extract opcode from rINST 7075 SET_VREG(r0, r9) @ vAA<- r0 7076 GOTO_OPCODE(ip) @ jump to next instruction 7077 /* 10-12 instructions */ 7078 7079 7080 7081/* ------------------------------ */ 7082 .balign 64 7083.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7084/* File: armv5te/OP_SHL_INT_LIT8.S */ 7085/* File: armv5te/binopLit8.S */ 7086 /* 7087 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7088 * that specifies an instruction that performs "result = r0 op r1". 7089 * This could be an ARM instruction or a function call. (If the result 7090 * comes back in a register other than r0, you can override "result".) 7091 * 7092 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7093 * vCC (r1). Useful for integer division and modulus. 7094 * 7095 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7096 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7097 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7098 */ 7099 /* binop/lit8 vAA, vBB, #+CC */ 7100 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7101 mov r9, rINST, lsr #8 @ r9<- AA 7102 and r2, r3, #255 @ r2<- BB 7103 GET_VREG(r0, r2) @ r0<- vBB 7104 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7105 .if 0 7106 @cmp r1, #0 @ is second operand zero? 7107 beq common_errDivideByZero 7108 .endif 7109 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7110 7111 and r1, r1, #31 @ optional op; may set condition codes 7112 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7113 GET_INST_OPCODE(ip) @ extract opcode from rINST 7114 SET_VREG(r0, r9) @ vAA<- r0 7115 GOTO_OPCODE(ip) @ jump to next instruction 7116 /* 10-12 instructions */ 7117 7118 7119 7120/* ------------------------------ */ 7121 .balign 64 7122.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7123/* File: armv5te/OP_SHR_INT_LIT8.S */ 7124/* File: armv5te/binopLit8.S */ 7125 /* 7126 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7127 * that specifies an instruction that performs "result = r0 op r1". 7128 * This could be an ARM instruction or a function call. (If the result 7129 * comes back in a register other than r0, you can override "result".) 7130 * 7131 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7132 * vCC (r1). Useful for integer division and modulus. 7133 * 7134 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7135 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7136 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7137 */ 7138 /* binop/lit8 vAA, vBB, #+CC */ 7139 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7140 mov r9, rINST, lsr #8 @ r9<- AA 7141 and r2, r3, #255 @ r2<- BB 7142 GET_VREG(r0, r2) @ r0<- vBB 7143 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7144 .if 0 7145 @cmp r1, #0 @ is second operand zero? 7146 beq common_errDivideByZero 7147 .endif 7148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7149 7150 and r1, r1, #31 @ optional op; may set condition codes 7151 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7152 GET_INST_OPCODE(ip) @ extract opcode from rINST 7153 SET_VREG(r0, r9) @ vAA<- r0 7154 GOTO_OPCODE(ip) @ jump to next instruction 7155 /* 10-12 instructions */ 7156 7157 7158 7159/* ------------------------------ */ 7160 .balign 64 7161.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7162/* File: armv5te/OP_USHR_INT_LIT8.S */ 7163/* File: armv5te/binopLit8.S */ 7164 /* 7165 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7166 * that specifies an instruction that performs "result = r0 op r1". 7167 * This could be an ARM instruction or a function call. (If the result 7168 * comes back in a register other than r0, you can override "result".) 7169 * 7170 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7171 * vCC (r1). Useful for integer division and modulus. 7172 * 7173 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7174 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7175 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7176 */ 7177 /* binop/lit8 vAA, vBB, #+CC */ 7178 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7179 mov r9, rINST, lsr #8 @ r9<- AA 7180 and r2, r3, #255 @ r2<- BB 7181 GET_VREG(r0, r2) @ r0<- vBB 7182 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7183 .if 0 7184 @cmp r1, #0 @ is second operand zero? 7185 beq common_errDivideByZero 7186 .endif 7187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7188 7189 and r1, r1, #31 @ optional op; may set condition codes 7190 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7191 GET_INST_OPCODE(ip) @ extract opcode from rINST 7192 SET_VREG(r0, r9) @ vAA<- r0 7193 GOTO_OPCODE(ip) @ jump to next instruction 7194 /* 10-12 instructions */ 7195 7196 7197 7198/* ------------------------------ */ 7199 .balign 64 7200.L_OP_UNUSED_E3: /* 0xe3 */ 7201/* File: armv5te/OP_UNUSED_E3.S */ 7202/* File: armv5te/unused.S */ 7203 bl common_abort 7204 7205 7206 7207/* ------------------------------ */ 7208 .balign 64 7209.L_OP_UNUSED_E4: /* 0xe4 */ 7210/* File: armv5te/OP_UNUSED_E4.S */ 7211/* File: armv5te/unused.S */ 7212 bl common_abort 7213 7214 7215 7216/* ------------------------------ */ 7217 .balign 64 7218.L_OP_UNUSED_E5: /* 0xe5 */ 7219/* File: armv5te/OP_UNUSED_E5.S */ 7220/* File: armv5te/unused.S */ 7221 bl common_abort 7222 7223 7224 7225/* ------------------------------ */ 7226 .balign 64 7227.L_OP_UNUSED_E6: /* 0xe6 */ 7228/* File: armv5te/OP_UNUSED_E6.S */ 7229/* File: armv5te/unused.S */ 7230 bl common_abort 7231 7232 7233 7234/* ------------------------------ */ 7235 .balign 64 7236.L_OP_UNUSED_E7: /* 0xe7 */ 7237/* File: armv5te/OP_UNUSED_E7.S */ 7238/* File: armv5te/unused.S */ 7239 bl common_abort 7240 7241 7242 7243/* ------------------------------ */ 7244 .balign 64 7245.L_OP_UNUSED_E8: /* 0xe8 */ 7246/* File: armv5te/OP_UNUSED_E8.S */ 7247/* File: armv5te/unused.S */ 7248 bl common_abort 7249 7250 7251 7252/* ------------------------------ */ 7253 .balign 64 7254.L_OP_UNUSED_E9: /* 0xe9 */ 7255/* File: armv5te/OP_UNUSED_E9.S */ 7256/* File: armv5te/unused.S */ 7257 bl common_abort 7258 7259 7260 7261/* ------------------------------ */ 7262 .balign 64 7263.L_OP_UNUSED_EA: /* 0xea */ 7264/* File: armv5te/OP_UNUSED_EA.S */ 7265/* File: armv5te/unused.S */ 7266 bl common_abort 7267 7268 7269 7270/* ------------------------------ */ 7271 .balign 64 7272.L_OP_UNUSED_EB: /* 0xeb */ 7273/* File: armv5te/OP_UNUSED_EB.S */ 7274/* File: armv5te/unused.S */ 7275 bl common_abort 7276 7277 7278 7279/* ------------------------------ */ 7280 .balign 64 7281.L_OP_UNUSED_EC: /* 0xec */ 7282/* File: armv5te/OP_UNUSED_EC.S */ 7283/* File: armv5te/unused.S */ 7284 bl common_abort 7285 7286 7287 7288/* ------------------------------ */ 7289 .balign 64 7290.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7291/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7292 /* 7293 * Handle a throw-verification-error instruction. This throws an 7294 * exception for an error discovered during verification. The 7295 * exception is indicated by AA, with some detail provided by BBBB. 7296 */ 7297 /* op AA, ref@BBBB */ 7298 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7299 FETCH(r2, 1) @ r2<- BBBB 7300 EXPORT_PC() @ export the PC 7301 mov r1, rINST, lsr #8 @ r1<- AA 7302 bl dvmThrowVerificationError @ always throws 7303 b common_exceptionThrown @ handle exception 7304 7305 7306/* ------------------------------ */ 7307 .balign 64 7308.L_OP_EXECUTE_INLINE: /* 0xee */ 7309/* File: armv5te/OP_EXECUTE_INLINE.S */ 7310 /* 7311 * Execute a "native inline" instruction. 7312 * 7313 * We need to call: 7314 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7315 * 7316 * The first four args are in r0-r3, but the last two must be pushed 7317 * onto the stack. 7318 */ 7319 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7320 FETCH(r10, 1) @ r10<- BBBB 7321 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7322 EXPORT_PC() @ can throw 7323 sub sp, sp, #8 @ make room for arg(s) 7324 mov r0, rINST, lsr #12 @ r0<- B 7325 str r1, [sp] @ push &glue->retval 7326 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7327 add sp, sp, #8 @ pop stack 7328 cmp r0, #0 @ test boolean result of inline 7329 beq common_exceptionThrown @ returned false, handle exception 7330 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7331 GET_INST_OPCODE(ip) @ extract opcode from rINST 7332 GOTO_OPCODE(ip) @ jump to next instruction 7333 7334/* ------------------------------ */ 7335 .balign 64 7336.L_OP_UNUSED_EF: /* 0xef */ 7337/* File: armv5te/OP_UNUSED_EF.S */ 7338/* File: armv5te/unused.S */ 7339 bl common_abort 7340 7341 7342 7343/* ------------------------------ */ 7344 .balign 64 7345.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7346/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7347 /* 7348 * invoke-direct-empty is a no-op in a "standard" interpreter. 7349 */ 7350 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7351 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7352 GOTO_OPCODE(ip) @ execute it 7353 7354/* ------------------------------ */ 7355 .balign 64 7356.L_OP_UNUSED_F1: /* 0xf1 */ 7357/* File: armv5te/OP_UNUSED_F1.S */ 7358/* File: armv5te/unused.S */ 7359 bl common_abort 7360 7361 7362 7363/* ------------------------------ */ 7364 .balign 64 7365.L_OP_IGET_QUICK: /* 0xf2 */ 7366/* File: armv5te/OP_IGET_QUICK.S */ 7367 /* For: iget-quick, iget-object-quick */ 7368 /* op vA, vB, offset@CCCC */ 7369 mov r2, rINST, lsr #12 @ r2<- B 7370 GET_VREG(r3, r2) @ r3<- object we're operating on 7371 FETCH(r1, 1) @ r1<- field byte offset 7372 cmp r3, #0 @ check object for null 7373 mov r2, rINST, lsr #8 @ r2<- A(+) 7374 beq common_errNullObject @ object was null 7375 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7377 and r2, r2, #15 7378 GET_INST_OPCODE(ip) @ extract opcode from rINST 7379 SET_VREG(r0, r2) @ fp[A]<- r0 7380 GOTO_OPCODE(ip) @ jump to next instruction 7381 7382 7383/* ------------------------------ */ 7384 .balign 64 7385.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7386/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7387 /* iget-wide-quick vA, vB, offset@CCCC */ 7388 mov r2, rINST, lsr #12 @ r2<- B 7389 GET_VREG(r3, r2) @ r3<- object we're operating on 7390 FETCH(r1, 1) @ r1<- field byte offset 7391 cmp r3, #0 @ check object for null 7392 mov r2, rINST, lsr #8 @ r2<- A(+) 7393 beq common_errNullObject @ object was null 7394 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7395 and r2, r2, #15 7396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7397 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7398 GET_INST_OPCODE(ip) @ extract opcode from rINST 7399 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7400 GOTO_OPCODE(ip) @ jump to next instruction 7401 7402 7403/* ------------------------------ */ 7404 .balign 64 7405.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7406/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7407/* File: armv5te/OP_IGET_QUICK.S */ 7408 /* For: iget-quick, iget-object-quick */ 7409 /* op vA, vB, offset@CCCC */ 7410 mov r2, rINST, lsr #12 @ r2<- B 7411 GET_VREG(r3, r2) @ r3<- object we're operating on 7412 FETCH(r1, 1) @ r1<- field byte offset 7413 cmp r3, #0 @ check object for null 7414 mov r2, rINST, lsr #8 @ r2<- A(+) 7415 beq common_errNullObject @ object was null 7416 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7417 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7418 and r2, r2, #15 7419 GET_INST_OPCODE(ip) @ extract opcode from rINST 7420 SET_VREG(r0, r2) @ fp[A]<- r0 7421 GOTO_OPCODE(ip) @ jump to next instruction 7422 7423 7424 7425/* ------------------------------ */ 7426 .balign 64 7427.L_OP_IPUT_QUICK: /* 0xf5 */ 7428/* File: armv5te/OP_IPUT_QUICK.S */ 7429 /* For: iput-quick, iput-object-quick */ 7430 /* op vA, vB, offset@CCCC */ 7431 mov r2, rINST, lsr #12 @ r2<- B 7432 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7433 FETCH(r1, 1) @ r1<- field byte offset 7434 cmp r3, #0 @ check object for null 7435 mov r2, rINST, lsr #8 @ r2<- A(+) 7436 beq common_errNullObject @ object was null 7437 and r2, r2, #15 7438 GET_VREG(r0, r2) @ r0<- fp[A] 7439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7440 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7441 GET_INST_OPCODE(ip) @ extract opcode from rINST 7442 GOTO_OPCODE(ip) @ jump to next instruction 7443 7444 7445/* ------------------------------ */ 7446 .balign 64 7447.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7448/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7449 /* iput-wide-quick vA, vB, offset@CCCC */ 7450 mov r0, rINST, lsr #8 @ r0<- A(+) 7451 mov r1, rINST, lsr #12 @ r1<- B 7452 and r0, r0, #15 7453 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7454 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7455 cmp r2, #0 @ check object for null 7456 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7457 beq common_errNullObject @ object was null 7458 FETCH(r3, 1) @ r3<- field byte offset 7459 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7460 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7461 GET_INST_OPCODE(ip) @ extract opcode from rINST 7462 GOTO_OPCODE(ip) @ jump to next instruction 7463 7464 7465/* ------------------------------ */ 7466 .balign 64 7467.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7468/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7469/* File: armv5te/OP_IPUT_QUICK.S */ 7470 /* For: iput-quick, iput-object-quick */ 7471 /* op vA, vB, offset@CCCC */ 7472 mov r2, rINST, lsr #12 @ r2<- B 7473 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7474 FETCH(r1, 1) @ r1<- field byte offset 7475 cmp r3, #0 @ check object for null 7476 mov r2, rINST, lsr #8 @ r2<- A(+) 7477 beq common_errNullObject @ object was null 7478 and r2, r2, #15 7479 GET_VREG(r0, r2) @ r0<- fp[A] 7480 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7481 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7482 GET_INST_OPCODE(ip) @ extract opcode from rINST 7483 GOTO_OPCODE(ip) @ jump to next instruction 7484 7485 7486 7487/* ------------------------------ */ 7488 .balign 64 7489.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7490/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7491 /* 7492 * Handle an optimized virtual method call. 7493 * 7494 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7495 */ 7496 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7497 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7498 FETCH(r3, 2) @ r3<- FEDC or CCCC 7499 FETCH(r1, 1) @ r1<- BBBB 7500 .if (!0) 7501 and r3, r3, #15 @ r3<- C (or stays CCCC) 7502 .endif 7503 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7504 cmp r2, #0 @ is "this" null? 7505 beq common_errNullObject @ null "this", throw exception 7506 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7507 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7508 EXPORT_PC() @ invoke must export 7509 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7510 bl common_invokeMethodNoRange @ continue on 7511 7512/* ------------------------------ */ 7513 .balign 64 7514.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7515/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7516/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7517 /* 7518 * Handle an optimized virtual method call. 7519 * 7520 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7521 */ 7522 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7523 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7524 FETCH(r3, 2) @ r3<- FEDC or CCCC 7525 FETCH(r1, 1) @ r1<- BBBB 7526 .if (!1) 7527 and r3, r3, #15 @ r3<- C (or stays CCCC) 7528 .endif 7529 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7530 cmp r2, #0 @ is "this" null? 7531 beq common_errNullObject @ null "this", throw exception 7532 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7533 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7534 EXPORT_PC() @ invoke must export 7535 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7536 bl common_invokeMethodRange @ continue on 7537 7538 7539/* ------------------------------ */ 7540 .balign 64 7541.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7542/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7543 /* 7544 * Handle an optimized "super" method call. 7545 * 7546 * for: [opt] invoke-super-quick, invoke-super-quick/range 7547 */ 7548 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7549 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7550 FETCH(r10, 2) @ r10<- GFED or CCCC 7551 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7552 .if (!0) 7553 and r10, r10, #15 @ r10<- D (or stays CCCC) 7554 .endif 7555 FETCH(r1, 1) @ r1<- BBBB 7556 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7557 EXPORT_PC() @ must export for invoke 7558 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7559 GET_VREG(r3, r10) @ r3<- "this" 7560 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7561 cmp r3, #0 @ null "this" ref? 7562 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7563 beq common_errNullObject @ "this" is null, throw exception 7564 bl common_invokeMethodNoRange @ continue on 7565 7566 7567/* ------------------------------ */ 7568 .balign 64 7569.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7570/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7571/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7572 /* 7573 * Handle an optimized "super" method call. 7574 * 7575 * for: [opt] invoke-super-quick, invoke-super-quick/range 7576 */ 7577 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7578 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7579 FETCH(r10, 2) @ r10<- GFED or CCCC 7580 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7581 .if (!1) 7582 and r10, r10, #15 @ r10<- D (or stays CCCC) 7583 .endif 7584 FETCH(r1, 1) @ r1<- BBBB 7585 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7586 EXPORT_PC() @ must export for invoke 7587 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7588 GET_VREG(r3, r10) @ r3<- "this" 7589 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7590 cmp r3, #0 @ null "this" ref? 7591 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7592 beq common_errNullObject @ "this" is null, throw exception 7593 bl common_invokeMethodRange @ continue on 7594 7595 7596 7597/* ------------------------------ */ 7598 .balign 64 7599.L_OP_UNUSED_FC: /* 0xfc */ 7600/* File: armv5te/OP_UNUSED_FC.S */ 7601/* File: armv5te/unused.S */ 7602 bl common_abort 7603 7604 7605 7606/* ------------------------------ */ 7607 .balign 64 7608.L_OP_UNUSED_FD: /* 0xfd */ 7609/* File: armv5te/OP_UNUSED_FD.S */ 7610/* File: armv5te/unused.S */ 7611 bl common_abort 7612 7613 7614 7615/* ------------------------------ */ 7616 .balign 64 7617.L_OP_UNUSED_FE: /* 0xfe */ 7618/* File: armv5te/OP_UNUSED_FE.S */ 7619/* File: armv5te/unused.S */ 7620 bl common_abort 7621 7622 7623 7624/* ------------------------------ */ 7625 .balign 64 7626.L_OP_UNUSED_FF: /* 0xff */ 7627/* File: armv5te/OP_UNUSED_FF.S */ 7628/* File: armv5te/unused.S */ 7629 bl common_abort 7630 7631 7632 7633 7634 .balign 64 7635 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7636 .global dvmAsmInstructionEnd 7637dvmAsmInstructionEnd: 7638 7639/* 7640 * =========================================================================== 7641 * Sister implementations 7642 * =========================================================================== 7643 */ 7644 .global dvmAsmSisterStart 7645 .type dvmAsmSisterStart, %function 7646 .text 7647 .balign 4 7648dvmAsmSisterStart: 7649 7650/* continuation for OP_CONST_STRING */ 7651 7652 /* 7653 * Continuation if the String has not yet been resolved. 7654 * r1: BBBB (String ref) 7655 * r9: target register 7656 */ 7657.LOP_CONST_STRING_resolve: 7658 EXPORT_PC() 7659 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7660 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7661 bl dvmResolveString @ r0<- String reference 7662 cmp r0, #0 @ failed? 7663 beq common_exceptionThrown @ yup, handle the exception 7664 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7665 GET_INST_OPCODE(ip) @ extract opcode from rINST 7666 SET_VREG(r0, r9) @ vAA<- r0 7667 GOTO_OPCODE(ip) @ jump to next instruction 7668 7669 7670/* continuation for OP_CONST_STRING_JUMBO */ 7671 7672 /* 7673 * Continuation if the String has not yet been resolved. 7674 * r1: BBBBBBBB (String ref) 7675 * r9: target register 7676 */ 7677.LOP_CONST_STRING_JUMBO_resolve: 7678 EXPORT_PC() 7679 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7680 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7681 bl dvmResolveString @ r0<- String reference 7682 cmp r0, #0 @ failed? 7683 beq common_exceptionThrown @ yup, handle the exception 7684 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7685 GET_INST_OPCODE(ip) @ extract opcode from rINST 7686 SET_VREG(r0, r9) @ vAA<- r0 7687 GOTO_OPCODE(ip) @ jump to next instruction 7688 7689 7690/* continuation for OP_CONST_CLASS */ 7691 7692 /* 7693 * Continuation if the Class has not yet been resolved. 7694 * r1: BBBB (Class ref) 7695 * r9: target register 7696 */ 7697.LOP_CONST_CLASS_resolve: 7698 EXPORT_PC() 7699 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7700 mov r2, #1 @ r2<- true 7701 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7702 bl dvmResolveClass @ r0<- Class reference 7703 cmp r0, #0 @ failed? 7704 beq common_exceptionThrown @ yup, handle the exception 7705 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7706 GET_INST_OPCODE(ip) @ extract opcode from rINST 7707 SET_VREG(r0, r9) @ vAA<- r0 7708 GOTO_OPCODE(ip) @ jump to next instruction 7709 7710 7711/* continuation for OP_CHECK_CAST */ 7712 7713 /* 7714 * Trivial test failed, need to perform full check. This is common. 7715 * r0 holds obj->clazz 7716 * r1 holds class resolved from BBBB 7717 * r9 holds object 7718 */ 7719.LOP_CHECK_CAST_fullcheck: 7720 bl dvmInstanceofNonTrivial @ r0<- boolean result 7721 cmp r0, #0 @ failed? 7722 bne .LOP_CHECK_CAST_okay @ no, success 7723 7724 @ A cast has failed. We need to throw a ClassCastException with the 7725 @ class of the object that failed to be cast. 7726 EXPORT_PC() @ about to throw 7727 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7728 ldr r0, .LstrClassCastExceptionPtr 7729 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7730 bl dvmThrowExceptionWithClassMessage 7731 b common_exceptionThrown 7732 7733 /* 7734 * Resolution required. This is the least-likely path. 7735 * 7736 * r2 holds BBBB 7737 * r9 holds object 7738 */ 7739.LOP_CHECK_CAST_resolve: 7740 EXPORT_PC() @ resolve() could throw 7741 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7742 mov r1, r2 @ r1<- BBBB 7743 mov r2, #0 @ r2<- false 7744 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7745 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7746 cmp r0, #0 @ got null? 7747 beq common_exceptionThrown @ yes, handle exception 7748 mov r1, r0 @ r1<- class resolved from BBB 7749 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7750 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7751 7752.LstrClassCastExceptionPtr: 7753 .word .LstrClassCastException 7754 7755 7756/* continuation for OP_INSTANCE_OF */ 7757 7758 /* 7759 * Trivial test failed, need to perform full check. This is common. 7760 * r0 holds obj->clazz 7761 * r1 holds class resolved from BBBB 7762 * r9 holds A 7763 */ 7764.LOP_INSTANCE_OF_fullcheck: 7765 bl dvmInstanceofNonTrivial @ r0<- boolean result 7766 @ fall through to OP_INSTANCE_OF_store 7767 7768 /* 7769 * r0 holds boolean result 7770 * r9 holds A 7771 */ 7772.LOP_INSTANCE_OF_store: 7773 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7774 SET_VREG(r0, r9) @ vA<- r0 7775 GET_INST_OPCODE(ip) @ extract opcode from rINST 7776 GOTO_OPCODE(ip) @ jump to next instruction 7777 7778 /* 7779 * Trivial test succeeded, save and bail. 7780 * r9 holds A 7781 */ 7782.LOP_INSTANCE_OF_trivial: 7783 mov r0, #1 @ indicate success 7784 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7785 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7786 SET_VREG(r0, r9) @ vA<- r0 7787 GET_INST_OPCODE(ip) @ extract opcode from rINST 7788 GOTO_OPCODE(ip) @ jump to next instruction 7789 7790 /* 7791 * Resolution required. This is the least-likely path. 7792 * 7793 * r3 holds BBBB 7794 * r9 holds A 7795 */ 7796.LOP_INSTANCE_OF_resolve: 7797 EXPORT_PC() @ resolve() could throw 7798 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7799 mov r1, r3 @ r1<- BBBB 7800 mov r2, #1 @ r2<- true 7801 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7802 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7803 cmp r0, #0 @ got null? 7804 beq common_exceptionThrown @ yes, handle exception 7805 mov r1, r0 @ r1<- class resolved from BBB 7806 mov r3, rINST, lsr #12 @ r3<- B 7807 GET_VREG(r0, r3) @ r0<- vB (object) 7808 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7809 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7810 7811 7812/* continuation for OP_NEW_INSTANCE */ 7813 7814 .balign 32 @ minimize cache lines 7815.LOP_NEW_INSTANCE_finish: @ r0=new object 7816 mov r3, rINST, lsr #8 @ r3<- AA 7817 cmp r0, #0 @ failed? 7818 beq common_exceptionThrown @ yes, handle the exception 7819 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7820 GET_INST_OPCODE(ip) @ extract opcode from rINST 7821 SET_VREG(r0, r3) @ vAA<- r0 7822 GOTO_OPCODE(ip) @ jump to next instruction 7823 7824 /* 7825 * Class initialization required. 7826 * 7827 * r0 holds class object 7828 */ 7829.LOP_NEW_INSTANCE_needinit: 7830 mov r9, r0 @ save r0 7831 bl dvmInitClass @ initialize class 7832 cmp r0, #0 @ check boolean result 7833 mov r0, r9 @ restore r0 7834 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7835 b common_exceptionThrown @ failed, deal with init exception 7836 7837 /* 7838 * Resolution required. This is the least-likely path. 7839 * 7840 * r1 holds BBBB 7841 */ 7842.LOP_NEW_INSTANCE_resolve: 7843 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7844 mov r2, #0 @ r2<- false 7845 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7846 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7847 cmp r0, #0 @ got null? 7848 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7849 b common_exceptionThrown @ yes, handle exception 7850 7851.LstrInstantiationErrorPtr: 7852 .word .LstrInstantiationError 7853 7854 7855/* continuation for OP_NEW_ARRAY */ 7856 7857 7858 /* 7859 * Resolve class. (This is an uncommon case.) 7860 * 7861 * r1 holds array length 7862 * r2 holds class ref CCCC 7863 */ 7864.LOP_NEW_ARRAY_resolve: 7865 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7866 mov r9, r1 @ r9<- length (save) 7867 mov r1, r2 @ r1<- CCCC 7868 mov r2, #0 @ r2<- false 7869 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7870 bl dvmResolveClass @ r0<- call(clazz, ref) 7871 cmp r0, #0 @ got null? 7872 mov r1, r9 @ r1<- length (restore) 7873 beq common_exceptionThrown @ yes, handle exception 7874 @ fall through to OP_NEW_ARRAY_finish 7875 7876 /* 7877 * Finish allocation. 7878 * 7879 * r0 holds class 7880 * r1 holds array length 7881 */ 7882.LOP_NEW_ARRAY_finish: 7883 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7884 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7885 cmp r0, #0 @ failed? 7886 mov r2, rINST, lsr #8 @ r2<- A+ 7887 beq common_exceptionThrown @ yes, handle the exception 7888 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7889 and r2, r2, #15 @ r2<- A 7890 GET_INST_OPCODE(ip) @ extract opcode from rINST 7891 SET_VREG(r0, r2) @ vA<- r0 7892 GOTO_OPCODE(ip) @ jump to next instruction 7893 7894 7895/* continuation for OP_FILLED_NEW_ARRAY */ 7896 7897 /* 7898 * On entry: 7899 * r0 holds array class 7900 * r10 holds AA or BA 7901 */ 7902.LOP_FILLED_NEW_ARRAY_continue: 7903 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7904 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7905 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7906 .if 0 7907 mov r1, r10 @ r1<- AA (length) 7908 .else 7909 mov r1, r10, lsr #4 @ r1<- B (length) 7910 .endif 7911 cmp r3, #'I' @ array of ints? 7912 cmpne r3, #'L' @ array of objects? 7913 cmpne r3, #'[' @ array of arrays? 7914 mov r9, r1 @ save length in r9 7915 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7916 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7917 cmp r0, #0 @ null return? 7918 beq common_exceptionThrown @ alloc failed, handle exception 7919 7920 FETCH(r1, 2) @ r1<- FEDC or CCCC 7921 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7922 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7923 subs r9, r9, #1 @ length--, check for neg 7924 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7925 bmi 2f @ was zero, bail 7926 7927 @ copy values from registers into the array 7928 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7929 .if 0 7930 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79311: ldr r3, [r2], #4 @ r3<- *r2++ 7932 subs r9, r9, #1 @ count-- 7933 str r3, [r0], #4 @ *contents++ = vX 7934 bpl 1b 7935 @ continue at 2 7936 .else 7937 cmp r9, #4 @ length was initially 5? 7938 and r2, r10, #15 @ r2<- A 7939 bne 1f @ <= 4 args, branch 7940 GET_VREG(r3, r2) @ r3<- vA 7941 sub r9, r9, #1 @ count-- 7942 str r3, [r0, #16] @ contents[4] = vA 79431: and r2, r1, #15 @ r2<- F/E/D/C 7944 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7945 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7946 subs r9, r9, #1 @ count-- 7947 str r3, [r0], #4 @ *contents++ = vX 7948 bpl 1b 7949 @ continue at 2 7950 .endif 7951 79522: 7953 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7954 GOTO_OPCODE(ip) @ execute it 7955 7956 /* 7957 * Throw an exception indicating that we have not implemented this 7958 * mode of filled-new-array. 7959 */ 7960.LOP_FILLED_NEW_ARRAY_notimpl: 7961 ldr r0, .L_strInternalError 7962 ldr r1, .L_strFilledNewArrayNotImpl 7963 bl dvmThrowException 7964 b common_exceptionThrown 7965 7966 .if (!0) @ define in one or the other, not both 7967.L_strFilledNewArrayNotImpl: 7968 .word .LstrFilledNewArrayNotImpl 7969.L_strInternalError: 7970 .word .LstrInternalError 7971 .endif 7972 7973 7974/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7975 7976 /* 7977 * On entry: 7978 * r0 holds array class 7979 * r10 holds AA or BA 7980 */ 7981.LOP_FILLED_NEW_ARRAY_RANGE_continue: 7982 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7983 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7984 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7985 .if 1 7986 mov r1, r10 @ r1<- AA (length) 7987 .else 7988 mov r1, r10, lsr #4 @ r1<- B (length) 7989 .endif 7990 cmp r3, #'I' @ array of ints? 7991 cmpne r3, #'L' @ array of objects? 7992 cmpne r3, #'[' @ array of arrays? 7993 mov r9, r1 @ save length in r9 7994 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 7995 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7996 cmp r0, #0 @ null return? 7997 beq common_exceptionThrown @ alloc failed, handle exception 7998 7999 FETCH(r1, 2) @ r1<- FEDC or CCCC 8000 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8001 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8002 subs r9, r9, #1 @ length--, check for neg 8003 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8004 bmi 2f @ was zero, bail 8005 8006 @ copy values from registers into the array 8007 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8008 .if 1 8009 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80101: ldr r3, [r2], #4 @ r3<- *r2++ 8011 subs r9, r9, #1 @ count-- 8012 str r3, [r0], #4 @ *contents++ = vX 8013 bpl 1b 8014 @ continue at 2 8015 .else 8016 cmp r9, #4 @ length was initially 5? 8017 and r2, r10, #15 @ r2<- A 8018 bne 1f @ <= 4 args, branch 8019 GET_VREG(r3, r2) @ r3<- vA 8020 sub r9, r9, #1 @ count-- 8021 str r3, [r0, #16] @ contents[4] = vA 80221: and r2, r1, #15 @ r2<- F/E/D/C 8023 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8024 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8025 subs r9, r9, #1 @ count-- 8026 str r3, [r0], #4 @ *contents++ = vX 8027 bpl 1b 8028 @ continue at 2 8029 .endif 8030 80312: 8032 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8033 GOTO_OPCODE(ip) @ execute it 8034 8035 /* 8036 * Throw an exception indicating that we have not implemented this 8037 * mode of filled-new-array. 8038 */ 8039.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8040 ldr r0, .L_strInternalError 8041 ldr r1, .L_strFilledNewArrayNotImpl 8042 bl dvmThrowException 8043 b common_exceptionThrown 8044 8045 .if (!1) @ define in one or the other, not both 8046.L_strFilledNewArrayNotImpl: 8047 .word .LstrFilledNewArrayNotImpl 8048.L_strInternalError: 8049 .word .LstrInternalError 8050 .endif 8051 8052 8053/* continuation for OP_CMPL_FLOAT */ 8054.LOP_CMPL_FLOAT_finish: 8055 SET_VREG(r0, r9) @ vAA<- r0 8056 GOTO_OPCODE(ip) @ jump to next instruction 8057 8058 8059/* continuation for OP_CMPG_FLOAT */ 8060.LOP_CMPG_FLOAT_finish: 8061 SET_VREG(r0, r9) @ vAA<- r0 8062 GOTO_OPCODE(ip) @ jump to next instruction 8063 8064 8065/* continuation for OP_CMPL_DOUBLE */ 8066.LOP_CMPL_DOUBLE_finish: 8067 SET_VREG(r0, r9) @ vAA<- r0 8068 GOTO_OPCODE(ip) @ jump to next instruction 8069 8070 8071/* continuation for OP_CMPG_DOUBLE */ 8072.LOP_CMPG_DOUBLE_finish: 8073 SET_VREG(r0, r9) @ vAA<- r0 8074 GOTO_OPCODE(ip) @ jump to next instruction 8075 8076 8077/* continuation for OP_CMP_LONG */ 8078 8079.LOP_CMP_LONG_less: 8080 mvn r1, #0 @ r1<- -1 8081 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8082 @ instead, we just replicate the tail end. 8083 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8084 SET_VREG(r1, r9) @ vAA<- r1 8085 GET_INST_OPCODE(ip) @ extract opcode from rINST 8086 GOTO_OPCODE(ip) @ jump to next instruction 8087 8088.LOP_CMP_LONG_greater: 8089 mov r1, #1 @ r1<- 1 8090 @ fall through to _finish 8091 8092.LOP_CMP_LONG_finish: 8093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8094 SET_VREG(r1, r9) @ vAA<- r1 8095 GET_INST_OPCODE(ip) @ extract opcode from rINST 8096 GOTO_OPCODE(ip) @ jump to next instruction 8097 8098 8099/* continuation for OP_AGET_WIDE */ 8100 8101.LOP_AGET_WIDE_finish: 8102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8103 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8104 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8105 GET_INST_OPCODE(ip) @ extract opcode from rINST 8106 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8107 GOTO_OPCODE(ip) @ jump to next instruction 8108 8109 8110/* continuation for OP_APUT_WIDE */ 8111 8112.LOP_APUT_WIDE_finish: 8113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8114 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8115 GET_INST_OPCODE(ip) @ extract opcode from rINST 8116 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8117 GOTO_OPCODE(ip) @ jump to next instruction 8118 8119 8120/* continuation for OP_APUT_OBJECT */ 8121 /* 8122 * On entry: 8123 * r1 = vBB (arrayObj) 8124 * r9 = vAA (obj) 8125 * r10 = offset into array (vBB + vCC * width) 8126 */ 8127.LOP_APUT_OBJECT_finish: 8128 cmp r9, #0 @ storing null reference? 8129 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8130 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8131 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8132 bl dvmCanPutArrayElement @ test object type vs. array type 8133 cmp r0, #0 @ okay? 8134 beq common_errArrayStore @ no 8135.LOP_APUT_OBJECT_skip_check: 8136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8137 GET_INST_OPCODE(ip) @ extract opcode from rINST 8138 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8139 GOTO_OPCODE(ip) @ jump to next instruction 8140 8141 8142/* continuation for OP_IGET */ 8143 8144 /* 8145 * Currently: 8146 * r0 holds resolved field 8147 * r9 holds object 8148 */ 8149.LOP_IGET_finish: 8150 @bl common_squeak0 8151 cmp r9, #0 @ check object for null 8152 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8153 beq common_errNullObject @ object was null 8154 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8155 mov r2, rINST, lsr #8 @ r2<- A+ 8156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8157 and r2, r2, #15 @ r2<- A 8158 GET_INST_OPCODE(ip) @ extract opcode from rINST 8159 SET_VREG(r0, r2) @ fp[A]<- r0 8160 GOTO_OPCODE(ip) @ jump to next instruction 8161 8162 8163/* continuation for OP_IGET_WIDE */ 8164 8165 /* 8166 * Currently: 8167 * r0 holds resolved field 8168 * r9 holds object 8169 */ 8170.LOP_IGET_WIDE_finish: 8171 cmp r9, #0 @ check object for null 8172 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8173 beq common_errNullObject @ object was null 8174 mov r2, rINST, lsr #8 @ r2<- A+ 8175 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8176 and r2, r2, #15 @ r2<- A 8177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8178 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8179 GET_INST_OPCODE(ip) @ extract opcode from rINST 8180 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8181 GOTO_OPCODE(ip) @ jump to next instruction 8182 8183 8184/* continuation for OP_IGET_OBJECT */ 8185 8186 /* 8187 * Currently: 8188 * r0 holds resolved field 8189 * r9 holds object 8190 */ 8191.LOP_IGET_OBJECT_finish: 8192 @bl common_squeak0 8193 cmp r9, #0 @ check object for null 8194 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8195 beq common_errNullObject @ object was null 8196 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8197 mov r2, rINST, lsr #8 @ r2<- A+ 8198 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8199 and r2, r2, #15 @ r2<- A 8200 GET_INST_OPCODE(ip) @ extract opcode from rINST 8201 SET_VREG(r0, r2) @ fp[A]<- r0 8202 GOTO_OPCODE(ip) @ jump to next instruction 8203 8204 8205/* continuation for OP_IGET_BOOLEAN */ 8206 8207 /* 8208 * Currently: 8209 * r0 holds resolved field 8210 * r9 holds object 8211 */ 8212.LOP_IGET_BOOLEAN_finish: 8213 @bl common_squeak1 8214 cmp r9, #0 @ check object for null 8215 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8216 beq common_errNullObject @ object was null 8217 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8218 mov r2, rINST, lsr #8 @ r2<- A+ 8219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8220 and r2, r2, #15 @ r2<- A 8221 GET_INST_OPCODE(ip) @ extract opcode from rINST 8222 SET_VREG(r0, r2) @ fp[A]<- r0 8223 GOTO_OPCODE(ip) @ jump to next instruction 8224 8225 8226/* continuation for OP_IGET_BYTE */ 8227 8228 /* 8229 * Currently: 8230 * r0 holds resolved field 8231 * r9 holds object 8232 */ 8233.LOP_IGET_BYTE_finish: 8234 @bl common_squeak2 8235 cmp r9, #0 @ check object for null 8236 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8237 beq common_errNullObject @ object was null 8238 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8239 mov r2, rINST, lsr #8 @ r2<- A+ 8240 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8241 and r2, r2, #15 @ r2<- A 8242 GET_INST_OPCODE(ip) @ extract opcode from rINST 8243 SET_VREG(r0, r2) @ fp[A]<- r0 8244 GOTO_OPCODE(ip) @ jump to next instruction 8245 8246 8247/* continuation for OP_IGET_CHAR */ 8248 8249 /* 8250 * Currently: 8251 * r0 holds resolved field 8252 * r9 holds object 8253 */ 8254.LOP_IGET_CHAR_finish: 8255 @bl common_squeak3 8256 cmp r9, #0 @ check object for null 8257 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8258 beq common_errNullObject @ object was null 8259 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8260 mov r2, rINST, lsr #8 @ r2<- A+ 8261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8262 and r2, r2, #15 @ r2<- A 8263 GET_INST_OPCODE(ip) @ extract opcode from rINST 8264 SET_VREG(r0, r2) @ fp[A]<- r0 8265 GOTO_OPCODE(ip) @ jump to next instruction 8266 8267 8268/* continuation for OP_IGET_SHORT */ 8269 8270 /* 8271 * Currently: 8272 * r0 holds resolved field 8273 * r9 holds object 8274 */ 8275.LOP_IGET_SHORT_finish: 8276 @bl common_squeak4 8277 cmp r9, #0 @ check object for null 8278 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8279 beq common_errNullObject @ object was null 8280 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8281 mov r2, rINST, lsr #8 @ r2<- A+ 8282 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8283 and r2, r2, #15 @ r2<- A 8284 GET_INST_OPCODE(ip) @ extract opcode from rINST 8285 SET_VREG(r0, r2) @ fp[A]<- r0 8286 GOTO_OPCODE(ip) @ jump to next instruction 8287 8288 8289/* continuation for OP_IPUT */ 8290 8291 /* 8292 * Currently: 8293 * r0 holds resolved field 8294 * r9 holds object 8295 */ 8296.LOP_IPUT_finish: 8297 @bl common_squeak0 8298 mov r1, rINST, lsr #8 @ r1<- A+ 8299 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8300 and r1, r1, #15 @ r1<- A 8301 cmp r9, #0 @ check object for null 8302 GET_VREG(r0, r1) @ r0<- fp[A] 8303 beq common_errNullObject @ object was null 8304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8305 GET_INST_OPCODE(ip) @ extract opcode from rINST 8306 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8307 GOTO_OPCODE(ip) @ jump to next instruction 8308 8309 8310/* continuation for OP_IPUT_WIDE */ 8311 8312 /* 8313 * Currently: 8314 * r0 holds resolved field 8315 * r9 holds object 8316 */ 8317.LOP_IPUT_WIDE_finish: 8318 mov r2, rINST, lsr #8 @ r2<- A+ 8319 cmp r9, #0 @ check object for null 8320 and r2, r2, #15 @ r2<- A 8321 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8322 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8323 beq common_errNullObject @ object was null 8324 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8325 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8326 GET_INST_OPCODE(ip) @ extract opcode from rINST 8327 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8328 GOTO_OPCODE(ip) @ jump to next instruction 8329 8330 8331/* continuation for OP_IPUT_OBJECT */ 8332 8333 /* 8334 * Currently: 8335 * r0 holds resolved field 8336 * r9 holds object 8337 */ 8338.LOP_IPUT_OBJECT_finish: 8339 @bl common_squeak0 8340 mov r1, rINST, lsr #8 @ r1<- A+ 8341 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8342 and r1, r1, #15 @ r1<- A 8343 cmp r9, #0 @ check object for null 8344 GET_VREG(r0, r1) @ r0<- fp[A] 8345 beq common_errNullObject @ object was null 8346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8347 GET_INST_OPCODE(ip) @ extract opcode from rINST 8348 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8349 GOTO_OPCODE(ip) @ jump to next instruction 8350 8351 8352/* continuation for OP_IPUT_BOOLEAN */ 8353 8354 /* 8355 * Currently: 8356 * r0 holds resolved field 8357 * r9 holds object 8358 */ 8359.LOP_IPUT_BOOLEAN_finish: 8360 @bl common_squeak1 8361 mov r1, rINST, lsr #8 @ r1<- A+ 8362 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8363 and r1, r1, #15 @ r1<- A 8364 cmp r9, #0 @ check object for null 8365 GET_VREG(r0, r1) @ r0<- fp[A] 8366 beq common_errNullObject @ object was null 8367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8368 GET_INST_OPCODE(ip) @ extract opcode from rINST 8369 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8370 GOTO_OPCODE(ip) @ jump to next instruction 8371 8372 8373/* continuation for OP_IPUT_BYTE */ 8374 8375 /* 8376 * Currently: 8377 * r0 holds resolved field 8378 * r9 holds object 8379 */ 8380.LOP_IPUT_BYTE_finish: 8381 @bl common_squeak2 8382 mov r1, rINST, lsr #8 @ r1<- A+ 8383 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8384 and r1, r1, #15 @ r1<- A 8385 cmp r9, #0 @ check object for null 8386 GET_VREG(r0, r1) @ r0<- fp[A] 8387 beq common_errNullObject @ object was null 8388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8389 GET_INST_OPCODE(ip) @ extract opcode from rINST 8390 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8391 GOTO_OPCODE(ip) @ jump to next instruction 8392 8393 8394/* continuation for OP_IPUT_CHAR */ 8395 8396 /* 8397 * Currently: 8398 * r0 holds resolved field 8399 * r9 holds object 8400 */ 8401.LOP_IPUT_CHAR_finish: 8402 @bl common_squeak3 8403 mov r1, rINST, lsr #8 @ r1<- A+ 8404 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8405 and r1, r1, #15 @ r1<- A 8406 cmp r9, #0 @ check object for null 8407 GET_VREG(r0, r1) @ r0<- fp[A] 8408 beq common_errNullObject @ object was null 8409 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8410 GET_INST_OPCODE(ip) @ extract opcode from rINST 8411 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8412 GOTO_OPCODE(ip) @ jump to next instruction 8413 8414 8415/* continuation for OP_IPUT_SHORT */ 8416 8417 /* 8418 * Currently: 8419 * r0 holds resolved field 8420 * r9 holds object 8421 */ 8422.LOP_IPUT_SHORT_finish: 8423 @bl common_squeak4 8424 mov r1, rINST, lsr #8 @ r1<- A+ 8425 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8426 and r1, r1, #15 @ r1<- A 8427 cmp r9, #0 @ check object for null 8428 GET_VREG(r0, r1) @ r0<- fp[A] 8429 beq common_errNullObject @ object was null 8430 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8431 GET_INST_OPCODE(ip) @ extract opcode from rINST 8432 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8433 GOTO_OPCODE(ip) @ jump to next instruction 8434 8435 8436/* continuation for OP_SGET */ 8437 8438 /* 8439 * Continuation if the field has not yet been resolved. 8440 * r1: BBBB field ref 8441 */ 8442.LOP_SGET_resolve: 8443 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8444 EXPORT_PC() @ resolve() could throw, so export now 8445 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8446 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8447 cmp r0, #0 @ success? 8448 bne .LOP_SGET_finish @ yes, finish 8449 b common_exceptionThrown @ no, handle exception 8450 8451 8452/* continuation for OP_SGET_WIDE */ 8453 8454 /* 8455 * Continuation if the field has not yet been resolved. 8456 * r1: BBBB field ref 8457 */ 8458.LOP_SGET_WIDE_resolve: 8459 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8460 EXPORT_PC() @ resolve() could throw, so export now 8461 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8462 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8463 cmp r0, #0 @ success? 8464 bne .LOP_SGET_WIDE_finish @ yes, finish 8465 b common_exceptionThrown @ no, handle exception 8466 8467 8468/* continuation for OP_SGET_OBJECT */ 8469 8470 /* 8471 * Continuation if the field has not yet been resolved. 8472 * r1: BBBB field ref 8473 */ 8474.LOP_SGET_OBJECT_resolve: 8475 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8476 EXPORT_PC() @ resolve() could throw, so export now 8477 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8478 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8479 cmp r0, #0 @ success? 8480 bne .LOP_SGET_OBJECT_finish @ yes, finish 8481 b common_exceptionThrown @ no, handle exception 8482 8483 8484/* continuation for OP_SGET_BOOLEAN */ 8485 8486 /* 8487 * Continuation if the field has not yet been resolved. 8488 * r1: BBBB field ref 8489 */ 8490.LOP_SGET_BOOLEAN_resolve: 8491 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8492 EXPORT_PC() @ resolve() could throw, so export now 8493 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8494 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8495 cmp r0, #0 @ success? 8496 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8497 b common_exceptionThrown @ no, handle exception 8498 8499 8500/* continuation for OP_SGET_BYTE */ 8501 8502 /* 8503 * Continuation if the field has not yet been resolved. 8504 * r1: BBBB field ref 8505 */ 8506.LOP_SGET_BYTE_resolve: 8507 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8508 EXPORT_PC() @ resolve() could throw, so export now 8509 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8510 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8511 cmp r0, #0 @ success? 8512 bne .LOP_SGET_BYTE_finish @ yes, finish 8513 b common_exceptionThrown @ no, handle exception 8514 8515 8516/* continuation for OP_SGET_CHAR */ 8517 8518 /* 8519 * Continuation if the field has not yet been resolved. 8520 * r1: BBBB field ref 8521 */ 8522.LOP_SGET_CHAR_resolve: 8523 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8524 EXPORT_PC() @ resolve() could throw, so export now 8525 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8526 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8527 cmp r0, #0 @ success? 8528 bne .LOP_SGET_CHAR_finish @ yes, finish 8529 b common_exceptionThrown @ no, handle exception 8530 8531 8532/* continuation for OP_SGET_SHORT */ 8533 8534 /* 8535 * Continuation if the field has not yet been resolved. 8536 * r1: BBBB field ref 8537 */ 8538.LOP_SGET_SHORT_resolve: 8539 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8540 EXPORT_PC() @ resolve() could throw, so export now 8541 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8542 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8543 cmp r0, #0 @ success? 8544 bne .LOP_SGET_SHORT_finish @ yes, finish 8545 b common_exceptionThrown @ no, handle exception 8546 8547 8548/* continuation for OP_SPUT */ 8549 8550 /* 8551 * Continuation if the field has not yet been resolved. 8552 * r1: BBBB field ref 8553 */ 8554.LOP_SPUT_resolve: 8555 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8556 EXPORT_PC() @ resolve() could throw, so export now 8557 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8558 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8559 cmp r0, #0 @ success? 8560 bne .LOP_SPUT_finish @ yes, finish 8561 b common_exceptionThrown @ no, handle exception 8562 8563 8564/* continuation for OP_SPUT_WIDE */ 8565 8566 /* 8567 * Continuation if the field has not yet been resolved. 8568 * r1: BBBB field ref 8569 * r9: &fp[AA] 8570 */ 8571.LOP_SPUT_WIDE_resolve: 8572 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8573 EXPORT_PC() @ resolve() could throw, so export now 8574 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8575 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8576 cmp r0, #0 @ success? 8577 bne .LOP_SPUT_WIDE_finish @ yes, finish 8578 b common_exceptionThrown @ no, handle exception 8579 8580 8581/* continuation for OP_SPUT_OBJECT */ 8582 8583 /* 8584 * Continuation if the field has not yet been resolved. 8585 * r1: BBBB field ref 8586 */ 8587.LOP_SPUT_OBJECT_resolve: 8588 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8589 EXPORT_PC() @ resolve() could throw, so export now 8590 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8591 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8592 cmp r0, #0 @ success? 8593 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8594 b common_exceptionThrown @ no, handle exception 8595 8596 8597/* continuation for OP_SPUT_BOOLEAN */ 8598 8599 /* 8600 * Continuation if the field has not yet been resolved. 8601 * r1: BBBB field ref 8602 */ 8603.LOP_SPUT_BOOLEAN_resolve: 8604 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8605 EXPORT_PC() @ resolve() could throw, so export now 8606 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8607 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8608 cmp r0, #0 @ success? 8609 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8610 b common_exceptionThrown @ no, handle exception 8611 8612 8613/* continuation for OP_SPUT_BYTE */ 8614 8615 /* 8616 * Continuation if the field has not yet been resolved. 8617 * r1: BBBB field ref 8618 */ 8619.LOP_SPUT_BYTE_resolve: 8620 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8621 EXPORT_PC() @ resolve() could throw, so export now 8622 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8623 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8624 cmp r0, #0 @ success? 8625 bne .LOP_SPUT_BYTE_finish @ yes, finish 8626 b common_exceptionThrown @ no, handle exception 8627 8628 8629/* continuation for OP_SPUT_CHAR */ 8630 8631 /* 8632 * Continuation if the field has not yet been resolved. 8633 * r1: BBBB field ref 8634 */ 8635.LOP_SPUT_CHAR_resolve: 8636 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8637 EXPORT_PC() @ resolve() could throw, so export now 8638 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8639 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8640 cmp r0, #0 @ success? 8641 bne .LOP_SPUT_CHAR_finish @ yes, finish 8642 b common_exceptionThrown @ no, handle exception 8643 8644 8645/* continuation for OP_SPUT_SHORT */ 8646 8647 /* 8648 * Continuation if the field has not yet been resolved. 8649 * r1: BBBB field ref 8650 */ 8651.LOP_SPUT_SHORT_resolve: 8652 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8653 EXPORT_PC() @ resolve() could throw, so export now 8654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8655 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8656 cmp r0, #0 @ success? 8657 bne .LOP_SPUT_SHORT_finish @ yes, finish 8658 b common_exceptionThrown @ no, handle exception 8659 8660 8661/* continuation for OP_INVOKE_VIRTUAL */ 8662 8663 /* 8664 * At this point: 8665 * r0 = resolved base method 8666 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8667 */ 8668.LOP_INVOKE_VIRTUAL_continue: 8669 GET_VREG(r1, r10) @ r1<- "this" ptr 8670 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8671 cmp r1, #0 @ is "this" null? 8672 beq common_errNullObject @ null "this", throw exception 8673 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8674 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8675 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8676 bl common_invokeMethodNoRange @ continue on 8677 8678 8679/* continuation for OP_INVOKE_SUPER */ 8680 8681 /* 8682 * At this point: 8683 * r0 = resolved base method 8684 * r9 = method->clazz 8685 */ 8686.LOP_INVOKE_SUPER_continue: 8687 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8688 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8689 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8690 EXPORT_PC() @ must export for invoke 8691 cmp r2, r3 @ compare (methodIndex, vtableCount) 8692 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8693 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8694 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8695 bl common_invokeMethodNoRange @ continue on 8696 8697.LOP_INVOKE_SUPER_resolve: 8698 mov r0, r9 @ r0<- method->clazz 8699 mov r2, #METHOD_VIRTUAL @ resolver method type 8700 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8701 cmp r0, #0 @ got null? 8702 bne .LOP_INVOKE_SUPER_continue @ no, continue 8703 b common_exceptionThrown @ yes, handle exception 8704 8705 /* 8706 * Throw a NoSuchMethodError with the method name as the message. 8707 * r0 = resolved base method 8708 */ 8709.LOP_INVOKE_SUPER_nsm: 8710 ldr r1, [r0, #offMethod_name] @ r1<- method name 8711 b common_errNoSuchMethod 8712 8713 8714/* continuation for OP_INVOKE_DIRECT */ 8715 8716 /* 8717 * On entry: 8718 * r1 = reference (BBBB or CCCC) 8719 * r10 = "this" register 8720 */ 8721.LOP_INVOKE_DIRECT_resolve: 8722 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8723 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8724 mov r2, #METHOD_DIRECT @ resolver method type 8725 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8726 cmp r0, #0 @ got null? 8727 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8728 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8729 b common_exceptionThrown @ yes, handle exception 8730 8731 8732/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8733 8734 /* 8735 * At this point: 8736 * r0 = resolved base method 8737 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8738 */ 8739.LOP_INVOKE_VIRTUAL_RANGE_continue: 8740 GET_VREG(r1, r10) @ r1<- "this" ptr 8741 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8742 cmp r1, #0 @ is "this" null? 8743 beq common_errNullObject @ null "this", throw exception 8744 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8745 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8746 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8747 bl common_invokeMethodRange @ continue on 8748 8749 8750/* continuation for OP_INVOKE_SUPER_RANGE */ 8751 8752 /* 8753 * At this point: 8754 * r0 = resolved base method 8755 * r9 = method->clazz 8756 */ 8757.LOP_INVOKE_SUPER_RANGE_continue: 8758 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8759 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8760 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8761 EXPORT_PC() @ must export for invoke 8762 cmp r2, r3 @ compare (methodIndex, vtableCount) 8763 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8764 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8765 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8766 bl common_invokeMethodRange @ continue on 8767 8768.LOP_INVOKE_SUPER_RANGE_resolve: 8769 mov r0, r9 @ r0<- method->clazz 8770 mov r2, #METHOD_VIRTUAL @ resolver method type 8771 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8772 cmp r0, #0 @ got null? 8773 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8774 b common_exceptionThrown @ yes, handle exception 8775 8776 /* 8777 * Throw a NoSuchMethodError with the method name as the message. 8778 * r0 = resolved base method 8779 */ 8780.LOP_INVOKE_SUPER_RANGE_nsm: 8781 ldr r1, [r0, #offMethod_name] @ r1<- method name 8782 b common_errNoSuchMethod 8783 8784 8785/* continuation for OP_INVOKE_DIRECT_RANGE */ 8786 8787 /* 8788 * On entry: 8789 * r1 = reference (BBBB or CCCC) 8790 * r10 = "this" register 8791 */ 8792.LOP_INVOKE_DIRECT_RANGE_resolve: 8793 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8794 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8795 mov r2, #METHOD_DIRECT @ resolver method type 8796 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8797 cmp r0, #0 @ got null? 8798 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8799 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8800 b common_exceptionThrown @ yes, handle exception 8801 8802 8803/* continuation for OP_FLOAT_TO_LONG */ 8804/* 8805 * Convert the float in r0 to a long in r0/r1. 8806 * 8807 * We have to clip values to long min/max per the specification. The 8808 * expected common case is a "reasonable" value that converts directly 8809 * to modest integer. The EABI convert function isn't doing this for us. 8810 */ 8811f2l_doconv: 8812 stmfd sp!, {r4, lr} 8813 mov r1, #0x5f000000 @ (float)maxlong 8814 mov r4, r0 8815 bl __aeabi_fcmpge @ is arg >= maxlong? 8816 cmp r0, #0 @ nonzero == yes 8817 mvnne r0, #0 @ return maxlong (7fffffff) 8818 mvnne r1, #0x80000000 8819 ldmnefd sp!, {r4, pc} 8820 8821 mov r0, r4 @ recover arg 8822 mov r1, #0xdf000000 @ (float)minlong 8823 bl __aeabi_fcmple @ is arg <= minlong? 8824 cmp r0, #0 @ nonzero == yes 8825 movne r0, #0 @ return minlong (80000000) 8826 movne r1, #0x80000000 8827 ldmnefd sp!, {r4, pc} 8828 8829 mov r0, r4 @ recover arg 8830 mov r1, r4 8831 bl __aeabi_fcmpeq @ is arg == self? 8832 cmp r0, #0 @ zero == no 8833 moveq r1, #0 @ return zero for NaN 8834 ldmeqfd sp!, {r4, pc} 8835 8836 mov r0, r4 @ recover arg 8837 bl __aeabi_f2lz @ convert float to long 8838 ldmfd sp!, {r4, pc} 8839 8840 8841/* continuation for OP_DOUBLE_TO_LONG */ 8842/* 8843 * Convert the double in r0/r1 to a long in r0/r1. 8844 * 8845 * We have to clip values to long min/max per the specification. The 8846 * expected common case is a "reasonable" value that converts directly 8847 * to modest integer. The EABI convert function isn't doing this for us. 8848 */ 8849d2l_doconv: 8850 stmfd sp!, {r4, r5, lr} @ save regs 8851 mov r3, #0x43000000 @ maxlong, as a double (high word) 8852 add r3, #0x00e00000 @ 0x43e00000 8853 mov r2, #0 @ maxlong, as a double (low word) 8854 sub sp, sp, #4 @ align for EABI 8855 mov r4, r0 @ save a copy of r0 8856 mov r5, r1 @ and r1 8857 bl __aeabi_dcmpge @ is arg >= maxlong? 8858 cmp r0, #0 @ nonzero == yes 8859 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8860 mvnne r1, #0x80000000 8861 bne 1f 8862 8863 mov r0, r4 @ recover arg 8864 mov r1, r5 8865 mov r3, #0xc3000000 @ minlong, as a double (high word) 8866 add r3, #0x00e00000 @ 0xc3e00000 8867 mov r2, #0 @ minlong, as a double (low word) 8868 bl __aeabi_dcmple @ is arg <= minlong? 8869 cmp r0, #0 @ nonzero == yes 8870 movne r0, #0 @ return minlong (8000000000000000) 8871 movne r1, #0x80000000 8872 bne 1f 8873 8874 mov r0, r4 @ recover arg 8875 mov r1, r5 8876 mov r2, r4 @ compare against self 8877 mov r3, r5 8878 bl __aeabi_dcmpeq @ is arg == self? 8879 cmp r0, #0 @ zero == no 8880 moveq r1, #0 @ return zero for NaN 8881 beq 1f 8882 8883 mov r0, r4 @ recover arg 8884 mov r1, r5 8885 bl __aeabi_d2lz @ convert double to long 8886 88871: 8888 add sp, sp, #4 8889 ldmfd sp!, {r4, r5, pc} 8890 8891 8892/* continuation for OP_MUL_LONG */ 8893 8894.LOP_MUL_LONG_finish: 8895 GET_INST_OPCODE(ip) @ extract opcode from rINST 8896 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8897 GOTO_OPCODE(ip) @ jump to next instruction 8898 8899 8900/* continuation for OP_SHL_LONG */ 8901 8902.LOP_SHL_LONG_finish: 8903 mov r0, r0, asl r2 @ r0<- r0 << r2 8904 GET_INST_OPCODE(ip) @ extract opcode from rINST 8905 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8906 GOTO_OPCODE(ip) @ jump to next instruction 8907 8908 8909/* continuation for OP_SHR_LONG */ 8910 8911.LOP_SHR_LONG_finish: 8912 mov r1, r1, asr r2 @ r1<- r1 >> r2 8913 GET_INST_OPCODE(ip) @ extract opcode from rINST 8914 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8915 GOTO_OPCODE(ip) @ jump to next instruction 8916 8917 8918/* continuation for OP_USHR_LONG */ 8919 8920.LOP_USHR_LONG_finish: 8921 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8922 GET_INST_OPCODE(ip) @ extract opcode from rINST 8923 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8924 GOTO_OPCODE(ip) @ jump to next instruction 8925 8926 8927/* continuation for OP_SHL_LONG_2ADDR */ 8928 8929.LOP_SHL_LONG_2ADDR_finish: 8930 GET_INST_OPCODE(ip) @ extract opcode from rINST 8931 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8932 GOTO_OPCODE(ip) @ jump to next instruction 8933 8934 8935/* continuation for OP_SHR_LONG_2ADDR */ 8936 8937.LOP_SHR_LONG_2ADDR_finish: 8938 GET_INST_OPCODE(ip) @ extract opcode from rINST 8939 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8940 GOTO_OPCODE(ip) @ jump to next instruction 8941 8942 8943/* continuation for OP_USHR_LONG_2ADDR */ 8944 8945.LOP_USHR_LONG_2ADDR_finish: 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_EXECUTE_INLINE */ 8952 8953 /* 8954 * Extract args, call function. 8955 * r0 = #of args (0-4) 8956 * r10 = call index 8957 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8958 * 8959 * Other ideas: 8960 * - Use a jump table from the main piece to jump directly into the 8961 * AND/LDR pairs. Costs a data load, saves a branch. 8962 * - Have five separate pieces that do the loading, so we can work the 8963 * interleave a little better. Increases code size. 8964 */ 8965.LOP_EXECUTE_INLINE_continue: 8966 rsb r0, r0, #4 @ r0<- 4-r0 8967 FETCH(r9, 2) @ r9<- FEDC 8968 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8969 bl common_abort @ (skipped due to ARM prefetch) 89704: and ip, r9, #0xf000 @ isolate F 8971 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89723: and ip, r9, #0x0f00 @ isolate E 8973 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 89742: and ip, r9, #0x00f0 @ isolate D 8975 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 89761: and ip, r9, #0x000f @ isolate C 8977 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 89780: 8979 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 8980 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 8981 @ (not reached) 8982 8983.LOP_EXECUTE_INLINE_table: 8984 .word gDvmInlineOpsTable 8985 8986 8987 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8988 .global dvmAsmSisterEnd 8989dvmAsmSisterEnd: 8990 8991/* File: armv5te/footer.S */ 8992 8993/* 8994 * =========================================================================== 8995 * Common subroutines and data 8996 * =========================================================================== 8997 */ 8998 8999 9000 9001 .text 9002 .align 2 9003 9004#if defined(WITH_JIT) 9005#if defined(WITH_SELF_VERIFICATION) 9006 .global dvmJitToInterpPunt 9007dvmJitToInterpPunt: 9008 mov r2,#kSVSPunt @ r2<- interpreter entry point 9009 b dvmJitSelfVerificationEnd @ doesn't return 9010 9011 .global dvmJitToInterpSingleStep 9012dvmJitToInterpSingleStep: 9013 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9014 b dvmJitSelfVerificationEnd @ doesn't return 9015 9016 .global dvmJitToTraceSelect 9017dvmJitToTraceSelect: 9018 ldr r0,[lr, #-1] @ pass our target PC 9019 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9020 b dvmJitSelfVerificationEnd @ doesn't return 9021 9022 .global dvmJitToBackwardBranch 9023dvmJitToBackwardBranch: 9024 ldr r0,[lr, #-1] @ pass our target PC 9025 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9026 b dvmJitSelfVerificationEnd @ doesn't return 9027 9028 .global dvmJitToInterpNormal 9029dvmJitToInterpNormal: 9030 ldr r0,[lr, #-1] @ pass our target PC 9031 mov r2,#kSVSNormal @ r2<- interpreter entry point 9032 b dvmJitSelfVerificationEnd @ doesn't return 9033 9034 .global dvmJitToInterpNoChain 9035dvmJitToInterpNoChain: 9036 mov r0,rPC @ pass our target PC 9037 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9038 b dvmJitSelfVerificationEnd @ doesn't return 9039#else 9040/* 9041 * Return from the translation cache to the interpreter when the compiler is 9042 * having issues translating/executing a Dalvik instruction. We have to skip 9043 * the code cache lookup otherwise it is possible to indefinitely bouce 9044 * between the interpreter and the code cache if the instruction that fails 9045 * to be compiled happens to be at a trace start. 9046 */ 9047 .global dvmJitToInterpPunt 9048dvmJitToInterpPunt: 9049 mov rPC, r0 9050#ifdef EXIT_STATS 9051 mov r0,lr 9052 bl dvmBumpPunt; 9053#endif 9054 EXPORT_PC() 9055 adrl rIBASE, dvmAsmInstructionStart 9056 FETCH_INST() 9057 GET_INST_OPCODE(ip) 9058 GOTO_OPCODE(ip) 9059 9060/* 9061 * Return to the interpreter to handle a single instruction. 9062 * On entry: 9063 * r0 <= PC 9064 * r1 <= PC of resume instruction 9065 * lr <= resume point in translation 9066 */ 9067 .global dvmJitToInterpSingleStep 9068dvmJitToInterpSingleStep: 9069 str lr,[rGLUE,#offGlue_jitResume] 9070 str r1,[rGLUE,#offGlue_jitResumePC] 9071 mov r1,#kInterpEntryInstr 9072 @ enum is 4 byte in aapcs-EABI 9073 str r1, [rGLUE, #offGlue_entryPoint] 9074 mov rPC,r0 9075 EXPORT_PC() 9076 adrl rIBASE, dvmAsmInstructionStart 9077 mov r2,#kJitSingleStep @ Ask for single step and then revert 9078 str r2,[rGLUE,#offGlue_jitState] 9079 mov r1,#1 @ set changeInterp to bail to debug interp 9080 b common_gotoBail 9081 9082 9083/* 9084 * Return from the translation cache and immediately request 9085 * a translation for the exit target. Commonly used following 9086 * invokes. 9087 */ 9088 .global dvmJitToTraceSelect 9089dvmJitToTraceSelect: 9090 ldr rPC,[lr, #-1] @ get our target PC 9091 add rINST,lr,#-5 @ save start of chain branch 9092 mov r0,rPC 9093 bl dvmJitGetCodeAddr @ Is there a translation? 9094 cmp r0,#0 9095 beq 2f 9096 mov r1,rINST 9097 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9098 mov r1, rPC @ arg1 of translation may need this 9099 mov lr, #0 @ in case target is HANDLER_INTERPRET 9100 cmp r0,#0 @ successful chain? 9101 bxne r0 @ continue native execution 9102 b toInterpreter @ didn't chain - resume with interpreter 9103 9104/* No translation, so request one if profiling isn't disabled*/ 91052: 9106 adrl rIBASE, dvmAsmInstructionStart 9107 GET_JIT_PROF_TABLE(r0) 9108 FETCH_INST() 9109 cmp r0, #0 9110 bne common_selectTrace 9111 GET_INST_OPCODE(ip) 9112 GOTO_OPCODE(ip) 9113 9114/* 9115 * Return from the translation cache to the interpreter. 9116 * The return was done with a BLX from thumb mode, and 9117 * the following 32-bit word contains the target rPC value. 9118 * Note that lr (r14) will have its low-order bit set to denote 9119 * its thumb-mode origin. 9120 * 9121 * We'll need to stash our lr origin away, recover the new 9122 * target and then check to see if there is a translation available 9123 * for our new target. If so, we do a translation chain and 9124 * go back to native execution. Otherwise, it's back to the 9125 * interpreter (after treating this entry as a potential 9126 * trace start). 9127 */ 9128 .global dvmJitToInterpNormal 9129dvmJitToInterpNormal: 9130 ldr rPC,[lr, #-1] @ get our target PC 9131 add rINST,lr,#-5 @ save start of chain branch 9132#ifdef EXIT_STATS 9133 bl dvmBumpNormal 9134#endif 9135 mov r0,rPC 9136 bl dvmJitGetCodeAddr @ Is there a translation? 9137 cmp r0,#0 9138 beq toInterpreter @ go if not, otherwise do chain 9139 mov r1,rINST 9140 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9141 mov r1, rPC @ arg1 of translation may need this 9142 mov lr, #0 @ in case target is HANDLER_INTERPRET 9143 cmp r0,#0 @ successful chain? 9144 bxne r0 @ continue native execution 9145 b toInterpreter @ didn't chain - resume with interpreter 9146 9147/* 9148 * Return from the translation cache to the interpreter to do method invocation. 9149 * Check if translation exists for the callee, but don't chain to it. 9150 */ 9151 .global dvmJitToInterpNoChain 9152dvmJitToInterpNoChain: 9153#ifdef EXIT_STATS 9154 bl dvmBumpNoChain 9155#endif 9156 mov r0,rPC 9157 bl dvmJitGetCodeAddr @ Is there a translation? 9158 mov r1, rPC @ arg1 of translation may need this 9159 mov lr, #0 @ in case target is HANDLER_INTERPRET 9160 cmp r0,#0 9161 bxne r0 @ continue native execution if so 9162#endif 9163 9164/* 9165 * No translation, restore interpreter regs and start interpreting. 9166 * rGLUE & rFP were preserved in the translated code, and rPC has 9167 * already been restored by the time we get here. We'll need to set 9168 * up rIBASE & rINST, and load the address of the JitTable into r0. 9169 */ 9170toInterpreter: 9171 EXPORT_PC() 9172 adrl rIBASE, dvmAsmInstructionStart 9173 FETCH_INST() 9174 GET_JIT_PROF_TABLE(r0) 9175 @ NOTE: intended fallthrough 9176/* 9177 * Common code to update potential trace start counter, and initiate 9178 * a trace-build if appropriate. On entry, rPC should point to the 9179 * next instruction to execute, and rINST should be already loaded with 9180 * the next opcode word, and r0 holds a pointer to the jit profile 9181 * table (pJitProfTable). 9182 */ 9183common_testUpdateProfile: 9184 cmp r0,#0 9185 GET_INST_OPCODE(ip) 9186 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9187 9188common_updateProfile: 9189 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9190 lsl r3,r3,#23 @ shift out excess 511 9191 ldrb r1,[r0,r3,lsr #23] @ get counter 9192 GET_INST_OPCODE(ip) 9193 subs r1,r1,#1 @ decrement counter 9194 strb r1,[r0,r3,lsr #23] @ and store it 9195 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9196 9197/* 9198 * Here, we switch to the debug interpreter to request 9199 * trace selection. First, though, check to see if there 9200 * is already a native translation in place (and, if so, 9201 * jump to it now). 9202 */ 9203 GET_JIT_THRESHOLD(r1) 9204 strb r1,[r0,r3,lsr #23] @ reset counter 9205 EXPORT_PC() 9206 mov r0,rPC 9207 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9208 mov r1, rPC @ arg1 of translation may need this 9209 mov lr, #0 @ in case target is HANDLER_INTERPRET 9210 cmp r0,#0 9211#if !defined(WITH_SELF_VERIFICATION) 9212 bxne r0 @ jump to the translation 9213#else 9214 beq common_selectTrace 9215 /* 9216 * At this point, we have a target translation. However, if 9217 * that translation is actually the interpret-only pseudo-translation 9218 * we want to treat it the same as no translation. 9219 */ 9220 mov r10, r0 @ save target 9221 bl dvmCompilerGetInterpretTemplate 9222 cmp r0, r10 @ special case? 9223 bne dvmJitSelfVerificationStart @ set up self verification 9224 GET_INST_OPCODE(ip) 9225 GOTO_OPCODE(ip) 9226 /* no return */ 9227#endif 9228 9229common_selectTrace: 9230 mov r2,#kJitTSelectRequest @ ask for trace selection 9231 str r2,[rGLUE,#offGlue_jitState] 9232 mov r2,#kInterpEntryInstr @ normal entry reason 9233 str r2,[rGLUE,#offGlue_entryPoint] 9234 mov r1,#1 @ set changeInterp 9235 b common_gotoBail 9236 9237#if defined(WITH_SELF_VERIFICATION) 9238/* 9239 * Save PC and registers to shadow memory for self verification mode 9240 * before jumping to native translation. 9241 * On entry, r10 contains the address of the target translation. 9242 */ 9243dvmJitSelfVerificationStart: 9244 mov r0,rPC @ r0<- program counter 9245 mov r1,rFP @ r1<- frame pointer 9246 mov r2,rGLUE @ r2<- InterpState pointer 9247 mov r3,r10 @ r3<- target translation 9248 bl dvmSelfVerificationSaveState @ save registers to shadow space 9249 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9250 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9251 bx r10 @ jump to the translation 9252 9253/* 9254 * Restore PC, registers, and interpState to original values 9255 * before jumping back to the interpreter. 9256 */ 9257dvmJitSelfVerificationEnd: 9258 mov r1,rFP @ pass ending fp 9259 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9260 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9261 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9262 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9263 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9264 cmp r1,#0 @ check for punt condition 9265 beq 1f 9266 mov r2,#kJitSelfVerification @ ask for self verification 9267 str r2,[rGLUE,#offGlue_jitState] 9268 mov r2,#kInterpEntryInstr @ normal entry reason 9269 str r2,[rGLUE,#offGlue_entryPoint] 9270 mov r1,#1 @ set changeInterp 9271 b common_gotoBail 9272 92731: @ exit to interpreter without check 9274 EXPORT_PC() 9275 adrl rIBASE, dvmAsmInstructionStart 9276 FETCH_INST() 9277 GET_INST_OPCODE(ip) 9278 GOTO_OPCODE(ip) 9279#endif 9280 9281#endif 9282 9283/* 9284 * Common code when a backward branch is taken. 9285 * 9286 * On entry: 9287 * r9 is PC adjustment *in bytes* 9288 */ 9289common_backwardBranch: 9290 mov r0, #kInterpEntryInstr 9291 bl common_periodicChecks 9292#if defined(WITH_JIT) 9293 GET_JIT_PROF_TABLE(r0) 9294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9295 cmp r0,#0 9296 bne common_updateProfile 9297 GET_INST_OPCODE(ip) 9298 GOTO_OPCODE(ip) 9299#else 9300 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9301 GET_INST_OPCODE(ip) @ extract opcode from rINST 9302 GOTO_OPCODE(ip) @ jump to next instruction 9303#endif 9304 9305 9306/* 9307 * Need to see if the thread needs to be suspended or debugger/profiler 9308 * activity has begun. 9309 * 9310 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9311 * have to do the second ldr. 9312 * 9313 * TODO: reduce this so we're just checking a single location. 9314 * 9315 * On entry: 9316 * r0 is reentry type, e.g. kInterpEntryInstr 9317 * r9 is trampoline PC adjustment *in bytes* 9318 */ 9319common_periodicChecks: 9320 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9321 9322 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9323 str r0, [rGLUE, #offGlue_entryPoint] 9324 9325#if defined(WITH_DEBUGGER) 9326 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9327#endif 9328#if defined(WITH_PROFILER) 9329 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9330#endif 9331 9332 ldr r3, [r3] @ r3<- suspendCount (int) 9333 9334#if defined(WITH_DEBUGGER) 9335 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9336#endif 9337#if defined (WITH_PROFILER) 9338 ldr r2, [r2] @ r2<- activeProfilers (int) 9339#endif 9340 9341 cmp r3, #0 @ suspend pending? 9342 bne 2f @ yes, do full suspension check 9343 9344#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9345# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9346 orrs r1, r1, r2 @ r1<- r1 | r2 9347 cmp r1, #0 @ debugger attached or profiler started? 9348# elif defined(WITH_DEBUGGER) 9349 cmp r1, #0 @ debugger attached? 9350# elif defined(WITH_PROFILER) 9351 cmp r2, #0 @ profiler started? 9352# endif 9353 bne 3f @ debugger/profiler, switch interp 9354#endif 9355 9356 bx lr @ nothing to do, return 9357 93582: @ check suspend 9359 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9360 EXPORT_PC() @ need for precise GC 9361 b dvmCheckSuspendPending @ suspend if necessary, then return 9362 93633: @ debugger/profiler enabled, bail out 9364 add rPC, rPC, r9 @ update rPC 9365 mov r1, #1 @ "want switch" = true 9366 b common_gotoBail 9367 9368 9369/* 9370 * The equivalent of "goto bail", this calls through the "bail handler". 9371 * 9372 * State registers will be saved to the "glue" area before bailing. 9373 * 9374 * On entry: 9375 * r1 is "bool changeInterp", indicating if we want to switch to the 9376 * other interpreter or just bail all the way out 9377 */ 9378common_gotoBail: 9379 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9380 mov r0, rGLUE @ r0<- glue ptr 9381 b dvmMterpStdBail @ call(glue, changeInterp) 9382 9383 @add r1, r1, #1 @ using (boolean+1) 9384 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9385 @bl _longjmp @ does not return 9386 @bl common_abort 9387 9388 9389/* 9390 * Common code for method invocation with range. 9391 * 9392 * On entry: 9393 * r0 is "Method* methodToCall", the method we're trying to call 9394 */ 9395common_invokeMethodRange: 9396.LinvokeNewRange: 9397 @ prepare to copy args to "outs" area of current frame 9398 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9399 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9400 beq .LinvokeArgsDone @ if no args, skip the rest 9401 FETCH(r1, 2) @ r1<- CCCC 9402 9403 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9404 @ (very few methods have > 10 args; could unroll for common cases) 9405 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9406 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9407 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94081: ldr r1, [r3], #4 @ val = *fp++ 9409 subs r2, r2, #1 @ count-- 9410 str r1, [r10], #4 @ *outs++ = val 9411 bne 1b @ ...while count != 0 9412 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9413 b .LinvokeArgsDone 9414 9415/* 9416 * Common code for method invocation without range. 9417 * 9418 * On entry: 9419 * r0 is "Method* methodToCall", the method we're trying to call 9420 */ 9421common_invokeMethodNoRange: 9422.LinvokeNewNoRange: 9423 @ prepare to copy args to "outs" area of current frame 9424 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9425 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9426 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9427 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9428 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9429 beq .LinvokeArgsDone 9430 9431 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9432.LinvokeNonRange: 9433 rsb r2, r2, #5 @ r2<- 5-r2 9434 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9435 bl common_abort @ (skipped due to ARM prefetch) 94365: and ip, rINST, #0x0f00 @ isolate A 9437 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9438 mov r0, r0 @ nop 9439 str r2, [r10, #-4]! @ *--outs = vA 94404: and ip, r1, #0xf000 @ isolate G 9441 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9442 mov r0, r0 @ nop 9443 str r2, [r10, #-4]! @ *--outs = vG 94443: and ip, r1, #0x0f00 @ isolate F 9445 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9446 mov r0, r0 @ nop 9447 str r2, [r10, #-4]! @ *--outs = vF 94482: and ip, r1, #0x00f0 @ isolate E 9449 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9450 mov r0, r0 @ nop 9451 str r2, [r10, #-4]! @ *--outs = vE 94521: and ip, r1, #0x000f @ isolate D 9453 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9454 mov r0, r0 @ nop 9455 str r2, [r10, #-4]! @ *--outs = vD 94560: @ fall through to .LinvokeArgsDone 9457 9458.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9459 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9460 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9461 @ find space for the new stack frame, check for overflow 9462 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9463 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9464 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9465@ bl common_dumpRegs 9466 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9467 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9468 cmp r3, r9 @ bottom < interpStackEnd? 9469 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9470 blt .LstackOverflow @ yes, this frame will overflow stack 9471 9472 @ set up newSaveArea 9473#ifdef EASY_GDB 9474 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9475 str ip, [r10, #offStackSaveArea_prevSave] 9476#endif 9477 str rFP, [r10, #offStackSaveArea_prevFrame] 9478 str rPC, [r10, #offStackSaveArea_savedPc] 9479#if defined(WITH_JIT) 9480 mov r9, #0 9481 str r9, [r10, #offStackSaveArea_returnAddr] 9482#endif 9483 str r0, [r10, #offStackSaveArea_method] 9484 tst r3, #ACC_NATIVE 9485 bne .LinvokeNative 9486 9487 /* 9488 stmfd sp!, {r0-r3} 9489 bl common_printNewline 9490 mov r0, rFP 9491 mov r1, #0 9492 bl dvmDumpFp 9493 ldmfd sp!, {r0-r3} 9494 stmfd sp!, {r0-r3} 9495 mov r0, r1 9496 mov r1, r10 9497 bl dvmDumpFp 9498 bl common_printNewline 9499 ldmfd sp!, {r0-r3} 9500 */ 9501 9502 ldrh r9, [r2] @ r9 <- load INST from new PC 9503 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9504 mov rPC, r2 @ publish new rPC 9505 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9506 9507 @ Update "glue" values for the new method 9508 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9509 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9510 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9511#if defined(WITH_JIT) 9512 GET_JIT_PROF_TABLE(r0) 9513 mov rFP, r1 @ fp = newFp 9514 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9515 mov rINST, r9 @ publish new rINST 9516 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9517 cmp r0,#0 9518 bne common_updateProfile 9519 GOTO_OPCODE(ip) @ jump to next instruction 9520#else 9521 mov rFP, r1 @ fp = newFp 9522 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9523 mov rINST, r9 @ publish new rINST 9524 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9525 GOTO_OPCODE(ip) @ jump to next instruction 9526#endif 9527 9528.LinvokeNative: 9529 @ Prep for the native call 9530 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9531 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9532 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9533 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9534 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9535 mov r9, r3 @ r9<- glue->self (preserve) 9536 9537 mov r2, r0 @ r2<- methodToCall 9538 mov r0, r1 @ r0<- newFp (points to args) 9539 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9540 9541#ifdef ASSIST_DEBUGGER 9542 /* insert fake function header to help gdb find the stack frame */ 9543 b .Lskip 9544 .type dalvik_mterp, %function 9545dalvik_mterp: 9546 .fnstart 9547 MTERP_ENTRY1 9548 MTERP_ENTRY2 9549.Lskip: 9550#endif 9551 9552 @mov lr, pc @ set return addr 9553 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9554 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9555 9556 @ native return; r9=self, r10=newSaveArea 9557 @ equivalent to dvmPopJniLocals 9558 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9559 ldr r1, [r9, #offThread_exception] @ check for exception 9560 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9561 cmp r1, #0 @ null? 9562 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9563 bne common_exceptionThrown @ no, handle exception 9564 9565 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9566 GET_INST_OPCODE(ip) @ extract opcode from rINST 9567 GOTO_OPCODE(ip) @ jump to next instruction 9568 9569.LstackOverflow: @ r0=methodToCall 9570 mov r1, r0 @ r1<- methodToCall 9571 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9572 bl dvmHandleStackOverflow 9573 b common_exceptionThrown 9574#ifdef ASSIST_DEBUGGER 9575 .fnend 9576#endif 9577 9578 9579 /* 9580 * Common code for method invocation, calling through "glue code". 9581 * 9582 * TODO: now that we have range and non-range invoke handlers, this 9583 * needs to be split into two. Maybe just create entry points 9584 * that set r9 and jump here? 9585 * 9586 * On entry: 9587 * r0 is "Method* methodToCall", the method we're trying to call 9588 * r9 is "bool methodCallRange", indicating if this is a /range variant 9589 */ 9590 .if 0 9591.LinvokeOld: 9592 sub sp, sp, #8 @ space for args + pad 9593 FETCH(ip, 2) @ ip<- FEDC or CCCC 9594 mov r2, r0 @ A2<- methodToCall 9595 mov r0, rGLUE @ A0<- glue 9596 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9597 mov r1, r9 @ A1<- methodCallRange 9598 mov r3, rINST, lsr #8 @ A3<- AA 9599 str ip, [sp, #0] @ A4<- ip 9600 bl dvmMterp_invokeMethod @ call the C invokeMethod 9601 add sp, sp, #8 @ remove arg area 9602 b common_resumeAfterGlueCall @ continue to next instruction 9603 .endif 9604 9605 9606 9607/* 9608 * Common code for handling a return instruction. 9609 * 9610 * This does not return. 9611 */ 9612common_returnFromMethod: 9613.LreturnNew: 9614 mov r0, #kInterpEntryReturn 9615 mov r9, #0 9616 bl common_periodicChecks 9617 9618 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9619 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9620 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9621 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9622 @ r2<- method we're returning to 9623 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9624 cmp r2, #0 @ is this a break frame? 9625 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9626 mov r1, #0 @ "want switch" = false 9627 beq common_gotoBail @ break frame, bail out completely 9628 9629 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9630 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9631 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9632 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9633#if defined(WITH_JIT) 9634 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr 9635 GET_JIT_PROF_TABLE(r0) 9636 mov rPC, r9 @ publish new rPC 9637 str r1, [rGLUE, #offGlue_methodClassDex] 9638 cmp r3, #0 @ caller is compiled code 9639 blxne r3 9640 GET_INST_OPCODE(ip) @ extract opcode from rINST 9641 cmp r0,#0 9642 bne common_updateProfile 9643 GOTO_OPCODE(ip) @ jump to next instruction 9644#else 9645 GET_INST_OPCODE(ip) @ extract opcode from rINST 9646 mov rPC, r9 @ publish new rPC 9647 str r1, [rGLUE, #offGlue_methodClassDex] 9648 GOTO_OPCODE(ip) @ jump to next instruction 9649#endif 9650 9651 /* 9652 * Return handling, calls through "glue code". 9653 */ 9654 .if 0 9655.LreturnOld: 9656 SAVE_PC_FP_TO_GLUE() @ export state 9657 mov r0, rGLUE @ arg to function 9658 bl dvmMterp_returnFromMethod 9659 b common_resumeAfterGlueCall 9660 .endif 9661 9662 9663/* 9664 * Somebody has thrown an exception. Handle it. 9665 * 9666 * If the exception processing code returns to us (instead of falling 9667 * out of the interpreter), continue with whatever the next instruction 9668 * now happens to be. 9669 * 9670 * This does not return. 9671 */ 9672 .global dvmMterpCommonExceptionThrown 9673dvmMterpCommonExceptionThrown: 9674common_exceptionThrown: 9675.LexceptionNew: 9676 mov r0, #kInterpEntryThrow 9677 mov r9, #0 9678 bl common_periodicChecks 9679 9680#if defined(WITH_JIT) 9681 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9682 str r2,[rGLUE,#offGlue_jitState] 9683#endif 9684 9685 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9686 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9687 mov r1, r10 @ r1<- self 9688 mov r0, r9 @ r0<- exception 9689 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9690 mov r3, #0 @ r3<- NULL 9691 str r3, [r10, #offThread_exception] @ self->exception = NULL 9692 9693 /* set up args and a local for "&fp" */ 9694 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9695 str rFP, [sp, #-4]! @ *--sp = fp 9696 mov ip, sp @ ip<- &fp 9697 mov r3, #0 @ r3<- false 9698 str ip, [sp, #-4]! @ *--sp = &fp 9699 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9700 mov r0, r10 @ r0<- self 9701 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9702 mov r2, r9 @ r2<- exception 9703 sub r1, rPC, r1 @ r1<- pc - method->insns 9704 mov r1, r1, asr #1 @ r1<- offset in code units 9705 9706 /* call, r0 gets catchRelPc (a code-unit offset) */ 9707 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9708 9709 /* fix earlier stack overflow if necessary; may trash rFP */ 9710 ldrb r1, [r10, #offThread_stackOverflowed] 9711 cmp r1, #0 @ did we overflow earlier? 9712 beq 1f @ no, skip ahead 9713 mov rFP, r0 @ save relPc result in rFP 9714 mov r0, r10 @ r0<- self 9715 bl dvmCleanupStackOverflow @ call(self) 9716 mov r0, rFP @ restore result 97171: 9718 9719 /* update frame pointer and check result from dvmFindCatchBlock */ 9720 ldr rFP, [sp, #4] @ retrieve the updated rFP 9721 cmp r0, #0 @ is catchRelPc < 0? 9722 add sp, sp, #8 @ restore stack 9723 bmi .LnotCaughtLocally 9724 9725 /* adjust locals to match self->curFrame and updated PC */ 9726 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9727 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9728 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9729 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9730 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9731 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9732 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9733 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9734 9735 /* release the tracked alloc on the exception */ 9736 mov r0, r9 @ r0<- exception 9737 mov r1, r10 @ r1<- self 9738 bl dvmReleaseTrackedAlloc @ release the exception 9739 9740 /* restore the exception if the handler wants it */ 9741 FETCH_INST() @ load rINST from rPC 9742 GET_INST_OPCODE(ip) @ extract opcode from rINST 9743 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9744 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9745 GOTO_OPCODE(ip) @ jump to next instruction 9746 9747.LnotCaughtLocally: @ r9=exception, r10=self 9748 /* fix stack overflow if necessary */ 9749 ldrb r1, [r10, #offThread_stackOverflowed] 9750 cmp r1, #0 @ did we overflow earlier? 9751 movne r0, r10 @ if yes: r0<- self 9752 blne dvmCleanupStackOverflow @ if yes: call(self) 9753 9754 @ may want to show "not caught locally" debug messages here 9755#if DVM_SHOW_EXCEPTION >= 2 9756 /* call __android_log_print(prio, tag, format, ...) */ 9757 /* "Exception %s from %s:%d not caught locally" */ 9758 @ dvmLineNumFromPC(method, pc - method->insns) 9759 ldr r0, [rGLUE, #offGlue_method] 9760 ldr r1, [r0, #offMethod_insns] 9761 sub r1, rPC, r1 9762 asr r1, r1, #1 9763 bl dvmLineNumFromPC 9764 str r0, [sp, #-4]! 9765 @ dvmGetMethodSourceFile(method) 9766 ldr r0, [rGLUE, #offGlue_method] 9767 bl dvmGetMethodSourceFile 9768 str r0, [sp, #-4]! 9769 @ exception->clazz->descriptor 9770 ldr r3, [r9, #offObject_clazz] 9771 ldr r3, [r3, #offClassObject_descriptor] 9772 @ 9773 ldr r2, strExceptionNotCaughtLocally 9774 ldr r1, strLogTag 9775 mov r0, #3 @ LOG_DEBUG 9776 bl __android_log_print 9777#endif 9778 str r9, [r10, #offThread_exception] @ restore exception 9779 mov r0, r9 @ r0<- exception 9780 mov r1, r10 @ r1<- self 9781 bl dvmReleaseTrackedAlloc @ release the exception 9782 mov r1, #0 @ "want switch" = false 9783 b common_gotoBail @ bail out 9784 9785 9786 /* 9787 * Exception handling, calls through "glue code". 9788 */ 9789 .if 0 9790.LexceptionOld: 9791 SAVE_PC_FP_TO_GLUE() @ export state 9792 mov r0, rGLUE @ arg to function 9793 bl dvmMterp_exceptionThrown 9794 b common_resumeAfterGlueCall 9795 .endif 9796 9797 9798/* 9799 * After returning from a "glued" function, pull out the updated 9800 * values and start executing at the next instruction. 9801 */ 9802common_resumeAfterGlueCall: 9803 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9804 FETCH_INST() @ load rINST from rPC 9805 GET_INST_OPCODE(ip) @ extract opcode from rINST 9806 GOTO_OPCODE(ip) @ jump to next instruction 9807 9808/* 9809 * Invalid array index. 9810 */ 9811common_errArrayIndex: 9812 EXPORT_PC() 9813 ldr r0, strArrayIndexException 9814 mov r1, #0 9815 bl dvmThrowException 9816 b common_exceptionThrown 9817 9818/* 9819 * Invalid array value. 9820 */ 9821common_errArrayStore: 9822 EXPORT_PC() 9823 ldr r0, strArrayStoreException 9824 mov r1, #0 9825 bl dvmThrowException 9826 b common_exceptionThrown 9827 9828/* 9829 * Integer divide or mod by zero. 9830 */ 9831common_errDivideByZero: 9832 EXPORT_PC() 9833 ldr r0, strArithmeticException 9834 ldr r1, strDivideByZero 9835 bl dvmThrowException 9836 b common_exceptionThrown 9837 9838/* 9839 * Attempt to allocate an array with a negative size. 9840 */ 9841common_errNegativeArraySize: 9842 EXPORT_PC() 9843 ldr r0, strNegativeArraySizeException 9844 mov r1, #0 9845 bl dvmThrowException 9846 b common_exceptionThrown 9847 9848/* 9849 * Invocation of a non-existent method. 9850 */ 9851common_errNoSuchMethod: 9852 EXPORT_PC() 9853 ldr r0, strNoSuchMethodError 9854 mov r1, #0 9855 bl dvmThrowException 9856 b common_exceptionThrown 9857 9858/* 9859 * We encountered a null object when we weren't expecting one. We 9860 * export the PC, throw a NullPointerException, and goto the exception 9861 * processing code. 9862 */ 9863common_errNullObject: 9864 EXPORT_PC() 9865 ldr r0, strNullPointerException 9866 mov r1, #0 9867 bl dvmThrowException 9868 b common_exceptionThrown 9869 9870/* 9871 * For debugging, cause an immediate fault. The source address will 9872 * be in lr (use a bl instruction to jump here). 9873 */ 9874common_abort: 9875 ldr pc, .LdeadFood 9876.LdeadFood: 9877 .word 0xdeadf00d 9878 9879/* 9880 * Spit out a "we were here", preserving all registers. (The attempt 9881 * to save ip won't work, but we need to save an even number of 9882 * registers for EABI 64-bit stack alignment.) 9883 */ 9884 .macro SQUEAK num 9885common_squeak\num: 9886 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9887 ldr r0, strSqueak 9888 mov r1, #\num 9889 bl printf 9890 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9891 bx lr 9892 .endm 9893 9894 SQUEAK 0 9895 SQUEAK 1 9896 SQUEAK 2 9897 SQUEAK 3 9898 SQUEAK 4 9899 SQUEAK 5 9900 9901/* 9902 * Spit out the number in r0, preserving registers. 9903 */ 9904common_printNum: 9905 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9906 mov r1, r0 9907 ldr r0, strSqueak 9908 bl printf 9909 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9910 bx lr 9911 9912/* 9913 * Print a newline, preserving registers. 9914 */ 9915common_printNewline: 9916 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9917 ldr r0, strNewline 9918 bl printf 9919 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9920 bx lr 9921 9922 /* 9923 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9924 */ 9925common_printHex: 9926 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9927 mov r1, r0 9928 ldr r0, strPrintHex 9929 bl printf 9930 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9931 bx lr 9932 9933/* 9934 * Print the 64-bit quantity in r0-r1, preserving registers. 9935 */ 9936common_printLong: 9937 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9938 mov r3, r1 9939 mov r2, r0 9940 ldr r0, strPrintLong 9941 bl printf 9942 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9943 bx lr 9944 9945/* 9946 * Print full method info. Pass the Method* in r0. Preserves regs. 9947 */ 9948common_printMethod: 9949 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9950 bl dvmMterpPrintMethod 9951 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9952 bx lr 9953 9954/* 9955 * Call a C helper function that dumps regs and possibly some 9956 * additional info. Requires the C function to be compiled in. 9957 */ 9958 .if 0 9959common_dumpRegs: 9960 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9961 bl dvmMterpDumpArmRegs 9962 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9963 bx lr 9964 .endif 9965 9966#if 0 9967/* 9968 * Experiment on VFP mode. 9969 * 9970 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 9971 * 9972 * Updates the bits specified by "mask", setting them to the values in "val". 9973 */ 9974setFPSCR: 9975 and r0, r0, r1 @ make sure no stray bits are set 9976 fmrx r2, fpscr @ get VFP reg 9977 mvn r1, r1 @ bit-invert mask 9978 and r2, r2, r1 @ clear masked bits 9979 orr r2, r2, r0 @ set specified bits 9980 fmxr fpscr, r2 @ set VFP reg 9981 mov r0, r2 @ return new value 9982 bx lr 9983 9984 .align 2 9985 .global dvmConfigureFP 9986 .type dvmConfigureFP, %function 9987dvmConfigureFP: 9988 stmfd sp!, {ip, lr} 9989 /* 0x03000000 sets DN/FZ */ 9990 /* 0x00009f00 clears the six exception enable flags */ 9991 bl common_squeak0 9992 mov r0, #0x03000000 @ r0<- 0x03000000 9993 add r1, r0, #0x9f00 @ r1<- 0x03009f00 9994 bl setFPSCR 9995 ldmfd sp!, {ip, pc} 9996#endif 9997 9998 9999/* 10000 * String references, must be close to the code that uses them. 10001 */ 10002 .align 2 10003strArithmeticException: 10004 .word .LstrArithmeticException 10005strArrayIndexException: 10006 .word .LstrArrayIndexException 10007strArrayStoreException: 10008 .word .LstrArrayStoreException 10009strDivideByZero: 10010 .word .LstrDivideByZero 10011strNegativeArraySizeException: 10012 .word .LstrNegativeArraySizeException 10013strNoSuchMethodError: 10014 .word .LstrNoSuchMethodError 10015strNullPointerException: 10016 .word .LstrNullPointerException 10017 10018strLogTag: 10019 .word .LstrLogTag 10020strExceptionNotCaughtLocally: 10021 .word .LstrExceptionNotCaughtLocally 10022 10023strNewline: 10024 .word .LstrNewline 10025strSqueak: 10026 .word .LstrSqueak 10027strPrintHex: 10028 .word .LstrPrintHex 10029strPrintLong: 10030 .word .LstrPrintLong 10031 10032/* 10033 * Zero-terminated ASCII string data. 10034 * 10035 * On ARM we have two choices: do like gcc does, and LDR from a .word 10036 * with the address, or use an ADR pseudo-op to get the address 10037 * directly. ADR saves 4 bytes and an indirection, but it's using a 10038 * PC-relative addressing mode and hence has a limited range, which 10039 * makes it not work well with mergeable string sections. 10040 */ 10041 .section .rodata.str1.4,"aMS",%progbits,1 10042 10043.LstrBadEntryPoint: 10044 .asciz "Bad entry point %d\n" 10045.LstrArithmeticException: 10046 .asciz "Ljava/lang/ArithmeticException;" 10047.LstrArrayIndexException: 10048 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10049.LstrArrayStoreException: 10050 .asciz "Ljava/lang/ArrayStoreException;" 10051.LstrClassCastException: 10052 .asciz "Ljava/lang/ClassCastException;" 10053.LstrDivideByZero: 10054 .asciz "divide by zero" 10055.LstrFilledNewArrayNotImpl: 10056 .asciz "filled-new-array only implemented for objects and 'int'" 10057.LstrInternalError: 10058 .asciz "Ljava/lang/InternalError;" 10059.LstrInstantiationError: 10060 .asciz "Ljava/lang/InstantiationError;" 10061.LstrNegativeArraySizeException: 10062 .asciz "Ljava/lang/NegativeArraySizeException;" 10063.LstrNoSuchMethodError: 10064 .asciz "Ljava/lang/NoSuchMethodError;" 10065.LstrNullPointerException: 10066 .asciz "Ljava/lang/NullPointerException;" 10067 10068.LstrLogTag: 10069 .asciz "mterp" 10070.LstrExceptionNotCaughtLocally: 10071 .asciz "Exception %s from %s:%d not caught locally\n" 10072 10073.LstrNewline: 10074 .asciz "\n" 10075.LstrSqueak: 10076 .asciz "<%d>" 10077.LstrPrintHex: 10078 .asciz "<0x%x>" 10079.LstrPrintLong: 10080 .asciz "<%lld>" 10081 10082 10083