InterpAsm-armv5te-vfp.S revision ccd6c0102d1f898aaea1c94761167fdd083b5275
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#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204 205/* File: armv5te/platform.S */ 206/* 207 * =========================================================================== 208 * CPU-version-specific defines 209 * =========================================================================== 210 */ 211 212/* 213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 214 * one-way branch. 215 * 216 * May modify IP. Does not modify LR. 217 */ 218.macro LDR_PC source 219 ldr pc, \source 220.endm 221 222/* 223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 224 * Jump to subroutine. 225 * 226 * May modify IP and LR. 227 */ 228.macro LDR_PC_LR source 229 mov lr, pc 230 ldr pc, \source 231.endm 232 233/* 234 * Macro for "LDMFD SP!, {...regs...,PC}". 235 * 236 * May modify IP and LR. 237 */ 238.macro LDMFD_PC regs 239 ldmfd sp!, {\regs,pc} 240.endm 241 242 243/* File: armv5te/entry.S */ 244/* 245 * Copyright (C) 2008 The Android Open Source Project 246 * 247 * Licensed under the Apache License, Version 2.0 (the "License"); 248 * you may not use this file except in compliance with the License. 249 * You may obtain a copy of the License at 250 * 251 * http://www.apache.org/licenses/LICENSE-2.0 252 * 253 * Unless required by applicable law or agreed to in writing, software 254 * distributed under the License is distributed on an "AS IS" BASIS, 255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 256 * See the License for the specific language governing permissions and 257 * limitations under the License. 258 */ 259/* 260 * Interpreter entry point. 261 */ 262 263/* 264 * We don't have formal stack frames, so gdb scans upward in the code 265 * to find the start of the function (a label with the %function type), 266 * and then looks at the next few instructions to figure out what 267 * got pushed onto the stack. From this it figures out how to restore 268 * the registers, including PC, for the previous stack frame. If gdb 269 * sees a non-function label, it stops scanning, so either we need to 270 * have nothing but assembler-local labels between the entry point and 271 * the break, or we need to fake it out. 272 * 273 * When this is defined, we add some stuff to make gdb less confused. 274 */ 275#define ASSIST_DEBUGGER 1 276 277 .text 278 .align 2 279 .global dvmMterpStdRun 280 .type dvmMterpStdRun, %function 281 282/* 283 * On entry: 284 * r0 MterpGlue* glue 285 * 286 * This function returns a boolean "changeInterp" value. The return comes 287 * via a call to dvmMterpStdBail(). 288 */ 289dvmMterpStdRun: 290#define MTERP_ENTRY1 \ 291 .save {r4-r10,fp,lr}; \ 292 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 293#define MTERP_ENTRY2 \ 294 .pad #4; \ 295 sub sp, sp, #4 @ align 64 296 297 .fnstart 298 MTERP_ENTRY1 299 MTERP_ENTRY2 300 301 /* save stack pointer, add magic word for debuggerd */ 302 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 303 304 /* set up "named" registers, figure out entry point */ 305 mov rGLUE, r0 @ set rGLUE 306 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 307 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 308 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 309 cmp r1, #kInterpEntryInstr @ usual case? 310 bne .Lnot_instr @ no, handle it 311 312#if defined(WITH_JIT) 313.Lno_singleStep: 314 /* Entry is always a possible trace start */ 315 GET_JIT_PROF_TABLE(r0) 316 FETCH_INST() 317 cmp r0,#0 318 bne common_updateProfile 319 GET_INST_OPCODE(ip) 320 GOTO_OPCODE(ip) 321#else 322 /* start executing the instruction at rPC */ 323 FETCH_INST() @ load rINST from rPC 324 GET_INST_OPCODE(ip) @ extract opcode from rINST 325 GOTO_OPCODE(ip) @ jump to next instruction 326#endif 327 328.Lnot_instr: 329 cmp r1, #kInterpEntryReturn @ were we returning from a method? 330 beq common_returnFromMethod 331 332.Lnot_return: 333 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 334 beq common_exceptionThrown 335 336#if defined(WITH_JIT) 337.Lnot_throw: 338 ldr r0,[rGLUE, #offGlue_jitResume] 339 ldr r2,[rGLUE, #offGlue_jitResumePC] 340 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 341 bne .Lbad_arg 342 cmp rPC,r2 343 bne .Lno_singleStep @ must have branched, don't resume 344 mov r1, #kInterpEntryInstr 345 strb r1, [rGLUE, #offGlue_entryPoint] 346 ldr rINST, .LdvmCompilerTemplate 347 bx r0 @ re-enter the translation 348.LdvmCompilerTemplate: 349 .word dvmCompilerTemplateStart 350#endif 351 352.Lbad_arg: 353 ldr r0, strBadEntryPoint 354 @ r1 holds value of entryPoint 355 bl printf 356 bl dvmAbort 357 .fnend 358 359 360 .global dvmMterpStdBail 361 .type dvmMterpStdBail, %function 362 363/* 364 * Restore the stack pointer and PC from the save point established on entry. 365 * This is essentially the same as a longjmp, but should be cheaper. The 366 * last instruction causes us to return to whoever called dvmMterpStdRun. 367 * 368 * We pushed some registers on the stack in dvmMterpStdRun, then saved 369 * SP and LR. Here we restore SP, restore the registers, and then restore 370 * LR to PC. 371 * 372 * On entry: 373 * r0 MterpGlue* glue 374 * r1 bool changeInterp 375 */ 376dvmMterpStdBail: 377 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 378 mov r0, r1 @ return the changeInterp value 379 add sp, sp, #4 @ un-align 64 380 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 381 382 383/* 384 * String references. 385 */ 386strBadEntryPoint: 387 .word .LstrBadEntryPoint 388 389 390 391 .global dvmAsmInstructionStart 392 .type dvmAsmInstructionStart, %function 393dvmAsmInstructionStart = .L_OP_NOP 394 .text 395 396/* ------------------------------ */ 397 .balign 64 398.L_OP_NOP: /* 0x00 */ 399/* File: armv5te/OP_NOP.S */ 400 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 401 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 402 GOTO_OPCODE(ip) @ execute it 403 404#ifdef ASSIST_DEBUGGER 405 /* insert fake function header to help gdb find the stack frame */ 406 .type dalvik_inst, %function 407dalvik_inst: 408 .fnstart 409 MTERP_ENTRY1 410 MTERP_ENTRY2 411 .fnend 412#endif 413 414 415/* ------------------------------ */ 416 .balign 64 417.L_OP_MOVE: /* 0x01 */ 418/* File: armv5te/OP_MOVE.S */ 419 /* for move, move-object, long-to-int */ 420 /* op vA, vB */ 421 mov r1, rINST, lsr #12 @ r1<- B from 15:12 422 mov r0, rINST, lsr #8 @ r0<- A from 11:8 423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 424 GET_VREG(r2, r1) @ r2<- fp[B] 425 and r0, r0, #15 426 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 427 SET_VREG(r2, r0) @ fp[A]<- r2 428 GOTO_OPCODE(ip) @ execute next instruction 429 430 431/* ------------------------------ */ 432 .balign 64 433.L_OP_MOVE_FROM16: /* 0x02 */ 434/* File: armv5te/OP_MOVE_FROM16.S */ 435 /* for: move/from16, move-object/from16 */ 436 /* op vAA, vBBBB */ 437 FETCH(r1, 1) @ r1<- BBBB 438 mov r0, rINST, lsr #8 @ r0<- AA 439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 440 GET_VREG(r2, r1) @ r2<- fp[BBBB] 441 GET_INST_OPCODE(ip) @ extract opcode from rINST 442 SET_VREG(r2, r0) @ fp[AA]<- r2 443 GOTO_OPCODE(ip) @ jump to next instruction 444 445 446/* ------------------------------ */ 447 .balign 64 448.L_OP_MOVE_16: /* 0x03 */ 449/* File: armv5te/OP_MOVE_16.S */ 450 /* for: move/16, move-object/16 */ 451 /* op vAAAA, vBBBB */ 452 FETCH(r1, 2) @ r1<- BBBB 453 FETCH(r0, 1) @ r0<- AAAA 454 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 455 GET_VREG(r2, r1) @ r2<- fp[BBBB] 456 GET_INST_OPCODE(ip) @ extract opcode from rINST 457 SET_VREG(r2, r0) @ fp[AAAA]<- r2 458 GOTO_OPCODE(ip) @ jump to next instruction 459 460 461/* ------------------------------ */ 462 .balign 64 463.L_OP_MOVE_WIDE: /* 0x04 */ 464/* File: armv5te/OP_MOVE_WIDE.S */ 465 /* move-wide vA, vB */ 466 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 467 mov r2, rINST, lsr #8 @ r2<- A(+) 468 mov r3, rINST, lsr #12 @ r3<- B 469 and r2, r2, #15 470 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 471 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 472 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 473 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 474 GET_INST_OPCODE(ip) @ extract opcode from rINST 475 stmia r2, {r0-r1} @ fp[A]<- r0/r1 476 GOTO_OPCODE(ip) @ jump to next instruction 477 478 479/* ------------------------------ */ 480 .balign 64 481.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 482/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 483 /* move-wide/from16 vAA, vBBBB */ 484 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 485 FETCH(r3, 1) @ r3<- BBBB 486 mov r2, rINST, lsr #8 @ r2<- AA 487 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 488 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 489 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 490 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 491 GET_INST_OPCODE(ip) @ extract opcode from rINST 492 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 493 GOTO_OPCODE(ip) @ jump to next instruction 494 495 496/* ------------------------------ */ 497 .balign 64 498.L_OP_MOVE_WIDE_16: /* 0x06 */ 499/* File: armv5te/OP_MOVE_WIDE_16.S */ 500 /* move-wide/16 vAAAA, vBBBB */ 501 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 502 FETCH(r3, 2) @ r3<- BBBB 503 FETCH(r2, 1) @ r2<- AAAA 504 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 505 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 506 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 507 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 508 GET_INST_OPCODE(ip) @ extract opcode from rINST 509 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 510 GOTO_OPCODE(ip) @ jump to next instruction 511 512 513/* ------------------------------ */ 514 .balign 64 515.L_OP_MOVE_OBJECT: /* 0x07 */ 516/* File: armv5te/OP_MOVE_OBJECT.S */ 517/* File: armv5te/OP_MOVE.S */ 518 /* for move, move-object, long-to-int */ 519 /* op vA, vB */ 520 mov r1, rINST, lsr #12 @ r1<- B from 15:12 521 mov r0, rINST, lsr #8 @ r0<- A from 11:8 522 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 523 GET_VREG(r2, r1) @ r2<- fp[B] 524 and r0, r0, #15 525 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 526 SET_VREG(r2, r0) @ fp[A]<- r2 527 GOTO_OPCODE(ip) @ execute next instruction 528 529 530 531/* ------------------------------ */ 532 .balign 64 533.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 534/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 535/* File: armv5te/OP_MOVE_FROM16.S */ 536 /* for: move/from16, move-object/from16 */ 537 /* op vAA, vBBBB */ 538 FETCH(r1, 1) @ r1<- BBBB 539 mov r0, rINST, lsr #8 @ r0<- AA 540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 541 GET_VREG(r2, r1) @ r2<- fp[BBBB] 542 GET_INST_OPCODE(ip) @ extract opcode from rINST 543 SET_VREG(r2, r0) @ fp[AA]<- r2 544 GOTO_OPCODE(ip) @ jump to next instruction 545 546 547 548/* ------------------------------ */ 549 .balign 64 550.L_OP_MOVE_OBJECT_16: /* 0x09 */ 551/* File: armv5te/OP_MOVE_OBJECT_16.S */ 552/* File: armv5te/OP_MOVE_16.S */ 553 /* for: move/16, move-object/16 */ 554 /* op vAAAA, vBBBB */ 555 FETCH(r1, 2) @ r1<- BBBB 556 FETCH(r0, 1) @ r0<- AAAA 557 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 558 GET_VREG(r2, r1) @ r2<- fp[BBBB] 559 GET_INST_OPCODE(ip) @ extract opcode from rINST 560 SET_VREG(r2, r0) @ fp[AAAA]<- r2 561 GOTO_OPCODE(ip) @ jump to next instruction 562 563 564 565/* ------------------------------ */ 566 .balign 64 567.L_OP_MOVE_RESULT: /* 0x0a */ 568/* File: armv5te/OP_MOVE_RESULT.S */ 569 /* for: move-result, move-result-object */ 570 /* op vAA */ 571 mov r2, rINST, lsr #8 @ r2<- AA 572 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 573 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 574 GET_INST_OPCODE(ip) @ extract opcode from rINST 575 SET_VREG(r0, r2) @ fp[AA]<- r0 576 GOTO_OPCODE(ip) @ jump to next instruction 577 578 579/* ------------------------------ */ 580 .balign 64 581.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 582/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 583 /* move-result-wide vAA */ 584 mov r2, rINST, lsr #8 @ r2<- AA 585 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 586 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 587 ldmia r3, {r0-r1} @ r0/r1<- retval.j 588 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 589 GET_INST_OPCODE(ip) @ extract opcode from rINST 590 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 591 GOTO_OPCODE(ip) @ jump to next instruction 592 593 594/* ------------------------------ */ 595 .balign 64 596.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 597/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 598/* File: armv5te/OP_MOVE_RESULT.S */ 599 /* for: move-result, move-result-object */ 600 /* op vAA */ 601 mov r2, rINST, lsr #8 @ r2<- AA 602 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 603 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 604 GET_INST_OPCODE(ip) @ extract opcode from rINST 605 SET_VREG(r0, r2) @ fp[AA]<- r0 606 GOTO_OPCODE(ip) @ jump to next instruction 607 608 609 610/* ------------------------------ */ 611 .balign 64 612.L_OP_MOVE_EXCEPTION: /* 0x0d */ 613/* File: armv5te/OP_MOVE_EXCEPTION.S */ 614 /* move-exception vAA */ 615 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 616 mov r2, rINST, lsr #8 @ r2<- AA 617 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 618 mov r1, #0 @ r1<- 0 619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 620 SET_VREG(r3, r2) @ fp[AA]<- exception obj 621 GET_INST_OPCODE(ip) @ extract opcode from rINST 622 str r1, [r0, #offThread_exception] @ dvmClearException bypass 623 GOTO_OPCODE(ip) @ jump to next instruction 624 625 626/* ------------------------------ */ 627 .balign 64 628.L_OP_RETURN_VOID: /* 0x0e */ 629/* File: armv5te/OP_RETURN_VOID.S */ 630 b common_returnFromMethod 631 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN: /* 0x0f */ 636/* File: armv5te/OP_RETURN.S */ 637 /* 638 * Return a 32-bit value. Copies the return value into the "glue" 639 * structure, then jumps to the return handler. 640 * 641 * for: return, return-object 642 */ 643 /* op vAA */ 644 mov r2, rINST, lsr #8 @ r2<- AA 645 GET_VREG(r0, r2) @ r0<- vAA 646 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 647 b common_returnFromMethod 648 649 650/* ------------------------------ */ 651 .balign 64 652.L_OP_RETURN_WIDE: /* 0x10 */ 653/* File: armv5te/OP_RETURN_WIDE.S */ 654 /* 655 * Return a 64-bit value. Copies the return value into the "glue" 656 * structure, then jumps to the return handler. 657 */ 658 /* return-wide vAA */ 659 mov r2, rINST, lsr #8 @ r2<- AA 660 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 661 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 662 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 663 stmia r3, {r0-r1} @ retval<- r0/r1 664 b common_returnFromMethod 665 666 667/* ------------------------------ */ 668 .balign 64 669.L_OP_RETURN_OBJECT: /* 0x11 */ 670/* File: armv5te/OP_RETURN_OBJECT.S */ 671/* File: armv5te/OP_RETURN.S */ 672 /* 673 * Return a 32-bit value. Copies the return value into the "glue" 674 * structure, then jumps to the return handler. 675 * 676 * for: return, return-object 677 */ 678 /* op vAA */ 679 mov r2, rINST, lsr #8 @ r2<- AA 680 GET_VREG(r0, r2) @ r0<- vAA 681 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 682 b common_returnFromMethod 683 684 685 686/* ------------------------------ */ 687 .balign 64 688.L_OP_CONST_4: /* 0x12 */ 689/* File: armv5te/OP_CONST_4.S */ 690 /* const/4 vA, #+B */ 691 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 692 mov r0, rINST, lsr #8 @ r0<- A+ 693 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 694 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 695 and r0, r0, #15 696 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 697 SET_VREG(r1, r0) @ fp[A]<- r1 698 GOTO_OPCODE(ip) @ execute next instruction 699 700 701/* ------------------------------ */ 702 .balign 64 703.L_OP_CONST_16: /* 0x13 */ 704/* File: armv5te/OP_CONST_16.S */ 705 /* const/16 vAA, #+BBBB */ 706 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 707 mov r3, rINST, lsr #8 @ r3<- AA 708 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 709 SET_VREG(r0, r3) @ vAA<- r0 710 GET_INST_OPCODE(ip) @ extract opcode from rINST 711 GOTO_OPCODE(ip) @ jump to next instruction 712 713 714/* ------------------------------ */ 715 .balign 64 716.L_OP_CONST: /* 0x14 */ 717/* File: armv5te/OP_CONST.S */ 718 /* const vAA, #+BBBBbbbb */ 719 mov r3, rINST, lsr #8 @ r3<- AA 720 FETCH(r0, 1) @ r0<- bbbb (low) 721 FETCH(r1, 2) @ r1<- BBBB (high) 722 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 723 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 724 GET_INST_OPCODE(ip) @ extract opcode from rINST 725 SET_VREG(r0, r3) @ vAA<- r0 726 GOTO_OPCODE(ip) @ jump to next instruction 727 728 729/* ------------------------------ */ 730 .balign 64 731.L_OP_CONST_HIGH16: /* 0x15 */ 732/* File: armv5te/OP_CONST_HIGH16.S */ 733 /* const/high16 vAA, #+BBBB0000 */ 734 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 735 mov r3, rINST, lsr #8 @ r3<- AA 736 mov r0, r0, lsl #16 @ r0<- BBBB0000 737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 738 SET_VREG(r0, r3) @ vAA<- r0 739 GET_INST_OPCODE(ip) @ extract opcode from rINST 740 GOTO_OPCODE(ip) @ jump to next instruction 741 742 743/* ------------------------------ */ 744 .balign 64 745.L_OP_CONST_WIDE_16: /* 0x16 */ 746/* File: armv5te/OP_CONST_WIDE_16.S */ 747 /* const-wide/16 vAA, #+BBBB */ 748 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 749 mov r3, rINST, lsr #8 @ r3<- AA 750 mov r1, r0, asr #31 @ r1<- ssssssss 751 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 752 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 753 GET_INST_OPCODE(ip) @ extract opcode from rINST 754 stmia r3, {r0-r1} @ vAA<- r0/r1 755 GOTO_OPCODE(ip) @ jump to next instruction 756 757 758/* ------------------------------ */ 759 .balign 64 760.L_OP_CONST_WIDE_32: /* 0x17 */ 761/* File: armv5te/OP_CONST_WIDE_32.S */ 762 /* const-wide/32 vAA, #+BBBBbbbb */ 763 FETCH(r0, 1) @ r0<- 0000bbbb (low) 764 mov r3, rINST, lsr #8 @ r3<- AA 765 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 766 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 767 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 768 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 769 mov r1, r0, asr #31 @ r1<- ssssssss 770 GET_INST_OPCODE(ip) @ extract opcode from rINST 771 stmia r3, {r0-r1} @ vAA<- r0/r1 772 GOTO_OPCODE(ip) @ jump to next instruction 773 774 775/* ------------------------------ */ 776 .balign 64 777.L_OP_CONST_WIDE: /* 0x18 */ 778/* File: armv5te/OP_CONST_WIDE.S */ 779 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 780 FETCH(r0, 1) @ r0<- bbbb (low) 781 FETCH(r1, 2) @ r1<- BBBB (low middle) 782 FETCH(r2, 3) @ r2<- hhhh (high middle) 783 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 784 FETCH(r3, 4) @ r3<- HHHH (high) 785 mov r9, rINST, lsr #8 @ r9<- AA 786 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 787 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 788 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 789 GET_INST_OPCODE(ip) @ extract opcode from rINST 790 stmia r9, {r0-r1} @ vAA<- r0/r1 791 GOTO_OPCODE(ip) @ jump to next instruction 792 793 794/* ------------------------------ */ 795 .balign 64 796.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 797/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 798 /* const-wide/high16 vAA, #+BBBB000000000000 */ 799 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 800 mov r3, rINST, lsr #8 @ r3<- AA 801 mov r0, #0 @ r0<- 00000000 802 mov r1, r1, lsl #16 @ r1<- BBBB0000 803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 804 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 805 GET_INST_OPCODE(ip) @ extract opcode from rINST 806 stmia r3, {r0-r1} @ vAA<- r0/r1 807 GOTO_OPCODE(ip) @ jump to next instruction 808 809 810/* ------------------------------ */ 811 .balign 64 812.L_OP_CONST_STRING: /* 0x1a */ 813/* File: armv5te/OP_CONST_STRING.S */ 814 /* const/string vAA, String@BBBB */ 815 FETCH(r1, 1) @ r1<- BBBB 816 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 817 mov r9, rINST, lsr #8 @ r9<- AA 818 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 819 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 820 cmp r0, #0 @ not yet resolved? 821 beq .LOP_CONST_STRING_resolve 822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 823 GET_INST_OPCODE(ip) @ extract opcode from rINST 824 SET_VREG(r0, r9) @ vAA<- r0 825 GOTO_OPCODE(ip) @ jump to next instruction 826 827/* ------------------------------ */ 828 .balign 64 829.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 830/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 831 /* const/string vAA, String@BBBBBBBB */ 832 FETCH(r0, 1) @ r0<- bbbb (low) 833 FETCH(r1, 2) @ r1<- BBBB (high) 834 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 835 mov r9, rINST, lsr #8 @ r9<- AA 836 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 837 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 838 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 839 cmp r0, #0 840 beq .LOP_CONST_STRING_JUMBO_resolve 841 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 842 GET_INST_OPCODE(ip) @ extract opcode from rINST 843 SET_VREG(r0, r9) @ vAA<- r0 844 GOTO_OPCODE(ip) @ jump to next instruction 845 846/* ------------------------------ */ 847 .balign 64 848.L_OP_CONST_CLASS: /* 0x1c */ 849/* File: armv5te/OP_CONST_CLASS.S */ 850 /* const/class vAA, Class@BBBB */ 851 FETCH(r1, 1) @ r1<- BBBB 852 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 853 mov r9, rINST, lsr #8 @ r9<- AA 854 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 855 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 856 cmp r0, #0 @ not yet resolved? 857 beq .LOP_CONST_CLASS_resolve 858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 859 GET_INST_OPCODE(ip) @ extract opcode from rINST 860 SET_VREG(r0, r9) @ vAA<- r0 861 GOTO_OPCODE(ip) @ jump to next instruction 862 863/* ------------------------------ */ 864 .balign 64 865.L_OP_MONITOR_ENTER: /* 0x1d */ 866/* File: armv5te/OP_MONITOR_ENTER.S */ 867 /* 868 * Synchronize on an object. 869 */ 870 /* monitor-enter vAA */ 871 mov r2, rINST, lsr #8 @ r2<- AA 872 GET_VREG(r1, r2) @ r1<- vAA (object) 873 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 874 cmp r1, #0 @ null object? 875 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 876 beq common_errNullObject @ null object, throw an exception 877 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 878 bl dvmLockObject @ call(self, obj) 879#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 880 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 881 ldr r1, [r0, #offThread_exception] @ check for exception 882 cmp r1, #0 883 bne common_exceptionThrown @ exception raised, bail out 884#endif 885 GET_INST_OPCODE(ip) @ extract opcode from rINST 886 GOTO_OPCODE(ip) @ jump to next instruction 887 888 889/* ------------------------------ */ 890 .balign 64 891.L_OP_MONITOR_EXIT: /* 0x1e */ 892/* File: armv5te/OP_MONITOR_EXIT.S */ 893 /* 894 * Unlock an object. 895 * 896 * Exceptions that occur when unlocking a monitor need to appear as 897 * if they happened at the following instruction. See the Dalvik 898 * instruction spec. 899 */ 900 /* monitor-exit vAA */ 901 mov r2, rINST, lsr #8 @ r2<- AA 902 EXPORT_PC() @ before fetch: export the PC 903 GET_VREG(r1, r2) @ r1<- vAA (object) 904 cmp r1, #0 @ null object? 905 beq common_errNullObject @ yes 906 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 907 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 908 cmp r0, #0 @ failed? 909 beq common_exceptionThrown @ yes, exception is pending 910 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 911 GET_INST_OPCODE(ip) @ extract opcode from rINST 912 GOTO_OPCODE(ip) @ jump to next instruction 913 914 915/* ------------------------------ */ 916 .balign 64 917.L_OP_CHECK_CAST: /* 0x1f */ 918/* File: armv5te/OP_CHECK_CAST.S */ 919 /* 920 * Check to see if a cast from one class to another is allowed. 921 */ 922 /* check-cast vAA, class@BBBB */ 923 mov r3, rINST, lsr #8 @ r3<- AA 924 FETCH(r2, 1) @ r2<- BBBB 925 GET_VREG(r9, r3) @ r9<- object 926 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 927 cmp r9, #0 @ is object null? 928 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 929 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 930 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 931 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 932 cmp r1, #0 @ have we resolved this before? 933 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 934.LOP_CHECK_CAST_resolved: 935 cmp r0, r1 @ same class (trivial success)? 936 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 937.LOP_CHECK_CAST_okay: 938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 939 GET_INST_OPCODE(ip) @ extract opcode from rINST 940 GOTO_OPCODE(ip) @ jump to next instruction 941 942/* ------------------------------ */ 943 .balign 64 944.L_OP_INSTANCE_OF: /* 0x20 */ 945/* File: armv5te/OP_INSTANCE_OF.S */ 946 /* 947 * Check to see if an object reference is an instance of a class. 948 * 949 * Most common situation is a non-null object, being compared against 950 * an already-resolved class. 951 */ 952 /* instance-of vA, vB, class@CCCC */ 953 mov r3, rINST, lsr #12 @ r3<- B 954 mov r9, rINST, lsr #8 @ r9<- A+ 955 GET_VREG(r0, r3) @ r0<- vB (object) 956 and r9, r9, #15 @ r9<- A 957 cmp r0, #0 @ is object null? 958 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 959 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 960 FETCH(r3, 1) @ r3<- CCCC 961 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 962 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 963 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 964 cmp r1, #0 @ have we resolved this before? 965 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 966.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 967 cmp r0, r1 @ same class (trivial success)? 968 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 969 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 970 971/* ------------------------------ */ 972 .balign 64 973.L_OP_ARRAY_LENGTH: /* 0x21 */ 974/* File: armv5te/OP_ARRAY_LENGTH.S */ 975 /* 976 * Return the length of an array. 977 */ 978 mov r1, rINST, lsr #12 @ r1<- B 979 mov r2, rINST, lsr #8 @ r2<- A+ 980 GET_VREG(r0, r1) @ r0<- vB (object ref) 981 and r2, r2, #15 @ r2<- A 982 cmp r0, #0 @ is object null? 983 beq common_errNullObject @ yup, fail 984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 985 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 986 GET_INST_OPCODE(ip) @ extract opcode from rINST 987 SET_VREG(r3, r2) @ vB<- length 988 GOTO_OPCODE(ip) @ jump to next instruction 989 990 991/* ------------------------------ */ 992 .balign 64 993.L_OP_NEW_INSTANCE: /* 0x22 */ 994/* File: armv5te/OP_NEW_INSTANCE.S */ 995 /* 996 * Create a new instance of a class. 997 */ 998 /* new-instance vAA, class@BBBB */ 999 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1000 FETCH(r1, 1) @ r1<- BBBB 1001 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1002 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1003 EXPORT_PC() @ req'd for init, resolve, alloc 1004 cmp r0, #0 @ already resolved? 1005 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1006.LOP_NEW_INSTANCE_resolved: @ r0=class 1007 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1008 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1009 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1010.LOP_NEW_INSTANCE_initialized: @ r0=class 1011 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1012 bl dvmAllocObject @ r0<- new object 1013 b .LOP_NEW_INSTANCE_finish @ continue 1014 1015/* ------------------------------ */ 1016 .balign 64 1017.L_OP_NEW_ARRAY: /* 0x23 */ 1018/* File: armv5te/OP_NEW_ARRAY.S */ 1019 /* 1020 * Allocate an array of objects, specified with the array class 1021 * and a count. 1022 * 1023 * The verifier guarantees that this is an array class, so we don't 1024 * check for it here. 1025 */ 1026 /* new-array vA, vB, class@CCCC */ 1027 mov r0, rINST, lsr #12 @ r0<- B 1028 FETCH(r2, 1) @ r2<- CCCC 1029 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1030 GET_VREG(r1, r0) @ r1<- vB (array length) 1031 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1032 cmp r1, #0 @ check length 1033 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1034 bmi common_errNegativeArraySize @ negative length, bail 1035 cmp r0, #0 @ already resolved? 1036 EXPORT_PC() @ req'd for resolve, alloc 1037 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1038 b .LOP_NEW_ARRAY_resolve @ do resolve now 1039 1040/* ------------------------------ */ 1041 .balign 64 1042.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1043/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1044 /* 1045 * Create a new array with elements filled from registers. 1046 * 1047 * for: filled-new-array, filled-new-array/range 1048 */ 1049 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1050 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1051 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1052 FETCH(r1, 1) @ r1<- BBBB 1053 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1054 EXPORT_PC() @ need for resolve and alloc 1055 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1056 mov r10, rINST, lsr #8 @ r10<- AA or BA 1057 cmp r0, #0 @ already resolved? 1058 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10598: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1060 mov r2, #0 @ r2<- false 1061 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1062 bl dvmResolveClass @ r0<- call(clazz, ref) 1063 cmp r0, #0 @ got null? 1064 beq common_exceptionThrown @ yes, handle exception 1065 b .LOP_FILLED_NEW_ARRAY_continue 1066 1067/* ------------------------------ */ 1068 .balign 64 1069.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1070/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1071/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1072 /* 1073 * Create a new array with elements filled from registers. 1074 * 1075 * for: filled-new-array, filled-new-array/range 1076 */ 1077 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1078 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1079 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1080 FETCH(r1, 1) @ r1<- BBBB 1081 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1082 EXPORT_PC() @ need for resolve and alloc 1083 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1084 mov r10, rINST, lsr #8 @ r10<- AA or BA 1085 cmp r0, #0 @ already resolved? 1086 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10878: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1088 mov r2, #0 @ r2<- false 1089 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1090 bl dvmResolveClass @ r0<- call(clazz, ref) 1091 cmp r0, #0 @ got null? 1092 beq common_exceptionThrown @ yes, handle exception 1093 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1094 1095 1096/* ------------------------------ */ 1097 .balign 64 1098.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1099/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1100 /* fill-array-data vAA, +BBBBBBBB */ 1101 FETCH(r0, 1) @ r0<- bbbb (lo) 1102 FETCH(r1, 2) @ r1<- BBBB (hi) 1103 mov r3, rINST, lsr #8 @ r3<- AA 1104 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1105 GET_VREG(r0, r3) @ r0<- vAA (array object) 1106 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1107 EXPORT_PC(); 1108 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1109 cmp r0, #0 @ 0 means an exception is thrown 1110 beq common_exceptionThrown @ has exception 1111 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1112 GET_INST_OPCODE(ip) @ extract opcode from rINST 1113 GOTO_OPCODE(ip) @ jump to next instruction 1114 1115/* ------------------------------ */ 1116 .balign 64 1117.L_OP_THROW: /* 0x27 */ 1118/* File: armv5te/OP_THROW.S */ 1119 /* 1120 * Throw an exception object in the current thread. 1121 */ 1122 /* throw vAA */ 1123 mov r2, rINST, lsr #8 @ r2<- AA 1124 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1125 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1126 cmp r1, #0 @ null object? 1127 beq common_errNullObject @ yes, throw an NPE instead 1128 @ bypass dvmSetException, just store it 1129 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1130 b common_exceptionThrown 1131 1132 1133/* ------------------------------ */ 1134 .balign 64 1135.L_OP_GOTO: /* 0x28 */ 1136/* File: armv5te/OP_GOTO.S */ 1137 /* 1138 * Unconditional branch, 8-bit offset. 1139 * 1140 * The branch distance is a signed code-unit offset, which we need to 1141 * double to get a byte offset. 1142 */ 1143 /* goto +AA */ 1144 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1145 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1146 mov r9, r9, lsl #1 @ r9<- byte offset 1147 bmi common_backwardBranch @ backward branch, do periodic checks 1148#if defined(WITH_JIT) 1149 GET_JIT_PROF_TABLE(r0) 1150 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1151 cmp r0,#0 1152 bne common_updateProfile 1153 GET_INST_OPCODE(ip) @ extract opcode from rINST 1154 GOTO_OPCODE(ip) @ jump to next instruction 1155#else 1156 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1157 GET_INST_OPCODE(ip) @ extract opcode from rINST 1158 GOTO_OPCODE(ip) @ jump to next instruction 1159#endif 1160 1161/* ------------------------------ */ 1162 .balign 64 1163.L_OP_GOTO_16: /* 0x29 */ 1164/* File: armv5te/OP_GOTO_16.S */ 1165 /* 1166 * Unconditional branch, 16-bit offset. 1167 * 1168 * The branch distance is a signed code-unit offset, which we need to 1169 * double to get a byte offset. 1170 */ 1171 /* goto/16 +AAAA */ 1172 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1173 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1174 bmi common_backwardBranch @ backward branch, do periodic checks 1175#if defined(WITH_JIT) 1176 GET_JIT_PROF_TABLE(r0) 1177 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1178 cmp r0,#0 1179 bne common_updateProfile 1180 GET_INST_OPCODE(ip) @ extract opcode from rINST 1181 GOTO_OPCODE(ip) @ jump to next instruction 1182#else 1183 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1184 GET_INST_OPCODE(ip) @ extract opcode from rINST 1185 GOTO_OPCODE(ip) @ jump to next instruction 1186#endif 1187 1188 1189/* ------------------------------ */ 1190 .balign 64 1191.L_OP_GOTO_32: /* 0x2a */ 1192/* File: armv5te/OP_GOTO_32.S */ 1193 /* 1194 * Unconditional branch, 32-bit offset. 1195 * 1196 * The branch distance is a signed code-unit offset, which we need to 1197 * double to get a byte offset. 1198 * 1199 * Unlike most opcodes, this one is allowed to branch to itself, so 1200 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1201 * instruction doesn't affect the V flag, so we need to clear it 1202 * explicitly. 1203 */ 1204 /* goto/32 +AAAAAAAA */ 1205 FETCH(r0, 1) @ r0<- aaaa (lo) 1206 FETCH(r1, 2) @ r1<- AAAA (hi) 1207 cmp ip, ip @ (clear V flag during stall) 1208 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1209 mov r9, r0, asl #1 @ r9<- byte offset 1210 ble common_backwardBranch @ backward branch, do periodic checks 1211#if defined(WITH_JIT) 1212 GET_JIT_PROF_TABLE(r0) 1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1214 cmp r0,#0 1215 bne common_updateProfile 1216 GET_INST_OPCODE(ip) @ extract opcode from rINST 1217 GOTO_OPCODE(ip) @ jump to next instruction 1218#else 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 GET_INST_OPCODE(ip) @ extract opcode from rINST 1221 GOTO_OPCODE(ip) @ jump to next instruction 1222#endif 1223 1224/* ------------------------------ */ 1225 .balign 64 1226.L_OP_PACKED_SWITCH: /* 0x2b */ 1227/* File: armv5te/OP_PACKED_SWITCH.S */ 1228 /* 1229 * Handle a packed-switch or sparse-switch instruction. In both cases 1230 * we decode it and hand it off to a helper function. 1231 * 1232 * We don't really expect backward branches in a switch statement, but 1233 * they're perfectly legal, so we check for them here. 1234 * 1235 * for: packed-switch, sparse-switch 1236 */ 1237 /* op vAA, +BBBB */ 1238 FETCH(r0, 1) @ r0<- bbbb (lo) 1239 FETCH(r1, 2) @ r1<- BBBB (hi) 1240 mov r3, rINST, lsr #8 @ r3<- AA 1241 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1242 GET_VREG(r1, r3) @ r1<- vAA 1243 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1244 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1245 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1246 bmi common_backwardBranch @ backward branch, do periodic checks 1247 beq common_backwardBranch @ (want to use BLE but V is unknown) 1248#if defined(WITH_JIT) 1249 GET_JIT_PROF_TABLE(r0) 1250 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1251 cmp r0,#0 1252 bne common_updateProfile 1253 GET_INST_OPCODE(ip) @ extract opcode from rINST 1254 GOTO_OPCODE(ip) @ jump to next instruction 1255#else 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 GOTO_OPCODE(ip) @ jump to next instruction 1259#endif 1260 1261 1262/* ------------------------------ */ 1263 .balign 64 1264.L_OP_SPARSE_SWITCH: /* 0x2c */ 1265/* File: armv5te/OP_SPARSE_SWITCH.S */ 1266/* File: armv5te/OP_PACKED_SWITCH.S */ 1267 /* 1268 * Handle a packed-switch or sparse-switch instruction. In both cases 1269 * we decode it and hand it off to a helper function. 1270 * 1271 * We don't really expect backward branches in a switch statement, but 1272 * they're perfectly legal, so we check for them here. 1273 * 1274 * for: packed-switch, sparse-switch 1275 */ 1276 /* op vAA, +BBBB */ 1277 FETCH(r0, 1) @ r0<- bbbb (lo) 1278 FETCH(r1, 2) @ r1<- BBBB (hi) 1279 mov r3, rINST, lsr #8 @ r3<- AA 1280 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1281 GET_VREG(r1, r3) @ r1<- vAA 1282 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1283 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1284 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1285 bmi common_backwardBranch @ backward branch, do periodic checks 1286 beq common_backwardBranch @ (want to use BLE but V is unknown) 1287#if defined(WITH_JIT) 1288 GET_JIT_PROF_TABLE(r0) 1289 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1290 cmp r0,#0 1291 bne common_updateProfile 1292 GET_INST_OPCODE(ip) @ extract opcode from rINST 1293 GOTO_OPCODE(ip) @ jump to next instruction 1294#else 1295 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1296 GET_INST_OPCODE(ip) @ extract opcode from rINST 1297 GOTO_OPCODE(ip) @ jump to next instruction 1298#endif 1299 1300 1301 1302/* ------------------------------ */ 1303 .balign 64 1304.L_OP_CMPL_FLOAT: /* 0x2d */ 1305/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1306 /* 1307 * Compare two floating-point values. Puts 0, 1, or -1 into the 1308 * destination register based on the results of the comparison. 1309 * 1310 * int compare(x, y) { 1311 * if (x == y) { 1312 * return 0; 1313 * } else if (x > y) { 1314 * return 1; 1315 * } else if (x < y) { 1316 * return -1; 1317 * } else { 1318 * return -1; 1319 * } 1320 * } 1321 */ 1322 /* op vAA, vBB, vCC */ 1323 FETCH(r0, 1) @ r0<- CCBB 1324 mov r9, rINST, lsr #8 @ r9<- AA 1325 and r2, r0, #255 @ r2<- BB 1326 mov r3, r0, lsr #8 @ r3<- CC 1327 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1328 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1329 flds s0, [r2] @ s0<- vBB 1330 flds s1, [r3] @ s1<- vCC 1331 fcmpes s0, s1 @ compare (vBB, vCC) 1332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1333 mvn r0, #0 @ r0<- -1 (default) 1334 GET_INST_OPCODE(ip) @ extract opcode from rINST 1335 fmstat @ export status flags 1336 movgt r0, #1 @ (greater than) r1<- 1 1337 moveq r0, #0 @ (equal) r1<- 0 1338 b .LOP_CMPL_FLOAT_finish @ argh 1339 1340 1341/* ------------------------------ */ 1342 .balign 64 1343.L_OP_CMPG_FLOAT: /* 0x2e */ 1344/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1345 /* 1346 * Compare two floating-point values. Puts 0, 1, or -1 into the 1347 * destination register based on the results of the comparison. 1348 * 1349 * int compare(x, y) { 1350 * if (x == y) { 1351 * return 0; 1352 * } else if (x < y) { 1353 * return -1; 1354 * } else if (x > y) { 1355 * return 1; 1356 * } else { 1357 * return 1; 1358 * } 1359 * } 1360 */ 1361 /* op vAA, vBB, vCC */ 1362 FETCH(r0, 1) @ r0<- CCBB 1363 mov r9, rINST, lsr #8 @ r9<- AA 1364 and r2, r0, #255 @ r2<- BB 1365 mov r3, r0, lsr #8 @ r3<- CC 1366 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1367 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1368 flds s0, [r2] @ s0<- vBB 1369 flds s1, [r3] @ s1<- vCC 1370 fcmpes s0, s1 @ compare (vBB, vCC) 1371 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1372 mov r0, #1 @ r0<- 1 (default) 1373 GET_INST_OPCODE(ip) @ extract opcode from rINST 1374 fmstat @ export status flags 1375 mvnmi r0, #0 @ (less than) r1<- -1 1376 moveq r0, #0 @ (equal) r1<- 0 1377 b .LOP_CMPG_FLOAT_finish @ argh 1378 1379 1380/* ------------------------------ */ 1381 .balign 64 1382.L_OP_CMPL_DOUBLE: /* 0x2f */ 1383/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1384 /* 1385 * Compare two floating-point values. Puts 0, 1, or -1 into the 1386 * destination register based on the results of the comparison. 1387 * 1388 * int compare(x, y) { 1389 * if (x == y) { 1390 * return 0; 1391 * } else if (x > y) { 1392 * return 1; 1393 * } else if (x < y) { 1394 * return -1; 1395 * } else { 1396 * return -1; 1397 * } 1398 * } 1399 */ 1400 /* op vAA, vBB, vCC */ 1401 FETCH(r0, 1) @ r0<- CCBB 1402 mov r9, rINST, lsr #8 @ r9<- AA 1403 and r2, r0, #255 @ r2<- BB 1404 mov r3, r0, lsr #8 @ r3<- CC 1405 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1406 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1407 fldd d0, [r2] @ d0<- vBB 1408 fldd d1, [r3] @ d1<- vCC 1409 fcmped d0, d1 @ compare (vBB, vCC) 1410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1411 mvn r0, #0 @ r0<- -1 (default) 1412 GET_INST_OPCODE(ip) @ extract opcode from rINST 1413 fmstat @ export status flags 1414 movgt r0, #1 @ (greater than) r1<- 1 1415 moveq r0, #0 @ (equal) r1<- 0 1416 b .LOP_CMPL_DOUBLE_finish @ argh 1417 1418 1419/* ------------------------------ */ 1420 .balign 64 1421.L_OP_CMPG_DOUBLE: /* 0x30 */ 1422/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1423 /* 1424 * Compare two floating-point values. Puts 0, 1, or -1 into the 1425 * destination register based on the results of the comparison. 1426 * 1427 * int compare(x, y) { 1428 * if (x == y) { 1429 * return 0; 1430 * } else if (x < y) { 1431 * return -1; 1432 * } else if (x > y) { 1433 * return 1; 1434 * } else { 1435 * return 1; 1436 * } 1437 * } 1438 */ 1439 /* op vAA, vBB, vCC */ 1440 FETCH(r0, 1) @ r0<- CCBB 1441 mov r9, rINST, lsr #8 @ r9<- AA 1442 and r2, r0, #255 @ r2<- BB 1443 mov r3, r0, lsr #8 @ r3<- CC 1444 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1445 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1446 fldd d0, [r2] @ d0<- vBB 1447 fldd d1, [r3] @ d1<- vCC 1448 fcmped d0, d1 @ compare (vBB, vCC) 1449 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1450 mov r0, #1 @ r0<- 1 (default) 1451 GET_INST_OPCODE(ip) @ extract opcode from rINST 1452 fmstat @ export status flags 1453 mvnmi r0, #0 @ (less than) r1<- -1 1454 moveq r0, #0 @ (equal) r1<- 0 1455 b .LOP_CMPG_DOUBLE_finish @ argh 1456 1457 1458/* ------------------------------ */ 1459 .balign 64 1460.L_OP_CMP_LONG: /* 0x31 */ 1461/* File: armv5te/OP_CMP_LONG.S */ 1462 /* 1463 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1464 * register based on the results of the comparison. 1465 * 1466 * We load the full values with LDM, but in practice many values could 1467 * be resolved by only looking at the high word. This could be made 1468 * faster or slower by splitting the LDM into a pair of LDRs. 1469 * 1470 * If we just wanted to set condition flags, we could do this: 1471 * subs ip, r0, r2 1472 * sbcs ip, r1, r3 1473 * subeqs ip, r0, r2 1474 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1475 * integer value, which we can do with 2 conditional mov/mvn instructions 1476 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1477 * us a constant 5-cycle path plus a branch at the end to the 1478 * instruction epilogue code. The multi-compare approach below needs 1479 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1480 * in the worst case (the 64-bit values are equal). 1481 */ 1482 /* cmp-long vAA, vBB, vCC */ 1483 FETCH(r0, 1) @ r0<- CCBB 1484 mov r9, rINST, lsr #8 @ r9<- AA 1485 and r2, r0, #255 @ r2<- BB 1486 mov r3, r0, lsr #8 @ r3<- CC 1487 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1488 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1489 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1490 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1491 cmp r1, r3 @ compare (vBB+1, vCC+1) 1492 blt .LOP_CMP_LONG_less @ signed compare on high part 1493 bgt .LOP_CMP_LONG_greater 1494 subs r1, r0, r2 @ r1<- r0 - r2 1495 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1496 bne .LOP_CMP_LONG_less 1497 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1498 1499/* ------------------------------ */ 1500 .balign 64 1501.L_OP_IF_EQ: /* 0x32 */ 1502/* File: armv5te/OP_IF_EQ.S */ 1503/* File: armv5te/bincmp.S */ 1504 /* 1505 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1506 * fragment that specifies the *reverse* comparison to perform, e.g. 1507 * for "if-le" you would use "gt". 1508 * 1509 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1510 */ 1511 /* if-cmp vA, vB, +CCCC */ 1512 mov r0, rINST, lsr #8 @ r0<- A+ 1513 mov r1, rINST, lsr #12 @ r1<- B 1514 and r0, r0, #15 1515 GET_VREG(r3, r1) @ r3<- vB 1516 GET_VREG(r2, r0) @ r2<- vA 1517 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1518 cmp r2, r3 @ compare (vA, vB) 1519 bne 1f @ branch to 1 if comparison failed 1520 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1521 movs r9, r9, asl #1 @ convert to bytes, check sign 1522 bmi common_backwardBranch @ yes, do periodic checks 15231: 1524#if defined(WITH_JIT) 1525 GET_JIT_PROF_TABLE(r0) 1526 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1527 b common_testUpdateProfile 1528#else 1529 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1530 GET_INST_OPCODE(ip) @ extract opcode from rINST 1531 GOTO_OPCODE(ip) @ jump to next instruction 1532#endif 1533 1534 1535 1536/* ------------------------------ */ 1537 .balign 64 1538.L_OP_IF_NE: /* 0x33 */ 1539/* File: armv5te/OP_IF_NE.S */ 1540/* File: armv5te/bincmp.S */ 1541 /* 1542 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1543 * fragment that specifies the *reverse* comparison to perform, e.g. 1544 * for "if-le" you would use "gt". 1545 * 1546 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1547 */ 1548 /* if-cmp vA, vB, +CCCC */ 1549 mov r0, rINST, lsr #8 @ r0<- A+ 1550 mov r1, rINST, lsr #12 @ r1<- B 1551 and r0, r0, #15 1552 GET_VREG(r3, r1) @ r3<- vB 1553 GET_VREG(r2, r0) @ r2<- vA 1554 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1555 cmp r2, r3 @ compare (vA, vB) 1556 beq 1f @ branch to 1 if comparison failed 1557 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1558 movs r9, r9, asl #1 @ convert to bytes, check sign 1559 bmi common_backwardBranch @ yes, do periodic checks 15601: 1561#if defined(WITH_JIT) 1562 GET_JIT_PROF_TABLE(r0) 1563 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1564 b common_testUpdateProfile 1565#else 1566 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 GET_INST_OPCODE(ip) @ extract opcode from rINST 1568 GOTO_OPCODE(ip) @ jump to next instruction 1569#endif 1570 1571 1572 1573/* ------------------------------ */ 1574 .balign 64 1575.L_OP_IF_LT: /* 0x34 */ 1576/* File: armv5te/OP_IF_LT.S */ 1577/* File: armv5te/bincmp.S */ 1578 /* 1579 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1580 * fragment that specifies the *reverse* comparison to perform, e.g. 1581 * for "if-le" you would use "gt". 1582 * 1583 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1584 */ 1585 /* if-cmp vA, vB, +CCCC */ 1586 mov r0, rINST, lsr #8 @ r0<- A+ 1587 mov r1, rINST, lsr #12 @ r1<- B 1588 and r0, r0, #15 1589 GET_VREG(r3, r1) @ r3<- vB 1590 GET_VREG(r2, r0) @ r2<- vA 1591 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1592 cmp r2, r3 @ compare (vA, vB) 1593 bge 1f @ branch to 1 if comparison failed 1594 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1595 movs r9, r9, asl #1 @ convert to bytes, check sign 1596 bmi common_backwardBranch @ yes, do periodic checks 15971: 1598#if defined(WITH_JIT) 1599 GET_JIT_PROF_TABLE(r0) 1600 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1601 b common_testUpdateProfile 1602#else 1603 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1604 GET_INST_OPCODE(ip) @ extract opcode from rINST 1605 GOTO_OPCODE(ip) @ jump to next instruction 1606#endif 1607 1608 1609 1610/* ------------------------------ */ 1611 .balign 64 1612.L_OP_IF_GE: /* 0x35 */ 1613/* File: armv5te/OP_IF_GE.S */ 1614/* File: armv5te/bincmp.S */ 1615 /* 1616 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1617 * fragment that specifies the *reverse* comparison to perform, e.g. 1618 * for "if-le" you would use "gt". 1619 * 1620 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1621 */ 1622 /* if-cmp vA, vB, +CCCC */ 1623 mov r0, rINST, lsr #8 @ r0<- A+ 1624 mov r1, rINST, lsr #12 @ r1<- B 1625 and r0, r0, #15 1626 GET_VREG(r3, r1) @ r3<- vB 1627 GET_VREG(r2, r0) @ r2<- vA 1628 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1629 cmp r2, r3 @ compare (vA, vB) 1630 blt 1f @ branch to 1 if comparison failed 1631 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1632 movs r9, r9, asl #1 @ convert to bytes, check sign 1633 bmi common_backwardBranch @ yes, do periodic checks 16341: 1635#if defined(WITH_JIT) 1636 GET_JIT_PROF_TABLE(r0) 1637 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1638 b common_testUpdateProfile 1639#else 1640 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1641 GET_INST_OPCODE(ip) @ extract opcode from rINST 1642 GOTO_OPCODE(ip) @ jump to next instruction 1643#endif 1644 1645 1646 1647/* ------------------------------ */ 1648 .balign 64 1649.L_OP_IF_GT: /* 0x36 */ 1650/* File: armv5te/OP_IF_GT.S */ 1651/* File: armv5te/bincmp.S */ 1652 /* 1653 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1654 * fragment that specifies the *reverse* comparison to perform, e.g. 1655 * for "if-le" you would use "gt". 1656 * 1657 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1658 */ 1659 /* if-cmp vA, vB, +CCCC */ 1660 mov r0, rINST, lsr #8 @ r0<- A+ 1661 mov r1, rINST, lsr #12 @ r1<- B 1662 and r0, r0, #15 1663 GET_VREG(r3, r1) @ r3<- vB 1664 GET_VREG(r2, r0) @ r2<- vA 1665 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1666 cmp r2, r3 @ compare (vA, vB) 1667 ble 1f @ branch to 1 if comparison failed 1668 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1669 movs r9, r9, asl #1 @ convert to bytes, check sign 1670 bmi common_backwardBranch @ yes, do periodic checks 16711: 1672#if defined(WITH_JIT) 1673 GET_JIT_PROF_TABLE(r0) 1674 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1675 b common_testUpdateProfile 1676#else 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 GET_INST_OPCODE(ip) @ extract opcode from rINST 1679 GOTO_OPCODE(ip) @ jump to next instruction 1680#endif 1681 1682 1683 1684/* ------------------------------ */ 1685 .balign 64 1686.L_OP_IF_LE: /* 0x37 */ 1687/* File: armv5te/OP_IF_LE.S */ 1688/* File: armv5te/bincmp.S */ 1689 /* 1690 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1691 * fragment that specifies the *reverse* comparison to perform, e.g. 1692 * for "if-le" you would use "gt". 1693 * 1694 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1695 */ 1696 /* if-cmp vA, vB, +CCCC */ 1697 mov r0, rINST, lsr #8 @ r0<- A+ 1698 mov r1, rINST, lsr #12 @ r1<- B 1699 and r0, r0, #15 1700 GET_VREG(r3, r1) @ r3<- vB 1701 GET_VREG(r2, r0) @ r2<- vA 1702 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1703 cmp r2, r3 @ compare (vA, vB) 1704 bgt 1f @ branch to 1 if comparison failed 1705 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1706 movs r9, r9, asl #1 @ convert to bytes, check sign 1707 bmi common_backwardBranch @ yes, do periodic checks 17081: 1709#if defined(WITH_JIT) 1710 GET_JIT_PROF_TABLE(r0) 1711 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1712 b common_testUpdateProfile 1713#else 1714 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1715 GET_INST_OPCODE(ip) @ extract opcode from rINST 1716 GOTO_OPCODE(ip) @ jump to next instruction 1717#endif 1718 1719 1720 1721/* ------------------------------ */ 1722 .balign 64 1723.L_OP_IF_EQZ: /* 0x38 */ 1724/* File: armv5te/OP_IF_EQZ.S */ 1725/* File: armv5te/zcmp.S */ 1726 /* 1727 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1728 * fragment that specifies the *reverse* comparison to perform, e.g. 1729 * for "if-le" you would use "gt". 1730 * 1731 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1732 */ 1733 /* if-cmp vAA, +BBBB */ 1734 mov r0, rINST, lsr #8 @ r0<- AA 1735 GET_VREG(r2, r0) @ r2<- vAA 1736 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1737 cmp r2, #0 @ compare (vA, 0) 1738 bne 1f @ branch to 1 if comparison failed 1739 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1740 movs r9, r9, asl #1 @ convert to bytes, check sign 1741 bmi common_backwardBranch @ backward branch, do periodic checks 17421: 1743#if defined(WITH_JIT) 1744 GET_JIT_PROF_TABLE(r0) 1745 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1746 cmp r0,#0 1747 bne common_updateProfile 1748 GET_INST_OPCODE(ip) @ extract opcode from rINST 1749 GOTO_OPCODE(ip) @ jump to next instruction 1750#else 1751 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1752 GET_INST_OPCODE(ip) @ extract opcode from rINST 1753 GOTO_OPCODE(ip) @ jump to next instruction 1754#endif 1755 1756 1757 1758/* ------------------------------ */ 1759 .balign 64 1760.L_OP_IF_NEZ: /* 0x39 */ 1761/* File: armv5te/OP_IF_NEZ.S */ 1762/* File: armv5te/zcmp.S */ 1763 /* 1764 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1765 * fragment that specifies the *reverse* comparison to perform, e.g. 1766 * for "if-le" you would use "gt". 1767 * 1768 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1769 */ 1770 /* if-cmp vAA, +BBBB */ 1771 mov r0, rINST, lsr #8 @ r0<- AA 1772 GET_VREG(r2, r0) @ r2<- vAA 1773 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1774 cmp r2, #0 @ compare (vA, 0) 1775 beq 1f @ branch to 1 if comparison failed 1776 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1777 movs r9, r9, asl #1 @ convert to bytes, check sign 1778 bmi common_backwardBranch @ backward branch, do periodic checks 17791: 1780#if defined(WITH_JIT) 1781 GET_JIT_PROF_TABLE(r0) 1782 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1783 cmp r0,#0 1784 bne common_updateProfile 1785 GET_INST_OPCODE(ip) @ extract opcode from rINST 1786 GOTO_OPCODE(ip) @ jump to next instruction 1787#else 1788 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1789 GET_INST_OPCODE(ip) @ extract opcode from rINST 1790 GOTO_OPCODE(ip) @ jump to next instruction 1791#endif 1792 1793 1794 1795/* ------------------------------ */ 1796 .balign 64 1797.L_OP_IF_LTZ: /* 0x3a */ 1798/* File: armv5te/OP_IF_LTZ.S */ 1799/* File: armv5te/zcmp.S */ 1800 /* 1801 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1802 * fragment that specifies the *reverse* comparison to perform, e.g. 1803 * for "if-le" you would use "gt". 1804 * 1805 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1806 */ 1807 /* if-cmp vAA, +BBBB */ 1808 mov r0, rINST, lsr #8 @ r0<- AA 1809 GET_VREG(r2, r0) @ r2<- vAA 1810 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1811 cmp r2, #0 @ compare (vA, 0) 1812 bge 1f @ branch to 1 if comparison failed 1813 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1814 movs r9, r9, asl #1 @ convert to bytes, check sign 1815 bmi common_backwardBranch @ backward branch, do periodic checks 18161: 1817#if defined(WITH_JIT) 1818 GET_JIT_PROF_TABLE(r0) 1819 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1820 cmp r0,#0 1821 bne common_updateProfile 1822 GET_INST_OPCODE(ip) @ extract opcode from rINST 1823 GOTO_OPCODE(ip) @ jump to next instruction 1824#else 1825 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1826 GET_INST_OPCODE(ip) @ extract opcode from rINST 1827 GOTO_OPCODE(ip) @ jump to next instruction 1828#endif 1829 1830 1831 1832/* ------------------------------ */ 1833 .balign 64 1834.L_OP_IF_GEZ: /* 0x3b */ 1835/* File: armv5te/OP_IF_GEZ.S */ 1836/* File: armv5te/zcmp.S */ 1837 /* 1838 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1839 * fragment that specifies the *reverse* comparison to perform, e.g. 1840 * for "if-le" you would use "gt". 1841 * 1842 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1843 */ 1844 /* if-cmp vAA, +BBBB */ 1845 mov r0, rINST, lsr #8 @ r0<- AA 1846 GET_VREG(r2, r0) @ r2<- vAA 1847 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1848 cmp r2, #0 @ compare (vA, 0) 1849 blt 1f @ branch to 1 if comparison failed 1850 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1851 movs r9, r9, asl #1 @ convert to bytes, check sign 1852 bmi common_backwardBranch @ backward branch, do periodic checks 18531: 1854#if defined(WITH_JIT) 1855 GET_JIT_PROF_TABLE(r0) 1856 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1857 cmp r0,#0 1858 bne common_updateProfile 1859 GET_INST_OPCODE(ip) @ extract opcode from rINST 1860 GOTO_OPCODE(ip) @ jump to next instruction 1861#else 1862 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1863 GET_INST_OPCODE(ip) @ extract opcode from rINST 1864 GOTO_OPCODE(ip) @ jump to next instruction 1865#endif 1866 1867 1868 1869/* ------------------------------ */ 1870 .balign 64 1871.L_OP_IF_GTZ: /* 0x3c */ 1872/* File: armv5te/OP_IF_GTZ.S */ 1873/* File: armv5te/zcmp.S */ 1874 /* 1875 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1876 * fragment that specifies the *reverse* comparison to perform, e.g. 1877 * for "if-le" you would use "gt". 1878 * 1879 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1880 */ 1881 /* if-cmp vAA, +BBBB */ 1882 mov r0, rINST, lsr #8 @ r0<- AA 1883 GET_VREG(r2, r0) @ r2<- vAA 1884 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1885 cmp r2, #0 @ compare (vA, 0) 1886 ble 1f @ branch to 1 if comparison failed 1887 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1888 movs r9, r9, asl #1 @ convert to bytes, check sign 1889 bmi common_backwardBranch @ backward branch, do periodic checks 18901: 1891#if defined(WITH_JIT) 1892 GET_JIT_PROF_TABLE(r0) 1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1894 cmp r0,#0 1895 bne common_updateProfile 1896 GET_INST_OPCODE(ip) @ extract opcode from rINST 1897 GOTO_OPCODE(ip) @ jump to next instruction 1898#else 1899 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1900 GET_INST_OPCODE(ip) @ extract opcode from rINST 1901 GOTO_OPCODE(ip) @ jump to next instruction 1902#endif 1903 1904 1905 1906/* ------------------------------ */ 1907 .balign 64 1908.L_OP_IF_LEZ: /* 0x3d */ 1909/* File: armv5te/OP_IF_LEZ.S */ 1910/* File: armv5te/zcmp.S */ 1911 /* 1912 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1913 * fragment that specifies the *reverse* comparison to perform, e.g. 1914 * for "if-le" you would use "gt". 1915 * 1916 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1917 */ 1918 /* if-cmp vAA, +BBBB */ 1919 mov r0, rINST, lsr #8 @ r0<- AA 1920 GET_VREG(r2, r0) @ r2<- vAA 1921 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1922 cmp r2, #0 @ compare (vA, 0) 1923 bgt 1f @ branch to 1 if comparison failed 1924 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1925 movs r9, r9, asl #1 @ convert to bytes, check sign 1926 bmi common_backwardBranch @ backward branch, do periodic checks 19271: 1928#if defined(WITH_JIT) 1929 GET_JIT_PROF_TABLE(r0) 1930 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1931 cmp r0,#0 1932 bne common_updateProfile 1933 GET_INST_OPCODE(ip) @ extract opcode from rINST 1934 GOTO_OPCODE(ip) @ jump to next instruction 1935#else 1936 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1937 GET_INST_OPCODE(ip) @ extract opcode from rINST 1938 GOTO_OPCODE(ip) @ jump to next instruction 1939#endif 1940 1941 1942 1943/* ------------------------------ */ 1944 .balign 64 1945.L_OP_UNUSED_3E: /* 0x3e */ 1946/* File: armv5te/OP_UNUSED_3E.S */ 1947/* File: armv5te/unused.S */ 1948 bl common_abort 1949 1950 1951 1952/* ------------------------------ */ 1953 .balign 64 1954.L_OP_UNUSED_3F: /* 0x3f */ 1955/* File: armv5te/OP_UNUSED_3F.S */ 1956/* File: armv5te/unused.S */ 1957 bl common_abort 1958 1959 1960 1961/* ------------------------------ */ 1962 .balign 64 1963.L_OP_UNUSED_40: /* 0x40 */ 1964/* File: armv5te/OP_UNUSED_40.S */ 1965/* File: armv5te/unused.S */ 1966 bl common_abort 1967 1968 1969 1970/* ------------------------------ */ 1971 .balign 64 1972.L_OP_UNUSED_41: /* 0x41 */ 1973/* File: armv5te/OP_UNUSED_41.S */ 1974/* File: armv5te/unused.S */ 1975 bl common_abort 1976 1977 1978 1979/* ------------------------------ */ 1980 .balign 64 1981.L_OP_UNUSED_42: /* 0x42 */ 1982/* File: armv5te/OP_UNUSED_42.S */ 1983/* File: armv5te/unused.S */ 1984 bl common_abort 1985 1986 1987 1988/* ------------------------------ */ 1989 .balign 64 1990.L_OP_UNUSED_43: /* 0x43 */ 1991/* File: armv5te/OP_UNUSED_43.S */ 1992/* File: armv5te/unused.S */ 1993 bl common_abort 1994 1995 1996 1997/* ------------------------------ */ 1998 .balign 64 1999.L_OP_AGET: /* 0x44 */ 2000/* File: armv5te/OP_AGET.S */ 2001 /* 2002 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2003 * 2004 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2005 * instructions. We use a pair of FETCH_Bs instead. 2006 * 2007 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2008 */ 2009 /* op vAA, vBB, vCC */ 2010 FETCH_B(r2, 1, 0) @ r2<- BB 2011 mov r9, rINST, lsr #8 @ r9<- AA 2012 FETCH_B(r3, 1, 1) @ r3<- CC 2013 GET_VREG(r0, r2) @ r0<- vBB (array object) 2014 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2015 cmp r0, #0 @ null array object? 2016 beq common_errNullObject @ yes, bail 2017 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2018 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2019 cmp r1, r3 @ compare unsigned index, length 2020 bcs common_errArrayIndex @ index >= length, bail 2021 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2022 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2023 GET_INST_OPCODE(ip) @ extract opcode from rINST 2024 SET_VREG(r2, r9) @ vAA<- r2 2025 GOTO_OPCODE(ip) @ jump to next instruction 2026 2027 2028/* ------------------------------ */ 2029 .balign 64 2030.L_OP_AGET_WIDE: /* 0x45 */ 2031/* File: armv5te/OP_AGET_WIDE.S */ 2032 /* 2033 * Array get, 64 bits. vAA <- vBB[vCC]. 2034 * 2035 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2036 */ 2037 /* aget-wide vAA, vBB, vCC */ 2038 FETCH(r0, 1) @ r0<- CCBB 2039 mov r9, rINST, lsr #8 @ r9<- AA 2040 and r2, r0, #255 @ r2<- BB 2041 mov r3, r0, lsr #8 @ r3<- CC 2042 GET_VREG(r0, r2) @ r0<- vBB (array object) 2043 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2044 cmp r0, #0 @ null array object? 2045 beq common_errNullObject @ yes, bail 2046 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2047 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2048 cmp r1, r3 @ compare unsigned index, length 2049 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2050 b common_errArrayIndex @ index >= length, bail 2051 @ May want to swap the order of these two branches depending on how the 2052 @ branch prediction (if any) handles conditional forward branches vs. 2053 @ unconditional forward branches. 2054 2055/* ------------------------------ */ 2056 .balign 64 2057.L_OP_AGET_OBJECT: /* 0x46 */ 2058/* File: armv5te/OP_AGET_OBJECT.S */ 2059/* File: armv5te/OP_AGET.S */ 2060 /* 2061 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2062 * 2063 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2064 * instructions. We use a pair of FETCH_Bs instead. 2065 * 2066 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2067 */ 2068 /* op vAA, vBB, vCC */ 2069 FETCH_B(r2, 1, 0) @ r2<- BB 2070 mov r9, rINST, lsr #8 @ r9<- AA 2071 FETCH_B(r3, 1, 1) @ r3<- CC 2072 GET_VREG(r0, r2) @ r0<- vBB (array object) 2073 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2074 cmp r0, #0 @ null array object? 2075 beq common_errNullObject @ yes, bail 2076 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2077 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2078 cmp r1, r3 @ compare unsigned index, length 2079 bcs common_errArrayIndex @ index >= length, bail 2080 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2081 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2082 GET_INST_OPCODE(ip) @ extract opcode from rINST 2083 SET_VREG(r2, r9) @ vAA<- r2 2084 GOTO_OPCODE(ip) @ jump to next instruction 2085 2086 2087 2088/* ------------------------------ */ 2089 .balign 64 2090.L_OP_AGET_BOOLEAN: /* 0x47 */ 2091/* File: armv5te/OP_AGET_BOOLEAN.S */ 2092/* File: armv5te/OP_AGET.S */ 2093 /* 2094 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2095 * 2096 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2097 * instructions. We use a pair of FETCH_Bs instead. 2098 * 2099 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2100 */ 2101 /* op vAA, vBB, vCC */ 2102 FETCH_B(r2, 1, 0) @ r2<- BB 2103 mov r9, rINST, lsr #8 @ r9<- AA 2104 FETCH_B(r3, 1, 1) @ r3<- CC 2105 GET_VREG(r0, r2) @ r0<- vBB (array object) 2106 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2107 cmp r0, #0 @ null array object? 2108 beq common_errNullObject @ yes, bail 2109 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2110 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2111 cmp r1, r3 @ compare unsigned index, length 2112 bcs common_errArrayIndex @ index >= length, bail 2113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2114 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2115 GET_INST_OPCODE(ip) @ extract opcode from rINST 2116 SET_VREG(r2, r9) @ vAA<- r2 2117 GOTO_OPCODE(ip) @ jump to next instruction 2118 2119 2120 2121/* ------------------------------ */ 2122 .balign 64 2123.L_OP_AGET_BYTE: /* 0x48 */ 2124/* File: armv5te/OP_AGET_BYTE.S */ 2125/* File: armv5te/OP_AGET.S */ 2126 /* 2127 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2128 * 2129 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2130 * instructions. We use a pair of FETCH_Bs instead. 2131 * 2132 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2133 */ 2134 /* op vAA, vBB, vCC */ 2135 FETCH_B(r2, 1, 0) @ r2<- BB 2136 mov r9, rINST, lsr #8 @ r9<- AA 2137 FETCH_B(r3, 1, 1) @ r3<- CC 2138 GET_VREG(r0, r2) @ r0<- vBB (array object) 2139 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2140 cmp r0, #0 @ null array object? 2141 beq common_errNullObject @ yes, bail 2142 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2143 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2144 cmp r1, r3 @ compare unsigned index, length 2145 bcs common_errArrayIndex @ index >= length, bail 2146 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2147 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2148 GET_INST_OPCODE(ip) @ extract opcode from rINST 2149 SET_VREG(r2, r9) @ vAA<- r2 2150 GOTO_OPCODE(ip) @ jump to next instruction 2151 2152 2153 2154/* ------------------------------ */ 2155 .balign 64 2156.L_OP_AGET_CHAR: /* 0x49 */ 2157/* File: armv5te/OP_AGET_CHAR.S */ 2158/* File: armv5te/OP_AGET.S */ 2159 /* 2160 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2161 * 2162 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2163 * instructions. We use a pair of FETCH_Bs instead. 2164 * 2165 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2166 */ 2167 /* op vAA, vBB, vCC */ 2168 FETCH_B(r2, 1, 0) @ r2<- BB 2169 mov r9, rINST, lsr #8 @ r9<- AA 2170 FETCH_B(r3, 1, 1) @ r3<- CC 2171 GET_VREG(r0, r2) @ r0<- vBB (array object) 2172 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2173 cmp r0, #0 @ null array object? 2174 beq common_errNullObject @ yes, bail 2175 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2176 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2177 cmp r1, r3 @ compare unsigned index, length 2178 bcs common_errArrayIndex @ index >= length, bail 2179 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2180 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2181 GET_INST_OPCODE(ip) @ extract opcode from rINST 2182 SET_VREG(r2, r9) @ vAA<- r2 2183 GOTO_OPCODE(ip) @ jump to next instruction 2184 2185 2186 2187/* ------------------------------ */ 2188 .balign 64 2189.L_OP_AGET_SHORT: /* 0x4a */ 2190/* File: armv5te/OP_AGET_SHORT.S */ 2191/* File: armv5te/OP_AGET.S */ 2192 /* 2193 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2194 * 2195 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2196 * instructions. We use a pair of FETCH_Bs instead. 2197 * 2198 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2199 */ 2200 /* op vAA, vBB, vCC */ 2201 FETCH_B(r2, 1, 0) @ r2<- BB 2202 mov r9, rINST, lsr #8 @ r9<- AA 2203 FETCH_B(r3, 1, 1) @ r3<- CC 2204 GET_VREG(r0, r2) @ r0<- vBB (array object) 2205 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2206 cmp r0, #0 @ null array object? 2207 beq common_errNullObject @ yes, bail 2208 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2209 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2210 cmp r1, r3 @ compare unsigned index, length 2211 bcs common_errArrayIndex @ index >= length, bail 2212 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2213 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2214 GET_INST_OPCODE(ip) @ extract opcode from rINST 2215 SET_VREG(r2, r9) @ vAA<- r2 2216 GOTO_OPCODE(ip) @ jump to next instruction 2217 2218 2219 2220/* ------------------------------ */ 2221 .balign 64 2222.L_OP_APUT: /* 0x4b */ 2223/* File: armv5te/OP_APUT.S */ 2224 /* 2225 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2226 * 2227 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2228 * instructions. We use a pair of FETCH_Bs instead. 2229 * 2230 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2231 */ 2232 /* op vAA, vBB, vCC */ 2233 FETCH_B(r2, 1, 0) @ r2<- BB 2234 mov r9, rINST, lsr #8 @ r9<- AA 2235 FETCH_B(r3, 1, 1) @ r3<- CC 2236 GET_VREG(r0, r2) @ r0<- vBB (array object) 2237 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2238 cmp r0, #0 @ null array object? 2239 beq common_errNullObject @ yes, bail 2240 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2241 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2242 cmp r1, r3 @ compare unsigned index, length 2243 bcs common_errArrayIndex @ index >= length, bail 2244 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2245 GET_VREG(r2, r9) @ r2<- vAA 2246 GET_INST_OPCODE(ip) @ extract opcode from rINST 2247 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2248 GOTO_OPCODE(ip) @ jump to next instruction 2249 2250 2251/* ------------------------------ */ 2252 .balign 64 2253.L_OP_APUT_WIDE: /* 0x4c */ 2254/* File: armv5te/OP_APUT_WIDE.S */ 2255 /* 2256 * Array put, 64 bits. vBB[vCC] <- vAA. 2257 * 2258 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2259 */ 2260 /* aput-wide vAA, vBB, vCC */ 2261 FETCH(r0, 1) @ r0<- CCBB 2262 mov r9, rINST, lsr #8 @ r9<- AA 2263 and r2, r0, #255 @ r2<- BB 2264 mov r3, r0, lsr #8 @ r3<- CC 2265 GET_VREG(r0, r2) @ r0<- vBB (array object) 2266 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2267 cmp r0, #0 @ null array object? 2268 beq common_errNullObject @ yes, bail 2269 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2270 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2271 cmp r1, r3 @ compare unsigned index, length 2272 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2273 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2274 b common_errArrayIndex @ index >= length, bail 2275 @ May want to swap the order of these two branches depending on how the 2276 @ branch prediction (if any) handles conditional forward branches vs. 2277 @ unconditional forward branches. 2278 2279/* ------------------------------ */ 2280 .balign 64 2281.L_OP_APUT_OBJECT: /* 0x4d */ 2282/* File: armv5te/OP_APUT_OBJECT.S */ 2283 /* 2284 * Store an object into an array. vBB[vCC] <- vAA. 2285 * 2286 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2287 * instructions. We use a pair of FETCH_Bs instead. 2288 */ 2289 /* op vAA, vBB, vCC */ 2290 FETCH(r0, 1) @ r0<- CCBB 2291 mov r9, rINST, lsr #8 @ r9<- AA 2292 and r2, r0, #255 @ r2<- BB 2293 mov r3, r0, lsr #8 @ r3<- CC 2294 GET_VREG(r1, r2) @ r1<- vBB (array object) 2295 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2296 cmp r1, #0 @ null array object? 2297 GET_VREG(r9, r9) @ r9<- vAA 2298 beq common_errNullObject @ yes, bail 2299 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2300 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2301 cmp r0, r3 @ compare unsigned index, length 2302 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2303 b common_errArrayIndex @ index >= length, bail 2304 2305 2306/* ------------------------------ */ 2307 .balign 64 2308.L_OP_APUT_BOOLEAN: /* 0x4e */ 2309/* File: armv5te/OP_APUT_BOOLEAN.S */ 2310/* File: armv5te/OP_APUT.S */ 2311 /* 2312 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2313 * 2314 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2315 * instructions. We use a pair of FETCH_Bs instead. 2316 * 2317 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2318 */ 2319 /* op vAA, vBB, vCC */ 2320 FETCH_B(r2, 1, 0) @ r2<- BB 2321 mov r9, rINST, lsr #8 @ r9<- AA 2322 FETCH_B(r3, 1, 1) @ r3<- CC 2323 GET_VREG(r0, r2) @ r0<- vBB (array object) 2324 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2325 cmp r0, #0 @ null array object? 2326 beq common_errNullObject @ yes, bail 2327 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2328 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2329 cmp r1, r3 @ compare unsigned index, length 2330 bcs common_errArrayIndex @ index >= length, bail 2331 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2332 GET_VREG(r2, r9) @ r2<- vAA 2333 GET_INST_OPCODE(ip) @ extract opcode from rINST 2334 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2335 GOTO_OPCODE(ip) @ jump to next instruction 2336 2337 2338 2339/* ------------------------------ */ 2340 .balign 64 2341.L_OP_APUT_BYTE: /* 0x4f */ 2342/* File: armv5te/OP_APUT_BYTE.S */ 2343/* File: armv5te/OP_APUT.S */ 2344 /* 2345 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2346 * 2347 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2348 * instructions. We use a pair of FETCH_Bs instead. 2349 * 2350 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2351 */ 2352 /* op vAA, vBB, vCC */ 2353 FETCH_B(r2, 1, 0) @ r2<- BB 2354 mov r9, rINST, lsr #8 @ r9<- AA 2355 FETCH_B(r3, 1, 1) @ r3<- CC 2356 GET_VREG(r0, r2) @ r0<- vBB (array object) 2357 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2358 cmp r0, #0 @ null array object? 2359 beq common_errNullObject @ yes, bail 2360 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2361 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2362 cmp r1, r3 @ compare unsigned index, length 2363 bcs common_errArrayIndex @ index >= length, bail 2364 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2365 GET_VREG(r2, r9) @ r2<- vAA 2366 GET_INST_OPCODE(ip) @ extract opcode from rINST 2367 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2368 GOTO_OPCODE(ip) @ jump to next instruction 2369 2370 2371 2372/* ------------------------------ */ 2373 .balign 64 2374.L_OP_APUT_CHAR: /* 0x50 */ 2375/* File: armv5te/OP_APUT_CHAR.S */ 2376/* File: armv5te/OP_APUT.S */ 2377 /* 2378 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2379 * 2380 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2381 * instructions. We use a pair of FETCH_Bs instead. 2382 * 2383 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2384 */ 2385 /* op vAA, vBB, vCC */ 2386 FETCH_B(r2, 1, 0) @ r2<- BB 2387 mov r9, rINST, lsr #8 @ r9<- AA 2388 FETCH_B(r3, 1, 1) @ r3<- CC 2389 GET_VREG(r0, r2) @ r0<- vBB (array object) 2390 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2391 cmp r0, #0 @ null array object? 2392 beq common_errNullObject @ yes, bail 2393 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2394 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2395 cmp r1, r3 @ compare unsigned index, length 2396 bcs common_errArrayIndex @ index >= length, bail 2397 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2398 GET_VREG(r2, r9) @ r2<- vAA 2399 GET_INST_OPCODE(ip) @ extract opcode from rINST 2400 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2401 GOTO_OPCODE(ip) @ jump to next instruction 2402 2403 2404 2405/* ------------------------------ */ 2406 .balign 64 2407.L_OP_APUT_SHORT: /* 0x51 */ 2408/* File: armv5te/OP_APUT_SHORT.S */ 2409/* File: armv5te/OP_APUT.S */ 2410 /* 2411 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2412 * 2413 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2414 * instructions. We use a pair of FETCH_Bs instead. 2415 * 2416 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2417 */ 2418 /* op vAA, vBB, vCC */ 2419 FETCH_B(r2, 1, 0) @ r2<- BB 2420 mov r9, rINST, lsr #8 @ r9<- AA 2421 FETCH_B(r3, 1, 1) @ r3<- CC 2422 GET_VREG(r0, r2) @ r0<- vBB (array object) 2423 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2424 cmp r0, #0 @ null array object? 2425 beq common_errNullObject @ yes, bail 2426 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2427 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2428 cmp r1, r3 @ compare unsigned index, length 2429 bcs common_errArrayIndex @ index >= length, bail 2430 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2431 GET_VREG(r2, r9) @ r2<- vAA 2432 GET_INST_OPCODE(ip) @ extract opcode from rINST 2433 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2434 GOTO_OPCODE(ip) @ jump to next instruction 2435 2436 2437 2438/* ------------------------------ */ 2439 .balign 64 2440.L_OP_IGET: /* 0x52 */ 2441/* File: armv5te/OP_IGET.S */ 2442 /* 2443 * General 32-bit instance field get. 2444 * 2445 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2446 */ 2447 /* op vA, vB, field@CCCC */ 2448 mov r0, rINST, lsr #12 @ r0<- B 2449 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2450 FETCH(r1, 1) @ r1<- field ref CCCC 2451 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2452 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2453 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2454 cmp r0, #0 @ is resolved entry null? 2455 bne .LOP_IGET_finish @ no, already resolved 24568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2457 EXPORT_PC() @ resolve() could throw 2458 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2459 bl dvmResolveInstField @ r0<- resolved InstField ptr 2460 cmp r0, #0 2461 bne .LOP_IGET_finish 2462 b common_exceptionThrown 2463 2464/* ------------------------------ */ 2465 .balign 64 2466.L_OP_IGET_WIDE: /* 0x53 */ 2467/* File: armv5te/OP_IGET_WIDE.S */ 2468 /* 2469 * Wide 32-bit instance field get. 2470 */ 2471 /* iget-wide vA, vB, field@CCCC */ 2472 mov r0, rINST, lsr #12 @ r0<- B 2473 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2474 FETCH(r1, 1) @ r1<- field ref CCCC 2475 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2476 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2477 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2478 cmp r0, #0 @ is resolved entry null? 2479 bne .LOP_IGET_WIDE_finish @ no, already resolved 24808: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2481 EXPORT_PC() @ resolve() could throw 2482 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2483 bl dvmResolveInstField @ r0<- resolved InstField ptr 2484 cmp r0, #0 2485 bne .LOP_IGET_WIDE_finish 2486 b common_exceptionThrown 2487 2488/* ------------------------------ */ 2489 .balign 64 2490.L_OP_IGET_OBJECT: /* 0x54 */ 2491/* File: armv5te/OP_IGET_OBJECT.S */ 2492/* File: armv5te/OP_IGET.S */ 2493 /* 2494 * General 32-bit instance field get. 2495 * 2496 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2497 */ 2498 /* op vA, vB, field@CCCC */ 2499 mov r0, rINST, lsr #12 @ r0<- B 2500 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2501 FETCH(r1, 1) @ r1<- field ref CCCC 2502 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2503 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2504 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2505 cmp r0, #0 @ is resolved entry null? 2506 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2508 EXPORT_PC() @ resolve() could throw 2509 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2510 bl dvmResolveInstField @ r0<- resolved InstField ptr 2511 cmp r0, #0 2512 bne .LOP_IGET_OBJECT_finish 2513 b common_exceptionThrown 2514 2515 2516/* ------------------------------ */ 2517 .balign 64 2518.L_OP_IGET_BOOLEAN: /* 0x55 */ 2519/* File: armv5te/OP_IGET_BOOLEAN.S */ 2520@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2521/* File: armv5te/OP_IGET.S */ 2522 /* 2523 * General 32-bit instance field get. 2524 * 2525 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2526 */ 2527 /* op vA, vB, field@CCCC */ 2528 mov r0, rINST, lsr #12 @ r0<- B 2529 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2530 FETCH(r1, 1) @ r1<- field ref CCCC 2531 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2532 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2533 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2534 cmp r0, #0 @ is resolved entry null? 2535 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2537 EXPORT_PC() @ resolve() could throw 2538 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2539 bl dvmResolveInstField @ r0<- resolved InstField ptr 2540 cmp r0, #0 2541 bne .LOP_IGET_BOOLEAN_finish 2542 b common_exceptionThrown 2543 2544 2545/* ------------------------------ */ 2546 .balign 64 2547.L_OP_IGET_BYTE: /* 0x56 */ 2548/* File: armv5te/OP_IGET_BYTE.S */ 2549@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2550/* File: armv5te/OP_IGET.S */ 2551 /* 2552 * General 32-bit instance field get. 2553 * 2554 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2555 */ 2556 /* op vA, vB, field@CCCC */ 2557 mov r0, rINST, lsr #12 @ r0<- B 2558 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2559 FETCH(r1, 1) @ r1<- field ref CCCC 2560 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2561 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2562 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2563 cmp r0, #0 @ is resolved entry null? 2564 bne .LOP_IGET_BYTE_finish @ no, already resolved 25658: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2566 EXPORT_PC() @ resolve() could throw 2567 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2568 bl dvmResolveInstField @ r0<- resolved InstField ptr 2569 cmp r0, #0 2570 bne .LOP_IGET_BYTE_finish 2571 b common_exceptionThrown 2572 2573 2574/* ------------------------------ */ 2575 .balign 64 2576.L_OP_IGET_CHAR: /* 0x57 */ 2577/* File: armv5te/OP_IGET_CHAR.S */ 2578@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2579/* File: armv5te/OP_IGET.S */ 2580 /* 2581 * General 32-bit instance field get. 2582 * 2583 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2584 */ 2585 /* op vA, vB, field@CCCC */ 2586 mov r0, rINST, lsr #12 @ r0<- B 2587 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2588 FETCH(r1, 1) @ r1<- field ref CCCC 2589 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2590 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2591 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2592 cmp r0, #0 @ is resolved entry null? 2593 bne .LOP_IGET_CHAR_finish @ no, already resolved 25948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2595 EXPORT_PC() @ resolve() could throw 2596 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2597 bl dvmResolveInstField @ r0<- resolved InstField ptr 2598 cmp r0, #0 2599 bne .LOP_IGET_CHAR_finish 2600 b common_exceptionThrown 2601 2602 2603/* ------------------------------ */ 2604 .balign 64 2605.L_OP_IGET_SHORT: /* 0x58 */ 2606/* File: armv5te/OP_IGET_SHORT.S */ 2607@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2608/* File: armv5te/OP_IGET.S */ 2609 /* 2610 * General 32-bit instance field get. 2611 * 2612 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2613 */ 2614 /* op vA, vB, field@CCCC */ 2615 mov r0, rINST, lsr #12 @ r0<- B 2616 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2617 FETCH(r1, 1) @ r1<- field ref CCCC 2618 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2619 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2620 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2621 cmp r0, #0 @ is resolved entry null? 2622 bne .LOP_IGET_SHORT_finish @ no, already resolved 26238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2624 EXPORT_PC() @ resolve() could throw 2625 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2626 bl dvmResolveInstField @ r0<- resolved InstField ptr 2627 cmp r0, #0 2628 bne .LOP_IGET_SHORT_finish 2629 b common_exceptionThrown 2630 2631 2632/* ------------------------------ */ 2633 .balign 64 2634.L_OP_IPUT: /* 0x59 */ 2635/* File: armv5te/OP_IPUT.S */ 2636 /* 2637 * General 32-bit instance field put. 2638 * 2639 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2640 */ 2641 /* op vA, vB, field@CCCC */ 2642 mov r0, rINST, lsr #12 @ r0<- B 2643 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2644 FETCH(r1, 1) @ r1<- field ref CCCC 2645 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2646 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2647 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2648 cmp r0, #0 @ is resolved entry null? 2649 bne .LOP_IPUT_finish @ no, already resolved 26508: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2651 EXPORT_PC() @ resolve() could throw 2652 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2653 bl dvmResolveInstField @ r0<- resolved InstField ptr 2654 cmp r0, #0 @ success? 2655 bne .LOP_IPUT_finish @ yes, finish up 2656 b common_exceptionThrown 2657 2658/* ------------------------------ */ 2659 .balign 64 2660.L_OP_IPUT_WIDE: /* 0x5a */ 2661/* File: armv5te/OP_IPUT_WIDE.S */ 2662 /* iput-wide vA, vB, field@CCCC */ 2663 mov r0, rINST, lsr #12 @ r0<- B 2664 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2665 FETCH(r1, 1) @ r1<- field ref CCCC 2666 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2667 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2668 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2669 cmp r0, #0 @ is resolved entry null? 2670 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2672 EXPORT_PC() @ resolve() could throw 2673 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2674 bl dvmResolveInstField @ r0<- resolved InstField ptr 2675 cmp r0, #0 @ success? 2676 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2677 b common_exceptionThrown 2678 2679/* ------------------------------ */ 2680 .balign 64 2681.L_OP_IPUT_OBJECT: /* 0x5b */ 2682/* File: armv5te/OP_IPUT_OBJECT.S */ 2683/* File: armv5te/OP_IPUT.S */ 2684 /* 2685 * General 32-bit instance field put. 2686 * 2687 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2688 */ 2689 /* op vA, vB, field@CCCC */ 2690 mov r0, rINST, lsr #12 @ r0<- B 2691 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2692 FETCH(r1, 1) @ r1<- field ref CCCC 2693 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2694 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2695 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2696 cmp r0, #0 @ is resolved entry null? 2697 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2699 EXPORT_PC() @ resolve() could throw 2700 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2701 bl dvmResolveInstField @ r0<- resolved InstField ptr 2702 cmp r0, #0 @ success? 2703 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2704 b common_exceptionThrown 2705 2706 2707/* ------------------------------ */ 2708 .balign 64 2709.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2710/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2711@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2712/* File: armv5te/OP_IPUT.S */ 2713 /* 2714 * General 32-bit instance field put. 2715 * 2716 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2717 */ 2718 /* op vA, vB, field@CCCC */ 2719 mov r0, rINST, lsr #12 @ r0<- B 2720 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2721 FETCH(r1, 1) @ r1<- field ref CCCC 2722 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2723 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2724 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2725 cmp r0, #0 @ is resolved entry null? 2726 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27278: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2728 EXPORT_PC() @ resolve() could throw 2729 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2730 bl dvmResolveInstField @ r0<- resolved InstField ptr 2731 cmp r0, #0 @ success? 2732 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2733 b common_exceptionThrown 2734 2735 2736/* ------------------------------ */ 2737 .balign 64 2738.L_OP_IPUT_BYTE: /* 0x5d */ 2739/* File: armv5te/OP_IPUT_BYTE.S */ 2740@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2741/* File: armv5te/OP_IPUT.S */ 2742 /* 2743 * General 32-bit instance field put. 2744 * 2745 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2746 */ 2747 /* op vA, vB, field@CCCC */ 2748 mov r0, rINST, lsr #12 @ r0<- B 2749 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2750 FETCH(r1, 1) @ r1<- field ref CCCC 2751 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2752 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2753 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2754 cmp r0, #0 @ is resolved entry null? 2755 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2757 EXPORT_PC() @ resolve() could throw 2758 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2759 bl dvmResolveInstField @ r0<- resolved InstField ptr 2760 cmp r0, #0 @ success? 2761 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2762 b common_exceptionThrown 2763 2764 2765/* ------------------------------ */ 2766 .balign 64 2767.L_OP_IPUT_CHAR: /* 0x5e */ 2768/* File: armv5te/OP_IPUT_CHAR.S */ 2769@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2770/* File: armv5te/OP_IPUT.S */ 2771 /* 2772 * General 32-bit instance field put. 2773 * 2774 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2775 */ 2776 /* op vA, vB, field@CCCC */ 2777 mov r0, rINST, lsr #12 @ r0<- B 2778 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2779 FETCH(r1, 1) @ r1<- field ref CCCC 2780 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2781 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2782 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2783 cmp r0, #0 @ is resolved entry null? 2784 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27858: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2786 EXPORT_PC() @ resolve() could throw 2787 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2788 bl dvmResolveInstField @ r0<- resolved InstField ptr 2789 cmp r0, #0 @ success? 2790 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2791 b common_exceptionThrown 2792 2793 2794/* ------------------------------ */ 2795 .balign 64 2796.L_OP_IPUT_SHORT: /* 0x5f */ 2797/* File: armv5te/OP_IPUT_SHORT.S */ 2798@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2799/* File: armv5te/OP_IPUT.S */ 2800 /* 2801 * General 32-bit instance field put. 2802 * 2803 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2804 */ 2805 /* op vA, vB, field@CCCC */ 2806 mov r0, rINST, lsr #12 @ r0<- B 2807 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2808 FETCH(r1, 1) @ r1<- field ref CCCC 2809 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2810 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2811 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2812 cmp r0, #0 @ is resolved entry null? 2813 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28148: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2815 EXPORT_PC() @ resolve() could throw 2816 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2817 bl dvmResolveInstField @ r0<- resolved InstField ptr 2818 cmp r0, #0 @ success? 2819 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2820 b common_exceptionThrown 2821 2822 2823/* ------------------------------ */ 2824 .balign 64 2825.L_OP_SGET: /* 0x60 */ 2826/* File: armv5te/OP_SGET.S */ 2827 /* 2828 * General 32-bit SGET handler. 2829 * 2830 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2831 */ 2832 /* op vAA, field@BBBB */ 2833 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2834 FETCH(r1, 1) @ r1<- field ref BBBB 2835 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2836 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2837 cmp r0, #0 @ is resolved entry null? 2838 beq .LOP_SGET_resolve @ yes, do resolve 2839.LOP_SGET_finish: @ field ptr in r0 2840 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2841 mov r2, rINST, lsr #8 @ r2<- AA 2842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2843 SET_VREG(r1, r2) @ fp[AA]<- r1 2844 GET_INST_OPCODE(ip) @ extract opcode from rINST 2845 GOTO_OPCODE(ip) @ jump to next instruction 2846 2847/* ------------------------------ */ 2848 .balign 64 2849.L_OP_SGET_WIDE: /* 0x61 */ 2850/* File: armv5te/OP_SGET_WIDE.S */ 2851 /* 2852 * 64-bit SGET handler. 2853 */ 2854 /* sget-wide vAA, field@BBBB */ 2855 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2856 FETCH(r1, 1) @ r1<- field ref BBBB 2857 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2858 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2859 cmp r0, #0 @ is resolved entry null? 2860 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2861.LOP_SGET_WIDE_finish: 2862 mov r1, rINST, lsr #8 @ r1<- AA 2863 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2864 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2865 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2866 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2867 GET_INST_OPCODE(ip) @ extract opcode from rINST 2868 GOTO_OPCODE(ip) @ jump to next instruction 2869 2870/* ------------------------------ */ 2871 .balign 64 2872.L_OP_SGET_OBJECT: /* 0x62 */ 2873/* File: armv5te/OP_SGET_OBJECT.S */ 2874/* File: armv5te/OP_SGET.S */ 2875 /* 2876 * General 32-bit SGET handler. 2877 * 2878 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2879 */ 2880 /* op vAA, field@BBBB */ 2881 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2882 FETCH(r1, 1) @ r1<- field ref BBBB 2883 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2884 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2885 cmp r0, #0 @ is resolved entry null? 2886 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2887.LOP_SGET_OBJECT_finish: @ field ptr in r0 2888 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2889 mov r2, rINST, lsr #8 @ r2<- AA 2890 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2891 SET_VREG(r1, r2) @ fp[AA]<- r1 2892 GET_INST_OPCODE(ip) @ extract opcode from rINST 2893 GOTO_OPCODE(ip) @ jump to next instruction 2894 2895 2896/* ------------------------------ */ 2897 .balign 64 2898.L_OP_SGET_BOOLEAN: /* 0x63 */ 2899/* File: armv5te/OP_SGET_BOOLEAN.S */ 2900/* File: armv5te/OP_SGET.S */ 2901 /* 2902 * General 32-bit SGET handler. 2903 * 2904 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2905 */ 2906 /* op vAA, field@BBBB */ 2907 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2908 FETCH(r1, 1) @ r1<- field ref BBBB 2909 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2910 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2911 cmp r0, #0 @ is resolved entry null? 2912 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2913.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2914 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2915 mov r2, rINST, lsr #8 @ r2<- AA 2916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2917 SET_VREG(r1, r2) @ fp[AA]<- r1 2918 GET_INST_OPCODE(ip) @ extract opcode from rINST 2919 GOTO_OPCODE(ip) @ jump to next instruction 2920 2921 2922/* ------------------------------ */ 2923 .balign 64 2924.L_OP_SGET_BYTE: /* 0x64 */ 2925/* File: armv5te/OP_SGET_BYTE.S */ 2926/* File: armv5te/OP_SGET.S */ 2927 /* 2928 * General 32-bit SGET handler. 2929 * 2930 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2931 */ 2932 /* op vAA, field@BBBB */ 2933 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2934 FETCH(r1, 1) @ r1<- field ref BBBB 2935 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2936 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2937 cmp r0, #0 @ is resolved entry null? 2938 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2939.LOP_SGET_BYTE_finish: @ field ptr in r0 2940 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2941 mov r2, rINST, lsr #8 @ r2<- AA 2942 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2943 SET_VREG(r1, r2) @ fp[AA]<- r1 2944 GET_INST_OPCODE(ip) @ extract opcode from rINST 2945 GOTO_OPCODE(ip) @ jump to next instruction 2946 2947 2948/* ------------------------------ */ 2949 .balign 64 2950.L_OP_SGET_CHAR: /* 0x65 */ 2951/* File: armv5te/OP_SGET_CHAR.S */ 2952/* File: armv5te/OP_SGET.S */ 2953 /* 2954 * General 32-bit SGET handler. 2955 * 2956 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2957 */ 2958 /* op vAA, field@BBBB */ 2959 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2960 FETCH(r1, 1) @ r1<- field ref BBBB 2961 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2962 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2963 cmp r0, #0 @ is resolved entry null? 2964 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2965.LOP_SGET_CHAR_finish: @ field ptr in r0 2966 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2967 mov r2, rINST, lsr #8 @ r2<- AA 2968 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2969 SET_VREG(r1, r2) @ fp[AA]<- r1 2970 GET_INST_OPCODE(ip) @ extract opcode from rINST 2971 GOTO_OPCODE(ip) @ jump to next instruction 2972 2973 2974/* ------------------------------ */ 2975 .balign 64 2976.L_OP_SGET_SHORT: /* 0x66 */ 2977/* File: armv5te/OP_SGET_SHORT.S */ 2978/* File: armv5te/OP_SGET.S */ 2979 /* 2980 * General 32-bit SGET handler. 2981 * 2982 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2983 */ 2984 /* op vAA, field@BBBB */ 2985 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2986 FETCH(r1, 1) @ r1<- field ref BBBB 2987 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2988 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2989 cmp r0, #0 @ is resolved entry null? 2990 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2991.LOP_SGET_SHORT_finish: @ field ptr in r0 2992 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2993 mov r2, rINST, lsr #8 @ r2<- AA 2994 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2995 SET_VREG(r1, r2) @ fp[AA]<- r1 2996 GET_INST_OPCODE(ip) @ extract opcode from rINST 2997 GOTO_OPCODE(ip) @ jump to next instruction 2998 2999 3000/* ------------------------------ */ 3001 .balign 64 3002.L_OP_SPUT: /* 0x67 */ 3003/* File: armv5te/OP_SPUT.S */ 3004 /* 3005 * General 32-bit SPUT handler. 3006 * 3007 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3008 */ 3009 /* op vAA, field@BBBB */ 3010 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3011 FETCH(r1, 1) @ r1<- field ref BBBB 3012 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3013 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3014 cmp r0, #0 @ is resolved entry null? 3015 beq .LOP_SPUT_resolve @ yes, do resolve 3016.LOP_SPUT_finish: @ field ptr in r0 3017 mov r2, rINST, lsr #8 @ r2<- AA 3018 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3019 GET_VREG(r1, r2) @ r1<- fp[AA] 3020 GET_INST_OPCODE(ip) @ extract opcode from rINST 3021 str r1, [r0, #offStaticField_value] @ field<- vAA 3022 GOTO_OPCODE(ip) @ jump to next instruction 3023 3024/* ------------------------------ */ 3025 .balign 64 3026.L_OP_SPUT_WIDE: /* 0x68 */ 3027/* File: armv5te/OP_SPUT_WIDE.S */ 3028 /* 3029 * 64-bit SPUT handler. 3030 */ 3031 /* sput-wide vAA, field@BBBB */ 3032 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3033 FETCH(r1, 1) @ r1<- field ref BBBB 3034 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3035 mov r9, rINST, lsr #8 @ r9<- AA 3036 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3037 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3038 cmp r0, #0 @ is resolved entry null? 3039 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3040.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3041 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3042 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3043 GET_INST_OPCODE(ip) @ extract opcode from rINST 3044 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3045 GOTO_OPCODE(ip) @ jump to next instruction 3046 3047/* ------------------------------ */ 3048 .balign 64 3049.L_OP_SPUT_OBJECT: /* 0x69 */ 3050/* File: armv5te/OP_SPUT_OBJECT.S */ 3051/* File: armv5te/OP_SPUT.S */ 3052 /* 3053 * General 32-bit SPUT handler. 3054 * 3055 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3056 */ 3057 /* op vAA, field@BBBB */ 3058 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3059 FETCH(r1, 1) @ r1<- field ref BBBB 3060 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3061 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3062 cmp r0, #0 @ is resolved entry null? 3063 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3064.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3065 mov r2, rINST, lsr #8 @ r2<- AA 3066 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3067 GET_VREG(r1, r2) @ r1<- fp[AA] 3068 GET_INST_OPCODE(ip) @ extract opcode from rINST 3069 str r1, [r0, #offStaticField_value] @ field<- vAA 3070 GOTO_OPCODE(ip) @ jump to next instruction 3071 3072 3073/* ------------------------------ */ 3074 .balign 64 3075.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3076/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3077/* File: armv5te/OP_SPUT.S */ 3078 /* 3079 * General 32-bit SPUT handler. 3080 * 3081 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3082 */ 3083 /* op vAA, field@BBBB */ 3084 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3085 FETCH(r1, 1) @ r1<- field ref BBBB 3086 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3087 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3088 cmp r0, #0 @ is resolved entry null? 3089 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3090.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3091 mov r2, rINST, lsr #8 @ r2<- AA 3092 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3093 GET_VREG(r1, r2) @ r1<- fp[AA] 3094 GET_INST_OPCODE(ip) @ extract opcode from rINST 3095 str r1, [r0, #offStaticField_value] @ field<- vAA 3096 GOTO_OPCODE(ip) @ jump to next instruction 3097 3098 3099/* ------------------------------ */ 3100 .balign 64 3101.L_OP_SPUT_BYTE: /* 0x6b */ 3102/* File: armv5te/OP_SPUT_BYTE.S */ 3103/* File: armv5te/OP_SPUT.S */ 3104 /* 3105 * General 32-bit SPUT handler. 3106 * 3107 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3108 */ 3109 /* op vAA, field@BBBB */ 3110 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3111 FETCH(r1, 1) @ r1<- field ref BBBB 3112 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3113 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3114 cmp r0, #0 @ is resolved entry null? 3115 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3116.LOP_SPUT_BYTE_finish: @ field ptr in r0 3117 mov r2, rINST, lsr #8 @ r2<- AA 3118 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3119 GET_VREG(r1, r2) @ r1<- fp[AA] 3120 GET_INST_OPCODE(ip) @ extract opcode from rINST 3121 str r1, [r0, #offStaticField_value] @ field<- vAA 3122 GOTO_OPCODE(ip) @ jump to next instruction 3123 3124 3125/* ------------------------------ */ 3126 .balign 64 3127.L_OP_SPUT_CHAR: /* 0x6c */ 3128/* File: armv5te/OP_SPUT_CHAR.S */ 3129/* File: armv5te/OP_SPUT.S */ 3130 /* 3131 * General 32-bit SPUT handler. 3132 * 3133 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3134 */ 3135 /* op vAA, field@BBBB */ 3136 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3137 FETCH(r1, 1) @ r1<- field ref BBBB 3138 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3139 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3140 cmp r0, #0 @ is resolved entry null? 3141 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3142.LOP_SPUT_CHAR_finish: @ field ptr in r0 3143 mov r2, rINST, lsr #8 @ r2<- AA 3144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3145 GET_VREG(r1, r2) @ r1<- fp[AA] 3146 GET_INST_OPCODE(ip) @ extract opcode from rINST 3147 str r1, [r0, #offStaticField_value] @ field<- vAA 3148 GOTO_OPCODE(ip) @ jump to next instruction 3149 3150 3151/* ------------------------------ */ 3152 .balign 64 3153.L_OP_SPUT_SHORT: /* 0x6d */ 3154/* File: armv5te/OP_SPUT_SHORT.S */ 3155/* File: armv5te/OP_SPUT.S */ 3156 /* 3157 * General 32-bit SPUT handler. 3158 * 3159 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3160 */ 3161 /* op vAA, field@BBBB */ 3162 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3163 FETCH(r1, 1) @ r1<- field ref BBBB 3164 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3165 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3166 cmp r0, #0 @ is resolved entry null? 3167 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3168.LOP_SPUT_SHORT_finish: @ field ptr in r0 3169 mov r2, rINST, lsr #8 @ r2<- AA 3170 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3171 GET_VREG(r1, r2) @ r1<- fp[AA] 3172 GET_INST_OPCODE(ip) @ extract opcode from rINST 3173 str r1, [r0, #offStaticField_value] @ field<- vAA 3174 GOTO_OPCODE(ip) @ jump to next instruction 3175 3176 3177/* ------------------------------ */ 3178 .balign 64 3179.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3180/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3181 /* 3182 * Handle a virtual method call. 3183 * 3184 * for: invoke-virtual, invoke-virtual/range 3185 */ 3186 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3187 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3188 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3189 FETCH(r1, 1) @ r1<- BBBB 3190 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3191 FETCH(r10, 2) @ r10<- GFED or CCCC 3192 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3193 .if (!0) 3194 and r10, r10, #15 @ r10<- D (or stays CCCC) 3195 .endif 3196 cmp r0, #0 @ already resolved? 3197 EXPORT_PC() @ must export for invoke 3198 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3199 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3200 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3201 mov r2, #METHOD_VIRTUAL @ resolver method type 3202 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3203 cmp r0, #0 @ got null? 3204 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3205 b common_exceptionThrown @ yes, handle exception 3206 3207/* ------------------------------ */ 3208 .balign 64 3209.L_OP_INVOKE_SUPER: /* 0x6f */ 3210/* File: armv5te/OP_INVOKE_SUPER.S */ 3211 /* 3212 * Handle a "super" method call. 3213 * 3214 * for: invoke-super, invoke-super/range 3215 */ 3216 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3217 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3218 FETCH(r10, 2) @ r10<- GFED or CCCC 3219 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3220 .if (!0) 3221 and r10, r10, #15 @ r10<- D (or stays CCCC) 3222 .endif 3223 FETCH(r1, 1) @ r1<- BBBB 3224 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3225 GET_VREG(r2, r10) @ r2<- "this" ptr 3226 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3227 cmp r2, #0 @ null "this"? 3228 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3229 beq common_errNullObject @ null "this", throw exception 3230 cmp r0, #0 @ already resolved? 3231 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3232 EXPORT_PC() @ must export for invoke 3233 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3234 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3235 3236/* ------------------------------ */ 3237 .balign 64 3238.L_OP_INVOKE_DIRECT: /* 0x70 */ 3239/* File: armv5te/OP_INVOKE_DIRECT.S */ 3240 /* 3241 * Handle a direct method call. 3242 * 3243 * (We could defer the "is 'this' pointer null" test to the common 3244 * method invocation code, and use a flag to indicate that static 3245 * calls don't count. If we do this as part of copying the arguments 3246 * out we could avoiding loading the first arg twice.) 3247 * 3248 * for: invoke-direct, invoke-direct/range 3249 */ 3250 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3251 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3252 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3253 FETCH(r1, 1) @ r1<- BBBB 3254 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3255 FETCH(r10, 2) @ r10<- GFED or CCCC 3256 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3257 .if (!0) 3258 and r10, r10, #15 @ r10<- D (or stays CCCC) 3259 .endif 3260 cmp r0, #0 @ already resolved? 3261 EXPORT_PC() @ must export for invoke 3262 GET_VREG(r2, r10) @ r2<- "this" ptr 3263 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3264.LOP_INVOKE_DIRECT_finish: 3265 cmp r2, #0 @ null "this" ref? 3266 bne common_invokeMethodNoRange @ no, continue on 3267 b common_errNullObject @ yes, throw exception 3268 3269/* ------------------------------ */ 3270 .balign 64 3271.L_OP_INVOKE_STATIC: /* 0x71 */ 3272/* File: armv5te/OP_INVOKE_STATIC.S */ 3273 /* 3274 * Handle a static method call. 3275 * 3276 * for: invoke-static, invoke-static/range 3277 */ 3278 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3279 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3280 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3281 FETCH(r1, 1) @ r1<- BBBB 3282 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3283 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3284 cmp r0, #0 @ already resolved? 3285 EXPORT_PC() @ must export for invoke 3286 bne common_invokeMethodNoRange @ yes, continue on 32870: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3288 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3289 mov r2, #METHOD_STATIC @ resolver method type 3290 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3291 cmp r0, #0 @ got null? 3292 bne common_invokeMethodNoRange @ no, continue 3293 b common_exceptionThrown @ yes, handle exception 3294 3295 3296/* ------------------------------ */ 3297 .balign 64 3298.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3299/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3300 /* 3301 * Handle an interface method call. 3302 * 3303 * for: invoke-interface, invoke-interface/range 3304 */ 3305 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3306 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3307 FETCH(r2, 2) @ r2<- FEDC or CCCC 3308 FETCH(r1, 1) @ r1<- BBBB 3309 .if (!0) 3310 and r2, r2, #15 @ r2<- C (or stays CCCC) 3311 .endif 3312 EXPORT_PC() @ must export for invoke 3313 GET_VREG(r0, r2) @ r0<- first arg ("this") 3314 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3315 cmp r0, #0 @ null obj? 3316 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3317 beq common_errNullObject @ yes, fail 3318 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3319 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3320 cmp r0, #0 @ failed? 3321 beq common_exceptionThrown @ yes, handle exception 3322 b common_invokeMethodNoRange @ jump to common handler 3323 3324 3325/* ------------------------------ */ 3326 .balign 64 3327.L_OP_UNUSED_73: /* 0x73 */ 3328/* File: armv5te/OP_UNUSED_73.S */ 3329/* File: armv5te/unused.S */ 3330 bl common_abort 3331 3332 3333 3334/* ------------------------------ */ 3335 .balign 64 3336.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3337/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3338/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3339 /* 3340 * Handle a virtual method call. 3341 * 3342 * for: invoke-virtual, invoke-virtual/range 3343 */ 3344 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3345 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3346 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3347 FETCH(r1, 1) @ r1<- BBBB 3348 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3349 FETCH(r10, 2) @ r10<- GFED or CCCC 3350 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3351 .if (!1) 3352 and r10, r10, #15 @ r10<- D (or stays CCCC) 3353 .endif 3354 cmp r0, #0 @ already resolved? 3355 EXPORT_PC() @ must export for invoke 3356 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3357 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3358 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3359 mov r2, #METHOD_VIRTUAL @ resolver method type 3360 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3361 cmp r0, #0 @ got null? 3362 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3363 b common_exceptionThrown @ yes, handle exception 3364 3365 3366/* ------------------------------ */ 3367 .balign 64 3368.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3369/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3370/* File: armv5te/OP_INVOKE_SUPER.S */ 3371 /* 3372 * Handle a "super" method call. 3373 * 3374 * for: invoke-super, invoke-super/range 3375 */ 3376 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3377 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3378 FETCH(r10, 2) @ r10<- GFED or CCCC 3379 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3380 .if (!1) 3381 and r10, r10, #15 @ r10<- D (or stays CCCC) 3382 .endif 3383 FETCH(r1, 1) @ r1<- BBBB 3384 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3385 GET_VREG(r2, r10) @ r2<- "this" ptr 3386 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3387 cmp r2, #0 @ null "this"? 3388 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3389 beq common_errNullObject @ null "this", throw exception 3390 cmp r0, #0 @ already resolved? 3391 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3392 EXPORT_PC() @ must export for invoke 3393 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3394 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3395 3396 3397/* ------------------------------ */ 3398 .balign 64 3399.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3400/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3401/* File: armv5te/OP_INVOKE_DIRECT.S */ 3402 /* 3403 * Handle a direct method call. 3404 * 3405 * (We could defer the "is 'this' pointer null" test to the common 3406 * method invocation code, and use a flag to indicate that static 3407 * calls don't count. If we do this as part of copying the arguments 3408 * out we could avoiding loading the first arg twice.) 3409 * 3410 * for: invoke-direct, invoke-direct/range 3411 */ 3412 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3413 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3414 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3415 FETCH(r1, 1) @ r1<- BBBB 3416 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3417 FETCH(r10, 2) @ r10<- GFED or CCCC 3418 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3419 .if (!1) 3420 and r10, r10, #15 @ r10<- D (or stays CCCC) 3421 .endif 3422 cmp r0, #0 @ already resolved? 3423 EXPORT_PC() @ must export for invoke 3424 GET_VREG(r2, r10) @ r2<- "this" ptr 3425 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3426.LOP_INVOKE_DIRECT_RANGE_finish: 3427 cmp r2, #0 @ null "this" ref? 3428 bne common_invokeMethodRange @ no, continue on 3429 b common_errNullObject @ yes, throw exception 3430 3431 3432/* ------------------------------ */ 3433 .balign 64 3434.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3435/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3436/* File: armv5te/OP_INVOKE_STATIC.S */ 3437 /* 3438 * Handle a static method call. 3439 * 3440 * for: invoke-static, invoke-static/range 3441 */ 3442 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3443 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3444 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3445 FETCH(r1, 1) @ r1<- BBBB 3446 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3447 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3448 cmp r0, #0 @ already resolved? 3449 EXPORT_PC() @ must export for invoke 3450 bne common_invokeMethodRange @ yes, continue on 34510: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3452 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3453 mov r2, #METHOD_STATIC @ resolver method type 3454 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3455 cmp r0, #0 @ got null? 3456 bne common_invokeMethodRange @ no, continue 3457 b common_exceptionThrown @ yes, handle exception 3458 3459 3460 3461/* ------------------------------ */ 3462 .balign 64 3463.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3464/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3465/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3466 /* 3467 * Handle an interface method call. 3468 * 3469 * for: invoke-interface, invoke-interface/range 3470 */ 3471 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3472 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3473 FETCH(r2, 2) @ r2<- FEDC or CCCC 3474 FETCH(r1, 1) @ r1<- BBBB 3475 .if (!1) 3476 and r2, r2, #15 @ r2<- C (or stays CCCC) 3477 .endif 3478 EXPORT_PC() @ must export for invoke 3479 GET_VREG(r0, r2) @ r0<- first arg ("this") 3480 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3481 cmp r0, #0 @ null obj? 3482 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3483 beq common_errNullObject @ yes, fail 3484 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3485 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3486 cmp r0, #0 @ failed? 3487 beq common_exceptionThrown @ yes, handle exception 3488 b common_invokeMethodRange @ jump to common handler 3489 3490 3491 3492/* ------------------------------ */ 3493 .balign 64 3494.L_OP_UNUSED_79: /* 0x79 */ 3495/* File: armv5te/OP_UNUSED_79.S */ 3496/* File: armv5te/unused.S */ 3497 bl common_abort 3498 3499 3500 3501/* ------------------------------ */ 3502 .balign 64 3503.L_OP_UNUSED_7A: /* 0x7a */ 3504/* File: armv5te/OP_UNUSED_7A.S */ 3505/* File: armv5te/unused.S */ 3506 bl common_abort 3507 3508 3509 3510/* ------------------------------ */ 3511 .balign 64 3512.L_OP_NEG_INT: /* 0x7b */ 3513/* File: armv5te/OP_NEG_INT.S */ 3514/* File: armv5te/unop.S */ 3515 /* 3516 * Generic 32-bit unary operation. Provide an "instr" line that 3517 * specifies an instruction that performs "result = op r0". 3518 * This could be an ARM instruction or a function call. 3519 * 3520 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3521 * int-to-byte, int-to-char, int-to-short 3522 */ 3523 /* unop vA, vB */ 3524 mov r3, rINST, lsr #12 @ r3<- B 3525 mov r9, rINST, lsr #8 @ r9<- A+ 3526 GET_VREG(r0, r3) @ r0<- vB 3527 and r9, r9, #15 3528 @ optional op; may set condition codes 3529 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3530 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3531 GET_INST_OPCODE(ip) @ extract opcode from rINST 3532 SET_VREG(r0, r9) @ vAA<- r0 3533 GOTO_OPCODE(ip) @ jump to next instruction 3534 /* 9-10 instructions */ 3535 3536 3537/* ------------------------------ */ 3538 .balign 64 3539.L_OP_NOT_INT: /* 0x7c */ 3540/* File: armv5te/OP_NOT_INT.S */ 3541/* File: armv5te/unop.S */ 3542 /* 3543 * Generic 32-bit unary operation. Provide an "instr" line that 3544 * specifies an instruction that performs "result = op r0". 3545 * This could be an ARM instruction or a function call. 3546 * 3547 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3548 * int-to-byte, int-to-char, int-to-short 3549 */ 3550 /* unop vA, vB */ 3551 mov r3, rINST, lsr #12 @ r3<- B 3552 mov r9, rINST, lsr #8 @ r9<- A+ 3553 GET_VREG(r0, r3) @ r0<- vB 3554 and r9, r9, #15 3555 @ optional op; may set condition codes 3556 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3557 mvn r0, r0 @ r0<- op, r0-r3 changed 3558 GET_INST_OPCODE(ip) @ extract opcode from rINST 3559 SET_VREG(r0, r9) @ vAA<- r0 3560 GOTO_OPCODE(ip) @ jump to next instruction 3561 /* 9-10 instructions */ 3562 3563 3564/* ------------------------------ */ 3565 .balign 64 3566.L_OP_NEG_LONG: /* 0x7d */ 3567/* File: armv5te/OP_NEG_LONG.S */ 3568/* File: armv5te/unopWide.S */ 3569 /* 3570 * Generic 64-bit unary operation. Provide an "instr" line that 3571 * specifies an instruction that performs "result = op r0/r1". 3572 * This could be an ARM instruction or a function call. 3573 * 3574 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3575 */ 3576 /* unop vA, vB */ 3577 mov r9, rINST, lsr #8 @ r9<- A+ 3578 mov r3, rINST, lsr #12 @ r3<- B 3579 and r9, r9, #15 3580 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3581 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3582 ldmia r3, {r0-r1} @ r0/r1<- vAA 3583 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3584 rsbs r0, r0, #0 @ optional op; may set condition codes 3585 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3586 GET_INST_OPCODE(ip) @ extract opcode from rINST 3587 stmia r9, {r0-r1} @ vAA<- r0/r1 3588 GOTO_OPCODE(ip) @ jump to next instruction 3589 /* 12-13 instructions */ 3590 3591 3592 3593/* ------------------------------ */ 3594 .balign 64 3595.L_OP_NOT_LONG: /* 0x7e */ 3596/* File: armv5te/OP_NOT_LONG.S */ 3597/* File: armv5te/unopWide.S */ 3598 /* 3599 * Generic 64-bit unary operation. Provide an "instr" line that 3600 * specifies an instruction that performs "result = op r0/r1". 3601 * This could be an ARM instruction or a function call. 3602 * 3603 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3604 */ 3605 /* unop vA, vB */ 3606 mov r9, rINST, lsr #8 @ r9<- A+ 3607 mov r3, rINST, lsr #12 @ r3<- B 3608 and r9, r9, #15 3609 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3610 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3611 ldmia r3, {r0-r1} @ r0/r1<- vAA 3612 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3613 mvn r0, r0 @ optional op; may set condition codes 3614 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3615 GET_INST_OPCODE(ip) @ extract opcode from rINST 3616 stmia r9, {r0-r1} @ vAA<- r0/r1 3617 GOTO_OPCODE(ip) @ jump to next instruction 3618 /* 12-13 instructions */ 3619 3620 3621 3622/* ------------------------------ */ 3623 .balign 64 3624.L_OP_NEG_FLOAT: /* 0x7f */ 3625/* File: armv5te/OP_NEG_FLOAT.S */ 3626/* File: armv5te/unop.S */ 3627 /* 3628 * Generic 32-bit unary operation. Provide an "instr" line that 3629 * specifies an instruction that performs "result = op r0". 3630 * This could be an ARM instruction or a function call. 3631 * 3632 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3633 * int-to-byte, int-to-char, int-to-short 3634 */ 3635 /* unop vA, vB */ 3636 mov r3, rINST, lsr #12 @ r3<- B 3637 mov r9, rINST, lsr #8 @ r9<- A+ 3638 GET_VREG(r0, r3) @ r0<- vB 3639 and r9, r9, #15 3640 @ optional op; may set condition codes 3641 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3642 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3643 GET_INST_OPCODE(ip) @ extract opcode from rINST 3644 SET_VREG(r0, r9) @ vAA<- r0 3645 GOTO_OPCODE(ip) @ jump to next instruction 3646 /* 9-10 instructions */ 3647 3648 3649/* ------------------------------ */ 3650 .balign 64 3651.L_OP_NEG_DOUBLE: /* 0x80 */ 3652/* File: armv5te/OP_NEG_DOUBLE.S */ 3653/* File: armv5te/unopWide.S */ 3654 /* 3655 * Generic 64-bit unary operation. Provide an "instr" line that 3656 * specifies an instruction that performs "result = op r0/r1". 3657 * This could be an ARM instruction or a function call. 3658 * 3659 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3660 */ 3661 /* unop vA, vB */ 3662 mov r9, rINST, lsr #8 @ r9<- A+ 3663 mov r3, rINST, lsr #12 @ r3<- B 3664 and r9, r9, #15 3665 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3666 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3667 ldmia r3, {r0-r1} @ r0/r1<- vAA 3668 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3669 @ optional op; may set condition codes 3670 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3671 GET_INST_OPCODE(ip) @ extract opcode from rINST 3672 stmia r9, {r0-r1} @ vAA<- r0/r1 3673 GOTO_OPCODE(ip) @ jump to next instruction 3674 /* 12-13 instructions */ 3675 3676 3677 3678/* ------------------------------ */ 3679 .balign 64 3680.L_OP_INT_TO_LONG: /* 0x81 */ 3681/* File: armv5te/OP_INT_TO_LONG.S */ 3682/* File: armv5te/unopWider.S */ 3683 /* 3684 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3685 * that specifies an instruction that performs "result = op r0", where 3686 * "result" is a 64-bit quantity in r0/r1. 3687 * 3688 * For: int-to-long, int-to-double, float-to-long, float-to-double 3689 */ 3690 /* unop vA, vB */ 3691 mov r9, rINST, lsr #8 @ r9<- A+ 3692 mov r3, rINST, lsr #12 @ r3<- B 3693 and r9, r9, #15 3694 GET_VREG(r0, r3) @ r0<- vB 3695 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3696 @ optional op; may set condition codes 3697 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3698 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3699 GET_INST_OPCODE(ip) @ extract opcode from rINST 3700 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3701 GOTO_OPCODE(ip) @ jump to next instruction 3702 /* 10-11 instructions */ 3703 3704 3705/* ------------------------------ */ 3706 .balign 64 3707.L_OP_INT_TO_FLOAT: /* 0x82 */ 3708/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3709/* File: arm-vfp/funop.S */ 3710 /* 3711 * Generic 32-bit unary floating-point operation. Provide an "instr" 3712 * line that specifies an instruction that performs "s1 = op s0". 3713 * 3714 * for: int-to-float, float-to-int 3715 */ 3716 /* unop vA, vB */ 3717 mov r3, rINST, lsr #12 @ r3<- B 3718 mov r9, rINST, lsr #8 @ r9<- A+ 3719 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3720 flds s0, [r3] @ s0<- vB 3721 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3722 and r9, r9, #15 @ r9<- A 3723 fsitos s1, s0 @ s1<- op 3724 GET_INST_OPCODE(ip) @ extract opcode from rINST 3725 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3726 fsts s1, [r9] @ vA<- s1 3727 GOTO_OPCODE(ip) @ jump to next instruction 3728 3729 3730/* ------------------------------ */ 3731 .balign 64 3732.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3733/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3734/* File: arm-vfp/funopWider.S */ 3735 /* 3736 * Generic 32bit-to-64bit floating point unary operation. Provide an 3737 * "instr" line that specifies an instruction that performs "d0 = op s0". 3738 * 3739 * For: int-to-double, float-to-double 3740 */ 3741 /* unop vA, vB */ 3742 mov r3, rINST, lsr #12 @ r3<- B 3743 mov r9, rINST, lsr #8 @ r9<- A+ 3744 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3745 flds s0, [r3] @ s0<- vB 3746 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3747 and r9, r9, #15 @ r9<- A 3748 fsitod d0, s0 @ d0<- op 3749 GET_INST_OPCODE(ip) @ extract opcode from rINST 3750 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3751 fstd d0, [r9] @ vA<- d0 3752 GOTO_OPCODE(ip) @ jump to next instruction 3753 3754 3755/* ------------------------------ */ 3756 .balign 64 3757.L_OP_LONG_TO_INT: /* 0x84 */ 3758/* File: armv5te/OP_LONG_TO_INT.S */ 3759/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3760/* File: armv5te/OP_MOVE.S */ 3761 /* for move, move-object, long-to-int */ 3762 /* op vA, vB */ 3763 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3764 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3765 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3766 GET_VREG(r2, r1) @ r2<- fp[B] 3767 and r0, r0, #15 3768 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3769 SET_VREG(r2, r0) @ fp[A]<- r2 3770 GOTO_OPCODE(ip) @ execute next instruction 3771 3772 3773 3774/* ------------------------------ */ 3775 .balign 64 3776.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3777/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3778/* File: armv5te/unopNarrower.S */ 3779 /* 3780 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3781 * that specifies an instruction that performs "result = op r0/r1", where 3782 * "result" is a 32-bit quantity in r0. 3783 * 3784 * For: long-to-float, double-to-int, double-to-float 3785 * 3786 * (This would work for long-to-int, but that instruction is actually 3787 * an exact match for OP_MOVE.) 3788 */ 3789 /* unop vA, vB */ 3790 mov r3, rINST, lsr #12 @ r3<- B 3791 mov r9, rINST, lsr #8 @ r9<- A+ 3792 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3793 and r9, r9, #15 3794 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3795 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3796 @ optional op; may set condition codes 3797 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3798 GET_INST_OPCODE(ip) @ extract opcode from rINST 3799 SET_VREG(r0, r9) @ vA<- r0 3800 GOTO_OPCODE(ip) @ jump to next instruction 3801 /* 10-11 instructions */ 3802 3803 3804/* ------------------------------ */ 3805 .balign 64 3806.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3807/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3808/* File: armv5te/unopWide.S */ 3809 /* 3810 * Generic 64-bit unary operation. Provide an "instr" line that 3811 * specifies an instruction that performs "result = op r0/r1". 3812 * This could be an ARM instruction or a function call. 3813 * 3814 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3815 */ 3816 /* unop vA, vB */ 3817 mov r9, rINST, lsr #8 @ r9<- A+ 3818 mov r3, rINST, lsr #12 @ r3<- B 3819 and r9, r9, #15 3820 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3821 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3822 ldmia r3, {r0-r1} @ r0/r1<- vAA 3823 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3824 @ optional op; may set condition codes 3825 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3826 GET_INST_OPCODE(ip) @ extract opcode from rINST 3827 stmia r9, {r0-r1} @ vAA<- r0/r1 3828 GOTO_OPCODE(ip) @ jump to next instruction 3829 /* 12-13 instructions */ 3830 3831 3832 3833/* ------------------------------ */ 3834 .balign 64 3835.L_OP_FLOAT_TO_INT: /* 0x87 */ 3836/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3837/* File: arm-vfp/funop.S */ 3838 /* 3839 * Generic 32-bit unary floating-point operation. Provide an "instr" 3840 * line that specifies an instruction that performs "s1 = op s0". 3841 * 3842 * for: int-to-float, float-to-int 3843 */ 3844 /* unop vA, vB */ 3845 mov r3, rINST, lsr #12 @ r3<- B 3846 mov r9, rINST, lsr #8 @ r9<- A+ 3847 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3848 flds s0, [r3] @ s0<- vB 3849 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3850 and r9, r9, #15 @ r9<- A 3851 ftosizs s1, s0 @ s1<- op 3852 GET_INST_OPCODE(ip) @ extract opcode from rINST 3853 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3854 fsts s1, [r9] @ vA<- s1 3855 GOTO_OPCODE(ip) @ jump to next instruction 3856 3857 3858/* ------------------------------ */ 3859 .balign 64 3860.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3861/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3862@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3863/* File: armv5te/unopWider.S */ 3864 /* 3865 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3866 * that specifies an instruction that performs "result = op r0", where 3867 * "result" is a 64-bit quantity in r0/r1. 3868 * 3869 * For: int-to-long, int-to-double, float-to-long, float-to-double 3870 */ 3871 /* unop vA, vB */ 3872 mov r9, rINST, lsr #8 @ r9<- A+ 3873 mov r3, rINST, lsr #12 @ r3<- B 3874 and r9, r9, #15 3875 GET_VREG(r0, r3) @ r0<- vB 3876 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3877 @ optional op; may set condition codes 3878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3879 bl f2l_doconv @ r0<- op, r0-r3 changed 3880 GET_INST_OPCODE(ip) @ extract opcode from rINST 3881 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3882 GOTO_OPCODE(ip) @ jump to next instruction 3883 /* 10-11 instructions */ 3884 3885 3886 3887/* ------------------------------ */ 3888 .balign 64 3889.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3890/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3891/* File: arm-vfp/funopWider.S */ 3892 /* 3893 * Generic 32bit-to-64bit floating point unary operation. Provide an 3894 * "instr" line that specifies an instruction that performs "d0 = op s0". 3895 * 3896 * For: int-to-double, float-to-double 3897 */ 3898 /* unop vA, vB */ 3899 mov r3, rINST, lsr #12 @ r3<- B 3900 mov r9, rINST, lsr #8 @ r9<- A+ 3901 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3902 flds s0, [r3] @ s0<- vB 3903 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3904 and r9, r9, #15 @ r9<- A 3905 fcvtds d0, s0 @ d0<- op 3906 GET_INST_OPCODE(ip) @ extract opcode from rINST 3907 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3908 fstd d0, [r9] @ vA<- d0 3909 GOTO_OPCODE(ip) @ jump to next instruction 3910 3911 3912/* ------------------------------ */ 3913 .balign 64 3914.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3915/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3916/* File: arm-vfp/funopNarrower.S */ 3917 /* 3918 * Generic 64bit-to-32bit unary floating point operation. Provide an 3919 * "instr" line that specifies an instruction that performs "s0 = op d0". 3920 * 3921 * For: double-to-int, double-to-float 3922 */ 3923 /* unop vA, vB */ 3924 mov r3, rINST, lsr #12 @ r3<- B 3925 mov r9, rINST, lsr #8 @ r9<- A+ 3926 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3927 fldd d0, [r3] @ d0<- vB 3928 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3929 and r9, r9, #15 @ r9<- A 3930 ftosizd s0, d0 @ s0<- op 3931 GET_INST_OPCODE(ip) @ extract opcode from rINST 3932 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3933 fsts s0, [r9] @ vA<- s0 3934 GOTO_OPCODE(ip) @ jump to next instruction 3935 3936 3937/* ------------------------------ */ 3938 .balign 64 3939.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3940/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3941@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3942/* File: armv5te/unopWide.S */ 3943 /* 3944 * Generic 64-bit unary operation. Provide an "instr" line that 3945 * specifies an instruction that performs "result = op r0/r1". 3946 * This could be an ARM instruction or a function call. 3947 * 3948 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3949 */ 3950 /* unop vA, vB */ 3951 mov r9, rINST, lsr #8 @ r9<- A+ 3952 mov r3, rINST, lsr #12 @ r3<- B 3953 and r9, r9, #15 3954 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3955 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3956 ldmia r3, {r0-r1} @ r0/r1<- vAA 3957 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3958 @ optional op; may set condition codes 3959 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3960 GET_INST_OPCODE(ip) @ extract opcode from rINST 3961 stmia r9, {r0-r1} @ vAA<- r0/r1 3962 GOTO_OPCODE(ip) @ jump to next instruction 3963 /* 12-13 instructions */ 3964 3965 3966 3967 3968/* ------------------------------ */ 3969 .balign 64 3970.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3971/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3972/* File: arm-vfp/funopNarrower.S */ 3973 /* 3974 * Generic 64bit-to-32bit unary floating point operation. Provide an 3975 * "instr" line that specifies an instruction that performs "s0 = op d0". 3976 * 3977 * For: double-to-int, double-to-float 3978 */ 3979 /* unop vA, vB */ 3980 mov r3, rINST, lsr #12 @ r3<- B 3981 mov r9, rINST, lsr #8 @ r9<- A+ 3982 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3983 fldd d0, [r3] @ d0<- vB 3984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3985 and r9, r9, #15 @ r9<- A 3986 fcvtsd s0, d0 @ s0<- op 3987 GET_INST_OPCODE(ip) @ extract opcode from rINST 3988 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3989 fsts s0, [r9] @ vA<- s0 3990 GOTO_OPCODE(ip) @ jump to next instruction 3991 3992 3993/* ------------------------------ */ 3994 .balign 64 3995.L_OP_INT_TO_BYTE: /* 0x8d */ 3996/* File: armv5te/OP_INT_TO_BYTE.S */ 3997/* File: armv5te/unop.S */ 3998 /* 3999 * Generic 32-bit unary operation. Provide an "instr" line that 4000 * specifies an instruction that performs "result = op r0". 4001 * This could be an ARM instruction or a function call. 4002 * 4003 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4004 * int-to-byte, int-to-char, int-to-short 4005 */ 4006 /* unop vA, vB */ 4007 mov r3, rINST, lsr #12 @ r3<- B 4008 mov r9, rINST, lsr #8 @ r9<- A+ 4009 GET_VREG(r0, r3) @ r0<- vB 4010 and r9, r9, #15 4011 mov r0, r0, asl #24 @ optional op; may set condition codes 4012 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4013 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4014 GET_INST_OPCODE(ip) @ extract opcode from rINST 4015 SET_VREG(r0, r9) @ vAA<- r0 4016 GOTO_OPCODE(ip) @ jump to next instruction 4017 /* 9-10 instructions */ 4018 4019 4020/* ------------------------------ */ 4021 .balign 64 4022.L_OP_INT_TO_CHAR: /* 0x8e */ 4023/* File: armv5te/OP_INT_TO_CHAR.S */ 4024/* File: armv5te/unop.S */ 4025 /* 4026 * Generic 32-bit unary operation. Provide an "instr" line that 4027 * specifies an instruction that performs "result = op r0". 4028 * This could be an ARM instruction or a function call. 4029 * 4030 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4031 * int-to-byte, int-to-char, int-to-short 4032 */ 4033 /* unop vA, vB */ 4034 mov r3, rINST, lsr #12 @ r3<- B 4035 mov r9, rINST, lsr #8 @ r9<- A+ 4036 GET_VREG(r0, r3) @ r0<- vB 4037 and r9, r9, #15 4038 mov r0, r0, asl #16 @ optional op; may set condition codes 4039 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4040 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4041 GET_INST_OPCODE(ip) @ extract opcode from rINST 4042 SET_VREG(r0, r9) @ vAA<- r0 4043 GOTO_OPCODE(ip) @ jump to next instruction 4044 /* 9-10 instructions */ 4045 4046 4047/* ------------------------------ */ 4048 .balign 64 4049.L_OP_INT_TO_SHORT: /* 0x8f */ 4050/* File: armv5te/OP_INT_TO_SHORT.S */ 4051/* File: armv5te/unop.S */ 4052 /* 4053 * Generic 32-bit unary operation. Provide an "instr" line that 4054 * specifies an instruction that performs "result = op r0". 4055 * This could be an ARM instruction or a function call. 4056 * 4057 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4058 * int-to-byte, int-to-char, int-to-short 4059 */ 4060 /* unop vA, vB */ 4061 mov r3, rINST, lsr #12 @ r3<- B 4062 mov r9, rINST, lsr #8 @ r9<- A+ 4063 GET_VREG(r0, r3) @ r0<- vB 4064 and r9, r9, #15 4065 mov r0, r0, asl #16 @ optional op; may set condition codes 4066 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4067 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4068 GET_INST_OPCODE(ip) @ extract opcode from rINST 4069 SET_VREG(r0, r9) @ vAA<- r0 4070 GOTO_OPCODE(ip) @ jump to next instruction 4071 /* 9-10 instructions */ 4072 4073 4074/* ------------------------------ */ 4075 .balign 64 4076.L_OP_ADD_INT: /* 0x90 */ 4077/* File: armv5te/OP_ADD_INT.S */ 4078/* File: armv5te/binop.S */ 4079 /* 4080 * Generic 32-bit binary operation. Provide an "instr" line that 4081 * specifies an instruction that performs "result = r0 op r1". 4082 * This could be an ARM instruction or a function call. (If the result 4083 * comes back in a register other than r0, you can override "result".) 4084 * 4085 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4086 * vCC (r1). Useful for integer division and modulus. Note that we 4087 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4088 * handles it correctly. 4089 * 4090 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4091 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4092 * mul-float, div-float, rem-float 4093 */ 4094 /* binop vAA, vBB, vCC */ 4095 FETCH(r0, 1) @ r0<- CCBB 4096 mov r9, rINST, lsr #8 @ r9<- AA 4097 mov r3, r0, lsr #8 @ r3<- CC 4098 and r2, r0, #255 @ r2<- BB 4099 GET_VREG(r1, r3) @ r1<- vCC 4100 GET_VREG(r0, r2) @ r0<- vBB 4101 .if 0 4102 cmp r1, #0 @ is second operand zero? 4103 beq common_errDivideByZero 4104 .endif 4105 4106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4107 @ optional op; may set condition codes 4108 add r0, r0, r1 @ r0<- op, r0-r3 changed 4109 GET_INST_OPCODE(ip) @ extract opcode from rINST 4110 SET_VREG(r0, r9) @ vAA<- r0 4111 GOTO_OPCODE(ip) @ jump to next instruction 4112 /* 11-14 instructions */ 4113 4114 4115 4116/* ------------------------------ */ 4117 .balign 64 4118.L_OP_SUB_INT: /* 0x91 */ 4119/* File: armv5te/OP_SUB_INT.S */ 4120/* File: armv5te/binop.S */ 4121 /* 4122 * Generic 32-bit binary operation. Provide an "instr" line that 4123 * specifies an instruction that performs "result = r0 op r1". 4124 * This could be an ARM instruction or a function call. (If the result 4125 * comes back in a register other than r0, you can override "result".) 4126 * 4127 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4128 * vCC (r1). Useful for integer division and modulus. Note that we 4129 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4130 * handles it correctly. 4131 * 4132 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4133 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4134 * mul-float, div-float, rem-float 4135 */ 4136 /* binop vAA, vBB, vCC */ 4137 FETCH(r0, 1) @ r0<- CCBB 4138 mov r9, rINST, lsr #8 @ r9<- AA 4139 mov r3, r0, lsr #8 @ r3<- CC 4140 and r2, r0, #255 @ r2<- BB 4141 GET_VREG(r1, r3) @ r1<- vCC 4142 GET_VREG(r0, r2) @ r0<- vBB 4143 .if 0 4144 cmp r1, #0 @ is second operand zero? 4145 beq common_errDivideByZero 4146 .endif 4147 4148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4149 @ optional op; may set condition codes 4150 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4151 GET_INST_OPCODE(ip) @ extract opcode from rINST 4152 SET_VREG(r0, r9) @ vAA<- r0 4153 GOTO_OPCODE(ip) @ jump to next instruction 4154 /* 11-14 instructions */ 4155 4156 4157 4158/* ------------------------------ */ 4159 .balign 64 4160.L_OP_MUL_INT: /* 0x92 */ 4161/* File: armv5te/OP_MUL_INT.S */ 4162/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4163/* File: armv5te/binop.S */ 4164 /* 4165 * Generic 32-bit binary operation. Provide an "instr" line that 4166 * specifies an instruction that performs "result = r0 op r1". 4167 * This could be an ARM instruction or a function call. (If the result 4168 * comes back in a register other than r0, you can override "result".) 4169 * 4170 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4171 * vCC (r1). Useful for integer division and modulus. Note that we 4172 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4173 * handles it correctly. 4174 * 4175 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4176 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4177 * mul-float, div-float, rem-float 4178 */ 4179 /* binop vAA, vBB, vCC */ 4180 FETCH(r0, 1) @ r0<- CCBB 4181 mov r9, rINST, lsr #8 @ r9<- AA 4182 mov r3, r0, lsr #8 @ r3<- CC 4183 and r2, r0, #255 @ r2<- BB 4184 GET_VREG(r1, r3) @ r1<- vCC 4185 GET_VREG(r0, r2) @ r0<- vBB 4186 .if 0 4187 cmp r1, #0 @ is second operand zero? 4188 beq common_errDivideByZero 4189 .endif 4190 4191 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4192 @ optional op; may set condition codes 4193 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4194 GET_INST_OPCODE(ip) @ extract opcode from rINST 4195 SET_VREG(r0, r9) @ vAA<- r0 4196 GOTO_OPCODE(ip) @ jump to next instruction 4197 /* 11-14 instructions */ 4198 4199 4200 4201/* ------------------------------ */ 4202 .balign 64 4203.L_OP_DIV_INT: /* 0x93 */ 4204/* File: armv5te/OP_DIV_INT.S */ 4205/* File: armv5te/binop.S */ 4206 /* 4207 * Generic 32-bit binary operation. Provide an "instr" line that 4208 * specifies an instruction that performs "result = r0 op r1". 4209 * This could be an ARM instruction or a function call. (If the result 4210 * comes back in a register other than r0, you can override "result".) 4211 * 4212 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4213 * vCC (r1). Useful for integer division and modulus. Note that we 4214 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4215 * handles it correctly. 4216 * 4217 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4218 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4219 * mul-float, div-float, rem-float 4220 */ 4221 /* binop vAA, vBB, vCC */ 4222 FETCH(r0, 1) @ r0<- CCBB 4223 mov r9, rINST, lsr #8 @ r9<- AA 4224 mov r3, r0, lsr #8 @ r3<- CC 4225 and r2, r0, #255 @ r2<- BB 4226 GET_VREG(r1, r3) @ r1<- vCC 4227 GET_VREG(r0, r2) @ r0<- vBB 4228 .if 1 4229 cmp r1, #0 @ is second operand zero? 4230 beq common_errDivideByZero 4231 .endif 4232 4233 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4234 @ optional op; may set condition codes 4235 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4236 GET_INST_OPCODE(ip) @ extract opcode from rINST 4237 SET_VREG(r0, r9) @ vAA<- r0 4238 GOTO_OPCODE(ip) @ jump to next instruction 4239 /* 11-14 instructions */ 4240 4241 4242 4243/* ------------------------------ */ 4244 .balign 64 4245.L_OP_REM_INT: /* 0x94 */ 4246/* File: armv5te/OP_REM_INT.S */ 4247/* idivmod returns quotient in r0 and remainder in r1 */ 4248/* File: armv5te/binop.S */ 4249 /* 4250 * Generic 32-bit binary operation. Provide an "instr" line that 4251 * specifies an instruction that performs "result = r0 op r1". 4252 * This could be an ARM instruction or a function call. (If the result 4253 * comes back in a register other than r0, you can override "result".) 4254 * 4255 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4256 * vCC (r1). Useful for integer division and modulus. Note that we 4257 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4258 * handles it correctly. 4259 * 4260 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4261 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4262 * mul-float, div-float, rem-float 4263 */ 4264 /* binop vAA, vBB, vCC */ 4265 FETCH(r0, 1) @ r0<- CCBB 4266 mov r9, rINST, lsr #8 @ r9<- AA 4267 mov r3, r0, lsr #8 @ r3<- CC 4268 and r2, r0, #255 @ r2<- BB 4269 GET_VREG(r1, r3) @ r1<- vCC 4270 GET_VREG(r0, r2) @ r0<- vBB 4271 .if 1 4272 cmp r1, #0 @ is second operand zero? 4273 beq common_errDivideByZero 4274 .endif 4275 4276 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4277 @ optional op; may set condition codes 4278 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4279 GET_INST_OPCODE(ip) @ extract opcode from rINST 4280 SET_VREG(r1, r9) @ vAA<- r1 4281 GOTO_OPCODE(ip) @ jump to next instruction 4282 /* 11-14 instructions */ 4283 4284 4285 4286/* ------------------------------ */ 4287 .balign 64 4288.L_OP_AND_INT: /* 0x95 */ 4289/* File: armv5te/OP_AND_INT.S */ 4290/* File: armv5te/binop.S */ 4291 /* 4292 * Generic 32-bit binary operation. Provide an "instr" line that 4293 * specifies an instruction that performs "result = r0 op r1". 4294 * This could be an ARM instruction or a function call. (If the result 4295 * comes back in a register other than r0, you can override "result".) 4296 * 4297 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4298 * vCC (r1). Useful for integer division and modulus. Note that we 4299 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4300 * handles it correctly. 4301 * 4302 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4303 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4304 * mul-float, div-float, rem-float 4305 */ 4306 /* binop vAA, vBB, vCC */ 4307 FETCH(r0, 1) @ r0<- CCBB 4308 mov r9, rINST, lsr #8 @ r9<- AA 4309 mov r3, r0, lsr #8 @ r3<- CC 4310 and r2, r0, #255 @ r2<- BB 4311 GET_VREG(r1, r3) @ r1<- vCC 4312 GET_VREG(r0, r2) @ r0<- vBB 4313 .if 0 4314 cmp r1, #0 @ is second operand zero? 4315 beq common_errDivideByZero 4316 .endif 4317 4318 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4319 @ optional op; may set condition codes 4320 and r0, r0, r1 @ r0<- op, r0-r3 changed 4321 GET_INST_OPCODE(ip) @ extract opcode from rINST 4322 SET_VREG(r0, r9) @ vAA<- r0 4323 GOTO_OPCODE(ip) @ jump to next instruction 4324 /* 11-14 instructions */ 4325 4326 4327 4328/* ------------------------------ */ 4329 .balign 64 4330.L_OP_OR_INT: /* 0x96 */ 4331/* File: armv5te/OP_OR_INT.S */ 4332/* File: armv5te/binop.S */ 4333 /* 4334 * Generic 32-bit binary operation. Provide an "instr" line that 4335 * specifies an instruction that performs "result = r0 op r1". 4336 * This could be an ARM instruction or a function call. (If the result 4337 * comes back in a register other than r0, you can override "result".) 4338 * 4339 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4340 * vCC (r1). Useful for integer division and modulus. Note that we 4341 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4342 * handles it correctly. 4343 * 4344 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4345 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4346 * mul-float, div-float, rem-float 4347 */ 4348 /* binop vAA, vBB, vCC */ 4349 FETCH(r0, 1) @ r0<- CCBB 4350 mov r9, rINST, lsr #8 @ r9<- AA 4351 mov r3, r0, lsr #8 @ r3<- CC 4352 and r2, r0, #255 @ r2<- BB 4353 GET_VREG(r1, r3) @ r1<- vCC 4354 GET_VREG(r0, r2) @ r0<- vBB 4355 .if 0 4356 cmp r1, #0 @ is second operand zero? 4357 beq common_errDivideByZero 4358 .endif 4359 4360 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4361 @ optional op; may set condition codes 4362 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4363 GET_INST_OPCODE(ip) @ extract opcode from rINST 4364 SET_VREG(r0, r9) @ vAA<- r0 4365 GOTO_OPCODE(ip) @ jump to next instruction 4366 /* 11-14 instructions */ 4367 4368 4369 4370/* ------------------------------ */ 4371 .balign 64 4372.L_OP_XOR_INT: /* 0x97 */ 4373/* File: armv5te/OP_XOR_INT.S */ 4374/* File: armv5te/binop.S */ 4375 /* 4376 * Generic 32-bit binary operation. Provide an "instr" line that 4377 * specifies an instruction that performs "result = r0 op r1". 4378 * This could be an ARM instruction or a function call. (If the result 4379 * comes back in a register other than r0, you can override "result".) 4380 * 4381 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4382 * vCC (r1). Useful for integer division and modulus. Note that we 4383 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4384 * handles it correctly. 4385 * 4386 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4387 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4388 * mul-float, div-float, rem-float 4389 */ 4390 /* binop vAA, vBB, vCC */ 4391 FETCH(r0, 1) @ r0<- CCBB 4392 mov r9, rINST, lsr #8 @ r9<- AA 4393 mov r3, r0, lsr #8 @ r3<- CC 4394 and r2, r0, #255 @ r2<- BB 4395 GET_VREG(r1, r3) @ r1<- vCC 4396 GET_VREG(r0, r2) @ r0<- vBB 4397 .if 0 4398 cmp r1, #0 @ is second operand zero? 4399 beq common_errDivideByZero 4400 .endif 4401 4402 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4403 @ optional op; may set condition codes 4404 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4405 GET_INST_OPCODE(ip) @ extract opcode from rINST 4406 SET_VREG(r0, r9) @ vAA<- r0 4407 GOTO_OPCODE(ip) @ jump to next instruction 4408 /* 11-14 instructions */ 4409 4410 4411 4412/* ------------------------------ */ 4413 .balign 64 4414.L_OP_SHL_INT: /* 0x98 */ 4415/* File: armv5te/OP_SHL_INT.S */ 4416/* File: armv5te/binop.S */ 4417 /* 4418 * Generic 32-bit binary operation. Provide an "instr" line that 4419 * specifies an instruction that performs "result = r0 op r1". 4420 * This could be an ARM instruction or a function call. (If the result 4421 * comes back in a register other than r0, you can override "result".) 4422 * 4423 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4424 * vCC (r1). Useful for integer division and modulus. Note that we 4425 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4426 * handles it correctly. 4427 * 4428 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4429 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4430 * mul-float, div-float, rem-float 4431 */ 4432 /* binop vAA, vBB, vCC */ 4433 FETCH(r0, 1) @ r0<- CCBB 4434 mov r9, rINST, lsr #8 @ r9<- AA 4435 mov r3, r0, lsr #8 @ r3<- CC 4436 and r2, r0, #255 @ r2<- BB 4437 GET_VREG(r1, r3) @ r1<- vCC 4438 GET_VREG(r0, r2) @ r0<- vBB 4439 .if 0 4440 cmp r1, #0 @ is second operand zero? 4441 beq common_errDivideByZero 4442 .endif 4443 4444 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4445 and r1, r1, #31 @ optional op; may set condition codes 4446 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4447 GET_INST_OPCODE(ip) @ extract opcode from rINST 4448 SET_VREG(r0, r9) @ vAA<- r0 4449 GOTO_OPCODE(ip) @ jump to next instruction 4450 /* 11-14 instructions */ 4451 4452 4453 4454/* ------------------------------ */ 4455 .balign 64 4456.L_OP_SHR_INT: /* 0x99 */ 4457/* File: armv5te/OP_SHR_INT.S */ 4458/* File: armv5te/binop.S */ 4459 /* 4460 * Generic 32-bit binary operation. Provide an "instr" line that 4461 * specifies an instruction that performs "result = r0 op r1". 4462 * This could be an ARM instruction or a function call. (If the result 4463 * comes back in a register other than r0, you can override "result".) 4464 * 4465 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4466 * vCC (r1). Useful for integer division and modulus. Note that we 4467 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4468 * handles it correctly. 4469 * 4470 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4471 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4472 * mul-float, div-float, rem-float 4473 */ 4474 /* binop vAA, vBB, vCC */ 4475 FETCH(r0, 1) @ r0<- CCBB 4476 mov r9, rINST, lsr #8 @ r9<- AA 4477 mov r3, r0, lsr #8 @ r3<- CC 4478 and r2, r0, #255 @ r2<- BB 4479 GET_VREG(r1, r3) @ r1<- vCC 4480 GET_VREG(r0, r2) @ r0<- vBB 4481 .if 0 4482 cmp r1, #0 @ is second operand zero? 4483 beq common_errDivideByZero 4484 .endif 4485 4486 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4487 and r1, r1, #31 @ optional op; may set condition codes 4488 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4489 GET_INST_OPCODE(ip) @ extract opcode from rINST 4490 SET_VREG(r0, r9) @ vAA<- r0 4491 GOTO_OPCODE(ip) @ jump to next instruction 4492 /* 11-14 instructions */ 4493 4494 4495 4496/* ------------------------------ */ 4497 .balign 64 4498.L_OP_USHR_INT: /* 0x9a */ 4499/* File: armv5te/OP_USHR_INT.S */ 4500/* File: armv5te/binop.S */ 4501 /* 4502 * Generic 32-bit binary operation. Provide an "instr" line that 4503 * specifies an instruction that performs "result = r0 op r1". 4504 * This could be an ARM instruction or a function call. (If the result 4505 * comes back in a register other than r0, you can override "result".) 4506 * 4507 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4508 * vCC (r1). Useful for integer division and modulus. Note that we 4509 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4510 * handles it correctly. 4511 * 4512 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4513 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4514 * mul-float, div-float, rem-float 4515 */ 4516 /* binop vAA, vBB, vCC */ 4517 FETCH(r0, 1) @ r0<- CCBB 4518 mov r9, rINST, lsr #8 @ r9<- AA 4519 mov r3, r0, lsr #8 @ r3<- CC 4520 and r2, r0, #255 @ r2<- BB 4521 GET_VREG(r1, r3) @ r1<- vCC 4522 GET_VREG(r0, r2) @ r0<- vBB 4523 .if 0 4524 cmp r1, #0 @ is second operand zero? 4525 beq common_errDivideByZero 4526 .endif 4527 4528 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4529 and r1, r1, #31 @ optional op; may set condition codes 4530 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4531 GET_INST_OPCODE(ip) @ extract opcode from rINST 4532 SET_VREG(r0, r9) @ vAA<- r0 4533 GOTO_OPCODE(ip) @ jump to next instruction 4534 /* 11-14 instructions */ 4535 4536 4537 4538/* ------------------------------ */ 4539 .balign 64 4540.L_OP_ADD_LONG: /* 0x9b */ 4541/* File: armv5te/OP_ADD_LONG.S */ 4542/* File: armv5te/binopWide.S */ 4543 /* 4544 * Generic 64-bit binary operation. Provide an "instr" line that 4545 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4546 * This could be an ARM instruction or a function call. (If the result 4547 * comes back in a register other than r0, you can override "result".) 4548 * 4549 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4550 * vCC (r1). Useful for integer division and modulus. 4551 * 4552 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4553 * xor-long, add-double, sub-double, mul-double, div-double, 4554 * rem-double 4555 * 4556 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4557 */ 4558 /* binop vAA, vBB, vCC */ 4559 FETCH(r0, 1) @ r0<- CCBB 4560 mov r9, rINST, lsr #8 @ r9<- AA 4561 and r2, r0, #255 @ r2<- BB 4562 mov r3, r0, lsr #8 @ r3<- CC 4563 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4564 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4565 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4566 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4567 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4568 .if 0 4569 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4570 beq common_errDivideByZero 4571 .endif 4572 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4573 4574 adds r0, r0, r2 @ optional op; may set condition codes 4575 adc r1, r1, r3 @ result<- op, r0-r3 changed 4576 GET_INST_OPCODE(ip) @ extract opcode from rINST 4577 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4578 GOTO_OPCODE(ip) @ jump to next instruction 4579 /* 14-17 instructions */ 4580 4581 4582 4583/* ------------------------------ */ 4584 .balign 64 4585.L_OP_SUB_LONG: /* 0x9c */ 4586/* File: armv5te/OP_SUB_LONG.S */ 4587/* File: armv5te/binopWide.S */ 4588 /* 4589 * Generic 64-bit binary operation. Provide an "instr" line that 4590 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4591 * This could be an ARM instruction or a function call. (If the result 4592 * comes back in a register other than r0, you can override "result".) 4593 * 4594 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4595 * vCC (r1). Useful for integer division and modulus. 4596 * 4597 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4598 * xor-long, add-double, sub-double, mul-double, div-double, 4599 * rem-double 4600 * 4601 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4602 */ 4603 /* binop vAA, vBB, vCC */ 4604 FETCH(r0, 1) @ r0<- CCBB 4605 mov r9, rINST, lsr #8 @ r9<- AA 4606 and r2, r0, #255 @ r2<- BB 4607 mov r3, r0, lsr #8 @ r3<- CC 4608 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4609 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4610 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4611 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4612 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4613 .if 0 4614 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4615 beq common_errDivideByZero 4616 .endif 4617 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4618 4619 subs r0, r0, r2 @ optional op; may set condition codes 4620 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4621 GET_INST_OPCODE(ip) @ extract opcode from rINST 4622 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4623 GOTO_OPCODE(ip) @ jump to next instruction 4624 /* 14-17 instructions */ 4625 4626 4627 4628/* ------------------------------ */ 4629 .balign 64 4630.L_OP_MUL_LONG: /* 0x9d */ 4631/* File: armv5te/OP_MUL_LONG.S */ 4632 /* 4633 * Signed 64-bit integer multiply. 4634 * 4635 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4636 * WX 4637 * x YZ 4638 * -------- 4639 * ZW ZX 4640 * YW YX 4641 * 4642 * The low word of the result holds ZX, the high word holds 4643 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4644 * it doesn't fit in the low 64 bits. 4645 * 4646 * Unlike most ARM math operations, multiply instructions have 4647 * restrictions on using the same register more than once (Rd and Rm 4648 * cannot be the same). 4649 */ 4650 /* mul-long vAA, vBB, vCC */ 4651 FETCH(r0, 1) @ r0<- CCBB 4652 and r2, r0, #255 @ r2<- BB 4653 mov r3, r0, lsr #8 @ r3<- CC 4654 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4655 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4656 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4657 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4658 mul ip, r2, r1 @ ip<- ZxW 4659 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4660 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4661 mov r0, rINST, lsr #8 @ r0<- AA 4662 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4663 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4664 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4665 b .LOP_MUL_LONG_finish 4666 4667/* ------------------------------ */ 4668 .balign 64 4669.L_OP_DIV_LONG: /* 0x9e */ 4670/* File: armv5te/OP_DIV_LONG.S */ 4671/* File: armv5te/binopWide.S */ 4672 /* 4673 * Generic 64-bit binary operation. Provide an "instr" line that 4674 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4675 * This could be an ARM instruction or a function call. (If the result 4676 * comes back in a register other than r0, you can override "result".) 4677 * 4678 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4679 * vCC (r1). Useful for integer division and modulus. 4680 * 4681 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4682 * xor-long, add-double, sub-double, mul-double, div-double, 4683 * rem-double 4684 * 4685 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4686 */ 4687 /* binop vAA, vBB, vCC */ 4688 FETCH(r0, 1) @ r0<- CCBB 4689 mov r9, rINST, lsr #8 @ r9<- AA 4690 and r2, r0, #255 @ r2<- BB 4691 mov r3, r0, lsr #8 @ r3<- CC 4692 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4693 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4694 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4695 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4696 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4697 .if 1 4698 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4699 beq common_errDivideByZero 4700 .endif 4701 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4702 4703 @ optional op; may set condition codes 4704 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4705 GET_INST_OPCODE(ip) @ extract opcode from rINST 4706 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4707 GOTO_OPCODE(ip) @ jump to next instruction 4708 /* 14-17 instructions */ 4709 4710 4711 4712/* ------------------------------ */ 4713 .balign 64 4714.L_OP_REM_LONG: /* 0x9f */ 4715/* File: armv5te/OP_REM_LONG.S */ 4716/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4717/* File: armv5te/binopWide.S */ 4718 /* 4719 * Generic 64-bit binary operation. Provide an "instr" line that 4720 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4721 * This could be an ARM instruction or a function call. (If the result 4722 * comes back in a register other than r0, you can override "result".) 4723 * 4724 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4725 * vCC (r1). Useful for integer division and modulus. 4726 * 4727 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4728 * xor-long, add-double, sub-double, mul-double, div-double, 4729 * rem-double 4730 * 4731 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4732 */ 4733 /* binop vAA, vBB, vCC */ 4734 FETCH(r0, 1) @ r0<- CCBB 4735 mov r9, rINST, lsr #8 @ r9<- AA 4736 and r2, r0, #255 @ r2<- BB 4737 mov r3, r0, lsr #8 @ r3<- CC 4738 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4739 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4740 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4741 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4742 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4743 .if 1 4744 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4745 beq common_errDivideByZero 4746 .endif 4747 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4748 4749 @ optional op; may set condition codes 4750 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4751 GET_INST_OPCODE(ip) @ extract opcode from rINST 4752 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4753 GOTO_OPCODE(ip) @ jump to next instruction 4754 /* 14-17 instructions */ 4755 4756 4757 4758/* ------------------------------ */ 4759 .balign 64 4760.L_OP_AND_LONG: /* 0xa0 */ 4761/* File: armv5te/OP_AND_LONG.S */ 4762/* File: armv5te/binopWide.S */ 4763 /* 4764 * Generic 64-bit binary operation. Provide an "instr" line that 4765 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4766 * This could be an ARM instruction or a function call. (If the result 4767 * comes back in a register other than r0, you can override "result".) 4768 * 4769 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4770 * vCC (r1). Useful for integer division and modulus. 4771 * 4772 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4773 * xor-long, add-double, sub-double, mul-double, div-double, 4774 * rem-double 4775 * 4776 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4777 */ 4778 /* binop vAA, vBB, vCC */ 4779 FETCH(r0, 1) @ r0<- CCBB 4780 mov r9, rINST, lsr #8 @ r9<- AA 4781 and r2, r0, #255 @ r2<- BB 4782 mov r3, r0, lsr #8 @ r3<- CC 4783 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4784 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4785 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4786 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4787 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4788 .if 0 4789 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4790 beq common_errDivideByZero 4791 .endif 4792 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4793 4794 and r0, r0, r2 @ optional op; may set condition codes 4795 and r1, r1, r3 @ result<- op, r0-r3 changed 4796 GET_INST_OPCODE(ip) @ extract opcode from rINST 4797 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4798 GOTO_OPCODE(ip) @ jump to next instruction 4799 /* 14-17 instructions */ 4800 4801 4802 4803/* ------------------------------ */ 4804 .balign 64 4805.L_OP_OR_LONG: /* 0xa1 */ 4806/* File: armv5te/OP_OR_LONG.S */ 4807/* File: armv5te/binopWide.S */ 4808 /* 4809 * Generic 64-bit binary operation. Provide an "instr" line that 4810 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4811 * This could be an ARM instruction or a function call. (If the result 4812 * comes back in a register other than r0, you can override "result".) 4813 * 4814 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4815 * vCC (r1). Useful for integer division and modulus. 4816 * 4817 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4818 * xor-long, add-double, sub-double, mul-double, div-double, 4819 * rem-double 4820 * 4821 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4822 */ 4823 /* binop vAA, vBB, vCC */ 4824 FETCH(r0, 1) @ r0<- CCBB 4825 mov r9, rINST, lsr #8 @ r9<- AA 4826 and r2, r0, #255 @ r2<- BB 4827 mov r3, r0, lsr #8 @ r3<- CC 4828 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4829 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4830 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4831 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4832 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4833 .if 0 4834 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4835 beq common_errDivideByZero 4836 .endif 4837 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4838 4839 orr r0, r0, r2 @ optional op; may set condition codes 4840 orr r1, r1, r3 @ result<- op, r0-r3 changed 4841 GET_INST_OPCODE(ip) @ extract opcode from rINST 4842 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4843 GOTO_OPCODE(ip) @ jump to next instruction 4844 /* 14-17 instructions */ 4845 4846 4847 4848/* ------------------------------ */ 4849 .balign 64 4850.L_OP_XOR_LONG: /* 0xa2 */ 4851/* File: armv5te/OP_XOR_LONG.S */ 4852/* File: armv5te/binopWide.S */ 4853 /* 4854 * Generic 64-bit binary operation. Provide an "instr" line that 4855 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4856 * This could be an ARM instruction or a function call. (If the result 4857 * comes back in a register other than r0, you can override "result".) 4858 * 4859 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4860 * vCC (r1). Useful for integer division and modulus. 4861 * 4862 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4863 * xor-long, add-double, sub-double, mul-double, div-double, 4864 * rem-double 4865 * 4866 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4867 */ 4868 /* binop vAA, vBB, vCC */ 4869 FETCH(r0, 1) @ r0<- CCBB 4870 mov r9, rINST, lsr #8 @ r9<- AA 4871 and r2, r0, #255 @ r2<- BB 4872 mov r3, r0, lsr #8 @ r3<- CC 4873 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4874 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4875 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4876 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4877 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4878 .if 0 4879 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4880 beq common_errDivideByZero 4881 .endif 4882 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4883 4884 eor r0, r0, r2 @ optional op; may set condition codes 4885 eor r1, r1, r3 @ result<- op, r0-r3 changed 4886 GET_INST_OPCODE(ip) @ extract opcode from rINST 4887 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4888 GOTO_OPCODE(ip) @ jump to next instruction 4889 /* 14-17 instructions */ 4890 4891 4892 4893/* ------------------------------ */ 4894 .balign 64 4895.L_OP_SHL_LONG: /* 0xa3 */ 4896/* File: armv5te/OP_SHL_LONG.S */ 4897 /* 4898 * Long integer shift. This is different from the generic 32/64-bit 4899 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4900 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4901 * 6 bits of the shift distance. 4902 */ 4903 /* shl-long vAA, vBB, vCC */ 4904 FETCH(r0, 1) @ r0<- CCBB 4905 mov r9, rINST, lsr #8 @ r9<- AA 4906 and r3, r0, #255 @ r3<- BB 4907 mov r0, r0, lsr #8 @ r0<- CC 4908 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4909 GET_VREG(r2, r0) @ r2<- vCC 4910 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4911 and r2, r2, #63 @ r2<- r2 & 0x3f 4912 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4913 4914 mov r1, r1, asl r2 @ r1<- r1 << r2 4915 rsb r3, r2, #32 @ r3<- 32 - r2 4916 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4917 subs ip, r2, #32 @ ip<- r2 - 32 4918 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4920 b .LOP_SHL_LONG_finish 4921 4922/* ------------------------------ */ 4923 .balign 64 4924.L_OP_SHR_LONG: /* 0xa4 */ 4925/* File: armv5te/OP_SHR_LONG.S */ 4926 /* 4927 * Long integer shift. This is different from the generic 32/64-bit 4928 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4929 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4930 * 6 bits of the shift distance. 4931 */ 4932 /* shr-long vAA, vBB, vCC */ 4933 FETCH(r0, 1) @ r0<- CCBB 4934 mov r9, rINST, lsr #8 @ r9<- AA 4935 and r3, r0, #255 @ r3<- BB 4936 mov r0, r0, lsr #8 @ r0<- CC 4937 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4938 GET_VREG(r2, r0) @ r2<- vCC 4939 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4940 and r2, r2, #63 @ r0<- r0 & 0x3f 4941 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4942 4943 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4944 rsb r3, r2, #32 @ r3<- 32 - r2 4945 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4946 subs ip, r2, #32 @ ip<- r2 - 32 4947 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4948 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4949 b .LOP_SHR_LONG_finish 4950 4951/* ------------------------------ */ 4952 .balign 64 4953.L_OP_USHR_LONG: /* 0xa5 */ 4954/* File: armv5te/OP_USHR_LONG.S */ 4955 /* 4956 * Long integer shift. This is different from the generic 32/64-bit 4957 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4958 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4959 * 6 bits of the shift distance. 4960 */ 4961 /* ushr-long vAA, vBB, vCC */ 4962 FETCH(r0, 1) @ r0<- CCBB 4963 mov r9, rINST, lsr #8 @ r9<- AA 4964 and r3, r0, #255 @ r3<- BB 4965 mov r0, r0, lsr #8 @ r0<- CC 4966 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4967 GET_VREG(r2, r0) @ r2<- vCC 4968 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4969 and r2, r2, #63 @ r0<- r0 & 0x3f 4970 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4971 4972 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4973 rsb r3, r2, #32 @ r3<- 32 - r2 4974 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4975 subs ip, r2, #32 @ ip<- r2 - 32 4976 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4977 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4978 b .LOP_USHR_LONG_finish 4979 4980/* ------------------------------ */ 4981 .balign 64 4982.L_OP_ADD_FLOAT: /* 0xa6 */ 4983/* File: arm-vfp/OP_ADD_FLOAT.S */ 4984/* File: arm-vfp/fbinop.S */ 4985 /* 4986 * Generic 32-bit floating-point operation. Provide an "instr" line that 4987 * specifies an instruction that performs "s2 = s0 op s1". Because we 4988 * use the "softfp" ABI, this must be an instruction, not a function call. 4989 * 4990 * For: add-float, sub-float, mul-float, div-float 4991 */ 4992 /* floatop vAA, vBB, vCC */ 4993 FETCH(r0, 1) @ r0<- CCBB 4994 mov r9, rINST, lsr #8 @ r9<- AA 4995 mov r3, r0, lsr #8 @ r3<- CC 4996 and r2, r0, #255 @ r2<- BB 4997 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4998 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4999 flds s1, [r3] @ s1<- vCC 5000 flds s0, [r2] @ s0<- vBB 5001 5002 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5003 fadds s2, s0, s1 @ s2<- op 5004 GET_INST_OPCODE(ip) @ extract opcode from rINST 5005 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5006 fsts s2, [r9] @ vAA<- s2 5007 GOTO_OPCODE(ip) @ jump to next instruction 5008 5009 5010/* ------------------------------ */ 5011 .balign 64 5012.L_OP_SUB_FLOAT: /* 0xa7 */ 5013/* File: arm-vfp/OP_SUB_FLOAT.S */ 5014/* File: arm-vfp/fbinop.S */ 5015 /* 5016 * Generic 32-bit floating-point operation. Provide an "instr" line that 5017 * specifies an instruction that performs "s2 = s0 op s1". Because we 5018 * use the "softfp" ABI, this must be an instruction, not a function call. 5019 * 5020 * For: add-float, sub-float, mul-float, div-float 5021 */ 5022 /* floatop vAA, vBB, vCC */ 5023 FETCH(r0, 1) @ r0<- CCBB 5024 mov r9, rINST, lsr #8 @ r9<- AA 5025 mov r3, r0, lsr #8 @ r3<- CC 5026 and r2, r0, #255 @ r2<- BB 5027 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5028 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5029 flds s1, [r3] @ s1<- vCC 5030 flds s0, [r2] @ s0<- vBB 5031 5032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5033 fsubs s2, s0, s1 @ s2<- op 5034 GET_INST_OPCODE(ip) @ extract opcode from rINST 5035 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5036 fsts s2, [r9] @ vAA<- s2 5037 GOTO_OPCODE(ip) @ jump to next instruction 5038 5039 5040/* ------------------------------ */ 5041 .balign 64 5042.L_OP_MUL_FLOAT: /* 0xa8 */ 5043/* File: arm-vfp/OP_MUL_FLOAT.S */ 5044/* File: arm-vfp/fbinop.S */ 5045 /* 5046 * Generic 32-bit floating-point operation. Provide an "instr" line that 5047 * specifies an instruction that performs "s2 = s0 op s1". Because we 5048 * use the "softfp" ABI, this must be an instruction, not a function call. 5049 * 5050 * For: add-float, sub-float, mul-float, div-float 5051 */ 5052 /* floatop vAA, vBB, vCC */ 5053 FETCH(r0, 1) @ r0<- CCBB 5054 mov r9, rINST, lsr #8 @ r9<- AA 5055 mov r3, r0, lsr #8 @ r3<- CC 5056 and r2, r0, #255 @ r2<- BB 5057 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5058 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5059 flds s1, [r3] @ s1<- vCC 5060 flds s0, [r2] @ s0<- vBB 5061 5062 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5063 fmuls s2, s0, s1 @ s2<- op 5064 GET_INST_OPCODE(ip) @ extract opcode from rINST 5065 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5066 fsts s2, [r9] @ vAA<- s2 5067 GOTO_OPCODE(ip) @ jump to next instruction 5068 5069 5070/* ------------------------------ */ 5071 .balign 64 5072.L_OP_DIV_FLOAT: /* 0xa9 */ 5073/* File: arm-vfp/OP_DIV_FLOAT.S */ 5074/* File: arm-vfp/fbinop.S */ 5075 /* 5076 * Generic 32-bit floating-point operation. Provide an "instr" line that 5077 * specifies an instruction that performs "s2 = s0 op s1". Because we 5078 * use the "softfp" ABI, this must be an instruction, not a function call. 5079 * 5080 * For: add-float, sub-float, mul-float, div-float 5081 */ 5082 /* floatop vAA, vBB, vCC */ 5083 FETCH(r0, 1) @ r0<- CCBB 5084 mov r9, rINST, lsr #8 @ r9<- AA 5085 mov r3, r0, lsr #8 @ r3<- CC 5086 and r2, r0, #255 @ r2<- BB 5087 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5088 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5089 flds s1, [r3] @ s1<- vCC 5090 flds s0, [r2] @ s0<- vBB 5091 5092 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5093 fdivs s2, s0, s1 @ s2<- op 5094 GET_INST_OPCODE(ip) @ extract opcode from rINST 5095 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5096 fsts s2, [r9] @ vAA<- s2 5097 GOTO_OPCODE(ip) @ jump to next instruction 5098 5099 5100/* ------------------------------ */ 5101 .balign 64 5102.L_OP_REM_FLOAT: /* 0xaa */ 5103/* File: armv5te/OP_REM_FLOAT.S */ 5104/* EABI doesn't define a float remainder function, but libm does */ 5105/* File: armv5te/binop.S */ 5106 /* 5107 * Generic 32-bit binary operation. Provide an "instr" line that 5108 * specifies an instruction that performs "result = r0 op r1". 5109 * This could be an ARM instruction or a function call. (If the result 5110 * comes back in a register other than r0, you can override "result".) 5111 * 5112 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5113 * vCC (r1). Useful for integer division and modulus. Note that we 5114 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5115 * handles it correctly. 5116 * 5117 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5118 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5119 * mul-float, div-float, rem-float 5120 */ 5121 /* binop vAA, vBB, vCC */ 5122 FETCH(r0, 1) @ r0<- CCBB 5123 mov r9, rINST, lsr #8 @ r9<- AA 5124 mov r3, r0, lsr #8 @ r3<- CC 5125 and r2, r0, #255 @ r2<- BB 5126 GET_VREG(r1, r3) @ r1<- vCC 5127 GET_VREG(r0, r2) @ r0<- vBB 5128 .if 0 5129 cmp r1, #0 @ is second operand zero? 5130 beq common_errDivideByZero 5131 .endif 5132 5133 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5134 @ optional op; may set condition codes 5135 bl fmodf @ r0<- op, r0-r3 changed 5136 GET_INST_OPCODE(ip) @ extract opcode from rINST 5137 SET_VREG(r0, r9) @ vAA<- r0 5138 GOTO_OPCODE(ip) @ jump to next instruction 5139 /* 11-14 instructions */ 5140 5141 5142 5143/* ------------------------------ */ 5144 .balign 64 5145.L_OP_ADD_DOUBLE: /* 0xab */ 5146/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5147/* File: arm-vfp/fbinopWide.S */ 5148 /* 5149 * Generic 64-bit double-precision floating point binary operation. 5150 * Provide an "instr" line that specifies an instruction that performs 5151 * "d2 = d0 op d1". 5152 * 5153 * for: add-double, sub-double, mul-double, div-double 5154 */ 5155 /* doubleop vAA, vBB, vCC */ 5156 FETCH(r0, 1) @ r0<- CCBB 5157 mov r9, rINST, lsr #8 @ r9<- AA 5158 mov r3, r0, lsr #8 @ r3<- CC 5159 and r2, r0, #255 @ r2<- BB 5160 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5161 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5162 fldd d1, [r3] @ d1<- vCC 5163 fldd d0, [r2] @ d0<- vBB 5164 5165 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5166 faddd d2, d0, d1 @ s2<- op 5167 GET_INST_OPCODE(ip) @ extract opcode from rINST 5168 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5169 fstd d2, [r9] @ vAA<- d2 5170 GOTO_OPCODE(ip) @ jump to next instruction 5171 5172 5173/* ------------------------------ */ 5174 .balign 64 5175.L_OP_SUB_DOUBLE: /* 0xac */ 5176/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5177/* File: arm-vfp/fbinopWide.S */ 5178 /* 5179 * Generic 64-bit double-precision floating point binary operation. 5180 * Provide an "instr" line that specifies an instruction that performs 5181 * "d2 = d0 op d1". 5182 * 5183 * for: add-double, sub-double, mul-double, div-double 5184 */ 5185 /* doubleop vAA, vBB, vCC */ 5186 FETCH(r0, 1) @ r0<- CCBB 5187 mov r9, rINST, lsr #8 @ r9<- AA 5188 mov r3, r0, lsr #8 @ r3<- CC 5189 and r2, r0, #255 @ r2<- BB 5190 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5191 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5192 fldd d1, [r3] @ d1<- vCC 5193 fldd d0, [r2] @ d0<- vBB 5194 5195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5196 fsubd d2, d0, d1 @ s2<- op 5197 GET_INST_OPCODE(ip) @ extract opcode from rINST 5198 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5199 fstd d2, [r9] @ vAA<- d2 5200 GOTO_OPCODE(ip) @ jump to next instruction 5201 5202 5203/* ------------------------------ */ 5204 .balign 64 5205.L_OP_MUL_DOUBLE: /* 0xad */ 5206/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5207/* File: arm-vfp/fbinopWide.S */ 5208 /* 5209 * Generic 64-bit double-precision floating point binary operation. 5210 * Provide an "instr" line that specifies an instruction that performs 5211 * "d2 = d0 op d1". 5212 * 5213 * for: add-double, sub-double, mul-double, div-double 5214 */ 5215 /* doubleop vAA, vBB, vCC */ 5216 FETCH(r0, 1) @ r0<- CCBB 5217 mov r9, rINST, lsr #8 @ r9<- AA 5218 mov r3, r0, lsr #8 @ r3<- CC 5219 and r2, r0, #255 @ r2<- BB 5220 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5221 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5222 fldd d1, [r3] @ d1<- vCC 5223 fldd d0, [r2] @ d0<- vBB 5224 5225 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5226 fmuld d2, d0, d1 @ s2<- op 5227 GET_INST_OPCODE(ip) @ extract opcode from rINST 5228 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5229 fstd d2, [r9] @ vAA<- d2 5230 GOTO_OPCODE(ip) @ jump to next instruction 5231 5232 5233/* ------------------------------ */ 5234 .balign 64 5235.L_OP_DIV_DOUBLE: /* 0xae */ 5236/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5237/* File: arm-vfp/fbinopWide.S */ 5238 /* 5239 * Generic 64-bit double-precision floating point binary operation. 5240 * Provide an "instr" line that specifies an instruction that performs 5241 * "d2 = d0 op d1". 5242 * 5243 * for: add-double, sub-double, mul-double, div-double 5244 */ 5245 /* doubleop vAA, vBB, vCC */ 5246 FETCH(r0, 1) @ r0<- CCBB 5247 mov r9, rINST, lsr #8 @ r9<- AA 5248 mov r3, r0, lsr #8 @ r3<- CC 5249 and r2, r0, #255 @ r2<- BB 5250 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5251 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5252 fldd d1, [r3] @ d1<- vCC 5253 fldd d0, [r2] @ d0<- vBB 5254 5255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5256 fdivd d2, d0, d1 @ s2<- op 5257 GET_INST_OPCODE(ip) @ extract opcode from rINST 5258 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5259 fstd d2, [r9] @ vAA<- d2 5260 GOTO_OPCODE(ip) @ jump to next instruction 5261 5262 5263/* ------------------------------ */ 5264 .balign 64 5265.L_OP_REM_DOUBLE: /* 0xaf */ 5266/* File: armv5te/OP_REM_DOUBLE.S */ 5267/* EABI doesn't define a double remainder function, but libm does */ 5268/* File: armv5te/binopWide.S */ 5269 /* 5270 * Generic 64-bit binary operation. Provide an "instr" line that 5271 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5272 * This could be an ARM instruction or a function call. (If the result 5273 * comes back in a register other than r0, you can override "result".) 5274 * 5275 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5276 * vCC (r1). Useful for integer division and modulus. 5277 * 5278 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5279 * xor-long, add-double, sub-double, mul-double, div-double, 5280 * rem-double 5281 * 5282 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5283 */ 5284 /* binop vAA, vBB, vCC */ 5285 FETCH(r0, 1) @ r0<- CCBB 5286 mov r9, rINST, lsr #8 @ r9<- AA 5287 and r2, r0, #255 @ r2<- BB 5288 mov r3, r0, lsr #8 @ r3<- CC 5289 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5290 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5291 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5292 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5293 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5294 .if 0 5295 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5296 beq common_errDivideByZero 5297 .endif 5298 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5299 5300 @ optional op; may set condition codes 5301 bl fmod @ result<- op, r0-r3 changed 5302 GET_INST_OPCODE(ip) @ extract opcode from rINST 5303 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5304 GOTO_OPCODE(ip) @ jump to next instruction 5305 /* 14-17 instructions */ 5306 5307 5308 5309/* ------------------------------ */ 5310 .balign 64 5311.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5312/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5313/* File: armv5te/binop2addr.S */ 5314 /* 5315 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5316 * that specifies an instruction that performs "result = r0 op r1". 5317 * This could be an ARM instruction or a function call. (If the result 5318 * comes back in a register other than r0, you can override "result".) 5319 * 5320 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5321 * vCC (r1). Useful for integer division and modulus. 5322 * 5323 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5324 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5325 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5326 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5327 */ 5328 /* binop/2addr vA, vB */ 5329 mov r9, rINST, lsr #8 @ r9<- A+ 5330 mov r3, rINST, lsr #12 @ r3<- B 5331 and r9, r9, #15 5332 GET_VREG(r1, r3) @ r1<- vB 5333 GET_VREG(r0, r9) @ r0<- vA 5334 .if 0 5335 cmp r1, #0 @ is second operand zero? 5336 beq common_errDivideByZero 5337 .endif 5338 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5339 5340 @ optional op; may set condition codes 5341 add r0, r0, r1 @ r0<- op, r0-r3 changed 5342 GET_INST_OPCODE(ip) @ extract opcode from rINST 5343 SET_VREG(r0, r9) @ vAA<- r0 5344 GOTO_OPCODE(ip) @ jump to next instruction 5345 /* 10-13 instructions */ 5346 5347 5348 5349/* ------------------------------ */ 5350 .balign 64 5351.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5352/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5353/* File: armv5te/binop2addr.S */ 5354 /* 5355 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5356 * that specifies an instruction that performs "result = r0 op r1". 5357 * This could be an ARM instruction or a function call. (If the result 5358 * comes back in a register other than r0, you can override "result".) 5359 * 5360 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5361 * vCC (r1). Useful for integer division and modulus. 5362 * 5363 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5364 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5365 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5366 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5367 */ 5368 /* binop/2addr vA, vB */ 5369 mov r9, rINST, lsr #8 @ r9<- A+ 5370 mov r3, rINST, lsr #12 @ r3<- B 5371 and r9, r9, #15 5372 GET_VREG(r1, r3) @ r1<- vB 5373 GET_VREG(r0, r9) @ r0<- vA 5374 .if 0 5375 cmp r1, #0 @ is second operand zero? 5376 beq common_errDivideByZero 5377 .endif 5378 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5379 5380 @ optional op; may set condition codes 5381 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5382 GET_INST_OPCODE(ip) @ extract opcode from rINST 5383 SET_VREG(r0, r9) @ vAA<- r0 5384 GOTO_OPCODE(ip) @ jump to next instruction 5385 /* 10-13 instructions */ 5386 5387 5388 5389/* ------------------------------ */ 5390 .balign 64 5391.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5392/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5393/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5394/* File: armv5te/binop2addr.S */ 5395 /* 5396 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5397 * that specifies an instruction that performs "result = r0 op r1". 5398 * This could be an ARM instruction or a function call. (If the result 5399 * comes back in a register other than r0, you can override "result".) 5400 * 5401 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5402 * vCC (r1). Useful for integer division and modulus. 5403 * 5404 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5405 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5406 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5407 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5408 */ 5409 /* binop/2addr vA, vB */ 5410 mov r9, rINST, lsr #8 @ r9<- A+ 5411 mov r3, rINST, lsr #12 @ r3<- B 5412 and r9, r9, #15 5413 GET_VREG(r1, r3) @ r1<- vB 5414 GET_VREG(r0, r9) @ r0<- vA 5415 .if 0 5416 cmp r1, #0 @ is second operand zero? 5417 beq common_errDivideByZero 5418 .endif 5419 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5420 5421 @ optional op; may set condition codes 5422 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5423 GET_INST_OPCODE(ip) @ extract opcode from rINST 5424 SET_VREG(r0, r9) @ vAA<- r0 5425 GOTO_OPCODE(ip) @ jump to next instruction 5426 /* 10-13 instructions */ 5427 5428 5429 5430/* ------------------------------ */ 5431 .balign 64 5432.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5433/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5434/* File: armv5te/binop2addr.S */ 5435 /* 5436 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5437 * that specifies an instruction that performs "result = r0 op r1". 5438 * This could be an ARM instruction or a function call. (If the result 5439 * comes back in a register other than r0, you can override "result".) 5440 * 5441 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5442 * vCC (r1). Useful for integer division and modulus. 5443 * 5444 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5445 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5446 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5447 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5448 */ 5449 /* binop/2addr vA, vB */ 5450 mov r9, rINST, lsr #8 @ r9<- A+ 5451 mov r3, rINST, lsr #12 @ r3<- B 5452 and r9, r9, #15 5453 GET_VREG(r1, r3) @ r1<- vB 5454 GET_VREG(r0, r9) @ r0<- vA 5455 .if 1 5456 cmp r1, #0 @ is second operand zero? 5457 beq common_errDivideByZero 5458 .endif 5459 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5460 5461 @ optional op; may set condition codes 5462 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5463 GET_INST_OPCODE(ip) @ extract opcode from rINST 5464 SET_VREG(r0, r9) @ vAA<- r0 5465 GOTO_OPCODE(ip) @ jump to next instruction 5466 /* 10-13 instructions */ 5467 5468 5469 5470/* ------------------------------ */ 5471 .balign 64 5472.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5473/* File: armv5te/OP_REM_INT_2ADDR.S */ 5474/* idivmod returns quotient in r0 and remainder in r1 */ 5475/* File: armv5te/binop2addr.S */ 5476 /* 5477 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5478 * that specifies an instruction that performs "result = r0 op r1". 5479 * This could be an ARM instruction or a function call. (If the result 5480 * comes back in a register other than r0, you can override "result".) 5481 * 5482 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5483 * vCC (r1). Useful for integer division and modulus. 5484 * 5485 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5486 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5487 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5488 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5489 */ 5490 /* binop/2addr vA, vB */ 5491 mov r9, rINST, lsr #8 @ r9<- A+ 5492 mov r3, rINST, lsr #12 @ r3<- B 5493 and r9, r9, #15 5494 GET_VREG(r1, r3) @ r1<- vB 5495 GET_VREG(r0, r9) @ r0<- vA 5496 .if 1 5497 cmp r1, #0 @ is second operand zero? 5498 beq common_errDivideByZero 5499 .endif 5500 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5501 5502 @ optional op; may set condition codes 5503 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5504 GET_INST_OPCODE(ip) @ extract opcode from rINST 5505 SET_VREG(r1, r9) @ vAA<- r1 5506 GOTO_OPCODE(ip) @ jump to next instruction 5507 /* 10-13 instructions */ 5508 5509 5510 5511/* ------------------------------ */ 5512 .balign 64 5513.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5514/* File: armv5te/OP_AND_INT_2ADDR.S */ 5515/* File: armv5te/binop2addr.S */ 5516 /* 5517 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5518 * that specifies an instruction that performs "result = r0 op r1". 5519 * This could be an ARM instruction or a function call. (If the result 5520 * comes back in a register other than r0, you can override "result".) 5521 * 5522 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5523 * vCC (r1). Useful for integer division and modulus. 5524 * 5525 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5526 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5527 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5528 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5529 */ 5530 /* binop/2addr vA, vB */ 5531 mov r9, rINST, lsr #8 @ r9<- A+ 5532 mov r3, rINST, lsr #12 @ r3<- B 5533 and r9, r9, #15 5534 GET_VREG(r1, r3) @ r1<- vB 5535 GET_VREG(r0, r9) @ r0<- vA 5536 .if 0 5537 cmp r1, #0 @ is second operand zero? 5538 beq common_errDivideByZero 5539 .endif 5540 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5541 5542 @ optional op; may set condition codes 5543 and r0, r0, r1 @ r0<- op, r0-r3 changed 5544 GET_INST_OPCODE(ip) @ extract opcode from rINST 5545 SET_VREG(r0, r9) @ vAA<- r0 5546 GOTO_OPCODE(ip) @ jump to next instruction 5547 /* 10-13 instructions */ 5548 5549 5550 5551/* ------------------------------ */ 5552 .balign 64 5553.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5554/* File: armv5te/OP_OR_INT_2ADDR.S */ 5555/* File: armv5te/binop2addr.S */ 5556 /* 5557 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5558 * that specifies an instruction that performs "result = r0 op r1". 5559 * This could be an ARM instruction or a function call. (If the result 5560 * comes back in a register other than r0, you can override "result".) 5561 * 5562 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5563 * vCC (r1). Useful for integer division and modulus. 5564 * 5565 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5566 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5567 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5568 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5569 */ 5570 /* binop/2addr vA, vB */ 5571 mov r9, rINST, lsr #8 @ r9<- A+ 5572 mov r3, rINST, lsr #12 @ r3<- B 5573 and r9, r9, #15 5574 GET_VREG(r1, r3) @ r1<- vB 5575 GET_VREG(r0, r9) @ r0<- vA 5576 .if 0 5577 cmp r1, #0 @ is second operand zero? 5578 beq common_errDivideByZero 5579 .endif 5580 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5581 5582 @ optional op; may set condition codes 5583 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5584 GET_INST_OPCODE(ip) @ extract opcode from rINST 5585 SET_VREG(r0, r9) @ vAA<- r0 5586 GOTO_OPCODE(ip) @ jump to next instruction 5587 /* 10-13 instructions */ 5588 5589 5590 5591/* ------------------------------ */ 5592 .balign 64 5593.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5594/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5595/* File: armv5te/binop2addr.S */ 5596 /* 5597 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5598 * that specifies an instruction that performs "result = r0 op r1". 5599 * This could be an ARM instruction or a function call. (If the result 5600 * comes back in a register other than r0, you can override "result".) 5601 * 5602 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5603 * vCC (r1). Useful for integer division and modulus. 5604 * 5605 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5606 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5607 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5608 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5609 */ 5610 /* binop/2addr vA, vB */ 5611 mov r9, rINST, lsr #8 @ r9<- A+ 5612 mov r3, rINST, lsr #12 @ r3<- B 5613 and r9, r9, #15 5614 GET_VREG(r1, r3) @ r1<- vB 5615 GET_VREG(r0, r9) @ r0<- vA 5616 .if 0 5617 cmp r1, #0 @ is second operand zero? 5618 beq common_errDivideByZero 5619 .endif 5620 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5621 5622 @ optional op; may set condition codes 5623 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5624 GET_INST_OPCODE(ip) @ extract opcode from rINST 5625 SET_VREG(r0, r9) @ vAA<- r0 5626 GOTO_OPCODE(ip) @ jump to next instruction 5627 /* 10-13 instructions */ 5628 5629 5630 5631/* ------------------------------ */ 5632 .balign 64 5633.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5634/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5635/* File: armv5te/binop2addr.S */ 5636 /* 5637 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5638 * that specifies an instruction that performs "result = r0 op r1". 5639 * This could be an ARM instruction or a function call. (If the result 5640 * comes back in a register other than r0, you can override "result".) 5641 * 5642 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5643 * vCC (r1). Useful for integer division and modulus. 5644 * 5645 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5646 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5647 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5648 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5649 */ 5650 /* binop/2addr vA, vB */ 5651 mov r9, rINST, lsr #8 @ r9<- A+ 5652 mov r3, rINST, lsr #12 @ r3<- B 5653 and r9, r9, #15 5654 GET_VREG(r1, r3) @ r1<- vB 5655 GET_VREG(r0, r9) @ r0<- vA 5656 .if 0 5657 cmp r1, #0 @ is second operand zero? 5658 beq common_errDivideByZero 5659 .endif 5660 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5661 5662 and r1, r1, #31 @ optional op; may set condition codes 5663 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5664 GET_INST_OPCODE(ip) @ extract opcode from rINST 5665 SET_VREG(r0, r9) @ vAA<- r0 5666 GOTO_OPCODE(ip) @ jump to next instruction 5667 /* 10-13 instructions */ 5668 5669 5670 5671/* ------------------------------ */ 5672 .balign 64 5673.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5674/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5675/* File: armv5te/binop2addr.S */ 5676 /* 5677 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5678 * that specifies an instruction that performs "result = r0 op r1". 5679 * This could be an ARM instruction or a function call. (If the result 5680 * comes back in a register other than r0, you can override "result".) 5681 * 5682 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5683 * vCC (r1). Useful for integer division and modulus. 5684 * 5685 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5686 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5687 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5688 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5689 */ 5690 /* binop/2addr vA, vB */ 5691 mov r9, rINST, lsr #8 @ r9<- A+ 5692 mov r3, rINST, lsr #12 @ r3<- B 5693 and r9, r9, #15 5694 GET_VREG(r1, r3) @ r1<- vB 5695 GET_VREG(r0, r9) @ r0<- vA 5696 .if 0 5697 cmp r1, #0 @ is second operand zero? 5698 beq common_errDivideByZero 5699 .endif 5700 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5701 5702 and r1, r1, #31 @ optional op; may set condition codes 5703 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5704 GET_INST_OPCODE(ip) @ extract opcode from rINST 5705 SET_VREG(r0, r9) @ vAA<- r0 5706 GOTO_OPCODE(ip) @ jump to next instruction 5707 /* 10-13 instructions */ 5708 5709 5710 5711/* ------------------------------ */ 5712 .balign 64 5713.L_OP_USHR_INT_2ADDR: /* 0xba */ 5714/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5715/* File: armv5te/binop2addr.S */ 5716 /* 5717 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5718 * that specifies an instruction that performs "result = r0 op r1". 5719 * This could be an ARM instruction or a function call. (If the result 5720 * comes back in a register other than r0, you can override "result".) 5721 * 5722 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5723 * vCC (r1). Useful for integer division and modulus. 5724 * 5725 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5726 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5727 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5728 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5729 */ 5730 /* binop/2addr vA, vB */ 5731 mov r9, rINST, lsr #8 @ r9<- A+ 5732 mov r3, rINST, lsr #12 @ r3<- B 5733 and r9, r9, #15 5734 GET_VREG(r1, r3) @ r1<- vB 5735 GET_VREG(r0, r9) @ r0<- vA 5736 .if 0 5737 cmp r1, #0 @ is second operand zero? 5738 beq common_errDivideByZero 5739 .endif 5740 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5741 5742 and r1, r1, #31 @ optional op; may set condition codes 5743 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5744 GET_INST_OPCODE(ip) @ extract opcode from rINST 5745 SET_VREG(r0, r9) @ vAA<- r0 5746 GOTO_OPCODE(ip) @ jump to next instruction 5747 /* 10-13 instructions */ 5748 5749 5750 5751/* ------------------------------ */ 5752 .balign 64 5753.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5754/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5755/* File: armv5te/binopWide2addr.S */ 5756 /* 5757 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5758 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5759 * This could be an ARM instruction or a function call. (If the result 5760 * comes back in a register other than r0, you can override "result".) 5761 * 5762 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5763 * vCC (r1). Useful for integer division and modulus. 5764 * 5765 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5766 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5767 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5768 * rem-double/2addr 5769 */ 5770 /* binop/2addr vA, vB */ 5771 mov r9, rINST, lsr #8 @ r9<- A+ 5772 mov r1, rINST, lsr #12 @ r1<- B 5773 and r9, r9, #15 5774 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5775 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5776 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5777 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5778 .if 0 5779 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5780 beq common_errDivideByZero 5781 .endif 5782 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5783 5784 adds r0, r0, r2 @ optional op; may set condition codes 5785 adc r1, r1, r3 @ result<- op, r0-r3 changed 5786 GET_INST_OPCODE(ip) @ extract opcode from rINST 5787 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5788 GOTO_OPCODE(ip) @ jump to next instruction 5789 /* 12-15 instructions */ 5790 5791 5792 5793/* ------------------------------ */ 5794 .balign 64 5795.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5796/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5797/* File: armv5te/binopWide2addr.S */ 5798 /* 5799 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5800 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5801 * This could be an ARM instruction or a function call. (If the result 5802 * comes back in a register other than r0, you can override "result".) 5803 * 5804 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5805 * vCC (r1). Useful for integer division and modulus. 5806 * 5807 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5808 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5809 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5810 * rem-double/2addr 5811 */ 5812 /* binop/2addr vA, vB */ 5813 mov r9, rINST, lsr #8 @ r9<- A+ 5814 mov r1, rINST, lsr #12 @ r1<- B 5815 and r9, r9, #15 5816 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5817 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5818 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5819 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5820 .if 0 5821 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5822 beq common_errDivideByZero 5823 .endif 5824 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5825 5826 subs r0, r0, r2 @ optional op; may set condition codes 5827 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5828 GET_INST_OPCODE(ip) @ extract opcode from rINST 5829 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5830 GOTO_OPCODE(ip) @ jump to next instruction 5831 /* 12-15 instructions */ 5832 5833 5834 5835/* ------------------------------ */ 5836 .balign 64 5837.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5838/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5839 /* 5840 * Signed 64-bit integer multiply, "/2addr" version. 5841 * 5842 * See OP_MUL_LONG for an explanation. 5843 * 5844 * We get a little tight on registers, so to avoid looking up &fp[A] 5845 * again we stuff it into rINST. 5846 */ 5847 /* mul-long/2addr vA, vB */ 5848 mov r9, rINST, lsr #8 @ r9<- A+ 5849 mov r1, rINST, lsr #12 @ r1<- B 5850 and r9, r9, #15 5851 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5852 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5853 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5854 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5855 mul ip, r2, r1 @ ip<- ZxW 5856 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5857 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5858 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5859 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5860 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5861 GET_INST_OPCODE(ip) @ extract opcode from rINST 5862 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5863 GOTO_OPCODE(ip) @ jump to next instruction 5864 5865 5866/* ------------------------------ */ 5867 .balign 64 5868.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5869/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5870/* File: armv5te/binopWide2addr.S */ 5871 /* 5872 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5873 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5874 * This could be an ARM instruction or a function call. (If the result 5875 * comes back in a register other than r0, you can override "result".) 5876 * 5877 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5878 * vCC (r1). Useful for integer division and modulus. 5879 * 5880 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5881 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5882 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5883 * rem-double/2addr 5884 */ 5885 /* binop/2addr vA, vB */ 5886 mov r9, rINST, lsr #8 @ r9<- A+ 5887 mov r1, rINST, lsr #12 @ r1<- B 5888 and r9, r9, #15 5889 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5890 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5891 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5892 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5893 .if 1 5894 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5895 beq common_errDivideByZero 5896 .endif 5897 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5898 5899 @ optional op; may set condition codes 5900 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5901 GET_INST_OPCODE(ip) @ extract opcode from rINST 5902 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5903 GOTO_OPCODE(ip) @ jump to next instruction 5904 /* 12-15 instructions */ 5905 5906 5907 5908/* ------------------------------ */ 5909 .balign 64 5910.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5911/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5912/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5913/* File: armv5te/binopWide2addr.S */ 5914 /* 5915 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5916 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5917 * This could be an ARM instruction or a function call. (If the result 5918 * comes back in a register other than r0, you can override "result".) 5919 * 5920 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5921 * vCC (r1). Useful for integer division and modulus. 5922 * 5923 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5924 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5925 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5926 * rem-double/2addr 5927 */ 5928 /* binop/2addr vA, vB */ 5929 mov r9, rINST, lsr #8 @ r9<- A+ 5930 mov r1, rINST, lsr #12 @ r1<- B 5931 and r9, r9, #15 5932 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5933 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5934 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5935 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5936 .if 1 5937 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5938 beq common_errDivideByZero 5939 .endif 5940 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5941 5942 @ optional op; may set condition codes 5943 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5944 GET_INST_OPCODE(ip) @ extract opcode from rINST 5945 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5946 GOTO_OPCODE(ip) @ jump to next instruction 5947 /* 12-15 instructions */ 5948 5949 5950 5951/* ------------------------------ */ 5952 .balign 64 5953.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5954/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5955/* File: armv5te/binopWide2addr.S */ 5956 /* 5957 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5958 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5959 * This could be an ARM instruction or a function call. (If the result 5960 * comes back in a register other than r0, you can override "result".) 5961 * 5962 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5963 * vCC (r1). Useful for integer division and modulus. 5964 * 5965 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5966 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5967 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5968 * rem-double/2addr 5969 */ 5970 /* binop/2addr vA, vB */ 5971 mov r9, rINST, lsr #8 @ r9<- A+ 5972 mov r1, rINST, lsr #12 @ r1<- B 5973 and r9, r9, #15 5974 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5975 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5976 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5977 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5978 .if 0 5979 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5980 beq common_errDivideByZero 5981 .endif 5982 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5983 5984 and r0, r0, r2 @ optional op; may set condition codes 5985 and r1, r1, r3 @ result<- op, r0-r3 changed 5986 GET_INST_OPCODE(ip) @ extract opcode from rINST 5987 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5988 GOTO_OPCODE(ip) @ jump to next instruction 5989 /* 12-15 instructions */ 5990 5991 5992 5993/* ------------------------------ */ 5994 .balign 64 5995.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5996/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5997/* File: armv5te/binopWide2addr.S */ 5998 /* 5999 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6000 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6001 * This could be an ARM instruction or a function call. (If the result 6002 * comes back in a register other than r0, you can override "result".) 6003 * 6004 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6005 * vCC (r1). Useful for integer division and modulus. 6006 * 6007 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6008 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6009 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6010 * rem-double/2addr 6011 */ 6012 /* binop/2addr vA, vB */ 6013 mov r9, rINST, lsr #8 @ r9<- A+ 6014 mov r1, rINST, lsr #12 @ r1<- B 6015 and r9, r9, #15 6016 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6017 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6018 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6019 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6020 .if 0 6021 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6022 beq common_errDivideByZero 6023 .endif 6024 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6025 6026 orr r0, r0, r2 @ optional op; may set condition codes 6027 orr r1, r1, r3 @ result<- op, r0-r3 changed 6028 GET_INST_OPCODE(ip) @ extract opcode from rINST 6029 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6030 GOTO_OPCODE(ip) @ jump to next instruction 6031 /* 12-15 instructions */ 6032 6033 6034 6035/* ------------------------------ */ 6036 .balign 64 6037.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6038/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6039/* File: armv5te/binopWide2addr.S */ 6040 /* 6041 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6042 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6043 * This could be an ARM instruction or a function call. (If the result 6044 * comes back in a register other than r0, you can override "result".) 6045 * 6046 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6047 * vCC (r1). Useful for integer division and modulus. 6048 * 6049 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6050 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6051 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6052 * rem-double/2addr 6053 */ 6054 /* binop/2addr vA, vB */ 6055 mov r9, rINST, lsr #8 @ r9<- A+ 6056 mov r1, rINST, lsr #12 @ r1<- B 6057 and r9, r9, #15 6058 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6059 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6060 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6061 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6062 .if 0 6063 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6064 beq common_errDivideByZero 6065 .endif 6066 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6067 6068 eor r0, r0, r2 @ optional op; may set condition codes 6069 eor r1, r1, r3 @ result<- op, r0-r3 changed 6070 GET_INST_OPCODE(ip) @ extract opcode from rINST 6071 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6072 GOTO_OPCODE(ip) @ jump to next instruction 6073 /* 12-15 instructions */ 6074 6075 6076 6077/* ------------------------------ */ 6078 .balign 64 6079.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6080/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6081 /* 6082 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6083 * 32-bit shift distance. 6084 */ 6085 /* shl-long/2addr vA, vB */ 6086 mov r9, rINST, lsr #8 @ r9<- A+ 6087 mov r3, rINST, lsr #12 @ r3<- B 6088 and r9, r9, #15 6089 GET_VREG(r2, r3) @ r2<- vB 6090 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6091 and r2, r2, #63 @ r2<- r2 & 0x3f 6092 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6093 6094 mov r1, r1, asl r2 @ r1<- r1 << r2 6095 rsb r3, r2, #32 @ r3<- 32 - r2 6096 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6097 subs ip, r2, #32 @ ip<- r2 - 32 6098 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6099 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6100 mov r0, r0, asl r2 @ r0<- r0 << r2 6101 b .LOP_SHL_LONG_2ADDR_finish 6102 6103/* ------------------------------ */ 6104 .balign 64 6105.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6106/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6107 /* 6108 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6109 * 32-bit shift distance. 6110 */ 6111 /* shr-long/2addr vA, vB */ 6112 mov r9, rINST, lsr #8 @ r9<- A+ 6113 mov r3, rINST, lsr #12 @ r3<- B 6114 and r9, r9, #15 6115 GET_VREG(r2, r3) @ r2<- vB 6116 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6117 and r2, r2, #63 @ r2<- r2 & 0x3f 6118 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6119 6120 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6121 rsb r3, r2, #32 @ r3<- 32 - r2 6122 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6123 subs ip, r2, #32 @ ip<- r2 - 32 6124 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6125 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6126 mov r1, r1, asr r2 @ r1<- r1 >> r2 6127 b .LOP_SHR_LONG_2ADDR_finish 6128 6129/* ------------------------------ */ 6130 .balign 64 6131.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6132/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6133 /* 6134 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6135 * 32-bit shift distance. 6136 */ 6137 /* ushr-long/2addr vA, vB */ 6138 mov r9, rINST, lsr #8 @ r9<- A+ 6139 mov r3, rINST, lsr #12 @ r3<- B 6140 and r9, r9, #15 6141 GET_VREG(r2, r3) @ r2<- vB 6142 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6143 and r2, r2, #63 @ r2<- r2 & 0x3f 6144 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6145 6146 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6147 rsb r3, r2, #32 @ r3<- 32 - r2 6148 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6149 subs ip, r2, #32 @ ip<- r2 - 32 6150 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6151 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6152 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6153 b .LOP_USHR_LONG_2ADDR_finish 6154 6155/* ------------------------------ */ 6156 .balign 64 6157.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6158/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6159/* File: arm-vfp/fbinop2addr.S */ 6160 /* 6161 * Generic 32-bit floating point "/2addr" binary operation. Provide 6162 * an "instr" line that specifies an instruction that performs 6163 * "s2 = s0 op s1". 6164 * 6165 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6166 */ 6167 /* binop/2addr vA, vB */ 6168 mov r3, rINST, lsr #12 @ r3<- B 6169 mov r9, rINST, lsr #8 @ r9<- A+ 6170 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6171 and r9, r9, #15 @ r9<- A 6172 flds s1, [r3] @ s1<- vB 6173 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6174 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6175 flds s0, [r9] @ s0<- vA 6176 6177 fadds s2, s0, s1 @ s2<- op 6178 GET_INST_OPCODE(ip) @ extract opcode from rINST 6179 fsts s2, [r9] @ vAA<- s2 6180 GOTO_OPCODE(ip) @ jump to next instruction 6181 6182 6183/* ------------------------------ */ 6184 .balign 64 6185.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6186/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6187/* File: arm-vfp/fbinop2addr.S */ 6188 /* 6189 * Generic 32-bit floating point "/2addr" binary operation. Provide 6190 * an "instr" line that specifies an instruction that performs 6191 * "s2 = s0 op s1". 6192 * 6193 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6194 */ 6195 /* binop/2addr vA, vB */ 6196 mov r3, rINST, lsr #12 @ r3<- B 6197 mov r9, rINST, lsr #8 @ r9<- A+ 6198 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6199 and r9, r9, #15 @ r9<- A 6200 flds s1, [r3] @ s1<- vB 6201 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6202 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6203 flds s0, [r9] @ s0<- vA 6204 6205 fsubs s2, s0, s1 @ s2<- op 6206 GET_INST_OPCODE(ip) @ extract opcode from rINST 6207 fsts s2, [r9] @ vAA<- s2 6208 GOTO_OPCODE(ip) @ jump to next instruction 6209 6210 6211/* ------------------------------ */ 6212 .balign 64 6213.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6214/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6215/* File: arm-vfp/fbinop2addr.S */ 6216 /* 6217 * Generic 32-bit floating point "/2addr" binary operation. Provide 6218 * an "instr" line that specifies an instruction that performs 6219 * "s2 = s0 op s1". 6220 * 6221 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6222 */ 6223 /* binop/2addr vA, vB */ 6224 mov r3, rINST, lsr #12 @ r3<- B 6225 mov r9, rINST, lsr #8 @ r9<- A+ 6226 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6227 and r9, r9, #15 @ r9<- A 6228 flds s1, [r3] @ s1<- vB 6229 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6230 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6231 flds s0, [r9] @ s0<- vA 6232 6233 fmuls s2, s0, s1 @ s2<- op 6234 GET_INST_OPCODE(ip) @ extract opcode from rINST 6235 fsts s2, [r9] @ vAA<- s2 6236 GOTO_OPCODE(ip) @ jump to next instruction 6237 6238 6239/* ------------------------------ */ 6240 .balign 64 6241.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6242/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6243/* File: arm-vfp/fbinop2addr.S */ 6244 /* 6245 * Generic 32-bit floating point "/2addr" binary operation. Provide 6246 * an "instr" line that specifies an instruction that performs 6247 * "s2 = s0 op s1". 6248 * 6249 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6250 */ 6251 /* binop/2addr vA, vB */ 6252 mov r3, rINST, lsr #12 @ r3<- B 6253 mov r9, rINST, lsr #8 @ r9<- A+ 6254 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6255 and r9, r9, #15 @ r9<- A 6256 flds s1, [r3] @ s1<- vB 6257 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6258 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6259 flds s0, [r9] @ s0<- vA 6260 6261 fdivs s2, s0, s1 @ s2<- op 6262 GET_INST_OPCODE(ip) @ extract opcode from rINST 6263 fsts s2, [r9] @ vAA<- s2 6264 GOTO_OPCODE(ip) @ jump to next instruction 6265 6266 6267/* ------------------------------ */ 6268 .balign 64 6269.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6270/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6271/* EABI doesn't define a float remainder function, but libm does */ 6272/* File: armv5te/binop2addr.S */ 6273 /* 6274 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6275 * that specifies an instruction that performs "result = r0 op r1". 6276 * This could be an ARM instruction or a function call. (If the result 6277 * comes back in a register other than r0, you can override "result".) 6278 * 6279 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6280 * vCC (r1). Useful for integer division and modulus. 6281 * 6282 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6283 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6284 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6285 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6286 */ 6287 /* binop/2addr vA, vB */ 6288 mov r9, rINST, lsr #8 @ r9<- A+ 6289 mov r3, rINST, lsr #12 @ r3<- B 6290 and r9, r9, #15 6291 GET_VREG(r1, r3) @ r1<- vB 6292 GET_VREG(r0, r9) @ r0<- vA 6293 .if 0 6294 cmp r1, #0 @ is second operand zero? 6295 beq common_errDivideByZero 6296 .endif 6297 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6298 6299 @ optional op; may set condition codes 6300 bl fmodf @ r0<- op, r0-r3 changed 6301 GET_INST_OPCODE(ip) @ extract opcode from rINST 6302 SET_VREG(r0, r9) @ vAA<- r0 6303 GOTO_OPCODE(ip) @ jump to next instruction 6304 /* 10-13 instructions */ 6305 6306 6307 6308/* ------------------------------ */ 6309 .balign 64 6310.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6311/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6312/* File: arm-vfp/fbinopWide2addr.S */ 6313 /* 6314 * Generic 64-bit floating point "/2addr" binary operation. Provide 6315 * an "instr" line that specifies an instruction that performs 6316 * "d2 = d0 op d1". 6317 * 6318 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6319 * div-double/2addr 6320 */ 6321 /* binop/2addr vA, vB */ 6322 mov r3, rINST, lsr #12 @ r3<- B 6323 mov r9, rINST, lsr #8 @ r9<- A+ 6324 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6325 and r9, r9, #15 @ r9<- A 6326 fldd d1, [r3] @ d1<- vB 6327 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6328 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6329 fldd d0, [r9] @ d0<- vA 6330 6331 faddd d2, d0, d1 @ d2<- op 6332 GET_INST_OPCODE(ip) @ extract opcode from rINST 6333 fstd d2, [r9] @ vAA<- d2 6334 GOTO_OPCODE(ip) @ jump to next instruction 6335 6336 6337/* ------------------------------ */ 6338 .balign 64 6339.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6340/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6341/* File: arm-vfp/fbinopWide2addr.S */ 6342 /* 6343 * Generic 64-bit floating point "/2addr" binary operation. Provide 6344 * an "instr" line that specifies an instruction that performs 6345 * "d2 = d0 op d1". 6346 * 6347 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6348 * div-double/2addr 6349 */ 6350 /* binop/2addr vA, vB */ 6351 mov r3, rINST, lsr #12 @ r3<- B 6352 mov r9, rINST, lsr #8 @ r9<- A+ 6353 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6354 and r9, r9, #15 @ r9<- A 6355 fldd d1, [r3] @ d1<- vB 6356 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6357 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6358 fldd d0, [r9] @ d0<- vA 6359 6360 fsubd d2, d0, d1 @ d2<- op 6361 GET_INST_OPCODE(ip) @ extract opcode from rINST 6362 fstd d2, [r9] @ vAA<- d2 6363 GOTO_OPCODE(ip) @ jump to next instruction 6364 6365 6366/* ------------------------------ */ 6367 .balign 64 6368.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6369/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6370/* File: arm-vfp/fbinopWide2addr.S */ 6371 /* 6372 * Generic 64-bit floating point "/2addr" binary operation. Provide 6373 * an "instr" line that specifies an instruction that performs 6374 * "d2 = d0 op d1". 6375 * 6376 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6377 * div-double/2addr 6378 */ 6379 /* binop/2addr vA, vB */ 6380 mov r3, rINST, lsr #12 @ r3<- B 6381 mov r9, rINST, lsr #8 @ r9<- A+ 6382 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6383 and r9, r9, #15 @ r9<- A 6384 fldd d1, [r3] @ d1<- vB 6385 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6386 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6387 fldd d0, [r9] @ d0<- vA 6388 6389 fmuld d2, d0, d1 @ d2<- op 6390 GET_INST_OPCODE(ip) @ extract opcode from rINST 6391 fstd d2, [r9] @ vAA<- d2 6392 GOTO_OPCODE(ip) @ jump to next instruction 6393 6394 6395/* ------------------------------ */ 6396 .balign 64 6397.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6398/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6399/* File: arm-vfp/fbinopWide2addr.S */ 6400 /* 6401 * Generic 64-bit floating point "/2addr" binary operation. Provide 6402 * an "instr" line that specifies an instruction that performs 6403 * "d2 = d0 op d1". 6404 * 6405 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6406 * div-double/2addr 6407 */ 6408 /* binop/2addr vA, vB */ 6409 mov r3, rINST, lsr #12 @ r3<- B 6410 mov r9, rINST, lsr #8 @ r9<- A+ 6411 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6412 and r9, r9, #15 @ r9<- A 6413 fldd d1, [r3] @ d1<- vB 6414 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6415 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6416 fldd d0, [r9] @ d0<- vA 6417 6418 fdivd d2, d0, d1 @ d2<- op 6419 GET_INST_OPCODE(ip) @ extract opcode from rINST 6420 fstd d2, [r9] @ vAA<- d2 6421 GOTO_OPCODE(ip) @ jump to next instruction 6422 6423 6424/* ------------------------------ */ 6425 .balign 64 6426.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6427/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6428/* EABI doesn't define a double remainder function, but libm does */ 6429/* File: armv5te/binopWide2addr.S */ 6430 /* 6431 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6432 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6433 * This could be an ARM instruction or a function call. (If the result 6434 * comes back in a register other than r0, you can override "result".) 6435 * 6436 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6437 * vCC (r1). Useful for integer division and modulus. 6438 * 6439 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6440 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6441 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6442 * rem-double/2addr 6443 */ 6444 /* binop/2addr vA, vB */ 6445 mov r9, rINST, lsr #8 @ r9<- A+ 6446 mov r1, rINST, lsr #12 @ r1<- B 6447 and r9, r9, #15 6448 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6449 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6450 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6451 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6452 .if 0 6453 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6454 beq common_errDivideByZero 6455 .endif 6456 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6457 6458 @ optional op; may set condition codes 6459 bl fmod @ result<- op, r0-r3 changed 6460 GET_INST_OPCODE(ip) @ extract opcode from rINST 6461 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6462 GOTO_OPCODE(ip) @ jump to next instruction 6463 /* 12-15 instructions */ 6464 6465 6466 6467/* ------------------------------ */ 6468 .balign 64 6469.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6470/* File: armv5te/OP_ADD_INT_LIT16.S */ 6471/* File: armv5te/binopLit16.S */ 6472 /* 6473 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6474 * that specifies an instruction that performs "result = r0 op r1". 6475 * This could be an ARM instruction or a function call. (If the result 6476 * comes back in a register other than r0, you can override "result".) 6477 * 6478 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6479 * vCC (r1). Useful for integer division and modulus. 6480 * 6481 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6482 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6483 */ 6484 /* binop/lit16 vA, vB, #+CCCC */ 6485 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6486 mov r2, rINST, lsr #12 @ r2<- B 6487 mov r9, rINST, lsr #8 @ r9<- A+ 6488 GET_VREG(r0, r2) @ r0<- vB 6489 and r9, r9, #15 6490 .if 0 6491 cmp r1, #0 @ is second operand zero? 6492 beq common_errDivideByZero 6493 .endif 6494 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6495 6496 add r0, r0, r1 @ r0<- op, r0-r3 changed 6497 GET_INST_OPCODE(ip) @ extract opcode from rINST 6498 SET_VREG(r0, r9) @ vAA<- r0 6499 GOTO_OPCODE(ip) @ jump to next instruction 6500 /* 10-13 instructions */ 6501 6502 6503 6504/* ------------------------------ */ 6505 .balign 64 6506.L_OP_RSUB_INT: /* 0xd1 */ 6507/* File: armv5te/OP_RSUB_INT.S */ 6508/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6509/* File: armv5te/binopLit16.S */ 6510 /* 6511 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6512 * that specifies an instruction that performs "result = r0 op r1". 6513 * This could be an ARM instruction or a function call. (If the result 6514 * comes back in a register other than r0, you can override "result".) 6515 * 6516 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6517 * vCC (r1). Useful for integer division and modulus. 6518 * 6519 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6520 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6521 */ 6522 /* binop/lit16 vA, vB, #+CCCC */ 6523 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6524 mov r2, rINST, lsr #12 @ r2<- B 6525 mov r9, rINST, lsr #8 @ r9<- A+ 6526 GET_VREG(r0, r2) @ r0<- vB 6527 and r9, r9, #15 6528 .if 0 6529 cmp r1, #0 @ is second operand zero? 6530 beq common_errDivideByZero 6531 .endif 6532 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6533 6534 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6535 GET_INST_OPCODE(ip) @ extract opcode from rINST 6536 SET_VREG(r0, r9) @ vAA<- r0 6537 GOTO_OPCODE(ip) @ jump to next instruction 6538 /* 10-13 instructions */ 6539 6540 6541 6542/* ------------------------------ */ 6543 .balign 64 6544.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6545/* File: armv5te/OP_MUL_INT_LIT16.S */ 6546/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6547/* File: armv5te/binopLit16.S */ 6548 /* 6549 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6550 * that specifies an instruction that performs "result = r0 op r1". 6551 * This could be an ARM instruction or a function call. (If the result 6552 * comes back in a register other than r0, you can override "result".) 6553 * 6554 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6555 * vCC (r1). Useful for integer division and modulus. 6556 * 6557 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6558 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6559 */ 6560 /* binop/lit16 vA, vB, #+CCCC */ 6561 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6562 mov r2, rINST, lsr #12 @ r2<- B 6563 mov r9, rINST, lsr #8 @ r9<- A+ 6564 GET_VREG(r0, r2) @ r0<- vB 6565 and r9, r9, #15 6566 .if 0 6567 cmp r1, #0 @ is second operand zero? 6568 beq common_errDivideByZero 6569 .endif 6570 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6571 6572 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6573 GET_INST_OPCODE(ip) @ extract opcode from rINST 6574 SET_VREG(r0, r9) @ vAA<- r0 6575 GOTO_OPCODE(ip) @ jump to next instruction 6576 /* 10-13 instructions */ 6577 6578 6579 6580/* ------------------------------ */ 6581 .balign 64 6582.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6583/* File: armv5te/OP_DIV_INT_LIT16.S */ 6584/* File: armv5te/binopLit16.S */ 6585 /* 6586 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6587 * that specifies an instruction that performs "result = r0 op r1". 6588 * This could be an ARM instruction or a function call. (If the result 6589 * comes back in a register other than r0, you can override "result".) 6590 * 6591 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6592 * vCC (r1). Useful for integer division and modulus. 6593 * 6594 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6595 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6596 */ 6597 /* binop/lit16 vA, vB, #+CCCC */ 6598 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6599 mov r2, rINST, lsr #12 @ r2<- B 6600 mov r9, rINST, lsr #8 @ r9<- A+ 6601 GET_VREG(r0, r2) @ r0<- vB 6602 and r9, r9, #15 6603 .if 1 6604 cmp r1, #0 @ is second operand zero? 6605 beq common_errDivideByZero 6606 .endif 6607 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6608 6609 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6610 GET_INST_OPCODE(ip) @ extract opcode from rINST 6611 SET_VREG(r0, r9) @ vAA<- r0 6612 GOTO_OPCODE(ip) @ jump to next instruction 6613 /* 10-13 instructions */ 6614 6615 6616 6617/* ------------------------------ */ 6618 .balign 64 6619.L_OP_REM_INT_LIT16: /* 0xd4 */ 6620/* File: armv5te/OP_REM_INT_LIT16.S */ 6621/* idivmod returns quotient in r0 and remainder in r1 */ 6622/* File: armv5te/binopLit16.S */ 6623 /* 6624 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6625 * that specifies an instruction that performs "result = r0 op r1". 6626 * This could be an ARM instruction or a function call. (If the result 6627 * comes back in a register other than r0, you can override "result".) 6628 * 6629 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6630 * vCC (r1). Useful for integer division and modulus. 6631 * 6632 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6633 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6634 */ 6635 /* binop/lit16 vA, vB, #+CCCC */ 6636 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6637 mov r2, rINST, lsr #12 @ r2<- B 6638 mov r9, rINST, lsr #8 @ r9<- A+ 6639 GET_VREG(r0, r2) @ r0<- vB 6640 and r9, r9, #15 6641 .if 1 6642 cmp r1, #0 @ is second operand zero? 6643 beq common_errDivideByZero 6644 .endif 6645 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6646 6647 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6648 GET_INST_OPCODE(ip) @ extract opcode from rINST 6649 SET_VREG(r1, r9) @ vAA<- r1 6650 GOTO_OPCODE(ip) @ jump to next instruction 6651 /* 10-13 instructions */ 6652 6653 6654 6655/* ------------------------------ */ 6656 .balign 64 6657.L_OP_AND_INT_LIT16: /* 0xd5 */ 6658/* File: armv5te/OP_AND_INT_LIT16.S */ 6659/* File: armv5te/binopLit16.S */ 6660 /* 6661 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6662 * that specifies an instruction that performs "result = r0 op r1". 6663 * This could be an ARM instruction or a function call. (If the result 6664 * comes back in a register other than r0, you can override "result".) 6665 * 6666 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6667 * vCC (r1). Useful for integer division and modulus. 6668 * 6669 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6670 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6671 */ 6672 /* binop/lit16 vA, vB, #+CCCC */ 6673 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6674 mov r2, rINST, lsr #12 @ r2<- B 6675 mov r9, rINST, lsr #8 @ r9<- A+ 6676 GET_VREG(r0, r2) @ r0<- vB 6677 and r9, r9, #15 6678 .if 0 6679 cmp r1, #0 @ is second operand zero? 6680 beq common_errDivideByZero 6681 .endif 6682 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6683 6684 and r0, r0, r1 @ r0<- op, r0-r3 changed 6685 GET_INST_OPCODE(ip) @ extract opcode from rINST 6686 SET_VREG(r0, r9) @ vAA<- r0 6687 GOTO_OPCODE(ip) @ jump to next instruction 6688 /* 10-13 instructions */ 6689 6690 6691 6692/* ------------------------------ */ 6693 .balign 64 6694.L_OP_OR_INT_LIT16: /* 0xd6 */ 6695/* File: armv5te/OP_OR_INT_LIT16.S */ 6696/* File: armv5te/binopLit16.S */ 6697 /* 6698 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6699 * that specifies an instruction that performs "result = r0 op r1". 6700 * This could be an ARM instruction or a function call. (If the result 6701 * comes back in a register other than r0, you can override "result".) 6702 * 6703 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6704 * vCC (r1). Useful for integer division and modulus. 6705 * 6706 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6707 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6708 */ 6709 /* binop/lit16 vA, vB, #+CCCC */ 6710 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6711 mov r2, rINST, lsr #12 @ r2<- B 6712 mov r9, rINST, lsr #8 @ r9<- A+ 6713 GET_VREG(r0, r2) @ r0<- vB 6714 and r9, r9, #15 6715 .if 0 6716 cmp r1, #0 @ is second operand zero? 6717 beq common_errDivideByZero 6718 .endif 6719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6720 6721 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6722 GET_INST_OPCODE(ip) @ extract opcode from rINST 6723 SET_VREG(r0, r9) @ vAA<- r0 6724 GOTO_OPCODE(ip) @ jump to next instruction 6725 /* 10-13 instructions */ 6726 6727 6728 6729/* ------------------------------ */ 6730 .balign 64 6731.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6732/* File: armv5te/OP_XOR_INT_LIT16.S */ 6733/* File: armv5te/binopLit16.S */ 6734 /* 6735 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6736 * that specifies an instruction that performs "result = r0 op r1". 6737 * This could be an ARM instruction or a function call. (If the result 6738 * comes back in a register other than r0, you can override "result".) 6739 * 6740 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6741 * vCC (r1). Useful for integer division and modulus. 6742 * 6743 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6744 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6745 */ 6746 /* binop/lit16 vA, vB, #+CCCC */ 6747 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6748 mov r2, rINST, lsr #12 @ r2<- B 6749 mov r9, rINST, lsr #8 @ r9<- A+ 6750 GET_VREG(r0, r2) @ r0<- vB 6751 and r9, r9, #15 6752 .if 0 6753 cmp r1, #0 @ is second operand zero? 6754 beq common_errDivideByZero 6755 .endif 6756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6757 6758 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6759 GET_INST_OPCODE(ip) @ extract opcode from rINST 6760 SET_VREG(r0, r9) @ vAA<- r0 6761 GOTO_OPCODE(ip) @ jump to next instruction 6762 /* 10-13 instructions */ 6763 6764 6765 6766/* ------------------------------ */ 6767 .balign 64 6768.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6769/* File: armv5te/OP_ADD_INT_LIT8.S */ 6770/* File: armv5te/binopLit8.S */ 6771 /* 6772 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6773 * that specifies an instruction that performs "result = r0 op r1". 6774 * This could be an ARM instruction or a function call. (If the result 6775 * comes back in a register other than r0, you can override "result".) 6776 * 6777 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6778 * vCC (r1). Useful for integer division and modulus. 6779 * 6780 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6781 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6782 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6783 */ 6784 /* binop/lit8 vAA, vBB, #+CC */ 6785 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6786 mov r9, rINST, lsr #8 @ r9<- AA 6787 and r2, r3, #255 @ r2<- BB 6788 GET_VREG(r0, r2) @ r0<- vBB 6789 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6790 .if 0 6791 @cmp r1, #0 @ is second operand zero? 6792 beq common_errDivideByZero 6793 .endif 6794 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6795 6796 @ optional op; may set condition codes 6797 add r0, r0, r1 @ r0<- op, r0-r3 changed 6798 GET_INST_OPCODE(ip) @ extract opcode from rINST 6799 SET_VREG(r0, r9) @ vAA<- r0 6800 GOTO_OPCODE(ip) @ jump to next instruction 6801 /* 10-12 instructions */ 6802 6803 6804 6805/* ------------------------------ */ 6806 .balign 64 6807.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6808/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6809/* File: armv5te/binopLit8.S */ 6810 /* 6811 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6812 * that specifies an instruction that performs "result = r0 op r1". 6813 * This could be an ARM instruction or a function call. (If the result 6814 * comes back in a register other than r0, you can override "result".) 6815 * 6816 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6817 * vCC (r1). Useful for integer division and modulus. 6818 * 6819 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6820 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6821 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6822 */ 6823 /* binop/lit8 vAA, vBB, #+CC */ 6824 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6825 mov r9, rINST, lsr #8 @ r9<- AA 6826 and r2, r3, #255 @ r2<- BB 6827 GET_VREG(r0, r2) @ r0<- vBB 6828 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6829 .if 0 6830 @cmp r1, #0 @ is second operand zero? 6831 beq common_errDivideByZero 6832 .endif 6833 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6834 6835 @ optional op; may set condition codes 6836 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6837 GET_INST_OPCODE(ip) @ extract opcode from rINST 6838 SET_VREG(r0, r9) @ vAA<- r0 6839 GOTO_OPCODE(ip) @ jump to next instruction 6840 /* 10-12 instructions */ 6841 6842 6843 6844/* ------------------------------ */ 6845 .balign 64 6846.L_OP_MUL_INT_LIT8: /* 0xda */ 6847/* File: armv5te/OP_MUL_INT_LIT8.S */ 6848/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6849/* File: armv5te/binopLit8.S */ 6850 /* 6851 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6852 * that specifies an instruction that performs "result = r0 op r1". 6853 * This could be an ARM instruction or a function call. (If the result 6854 * comes back in a register other than r0, you can override "result".) 6855 * 6856 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6857 * vCC (r1). Useful for integer division and modulus. 6858 * 6859 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6860 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6861 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6862 */ 6863 /* binop/lit8 vAA, vBB, #+CC */ 6864 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6865 mov r9, rINST, lsr #8 @ r9<- AA 6866 and r2, r3, #255 @ r2<- BB 6867 GET_VREG(r0, r2) @ r0<- vBB 6868 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6869 .if 0 6870 @cmp r1, #0 @ is second operand zero? 6871 beq common_errDivideByZero 6872 .endif 6873 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6874 6875 @ optional op; may set condition codes 6876 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6877 GET_INST_OPCODE(ip) @ extract opcode from rINST 6878 SET_VREG(r0, r9) @ vAA<- r0 6879 GOTO_OPCODE(ip) @ jump to next instruction 6880 /* 10-12 instructions */ 6881 6882 6883 6884/* ------------------------------ */ 6885 .balign 64 6886.L_OP_DIV_INT_LIT8: /* 0xdb */ 6887/* File: armv5te/OP_DIV_INT_LIT8.S */ 6888/* File: armv5te/binopLit8.S */ 6889 /* 6890 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6891 * that specifies an instruction that performs "result = r0 op r1". 6892 * This could be an ARM instruction or a function call. (If the result 6893 * comes back in a register other than r0, you can override "result".) 6894 * 6895 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6896 * vCC (r1). Useful for integer division and modulus. 6897 * 6898 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6899 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6900 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6901 */ 6902 /* binop/lit8 vAA, vBB, #+CC */ 6903 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6904 mov r9, rINST, lsr #8 @ r9<- AA 6905 and r2, r3, #255 @ r2<- BB 6906 GET_VREG(r0, r2) @ r0<- vBB 6907 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6908 .if 1 6909 @cmp r1, #0 @ is second operand zero? 6910 beq common_errDivideByZero 6911 .endif 6912 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6913 6914 @ optional op; may set condition codes 6915 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6916 GET_INST_OPCODE(ip) @ extract opcode from rINST 6917 SET_VREG(r0, r9) @ vAA<- r0 6918 GOTO_OPCODE(ip) @ jump to next instruction 6919 /* 10-12 instructions */ 6920 6921 6922 6923/* ------------------------------ */ 6924 .balign 64 6925.L_OP_REM_INT_LIT8: /* 0xdc */ 6926/* File: armv5te/OP_REM_INT_LIT8.S */ 6927/* idivmod returns quotient in r0 and remainder in r1 */ 6928/* File: armv5te/binopLit8.S */ 6929 /* 6930 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6931 * that specifies an instruction that performs "result = r0 op r1". 6932 * This could be an ARM instruction or a function call. (If the result 6933 * comes back in a register other than r0, you can override "result".) 6934 * 6935 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6936 * vCC (r1). Useful for integer division and modulus. 6937 * 6938 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6939 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6940 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6941 */ 6942 /* binop/lit8 vAA, vBB, #+CC */ 6943 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6944 mov r9, rINST, lsr #8 @ r9<- AA 6945 and r2, r3, #255 @ r2<- BB 6946 GET_VREG(r0, r2) @ r0<- vBB 6947 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6948 .if 1 6949 @cmp r1, #0 @ is second operand zero? 6950 beq common_errDivideByZero 6951 .endif 6952 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6953 6954 @ optional op; may set condition codes 6955 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6956 GET_INST_OPCODE(ip) @ extract opcode from rINST 6957 SET_VREG(r1, r9) @ vAA<- r1 6958 GOTO_OPCODE(ip) @ jump to next instruction 6959 /* 10-12 instructions */ 6960 6961 6962 6963/* ------------------------------ */ 6964 .balign 64 6965.L_OP_AND_INT_LIT8: /* 0xdd */ 6966/* File: armv5te/OP_AND_INT_LIT8.S */ 6967/* File: armv5te/binopLit8.S */ 6968 /* 6969 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6970 * that specifies an instruction that performs "result = r0 op r1". 6971 * This could be an ARM instruction or a function call. (If the result 6972 * comes back in a register other than r0, you can override "result".) 6973 * 6974 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6975 * vCC (r1). Useful for integer division and modulus. 6976 * 6977 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6978 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6979 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6980 */ 6981 /* binop/lit8 vAA, vBB, #+CC */ 6982 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6983 mov r9, rINST, lsr #8 @ r9<- AA 6984 and r2, r3, #255 @ r2<- BB 6985 GET_VREG(r0, r2) @ r0<- vBB 6986 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6987 .if 0 6988 @cmp r1, #0 @ is second operand zero? 6989 beq common_errDivideByZero 6990 .endif 6991 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6992 6993 @ optional op; may set condition codes 6994 and r0, r0, r1 @ r0<- op, r0-r3 changed 6995 GET_INST_OPCODE(ip) @ extract opcode from rINST 6996 SET_VREG(r0, r9) @ vAA<- r0 6997 GOTO_OPCODE(ip) @ jump to next instruction 6998 /* 10-12 instructions */ 6999 7000 7001 7002/* ------------------------------ */ 7003 .balign 64 7004.L_OP_OR_INT_LIT8: /* 0xde */ 7005/* File: armv5te/OP_OR_INT_LIT8.S */ 7006/* File: armv5te/binopLit8.S */ 7007 /* 7008 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7009 * that specifies an instruction that performs "result = r0 op r1". 7010 * This could be an ARM instruction or a function call. (If the result 7011 * comes back in a register other than r0, you can override "result".) 7012 * 7013 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7014 * vCC (r1). Useful for integer division and modulus. 7015 * 7016 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7017 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7018 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7019 */ 7020 /* binop/lit8 vAA, vBB, #+CC */ 7021 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7022 mov r9, rINST, lsr #8 @ r9<- AA 7023 and r2, r3, #255 @ r2<- BB 7024 GET_VREG(r0, r2) @ r0<- vBB 7025 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7026 .if 0 7027 @cmp r1, #0 @ is second operand zero? 7028 beq common_errDivideByZero 7029 .endif 7030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7031 7032 @ optional op; may set condition codes 7033 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7034 GET_INST_OPCODE(ip) @ extract opcode from rINST 7035 SET_VREG(r0, r9) @ vAA<- r0 7036 GOTO_OPCODE(ip) @ jump to next instruction 7037 /* 10-12 instructions */ 7038 7039 7040 7041/* ------------------------------ */ 7042 .balign 64 7043.L_OP_XOR_INT_LIT8: /* 0xdf */ 7044/* File: armv5te/OP_XOR_INT_LIT8.S */ 7045/* File: armv5te/binopLit8.S */ 7046 /* 7047 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7048 * that specifies an instruction that performs "result = r0 op r1". 7049 * This could be an ARM instruction or a function call. (If the result 7050 * comes back in a register other than r0, you can override "result".) 7051 * 7052 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7053 * vCC (r1). Useful for integer division and modulus. 7054 * 7055 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7056 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7057 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7058 */ 7059 /* binop/lit8 vAA, vBB, #+CC */ 7060 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7061 mov r9, rINST, lsr #8 @ r9<- AA 7062 and r2, r3, #255 @ r2<- BB 7063 GET_VREG(r0, r2) @ r0<- vBB 7064 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7065 .if 0 7066 @cmp r1, #0 @ is second operand zero? 7067 beq common_errDivideByZero 7068 .endif 7069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7070 7071 @ optional op; may set condition codes 7072 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7073 GET_INST_OPCODE(ip) @ extract opcode from rINST 7074 SET_VREG(r0, r9) @ vAA<- r0 7075 GOTO_OPCODE(ip) @ jump to next instruction 7076 /* 10-12 instructions */ 7077 7078 7079 7080/* ------------------------------ */ 7081 .balign 64 7082.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7083/* File: armv5te/OP_SHL_INT_LIT8.S */ 7084/* File: armv5te/binopLit8.S */ 7085 /* 7086 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7087 * that specifies an instruction that performs "result = r0 op r1". 7088 * This could be an ARM instruction or a function call. (If the result 7089 * comes back in a register other than r0, you can override "result".) 7090 * 7091 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7092 * vCC (r1). Useful for integer division and modulus. 7093 * 7094 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7095 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7096 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7097 */ 7098 /* binop/lit8 vAA, vBB, #+CC */ 7099 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7100 mov r9, rINST, lsr #8 @ r9<- AA 7101 and r2, r3, #255 @ r2<- BB 7102 GET_VREG(r0, r2) @ r0<- vBB 7103 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7104 .if 0 7105 @cmp r1, #0 @ is second operand zero? 7106 beq common_errDivideByZero 7107 .endif 7108 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7109 7110 and r1, r1, #31 @ optional op; may set condition codes 7111 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7112 GET_INST_OPCODE(ip) @ extract opcode from rINST 7113 SET_VREG(r0, r9) @ vAA<- r0 7114 GOTO_OPCODE(ip) @ jump to next instruction 7115 /* 10-12 instructions */ 7116 7117 7118 7119/* ------------------------------ */ 7120 .balign 64 7121.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7122/* File: armv5te/OP_SHR_INT_LIT8.S */ 7123/* File: armv5te/binopLit8.S */ 7124 /* 7125 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7126 * that specifies an instruction that performs "result = r0 op r1". 7127 * This could be an ARM instruction or a function call. (If the result 7128 * comes back in a register other than r0, you can override "result".) 7129 * 7130 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7131 * vCC (r1). Useful for integer division and modulus. 7132 * 7133 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7134 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7135 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7136 */ 7137 /* binop/lit8 vAA, vBB, #+CC */ 7138 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7139 mov r9, rINST, lsr #8 @ r9<- AA 7140 and r2, r3, #255 @ r2<- BB 7141 GET_VREG(r0, r2) @ r0<- vBB 7142 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7143 .if 0 7144 @cmp r1, #0 @ is second operand zero? 7145 beq common_errDivideByZero 7146 .endif 7147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7148 7149 and r1, r1, #31 @ optional op; may set condition codes 7150 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7151 GET_INST_OPCODE(ip) @ extract opcode from rINST 7152 SET_VREG(r0, r9) @ vAA<- r0 7153 GOTO_OPCODE(ip) @ jump to next instruction 7154 /* 10-12 instructions */ 7155 7156 7157 7158/* ------------------------------ */ 7159 .balign 64 7160.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7161/* File: armv5te/OP_USHR_INT_LIT8.S */ 7162/* File: armv5te/binopLit8.S */ 7163 /* 7164 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7165 * that specifies an instruction that performs "result = r0 op r1". 7166 * This could be an ARM instruction or a function call. (If the result 7167 * comes back in a register other than r0, you can override "result".) 7168 * 7169 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7170 * vCC (r1). Useful for integer division and modulus. 7171 * 7172 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7173 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7174 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7175 */ 7176 /* binop/lit8 vAA, vBB, #+CC */ 7177 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7178 mov r9, rINST, lsr #8 @ r9<- AA 7179 and r2, r3, #255 @ r2<- BB 7180 GET_VREG(r0, r2) @ r0<- vBB 7181 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7182 .if 0 7183 @cmp r1, #0 @ is second operand zero? 7184 beq common_errDivideByZero 7185 .endif 7186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7187 7188 and r1, r1, #31 @ optional op; may set condition codes 7189 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7190 GET_INST_OPCODE(ip) @ extract opcode from rINST 7191 SET_VREG(r0, r9) @ vAA<- r0 7192 GOTO_OPCODE(ip) @ jump to next instruction 7193 /* 10-12 instructions */ 7194 7195 7196 7197/* ------------------------------ */ 7198 .balign 64 7199.L_OP_UNUSED_E3: /* 0xe3 */ 7200/* File: armv5te/OP_UNUSED_E3.S */ 7201/* File: armv5te/unused.S */ 7202 bl common_abort 7203 7204 7205 7206/* ------------------------------ */ 7207 .balign 64 7208.L_OP_UNUSED_E4: /* 0xe4 */ 7209/* File: armv5te/OP_UNUSED_E4.S */ 7210/* File: armv5te/unused.S */ 7211 bl common_abort 7212 7213 7214 7215/* ------------------------------ */ 7216 .balign 64 7217.L_OP_UNUSED_E5: /* 0xe5 */ 7218/* File: armv5te/OP_UNUSED_E5.S */ 7219/* File: armv5te/unused.S */ 7220 bl common_abort 7221 7222 7223 7224/* ------------------------------ */ 7225 .balign 64 7226.L_OP_UNUSED_E6: /* 0xe6 */ 7227/* File: armv5te/OP_UNUSED_E6.S */ 7228/* File: armv5te/unused.S */ 7229 bl common_abort 7230 7231 7232 7233/* ------------------------------ */ 7234 .balign 64 7235.L_OP_UNUSED_E7: /* 0xe7 */ 7236/* File: armv5te/OP_UNUSED_E7.S */ 7237/* File: armv5te/unused.S */ 7238 bl common_abort 7239 7240 7241 7242/* ------------------------------ */ 7243 .balign 64 7244.L_OP_UNUSED_E8: /* 0xe8 */ 7245/* File: armv5te/OP_UNUSED_E8.S */ 7246/* File: armv5te/unused.S */ 7247 bl common_abort 7248 7249 7250 7251/* ------------------------------ */ 7252 .balign 64 7253.L_OP_UNUSED_E9: /* 0xe9 */ 7254/* File: armv5te/OP_UNUSED_E9.S */ 7255/* File: armv5te/unused.S */ 7256 bl common_abort 7257 7258 7259 7260/* ------------------------------ */ 7261 .balign 64 7262.L_OP_UNUSED_EA: /* 0xea */ 7263/* File: armv5te/OP_UNUSED_EA.S */ 7264/* File: armv5te/unused.S */ 7265 bl common_abort 7266 7267 7268 7269/* ------------------------------ */ 7270 .balign 64 7271.L_OP_UNUSED_EB: /* 0xeb */ 7272/* File: armv5te/OP_UNUSED_EB.S */ 7273/* File: armv5te/unused.S */ 7274 bl common_abort 7275 7276 7277 7278/* ------------------------------ */ 7279 .balign 64 7280.L_OP_UNUSED_EC: /* 0xec */ 7281/* File: armv5te/OP_UNUSED_EC.S */ 7282/* File: armv5te/unused.S */ 7283 bl common_abort 7284 7285 7286 7287/* ------------------------------ */ 7288 .balign 64 7289.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7290/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7291 /* 7292 * Handle a throw-verification-error instruction. This throws an 7293 * exception for an error discovered during verification. The 7294 * exception is indicated by AA, with some detail provided by BBBB. 7295 */ 7296 /* op AA, ref@BBBB */ 7297 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7298 FETCH(r2, 1) @ r2<- BBBB 7299 EXPORT_PC() @ export the PC 7300 mov r1, rINST, lsr #8 @ r1<- AA 7301 bl dvmThrowVerificationError @ always throws 7302 b common_exceptionThrown @ handle exception 7303 7304 7305/* ------------------------------ */ 7306 .balign 64 7307.L_OP_EXECUTE_INLINE: /* 0xee */ 7308/* File: armv5te/OP_EXECUTE_INLINE.S */ 7309 /* 7310 * Execute a "native inline" instruction. 7311 * 7312 * We need to call: 7313 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7314 * 7315 * The first four args are in r0-r3, but the last two must be pushed 7316 * onto the stack. 7317 */ 7318 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7319 FETCH(r10, 1) @ r10<- BBBB 7320 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7321 EXPORT_PC() @ can throw 7322 sub sp, sp, #8 @ make room for arg(s) 7323 mov r0, rINST, lsr #12 @ r0<- B 7324 str r1, [sp] @ push &glue->retval 7325 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7326 add sp, sp, #8 @ pop stack 7327 cmp r0, #0 @ test boolean result of inline 7328 beq common_exceptionThrown @ returned false, handle exception 7329 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7330 GET_INST_OPCODE(ip) @ extract opcode from rINST 7331 GOTO_OPCODE(ip) @ jump to next instruction 7332 7333/* ------------------------------ */ 7334 .balign 64 7335.L_OP_UNUSED_EF: /* 0xef */ 7336/* File: armv5te/OP_UNUSED_EF.S */ 7337/* File: armv5te/unused.S */ 7338 bl common_abort 7339 7340 7341 7342/* ------------------------------ */ 7343 .balign 64 7344.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7345/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7346 /* 7347 * invoke-direct-empty is a no-op in a "standard" interpreter. 7348 */ 7349 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7350 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7351 GOTO_OPCODE(ip) @ execute it 7352 7353/* ------------------------------ */ 7354 .balign 64 7355.L_OP_UNUSED_F1: /* 0xf1 */ 7356/* File: armv5te/OP_UNUSED_F1.S */ 7357/* File: armv5te/unused.S */ 7358 bl common_abort 7359 7360 7361 7362/* ------------------------------ */ 7363 .balign 64 7364.L_OP_IGET_QUICK: /* 0xf2 */ 7365/* File: armv5te/OP_IGET_QUICK.S */ 7366 /* For: iget-quick, iget-object-quick */ 7367 /* op vA, vB, offset@CCCC */ 7368 mov r2, rINST, lsr #12 @ r2<- B 7369 GET_VREG(r3, r2) @ r3<- object we're operating on 7370 FETCH(r1, 1) @ r1<- field byte offset 7371 cmp r3, #0 @ check object for null 7372 mov r2, rINST, lsr #8 @ r2<- A(+) 7373 beq common_errNullObject @ object was null 7374 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7376 and r2, r2, #15 7377 GET_INST_OPCODE(ip) @ extract opcode from rINST 7378 SET_VREG(r0, r2) @ fp[A]<- r0 7379 GOTO_OPCODE(ip) @ jump to next instruction 7380 7381 7382/* ------------------------------ */ 7383 .balign 64 7384.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7385/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7386 /* iget-wide-quick vA, vB, offset@CCCC */ 7387 mov r2, rINST, lsr #12 @ r2<- B 7388 GET_VREG(r3, r2) @ r3<- object we're operating on 7389 FETCH(r1, 1) @ r1<- field byte offset 7390 cmp r3, #0 @ check object for null 7391 mov r2, rINST, lsr #8 @ r2<- A(+) 7392 beq common_errNullObject @ object was null 7393 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7394 and r2, r2, #15 7395 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7396 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7397 GET_INST_OPCODE(ip) @ extract opcode from rINST 7398 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7399 GOTO_OPCODE(ip) @ jump to next instruction 7400 7401 7402/* ------------------------------ */ 7403 .balign 64 7404.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7405/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7406/* File: armv5te/OP_IGET_QUICK.S */ 7407 /* For: iget-quick, iget-object-quick */ 7408 /* op vA, vB, offset@CCCC */ 7409 mov r2, rINST, lsr #12 @ r2<- B 7410 GET_VREG(r3, r2) @ r3<- object we're operating on 7411 FETCH(r1, 1) @ r1<- field byte offset 7412 cmp r3, #0 @ check object for null 7413 mov r2, rINST, lsr #8 @ r2<- A(+) 7414 beq common_errNullObject @ object was null 7415 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7416 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7417 and r2, r2, #15 7418 GET_INST_OPCODE(ip) @ extract opcode from rINST 7419 SET_VREG(r0, r2) @ fp[A]<- r0 7420 GOTO_OPCODE(ip) @ jump to next instruction 7421 7422 7423 7424/* ------------------------------ */ 7425 .balign 64 7426.L_OP_IPUT_QUICK: /* 0xf5 */ 7427/* File: armv5te/OP_IPUT_QUICK.S */ 7428 /* For: iput-quick, iput-object-quick */ 7429 /* op vA, vB, offset@CCCC */ 7430 mov r2, rINST, lsr #12 @ r2<- B 7431 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7432 FETCH(r1, 1) @ r1<- field byte offset 7433 cmp r3, #0 @ check object for null 7434 mov r2, rINST, lsr #8 @ r2<- A(+) 7435 beq common_errNullObject @ object was null 7436 and r2, r2, #15 7437 GET_VREG(r0, r2) @ r0<- fp[A] 7438 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7439 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7440 GET_INST_OPCODE(ip) @ extract opcode from rINST 7441 GOTO_OPCODE(ip) @ jump to next instruction 7442 7443 7444/* ------------------------------ */ 7445 .balign 64 7446.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7447/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7448 /* iput-wide-quick vA, vB, offset@CCCC */ 7449 mov r0, rINST, lsr #8 @ r0<- A(+) 7450 mov r1, rINST, lsr #12 @ r1<- B 7451 and r0, r0, #15 7452 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7453 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7454 cmp r2, #0 @ check object for null 7455 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7456 beq common_errNullObject @ object was null 7457 FETCH(r3, 1) @ r3<- field byte offset 7458 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7459 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7460 GET_INST_OPCODE(ip) @ extract opcode from rINST 7461 GOTO_OPCODE(ip) @ jump to next instruction 7462 7463 7464/* ------------------------------ */ 7465 .balign 64 7466.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7467/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7468/* File: armv5te/OP_IPUT_QUICK.S */ 7469 /* For: iput-quick, iput-object-quick */ 7470 /* op vA, vB, offset@CCCC */ 7471 mov r2, rINST, lsr #12 @ r2<- B 7472 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7473 FETCH(r1, 1) @ r1<- field byte offset 7474 cmp r3, #0 @ check object for null 7475 mov r2, rINST, lsr #8 @ r2<- A(+) 7476 beq common_errNullObject @ object was null 7477 and r2, r2, #15 7478 GET_VREG(r0, r2) @ r0<- fp[A] 7479 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7480 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7481 GET_INST_OPCODE(ip) @ extract opcode from rINST 7482 GOTO_OPCODE(ip) @ jump to next instruction 7483 7484 7485 7486/* ------------------------------ */ 7487 .balign 64 7488.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7489/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7490 /* 7491 * Handle an optimized virtual method call. 7492 * 7493 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7494 */ 7495 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7496 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7497 FETCH(r3, 2) @ r3<- FEDC or CCCC 7498 FETCH(r1, 1) @ r1<- BBBB 7499 .if (!0) 7500 and r3, r3, #15 @ r3<- C (or stays CCCC) 7501 .endif 7502 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7503 cmp r2, #0 @ is "this" null? 7504 beq common_errNullObject @ null "this", throw exception 7505 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7506 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7507 EXPORT_PC() @ invoke must export 7508 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7509 bl common_invokeMethodNoRange @ continue on 7510 7511/* ------------------------------ */ 7512 .balign 64 7513.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7514/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7515/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7516 /* 7517 * Handle an optimized virtual method call. 7518 * 7519 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7520 */ 7521 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7522 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7523 FETCH(r3, 2) @ r3<- FEDC or CCCC 7524 FETCH(r1, 1) @ r1<- BBBB 7525 .if (!1) 7526 and r3, r3, #15 @ r3<- C (or stays CCCC) 7527 .endif 7528 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7529 cmp r2, #0 @ is "this" null? 7530 beq common_errNullObject @ null "this", throw exception 7531 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7532 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7533 EXPORT_PC() @ invoke must export 7534 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7535 bl common_invokeMethodRange @ continue on 7536 7537 7538/* ------------------------------ */ 7539 .balign 64 7540.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7541/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7542 /* 7543 * Handle an optimized "super" method call. 7544 * 7545 * for: [opt] invoke-super-quick, invoke-super-quick/range 7546 */ 7547 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7548 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7549 FETCH(r10, 2) @ r10<- GFED or CCCC 7550 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7551 .if (!0) 7552 and r10, r10, #15 @ r10<- D (or stays CCCC) 7553 .endif 7554 FETCH(r1, 1) @ r1<- BBBB 7555 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7556 EXPORT_PC() @ must export for invoke 7557 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7558 GET_VREG(r3, r10) @ r3<- "this" 7559 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7560 cmp r3, #0 @ null "this" ref? 7561 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7562 beq common_errNullObject @ "this" is null, throw exception 7563 bl common_invokeMethodNoRange @ continue on 7564 7565 7566/* ------------------------------ */ 7567 .balign 64 7568.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7569/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7570/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7571 /* 7572 * Handle an optimized "super" method call. 7573 * 7574 * for: [opt] invoke-super-quick, invoke-super-quick/range 7575 */ 7576 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7577 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7578 FETCH(r10, 2) @ r10<- GFED or CCCC 7579 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7580 .if (!1) 7581 and r10, r10, #15 @ r10<- D (or stays CCCC) 7582 .endif 7583 FETCH(r1, 1) @ r1<- BBBB 7584 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7585 EXPORT_PC() @ must export for invoke 7586 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7587 GET_VREG(r3, r10) @ r3<- "this" 7588 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7589 cmp r3, #0 @ null "this" ref? 7590 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7591 beq common_errNullObject @ "this" is null, throw exception 7592 bl common_invokeMethodRange @ continue on 7593 7594 7595 7596/* ------------------------------ */ 7597 .balign 64 7598.L_OP_UNUSED_FC: /* 0xfc */ 7599/* File: armv5te/OP_UNUSED_FC.S */ 7600/* File: armv5te/unused.S */ 7601 bl common_abort 7602 7603 7604 7605/* ------------------------------ */ 7606 .balign 64 7607.L_OP_UNUSED_FD: /* 0xfd */ 7608/* File: armv5te/OP_UNUSED_FD.S */ 7609/* File: armv5te/unused.S */ 7610 bl common_abort 7611 7612 7613 7614/* ------------------------------ */ 7615 .balign 64 7616.L_OP_UNUSED_FE: /* 0xfe */ 7617/* File: armv5te/OP_UNUSED_FE.S */ 7618/* File: armv5te/unused.S */ 7619 bl common_abort 7620 7621 7622 7623/* ------------------------------ */ 7624 .balign 64 7625.L_OP_UNUSED_FF: /* 0xff */ 7626/* File: armv5te/OP_UNUSED_FF.S */ 7627/* File: armv5te/unused.S */ 7628 bl common_abort 7629 7630 7631 7632 7633 .balign 64 7634 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7635 .global dvmAsmInstructionEnd 7636dvmAsmInstructionEnd: 7637 7638/* 7639 * =========================================================================== 7640 * Sister implementations 7641 * =========================================================================== 7642 */ 7643 .global dvmAsmSisterStart 7644 .type dvmAsmSisterStart, %function 7645 .text 7646 .balign 4 7647dvmAsmSisterStart: 7648 7649/* continuation for OP_CONST_STRING */ 7650 7651 /* 7652 * Continuation if the String has not yet been resolved. 7653 * r1: BBBB (String ref) 7654 * r9: target register 7655 */ 7656.LOP_CONST_STRING_resolve: 7657 EXPORT_PC() 7658 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7659 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7660 bl dvmResolveString @ r0<- String reference 7661 cmp r0, #0 @ failed? 7662 beq common_exceptionThrown @ yup, handle the exception 7663 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7664 GET_INST_OPCODE(ip) @ extract opcode from rINST 7665 SET_VREG(r0, r9) @ vAA<- r0 7666 GOTO_OPCODE(ip) @ jump to next instruction 7667 7668 7669/* continuation for OP_CONST_STRING_JUMBO */ 7670 7671 /* 7672 * Continuation if the String has not yet been resolved. 7673 * r1: BBBBBBBB (String ref) 7674 * r9: target register 7675 */ 7676.LOP_CONST_STRING_JUMBO_resolve: 7677 EXPORT_PC() 7678 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7679 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7680 bl dvmResolveString @ r0<- String reference 7681 cmp r0, #0 @ failed? 7682 beq common_exceptionThrown @ yup, handle the exception 7683 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7684 GET_INST_OPCODE(ip) @ extract opcode from rINST 7685 SET_VREG(r0, r9) @ vAA<- r0 7686 GOTO_OPCODE(ip) @ jump to next instruction 7687 7688 7689/* continuation for OP_CONST_CLASS */ 7690 7691 /* 7692 * Continuation if the Class has not yet been resolved. 7693 * r1: BBBB (Class ref) 7694 * r9: target register 7695 */ 7696.LOP_CONST_CLASS_resolve: 7697 EXPORT_PC() 7698 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7699 mov r2, #1 @ r2<- true 7700 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7701 bl dvmResolveClass @ r0<- Class reference 7702 cmp r0, #0 @ failed? 7703 beq common_exceptionThrown @ yup, handle the exception 7704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7705 GET_INST_OPCODE(ip) @ extract opcode from rINST 7706 SET_VREG(r0, r9) @ vAA<- r0 7707 GOTO_OPCODE(ip) @ jump to next instruction 7708 7709 7710/* continuation for OP_CHECK_CAST */ 7711 7712 /* 7713 * Trivial test failed, need to perform full check. This is common. 7714 * r0 holds obj->clazz 7715 * r1 holds class resolved from BBBB 7716 * r9 holds object 7717 */ 7718.LOP_CHECK_CAST_fullcheck: 7719 bl dvmInstanceofNonTrivial @ r0<- boolean result 7720 cmp r0, #0 @ failed? 7721 bne .LOP_CHECK_CAST_okay @ no, success 7722 7723 @ A cast has failed. We need to throw a ClassCastException with the 7724 @ class of the object that failed to be cast. 7725 EXPORT_PC() @ about to throw 7726 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7727 ldr r0, .LstrClassCastExceptionPtr 7728 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7729 bl dvmThrowExceptionWithClassMessage 7730 b common_exceptionThrown 7731 7732 /* 7733 * Resolution required. This is the least-likely path. 7734 * 7735 * r2 holds BBBB 7736 * r9 holds object 7737 */ 7738.LOP_CHECK_CAST_resolve: 7739 EXPORT_PC() @ resolve() could throw 7740 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7741 mov r1, r2 @ r1<- BBBB 7742 mov r2, #0 @ r2<- false 7743 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7744 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7745 cmp r0, #0 @ got null? 7746 beq common_exceptionThrown @ yes, handle exception 7747 mov r1, r0 @ r1<- class resolved from BBB 7748 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7749 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7750 7751.LstrClassCastExceptionPtr: 7752 .word .LstrClassCastException 7753 7754 7755/* continuation for OP_INSTANCE_OF */ 7756 7757 /* 7758 * Trivial test failed, need to perform full check. This is common. 7759 * r0 holds obj->clazz 7760 * r1 holds class resolved from BBBB 7761 * r9 holds A 7762 */ 7763.LOP_INSTANCE_OF_fullcheck: 7764 bl dvmInstanceofNonTrivial @ r0<- boolean result 7765 @ fall through to OP_INSTANCE_OF_store 7766 7767 /* 7768 * r0 holds boolean result 7769 * r9 holds A 7770 */ 7771.LOP_INSTANCE_OF_store: 7772 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7773 SET_VREG(r0, r9) @ vA<- r0 7774 GET_INST_OPCODE(ip) @ extract opcode from rINST 7775 GOTO_OPCODE(ip) @ jump to next instruction 7776 7777 /* 7778 * Trivial test succeeded, save and bail. 7779 * r9 holds A 7780 */ 7781.LOP_INSTANCE_OF_trivial: 7782 mov r0, #1 @ indicate success 7783 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7784 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7785 SET_VREG(r0, r9) @ vA<- r0 7786 GET_INST_OPCODE(ip) @ extract opcode from rINST 7787 GOTO_OPCODE(ip) @ jump to next instruction 7788 7789 /* 7790 * Resolution required. This is the least-likely path. 7791 * 7792 * r3 holds BBBB 7793 * r9 holds A 7794 */ 7795.LOP_INSTANCE_OF_resolve: 7796 EXPORT_PC() @ resolve() could throw 7797 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7798 mov r1, r3 @ r1<- BBBB 7799 mov r2, #1 @ r2<- true 7800 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7801 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7802 cmp r0, #0 @ got null? 7803 beq common_exceptionThrown @ yes, handle exception 7804 mov r1, r0 @ r1<- class resolved from BBB 7805 mov r3, rINST, lsr #12 @ r3<- B 7806 GET_VREG(r0, r3) @ r0<- vB (object) 7807 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7808 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7809 7810 7811/* continuation for OP_NEW_INSTANCE */ 7812 7813 .balign 32 @ minimize cache lines 7814.LOP_NEW_INSTANCE_finish: @ r0=new object 7815 mov r3, rINST, lsr #8 @ r3<- AA 7816 cmp r0, #0 @ failed? 7817 beq common_exceptionThrown @ yes, handle the exception 7818 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7819 GET_INST_OPCODE(ip) @ extract opcode from rINST 7820 SET_VREG(r0, r3) @ vAA<- r0 7821 GOTO_OPCODE(ip) @ jump to next instruction 7822 7823 /* 7824 * Class initialization required. 7825 * 7826 * r0 holds class object 7827 */ 7828.LOP_NEW_INSTANCE_needinit: 7829 mov r9, r0 @ save r0 7830 bl dvmInitClass @ initialize class 7831 cmp r0, #0 @ check boolean result 7832 mov r0, r9 @ restore r0 7833 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7834 b common_exceptionThrown @ failed, deal with init exception 7835 7836 /* 7837 * Resolution required. This is the least-likely path. 7838 * 7839 * r1 holds BBBB 7840 */ 7841.LOP_NEW_INSTANCE_resolve: 7842 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7843 mov r2, #0 @ r2<- false 7844 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7845 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7846 cmp r0, #0 @ got null? 7847 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7848 b common_exceptionThrown @ yes, handle exception 7849 7850.LstrInstantiationErrorPtr: 7851 .word .LstrInstantiationError 7852 7853 7854/* continuation for OP_NEW_ARRAY */ 7855 7856 7857 /* 7858 * Resolve class. (This is an uncommon case.) 7859 * 7860 * r1 holds array length 7861 * r2 holds class ref CCCC 7862 */ 7863.LOP_NEW_ARRAY_resolve: 7864 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7865 mov r9, r1 @ r9<- length (save) 7866 mov r1, r2 @ r1<- CCCC 7867 mov r2, #0 @ r2<- false 7868 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7869 bl dvmResolveClass @ r0<- call(clazz, ref) 7870 cmp r0, #0 @ got null? 7871 mov r1, r9 @ r1<- length (restore) 7872 beq common_exceptionThrown @ yes, handle exception 7873 @ fall through to OP_NEW_ARRAY_finish 7874 7875 /* 7876 * Finish allocation. 7877 * 7878 * r0 holds class 7879 * r1 holds array length 7880 */ 7881.LOP_NEW_ARRAY_finish: 7882 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7883 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7884 cmp r0, #0 @ failed? 7885 mov r2, rINST, lsr #8 @ r2<- A+ 7886 beq common_exceptionThrown @ yes, handle the exception 7887 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7888 and r2, r2, #15 @ r2<- A 7889 GET_INST_OPCODE(ip) @ extract opcode from rINST 7890 SET_VREG(r0, r2) @ vA<- r0 7891 GOTO_OPCODE(ip) @ jump to next instruction 7892 7893 7894/* continuation for OP_FILLED_NEW_ARRAY */ 7895 7896 /* 7897 * On entry: 7898 * r0 holds array class 7899 * r10 holds AA or BA 7900 */ 7901.LOP_FILLED_NEW_ARRAY_continue: 7902 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7903 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7904 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7905 .if 0 7906 mov r1, r10 @ r1<- AA (length) 7907 .else 7908 mov r1, r10, lsr #4 @ r1<- B (length) 7909 .endif 7910 cmp r3, #'I' @ array of ints? 7911 cmpne r3, #'L' @ array of objects? 7912 cmpne r3, #'[' @ array of arrays? 7913 mov r9, r1 @ save length in r9 7914 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7915 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7916 cmp r0, #0 @ null return? 7917 beq common_exceptionThrown @ alloc failed, handle exception 7918 7919 FETCH(r1, 2) @ r1<- FEDC or CCCC 7920 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7921 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7922 subs r9, r9, #1 @ length--, check for neg 7923 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7924 bmi 2f @ was zero, bail 7925 7926 @ copy values from registers into the array 7927 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7928 .if 0 7929 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79301: ldr r3, [r2], #4 @ r3<- *r2++ 7931 subs r9, r9, #1 @ count-- 7932 str r3, [r0], #4 @ *contents++ = vX 7933 bpl 1b 7934 @ continue at 2 7935 .else 7936 cmp r9, #4 @ length was initially 5? 7937 and r2, r10, #15 @ r2<- A 7938 bne 1f @ <= 4 args, branch 7939 GET_VREG(r3, r2) @ r3<- vA 7940 sub r9, r9, #1 @ count-- 7941 str r3, [r0, #16] @ contents[4] = vA 79421: and r2, r1, #15 @ r2<- F/E/D/C 7943 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7944 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7945 subs r9, r9, #1 @ count-- 7946 str r3, [r0], #4 @ *contents++ = vX 7947 bpl 1b 7948 @ continue at 2 7949 .endif 7950 79512: 7952 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7953 GOTO_OPCODE(ip) @ execute it 7954 7955 /* 7956 * Throw an exception indicating that we have not implemented this 7957 * mode of filled-new-array. 7958 */ 7959.LOP_FILLED_NEW_ARRAY_notimpl: 7960 ldr r0, .L_strInternalError 7961 ldr r1, .L_strFilledNewArrayNotImpl 7962 bl dvmThrowException 7963 b common_exceptionThrown 7964 7965 .if (!0) @ define in one or the other, not both 7966.L_strFilledNewArrayNotImpl: 7967 .word .LstrFilledNewArrayNotImpl 7968.L_strInternalError: 7969 .word .LstrInternalError 7970 .endif 7971 7972 7973/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7974 7975 /* 7976 * On entry: 7977 * r0 holds array class 7978 * r10 holds AA or BA 7979 */ 7980.LOP_FILLED_NEW_ARRAY_RANGE_continue: 7981 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7982 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7983 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7984 .if 1 7985 mov r1, r10 @ r1<- AA (length) 7986 .else 7987 mov r1, r10, lsr #4 @ r1<- B (length) 7988 .endif 7989 cmp r3, #'I' @ array of ints? 7990 cmpne r3, #'L' @ array of objects? 7991 cmpne r3, #'[' @ array of arrays? 7992 mov r9, r1 @ save length in r9 7993 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 7994 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7995 cmp r0, #0 @ null return? 7996 beq common_exceptionThrown @ alloc failed, handle exception 7997 7998 FETCH(r1, 2) @ r1<- FEDC or CCCC 7999 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8000 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8001 subs r9, r9, #1 @ length--, check for neg 8002 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8003 bmi 2f @ was zero, bail 8004 8005 @ copy values from registers into the array 8006 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8007 .if 1 8008 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80091: ldr r3, [r2], #4 @ r3<- *r2++ 8010 subs r9, r9, #1 @ count-- 8011 str r3, [r0], #4 @ *contents++ = vX 8012 bpl 1b 8013 @ continue at 2 8014 .else 8015 cmp r9, #4 @ length was initially 5? 8016 and r2, r10, #15 @ r2<- A 8017 bne 1f @ <= 4 args, branch 8018 GET_VREG(r3, r2) @ r3<- vA 8019 sub r9, r9, #1 @ count-- 8020 str r3, [r0, #16] @ contents[4] = vA 80211: and r2, r1, #15 @ r2<- F/E/D/C 8022 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8023 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8024 subs r9, r9, #1 @ count-- 8025 str r3, [r0], #4 @ *contents++ = vX 8026 bpl 1b 8027 @ continue at 2 8028 .endif 8029 80302: 8031 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8032 GOTO_OPCODE(ip) @ execute it 8033 8034 /* 8035 * Throw an exception indicating that we have not implemented this 8036 * mode of filled-new-array. 8037 */ 8038.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8039 ldr r0, .L_strInternalError 8040 ldr r1, .L_strFilledNewArrayNotImpl 8041 bl dvmThrowException 8042 b common_exceptionThrown 8043 8044 .if (!1) @ define in one or the other, not both 8045.L_strFilledNewArrayNotImpl: 8046 .word .LstrFilledNewArrayNotImpl 8047.L_strInternalError: 8048 .word .LstrInternalError 8049 .endif 8050 8051 8052/* continuation for OP_CMPL_FLOAT */ 8053.LOP_CMPL_FLOAT_finish: 8054 SET_VREG(r0, r9) @ vAA<- r0 8055 GOTO_OPCODE(ip) @ jump to next instruction 8056 8057 8058/* continuation for OP_CMPG_FLOAT */ 8059.LOP_CMPG_FLOAT_finish: 8060 SET_VREG(r0, r9) @ vAA<- r0 8061 GOTO_OPCODE(ip) @ jump to next instruction 8062 8063 8064/* continuation for OP_CMPL_DOUBLE */ 8065.LOP_CMPL_DOUBLE_finish: 8066 SET_VREG(r0, r9) @ vAA<- r0 8067 GOTO_OPCODE(ip) @ jump to next instruction 8068 8069 8070/* continuation for OP_CMPG_DOUBLE */ 8071.LOP_CMPG_DOUBLE_finish: 8072 SET_VREG(r0, r9) @ vAA<- r0 8073 GOTO_OPCODE(ip) @ jump to next instruction 8074 8075 8076/* continuation for OP_CMP_LONG */ 8077 8078.LOP_CMP_LONG_less: 8079 mvn r1, #0 @ r1<- -1 8080 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8081 @ instead, we just replicate the tail end. 8082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8083 SET_VREG(r1, r9) @ vAA<- r1 8084 GET_INST_OPCODE(ip) @ extract opcode from rINST 8085 GOTO_OPCODE(ip) @ jump to next instruction 8086 8087.LOP_CMP_LONG_greater: 8088 mov r1, #1 @ r1<- 1 8089 @ fall through to _finish 8090 8091.LOP_CMP_LONG_finish: 8092 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8093 SET_VREG(r1, r9) @ vAA<- r1 8094 GET_INST_OPCODE(ip) @ extract opcode from rINST 8095 GOTO_OPCODE(ip) @ jump to next instruction 8096 8097 8098/* continuation for OP_AGET_WIDE */ 8099 8100.LOP_AGET_WIDE_finish: 8101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8102 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8103 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8104 GET_INST_OPCODE(ip) @ extract opcode from rINST 8105 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8106 GOTO_OPCODE(ip) @ jump to next instruction 8107 8108 8109/* continuation for OP_APUT_WIDE */ 8110 8111.LOP_APUT_WIDE_finish: 8112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8113 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8114 GET_INST_OPCODE(ip) @ extract opcode from rINST 8115 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8116 GOTO_OPCODE(ip) @ jump to next instruction 8117 8118 8119/* continuation for OP_APUT_OBJECT */ 8120 /* 8121 * On entry: 8122 * r1 = vBB (arrayObj) 8123 * r9 = vAA (obj) 8124 * r10 = offset into array (vBB + vCC * width) 8125 */ 8126.LOP_APUT_OBJECT_finish: 8127 cmp r9, #0 @ storing null reference? 8128 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8129 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8130 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8131 bl dvmCanPutArrayElement @ test object type vs. array type 8132 cmp r0, #0 @ okay? 8133 beq common_errArrayStore @ no 8134.LOP_APUT_OBJECT_skip_check: 8135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8136 GET_INST_OPCODE(ip) @ extract opcode from rINST 8137 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8138 GOTO_OPCODE(ip) @ jump to next instruction 8139 8140 8141/* continuation for OP_IGET */ 8142 8143 /* 8144 * Currently: 8145 * r0 holds resolved field 8146 * r9 holds object 8147 */ 8148.LOP_IGET_finish: 8149 @bl common_squeak0 8150 cmp r9, #0 @ check object for null 8151 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8152 beq common_errNullObject @ object was null 8153 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8154 mov r2, rINST, lsr #8 @ r2<- A+ 8155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8156 and r2, r2, #15 @ r2<- A 8157 GET_INST_OPCODE(ip) @ extract opcode from rINST 8158 SET_VREG(r0, r2) @ fp[A]<- r0 8159 GOTO_OPCODE(ip) @ jump to next instruction 8160 8161 8162/* continuation for OP_IGET_WIDE */ 8163 8164 /* 8165 * Currently: 8166 * r0 holds resolved field 8167 * r9 holds object 8168 */ 8169.LOP_IGET_WIDE_finish: 8170 cmp r9, #0 @ check object for null 8171 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8172 beq common_errNullObject @ object was null 8173 mov r2, rINST, lsr #8 @ r2<- A+ 8174 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8175 and r2, r2, #15 @ r2<- A 8176 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8177 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8178 GET_INST_OPCODE(ip) @ extract opcode from rINST 8179 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8180 GOTO_OPCODE(ip) @ jump to next instruction 8181 8182 8183/* continuation for OP_IGET_OBJECT */ 8184 8185 /* 8186 * Currently: 8187 * r0 holds resolved field 8188 * r9 holds object 8189 */ 8190.LOP_IGET_OBJECT_finish: 8191 @bl common_squeak0 8192 cmp r9, #0 @ check object for null 8193 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8194 beq common_errNullObject @ object was null 8195 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8196 mov r2, rINST, lsr #8 @ r2<- A+ 8197 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8198 and r2, r2, #15 @ r2<- A 8199 GET_INST_OPCODE(ip) @ extract opcode from rINST 8200 SET_VREG(r0, r2) @ fp[A]<- r0 8201 GOTO_OPCODE(ip) @ jump to next instruction 8202 8203 8204/* continuation for OP_IGET_BOOLEAN */ 8205 8206 /* 8207 * Currently: 8208 * r0 holds resolved field 8209 * r9 holds object 8210 */ 8211.LOP_IGET_BOOLEAN_finish: 8212 @bl common_squeak1 8213 cmp r9, #0 @ check object for null 8214 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8215 beq common_errNullObject @ object was null 8216 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8217 mov r2, rINST, lsr #8 @ r2<- A+ 8218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8219 and r2, r2, #15 @ r2<- A 8220 GET_INST_OPCODE(ip) @ extract opcode from rINST 8221 SET_VREG(r0, r2) @ fp[A]<- r0 8222 GOTO_OPCODE(ip) @ jump to next instruction 8223 8224 8225/* continuation for OP_IGET_BYTE */ 8226 8227 /* 8228 * Currently: 8229 * r0 holds resolved field 8230 * r9 holds object 8231 */ 8232.LOP_IGET_BYTE_finish: 8233 @bl common_squeak2 8234 cmp r9, #0 @ check object for null 8235 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8236 beq common_errNullObject @ object was null 8237 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8238 mov r2, rINST, lsr #8 @ r2<- A+ 8239 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8240 and r2, r2, #15 @ r2<- A 8241 GET_INST_OPCODE(ip) @ extract opcode from rINST 8242 SET_VREG(r0, r2) @ fp[A]<- r0 8243 GOTO_OPCODE(ip) @ jump to next instruction 8244 8245 8246/* continuation for OP_IGET_CHAR */ 8247 8248 /* 8249 * Currently: 8250 * r0 holds resolved field 8251 * r9 holds object 8252 */ 8253.LOP_IGET_CHAR_finish: 8254 @bl common_squeak3 8255 cmp r9, #0 @ check object for null 8256 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8257 beq common_errNullObject @ object was null 8258 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8259 mov r2, rINST, lsr #8 @ r2<- A+ 8260 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8261 and r2, r2, #15 @ r2<- A 8262 GET_INST_OPCODE(ip) @ extract opcode from rINST 8263 SET_VREG(r0, r2) @ fp[A]<- r0 8264 GOTO_OPCODE(ip) @ jump to next instruction 8265 8266 8267/* continuation for OP_IGET_SHORT */ 8268 8269 /* 8270 * Currently: 8271 * r0 holds resolved field 8272 * r9 holds object 8273 */ 8274.LOP_IGET_SHORT_finish: 8275 @bl common_squeak4 8276 cmp r9, #0 @ check object for null 8277 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8278 beq common_errNullObject @ object was null 8279 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8280 mov r2, rINST, lsr #8 @ r2<- A+ 8281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8282 and r2, r2, #15 @ r2<- A 8283 GET_INST_OPCODE(ip) @ extract opcode from rINST 8284 SET_VREG(r0, r2) @ fp[A]<- r0 8285 GOTO_OPCODE(ip) @ jump to next instruction 8286 8287 8288/* continuation for OP_IPUT */ 8289 8290 /* 8291 * Currently: 8292 * r0 holds resolved field 8293 * r9 holds object 8294 */ 8295.LOP_IPUT_finish: 8296 @bl common_squeak0 8297 mov r1, rINST, lsr #8 @ r1<- A+ 8298 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8299 and r1, r1, #15 @ r1<- A 8300 cmp r9, #0 @ check object for null 8301 GET_VREG(r0, r1) @ r0<- fp[A] 8302 beq common_errNullObject @ object was null 8303 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8304 GET_INST_OPCODE(ip) @ extract opcode from rINST 8305 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8306 GOTO_OPCODE(ip) @ jump to next instruction 8307 8308 8309/* continuation for OP_IPUT_WIDE */ 8310 8311 /* 8312 * Currently: 8313 * r0 holds resolved field 8314 * r9 holds object 8315 */ 8316.LOP_IPUT_WIDE_finish: 8317 mov r2, rINST, lsr #8 @ r2<- A+ 8318 cmp r9, #0 @ check object for null 8319 and r2, r2, #15 @ r2<- A 8320 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8321 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8322 beq common_errNullObject @ object was null 8323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8324 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8325 GET_INST_OPCODE(ip) @ extract opcode from rINST 8326 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8327 GOTO_OPCODE(ip) @ jump to next instruction 8328 8329 8330/* continuation for OP_IPUT_OBJECT */ 8331 8332 /* 8333 * Currently: 8334 * r0 holds resolved field 8335 * r9 holds object 8336 */ 8337.LOP_IPUT_OBJECT_finish: 8338 @bl common_squeak0 8339 mov r1, rINST, lsr #8 @ r1<- A+ 8340 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8341 and r1, r1, #15 @ r1<- A 8342 cmp r9, #0 @ check object for null 8343 GET_VREG(r0, r1) @ r0<- fp[A] 8344 beq common_errNullObject @ object was null 8345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8346 GET_INST_OPCODE(ip) @ extract opcode from rINST 8347 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8348 GOTO_OPCODE(ip) @ jump to next instruction 8349 8350 8351/* continuation for OP_IPUT_BOOLEAN */ 8352 8353 /* 8354 * Currently: 8355 * r0 holds resolved field 8356 * r9 holds object 8357 */ 8358.LOP_IPUT_BOOLEAN_finish: 8359 @bl common_squeak1 8360 mov r1, rINST, lsr #8 @ r1<- A+ 8361 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8362 and r1, r1, #15 @ r1<- A 8363 cmp r9, #0 @ check object for null 8364 GET_VREG(r0, r1) @ r0<- fp[A] 8365 beq common_errNullObject @ object was null 8366 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8367 GET_INST_OPCODE(ip) @ extract opcode from rINST 8368 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8369 GOTO_OPCODE(ip) @ jump to next instruction 8370 8371 8372/* continuation for OP_IPUT_BYTE */ 8373 8374 /* 8375 * Currently: 8376 * r0 holds resolved field 8377 * r9 holds object 8378 */ 8379.LOP_IPUT_BYTE_finish: 8380 @bl common_squeak2 8381 mov r1, rINST, lsr #8 @ r1<- A+ 8382 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8383 and r1, r1, #15 @ r1<- A 8384 cmp r9, #0 @ check object for null 8385 GET_VREG(r0, r1) @ r0<- fp[A] 8386 beq common_errNullObject @ object was null 8387 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8388 GET_INST_OPCODE(ip) @ extract opcode from rINST 8389 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8390 GOTO_OPCODE(ip) @ jump to next instruction 8391 8392 8393/* continuation for OP_IPUT_CHAR */ 8394 8395 /* 8396 * Currently: 8397 * r0 holds resolved field 8398 * r9 holds object 8399 */ 8400.LOP_IPUT_CHAR_finish: 8401 @bl common_squeak3 8402 mov r1, rINST, lsr #8 @ r1<- A+ 8403 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8404 and r1, r1, #15 @ r1<- A 8405 cmp r9, #0 @ check object for null 8406 GET_VREG(r0, r1) @ r0<- fp[A] 8407 beq common_errNullObject @ object was null 8408 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8409 GET_INST_OPCODE(ip) @ extract opcode from rINST 8410 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8411 GOTO_OPCODE(ip) @ jump to next instruction 8412 8413 8414/* continuation for OP_IPUT_SHORT */ 8415 8416 /* 8417 * Currently: 8418 * r0 holds resolved field 8419 * r9 holds object 8420 */ 8421.LOP_IPUT_SHORT_finish: 8422 @bl common_squeak4 8423 mov r1, rINST, lsr #8 @ r1<- A+ 8424 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8425 and r1, r1, #15 @ r1<- A 8426 cmp r9, #0 @ check object for null 8427 GET_VREG(r0, r1) @ r0<- fp[A] 8428 beq common_errNullObject @ object was null 8429 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8430 GET_INST_OPCODE(ip) @ extract opcode from rINST 8431 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8432 GOTO_OPCODE(ip) @ jump to next instruction 8433 8434 8435/* continuation for OP_SGET */ 8436 8437 /* 8438 * Continuation if the field has not yet been resolved. 8439 * r1: BBBB field ref 8440 */ 8441.LOP_SGET_resolve: 8442 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8443 EXPORT_PC() @ resolve() could throw, so export now 8444 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8445 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8446 cmp r0, #0 @ success? 8447 bne .LOP_SGET_finish @ yes, finish 8448 b common_exceptionThrown @ no, handle exception 8449 8450 8451/* continuation for OP_SGET_WIDE */ 8452 8453 /* 8454 * Continuation if the field has not yet been resolved. 8455 * r1: BBBB field ref 8456 */ 8457.LOP_SGET_WIDE_resolve: 8458 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8459 EXPORT_PC() @ resolve() could throw, so export now 8460 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8461 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8462 cmp r0, #0 @ success? 8463 bne .LOP_SGET_WIDE_finish @ yes, finish 8464 b common_exceptionThrown @ no, handle exception 8465 8466 8467/* continuation for OP_SGET_OBJECT */ 8468 8469 /* 8470 * Continuation if the field has not yet been resolved. 8471 * r1: BBBB field ref 8472 */ 8473.LOP_SGET_OBJECT_resolve: 8474 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8475 EXPORT_PC() @ resolve() could throw, so export now 8476 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8477 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8478 cmp r0, #0 @ success? 8479 bne .LOP_SGET_OBJECT_finish @ yes, finish 8480 b common_exceptionThrown @ no, handle exception 8481 8482 8483/* continuation for OP_SGET_BOOLEAN */ 8484 8485 /* 8486 * Continuation if the field has not yet been resolved. 8487 * r1: BBBB field ref 8488 */ 8489.LOP_SGET_BOOLEAN_resolve: 8490 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8491 EXPORT_PC() @ resolve() could throw, so export now 8492 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8493 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8494 cmp r0, #0 @ success? 8495 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8496 b common_exceptionThrown @ no, handle exception 8497 8498 8499/* continuation for OP_SGET_BYTE */ 8500 8501 /* 8502 * Continuation if the field has not yet been resolved. 8503 * r1: BBBB field ref 8504 */ 8505.LOP_SGET_BYTE_resolve: 8506 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8507 EXPORT_PC() @ resolve() could throw, so export now 8508 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8509 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8510 cmp r0, #0 @ success? 8511 bne .LOP_SGET_BYTE_finish @ yes, finish 8512 b common_exceptionThrown @ no, handle exception 8513 8514 8515/* continuation for OP_SGET_CHAR */ 8516 8517 /* 8518 * Continuation if the field has not yet been resolved. 8519 * r1: BBBB field ref 8520 */ 8521.LOP_SGET_CHAR_resolve: 8522 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8523 EXPORT_PC() @ resolve() could throw, so export now 8524 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8525 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8526 cmp r0, #0 @ success? 8527 bne .LOP_SGET_CHAR_finish @ yes, finish 8528 b common_exceptionThrown @ no, handle exception 8529 8530 8531/* continuation for OP_SGET_SHORT */ 8532 8533 /* 8534 * Continuation if the field has not yet been resolved. 8535 * r1: BBBB field ref 8536 */ 8537.LOP_SGET_SHORT_resolve: 8538 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8539 EXPORT_PC() @ resolve() could throw, so export now 8540 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8541 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8542 cmp r0, #0 @ success? 8543 bne .LOP_SGET_SHORT_finish @ yes, finish 8544 b common_exceptionThrown @ no, handle exception 8545 8546 8547/* continuation for OP_SPUT */ 8548 8549 /* 8550 * Continuation if the field has not yet been resolved. 8551 * r1: BBBB field ref 8552 */ 8553.LOP_SPUT_resolve: 8554 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8555 EXPORT_PC() @ resolve() could throw, so export now 8556 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8557 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8558 cmp r0, #0 @ success? 8559 bne .LOP_SPUT_finish @ yes, finish 8560 b common_exceptionThrown @ no, handle exception 8561 8562 8563/* continuation for OP_SPUT_WIDE */ 8564 8565 /* 8566 * Continuation if the field has not yet been resolved. 8567 * r1: BBBB field ref 8568 * r9: &fp[AA] 8569 */ 8570.LOP_SPUT_WIDE_resolve: 8571 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8572 EXPORT_PC() @ resolve() could throw, so export now 8573 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8574 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8575 cmp r0, #0 @ success? 8576 bne .LOP_SPUT_WIDE_finish @ yes, finish 8577 b common_exceptionThrown @ no, handle exception 8578 8579 8580/* continuation for OP_SPUT_OBJECT */ 8581 8582 /* 8583 * Continuation if the field has not yet been resolved. 8584 * r1: BBBB field ref 8585 */ 8586.LOP_SPUT_OBJECT_resolve: 8587 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8588 EXPORT_PC() @ resolve() could throw, so export now 8589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8590 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8591 cmp r0, #0 @ success? 8592 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8593 b common_exceptionThrown @ no, handle exception 8594 8595 8596/* continuation for OP_SPUT_BOOLEAN */ 8597 8598 /* 8599 * Continuation if the field has not yet been resolved. 8600 * r1: BBBB field ref 8601 */ 8602.LOP_SPUT_BOOLEAN_resolve: 8603 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8604 EXPORT_PC() @ resolve() could throw, so export now 8605 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8606 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8607 cmp r0, #0 @ success? 8608 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8609 b common_exceptionThrown @ no, handle exception 8610 8611 8612/* continuation for OP_SPUT_BYTE */ 8613 8614 /* 8615 * Continuation if the field has not yet been resolved. 8616 * r1: BBBB field ref 8617 */ 8618.LOP_SPUT_BYTE_resolve: 8619 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8620 EXPORT_PC() @ resolve() could throw, so export now 8621 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8622 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8623 cmp r0, #0 @ success? 8624 bne .LOP_SPUT_BYTE_finish @ yes, finish 8625 b common_exceptionThrown @ no, handle exception 8626 8627 8628/* continuation for OP_SPUT_CHAR */ 8629 8630 /* 8631 * Continuation if the field has not yet been resolved. 8632 * r1: BBBB field ref 8633 */ 8634.LOP_SPUT_CHAR_resolve: 8635 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8636 EXPORT_PC() @ resolve() could throw, so export now 8637 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8638 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8639 cmp r0, #0 @ success? 8640 bne .LOP_SPUT_CHAR_finish @ yes, finish 8641 b common_exceptionThrown @ no, handle exception 8642 8643 8644/* continuation for OP_SPUT_SHORT */ 8645 8646 /* 8647 * Continuation if the field has not yet been resolved. 8648 * r1: BBBB field ref 8649 */ 8650.LOP_SPUT_SHORT_resolve: 8651 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8652 EXPORT_PC() @ resolve() could throw, so export now 8653 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8654 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8655 cmp r0, #0 @ success? 8656 bne .LOP_SPUT_SHORT_finish @ yes, finish 8657 b common_exceptionThrown @ no, handle exception 8658 8659 8660/* continuation for OP_INVOKE_VIRTUAL */ 8661 8662 /* 8663 * At this point: 8664 * r0 = resolved base method 8665 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8666 */ 8667.LOP_INVOKE_VIRTUAL_continue: 8668 GET_VREG(r1, r10) @ r1<- "this" ptr 8669 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8670 cmp r1, #0 @ is "this" null? 8671 beq common_errNullObject @ null "this", throw exception 8672 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8673 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8674 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8675 bl common_invokeMethodNoRange @ continue on 8676 8677 8678/* continuation for OP_INVOKE_SUPER */ 8679 8680 /* 8681 * At this point: 8682 * r0 = resolved base method 8683 * r9 = method->clazz 8684 */ 8685.LOP_INVOKE_SUPER_continue: 8686 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8687 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8688 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8689 EXPORT_PC() @ must export for invoke 8690 cmp r2, r3 @ compare (methodIndex, vtableCount) 8691 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8692 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8693 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8694 bl common_invokeMethodNoRange @ continue on 8695 8696.LOP_INVOKE_SUPER_resolve: 8697 mov r0, r9 @ r0<- method->clazz 8698 mov r2, #METHOD_VIRTUAL @ resolver method type 8699 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8700 cmp r0, #0 @ got null? 8701 bne .LOP_INVOKE_SUPER_continue @ no, continue 8702 b common_exceptionThrown @ yes, handle exception 8703 8704 /* 8705 * Throw a NoSuchMethodError with the method name as the message. 8706 * r0 = resolved base method 8707 */ 8708.LOP_INVOKE_SUPER_nsm: 8709 ldr r1, [r0, #offMethod_name] @ r1<- method name 8710 b common_errNoSuchMethod 8711 8712 8713/* continuation for OP_INVOKE_DIRECT */ 8714 8715 /* 8716 * On entry: 8717 * r1 = reference (BBBB or CCCC) 8718 * r10 = "this" register 8719 */ 8720.LOP_INVOKE_DIRECT_resolve: 8721 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8722 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8723 mov r2, #METHOD_DIRECT @ resolver method type 8724 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8725 cmp r0, #0 @ got null? 8726 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8727 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8728 b common_exceptionThrown @ yes, handle exception 8729 8730 8731/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8732 8733 /* 8734 * At this point: 8735 * r0 = resolved base method 8736 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8737 */ 8738.LOP_INVOKE_VIRTUAL_RANGE_continue: 8739 GET_VREG(r1, r10) @ r1<- "this" ptr 8740 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8741 cmp r1, #0 @ is "this" null? 8742 beq common_errNullObject @ null "this", throw exception 8743 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8744 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8745 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8746 bl common_invokeMethodRange @ continue on 8747 8748 8749/* continuation for OP_INVOKE_SUPER_RANGE */ 8750 8751 /* 8752 * At this point: 8753 * r0 = resolved base method 8754 * r9 = method->clazz 8755 */ 8756.LOP_INVOKE_SUPER_RANGE_continue: 8757 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8758 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8759 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8760 EXPORT_PC() @ must export for invoke 8761 cmp r2, r3 @ compare (methodIndex, vtableCount) 8762 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8763 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8764 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8765 bl common_invokeMethodRange @ continue on 8766 8767.LOP_INVOKE_SUPER_RANGE_resolve: 8768 mov r0, r9 @ r0<- method->clazz 8769 mov r2, #METHOD_VIRTUAL @ resolver method type 8770 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8771 cmp r0, #0 @ got null? 8772 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8773 b common_exceptionThrown @ yes, handle exception 8774 8775 /* 8776 * Throw a NoSuchMethodError with the method name as the message. 8777 * r0 = resolved base method 8778 */ 8779.LOP_INVOKE_SUPER_RANGE_nsm: 8780 ldr r1, [r0, #offMethod_name] @ r1<- method name 8781 b common_errNoSuchMethod 8782 8783 8784/* continuation for OP_INVOKE_DIRECT_RANGE */ 8785 8786 /* 8787 * On entry: 8788 * r1 = reference (BBBB or CCCC) 8789 * r10 = "this" register 8790 */ 8791.LOP_INVOKE_DIRECT_RANGE_resolve: 8792 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8793 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8794 mov r2, #METHOD_DIRECT @ resolver method type 8795 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8796 cmp r0, #0 @ got null? 8797 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8798 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8799 b common_exceptionThrown @ yes, handle exception 8800 8801 8802/* continuation for OP_FLOAT_TO_LONG */ 8803/* 8804 * Convert the float in r0 to a long in r0/r1. 8805 * 8806 * We have to clip values to long min/max per the specification. The 8807 * expected common case is a "reasonable" value that converts directly 8808 * to modest integer. The EABI convert function isn't doing this for us. 8809 */ 8810f2l_doconv: 8811 stmfd sp!, {r4, lr} 8812 mov r1, #0x5f000000 @ (float)maxlong 8813 mov r4, r0 8814 bl __aeabi_fcmpge @ is arg >= maxlong? 8815 cmp r0, #0 @ nonzero == yes 8816 mvnne r0, #0 @ return maxlong (7fffffff) 8817 mvnne r1, #0x80000000 8818 ldmnefd sp!, {r4, pc} 8819 8820 mov r0, r4 @ recover arg 8821 mov r1, #0xdf000000 @ (float)minlong 8822 bl __aeabi_fcmple @ is arg <= minlong? 8823 cmp r0, #0 @ nonzero == yes 8824 movne r0, #0 @ return minlong (80000000) 8825 movne r1, #0x80000000 8826 ldmnefd sp!, {r4, pc} 8827 8828 mov r0, r4 @ recover arg 8829 mov r1, r4 8830 bl __aeabi_fcmpeq @ is arg == self? 8831 cmp r0, #0 @ zero == no 8832 moveq r1, #0 @ return zero for NaN 8833 ldmeqfd sp!, {r4, pc} 8834 8835 mov r0, r4 @ recover arg 8836 bl __aeabi_f2lz @ convert float to long 8837 ldmfd sp!, {r4, pc} 8838 8839 8840/* continuation for OP_DOUBLE_TO_LONG */ 8841/* 8842 * Convert the double in r0/r1 to a long in r0/r1. 8843 * 8844 * We have to clip values to long min/max per the specification. The 8845 * expected common case is a "reasonable" value that converts directly 8846 * to modest integer. The EABI convert function isn't doing this for us. 8847 */ 8848d2l_doconv: 8849 stmfd sp!, {r4, r5, lr} @ save regs 8850 mov r3, #0x43000000 @ maxlong, as a double (high word) 8851 add r3, #0x00e00000 @ 0x43e00000 8852 mov r2, #0 @ maxlong, as a double (low word) 8853 sub sp, sp, #4 @ align for EABI 8854 mov r4, r0 @ save a copy of r0 8855 mov r5, r1 @ and r1 8856 bl __aeabi_dcmpge @ is arg >= maxlong? 8857 cmp r0, #0 @ nonzero == yes 8858 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8859 mvnne r1, #0x80000000 8860 bne 1f 8861 8862 mov r0, r4 @ recover arg 8863 mov r1, r5 8864 mov r3, #0xc3000000 @ minlong, as a double (high word) 8865 add r3, #0x00e00000 @ 0xc3e00000 8866 mov r2, #0 @ minlong, as a double (low word) 8867 bl __aeabi_dcmple @ is arg <= minlong? 8868 cmp r0, #0 @ nonzero == yes 8869 movne r0, #0 @ return minlong (8000000000000000) 8870 movne r1, #0x80000000 8871 bne 1f 8872 8873 mov r0, r4 @ recover arg 8874 mov r1, r5 8875 mov r2, r4 @ compare against self 8876 mov r3, r5 8877 bl __aeabi_dcmpeq @ is arg == self? 8878 cmp r0, #0 @ zero == no 8879 moveq r1, #0 @ return zero for NaN 8880 beq 1f 8881 8882 mov r0, r4 @ recover arg 8883 mov r1, r5 8884 bl __aeabi_d2lz @ convert double to long 8885 88861: 8887 add sp, sp, #4 8888 ldmfd sp!, {r4, r5, pc} 8889 8890 8891/* continuation for OP_MUL_LONG */ 8892 8893.LOP_MUL_LONG_finish: 8894 GET_INST_OPCODE(ip) @ extract opcode from rINST 8895 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8896 GOTO_OPCODE(ip) @ jump to next instruction 8897 8898 8899/* continuation for OP_SHL_LONG */ 8900 8901.LOP_SHL_LONG_finish: 8902 mov r0, r0, asl r2 @ r0<- r0 << r2 8903 GET_INST_OPCODE(ip) @ extract opcode from rINST 8904 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8905 GOTO_OPCODE(ip) @ jump to next instruction 8906 8907 8908/* continuation for OP_SHR_LONG */ 8909 8910.LOP_SHR_LONG_finish: 8911 mov r1, r1, asr r2 @ r1<- r1 >> r2 8912 GET_INST_OPCODE(ip) @ extract opcode from rINST 8913 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8914 GOTO_OPCODE(ip) @ jump to next instruction 8915 8916 8917/* continuation for OP_USHR_LONG */ 8918 8919.LOP_USHR_LONG_finish: 8920 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8921 GET_INST_OPCODE(ip) @ extract opcode from rINST 8922 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8923 GOTO_OPCODE(ip) @ jump to next instruction 8924 8925 8926/* continuation for OP_SHL_LONG_2ADDR */ 8927 8928.LOP_SHL_LONG_2ADDR_finish: 8929 GET_INST_OPCODE(ip) @ extract opcode from rINST 8930 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8931 GOTO_OPCODE(ip) @ jump to next instruction 8932 8933 8934/* continuation for OP_SHR_LONG_2ADDR */ 8935 8936.LOP_SHR_LONG_2ADDR_finish: 8937 GET_INST_OPCODE(ip) @ extract opcode from rINST 8938 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8939 GOTO_OPCODE(ip) @ jump to next instruction 8940 8941 8942/* continuation for OP_USHR_LONG_2ADDR */ 8943 8944.LOP_USHR_LONG_2ADDR_finish: 8945 GET_INST_OPCODE(ip) @ extract opcode from rINST 8946 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8947 GOTO_OPCODE(ip) @ jump to next instruction 8948 8949 8950/* continuation for OP_EXECUTE_INLINE */ 8951 8952 /* 8953 * Extract args, call function. 8954 * r0 = #of args (0-4) 8955 * r10 = call index 8956 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8957 * 8958 * Other ideas: 8959 * - Use a jump table from the main piece to jump directly into the 8960 * AND/LDR pairs. Costs a data load, saves a branch. 8961 * - Have five separate pieces that do the loading, so we can work the 8962 * interleave a little better. Increases code size. 8963 */ 8964.LOP_EXECUTE_INLINE_continue: 8965 rsb r0, r0, #4 @ r0<- 4-r0 8966 FETCH(r9, 2) @ r9<- FEDC 8967 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8968 bl common_abort @ (skipped due to ARM prefetch) 89694: and ip, r9, #0xf000 @ isolate F 8970 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89713: and ip, r9, #0x0f00 @ isolate E 8972 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 89732: and ip, r9, #0x00f0 @ isolate D 8974 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 89751: and ip, r9, #0x000f @ isolate C 8976 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 89770: 8978 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 8979 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 8980 @ (not reached) 8981 8982.LOP_EXECUTE_INLINE_table: 8983 .word gDvmInlineOpsTable 8984 8985 8986 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8987 .global dvmAsmSisterEnd 8988dvmAsmSisterEnd: 8989 8990/* File: armv5te/footer.S */ 8991 8992/* 8993 * =========================================================================== 8994 * Common subroutines and data 8995 * =========================================================================== 8996 */ 8997 8998 8999 9000 .text 9001 .align 2 9002 9003#if defined(WITH_JIT) 9004#if defined(WITH_SELF_VERIFICATION) 9005 .global dvmJitToInterpPunt 9006dvmJitToInterpPunt: 9007 mov r2,#kSVSPunt @ r2<- interpreter entry point 9008 b dvmJitSelfVerificationEnd @ doesn't return 9009 9010 .global dvmJitToInterpSingleStep 9011dvmJitToInterpSingleStep: 9012 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9013 b dvmJitSelfVerificationEnd @ doesn't return 9014 9015 .global dvmJitToTraceSelect 9016dvmJitToTraceSelect: 9017 ldr r0,[r14, #-1] @ pass our target PC 9018 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9019 b dvmJitSelfVerificationEnd @ doesn't return 9020 9021 .global dvmJitToBackwardBranch 9022dvmJitToBackwardBranch: 9023 ldr r0,[r14, #-1] @ pass our target PC 9024 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9025 b dvmJitSelfVerificationEnd @ doesn't return 9026 9027 .global dvmJitToInterpNormal 9028dvmJitToInterpNormal: 9029 ldr r0,[r14, #-1] @ pass our target PC 9030 mov r2,#kSVSNormal @ r2<- interpreter entry point 9031 b dvmJitSelfVerificationEnd @ doesn't return 9032 9033 .global dvmJitToInterpNoChain 9034dvmJitToInterpNoChain: 9035 mov r0,rPC @ pass our target PC 9036 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9037 b dvmJitSelfVerificationEnd @ doesn't return 9038#else 9039/* 9040 * Return from the translation cache to the interpreter when the compiler is 9041 * having issues translating/executing a Dalvik instruction. We have to skip 9042 * the code cache lookup otherwise it is possible to indefinitely bouce 9043 * between the interpreter and the code cache if the instruction that fails 9044 * to be compiled happens to be at a trace start. 9045 */ 9046 .global dvmJitToInterpPunt 9047dvmJitToInterpPunt: 9048 mov rPC, r0 9049#ifdef EXIT_STATS 9050 mov r0,lr 9051 bl dvmBumpPunt; 9052#endif 9053 EXPORT_PC() 9054 adrl rIBASE, dvmAsmInstructionStart 9055 FETCH_INST() 9056 GET_INST_OPCODE(ip) 9057 GOTO_OPCODE(ip) 9058 9059/* 9060 * Return to the interpreter to handle a single instruction. 9061 * On entry: 9062 * r0 <= PC 9063 * r1 <= PC of resume instruction 9064 * lr <= resume point in translation 9065 */ 9066 .global dvmJitToInterpSingleStep 9067dvmJitToInterpSingleStep: 9068 str lr,[rGLUE,#offGlue_jitResume] 9069 str r1,[rGLUE,#offGlue_jitResumePC] 9070 mov r1,#kInterpEntryInstr 9071 @ enum is 4 byte in aapcs-EABI 9072 str r1, [rGLUE, #offGlue_entryPoint] 9073 mov rPC,r0 9074 EXPORT_PC() 9075 adrl rIBASE, dvmAsmInstructionStart 9076 mov r2,#kJitSingleStep @ Ask for single step and then revert 9077 str r2,[rGLUE,#offGlue_jitState] 9078 mov r1,#1 @ set changeInterp to bail to debug interp 9079 b common_gotoBail 9080 9081 9082/* 9083 * Return from the translation cache and immediately request 9084 * a translation for the exit target. Commonly used following 9085 * invokes. 9086 */ 9087 .global dvmJitToTraceSelect 9088dvmJitToTraceSelect: 9089 ldr rPC,[r14, #-1] @ get our target PC 9090 add rINST,r14,#-5 @ save start of chain branch 9091 mov r0,rPC 9092 bl dvmJitGetCodeAddr @ Is there a translation? 9093 cmp r0,#0 9094 beq 2f 9095 mov r1,rINST 9096 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9097 cmp r0,#0 @ successful chain? 9098 bxne r0 @ continue native execution 9099 b toInterpreter @ didn't chain - resume with interpreter 9100 9101/* No translation, so request one if profiling isn't disabled*/ 91022: 9103 adrl rIBASE, dvmAsmInstructionStart 9104 GET_JIT_PROF_TABLE(r0) 9105 FETCH_INST() 9106 cmp r0, #0 9107 bne common_selectTrace 9108 GET_INST_OPCODE(ip) 9109 GOTO_OPCODE(ip) 9110 9111/* 9112 * Return from the translation cache to the interpreter. 9113 * The return was done with a BLX from thumb mode, and 9114 * the following 32-bit word contains the target rPC value. 9115 * Note that lr (r14) will have its low-order bit set to denote 9116 * its thumb-mode origin. 9117 * 9118 * We'll need to stash our lr origin away, recover the new 9119 * target and then check to see if there is a translation available 9120 * for our new target. If so, we do a translation chain and 9121 * go back to native execution. Otherwise, it's back to the 9122 * interpreter (after treating this entry as a potential 9123 * trace start). 9124 */ 9125 .global dvmJitToInterpNormal 9126dvmJitToInterpNormal: 9127 ldr rPC,[r14, #-1] @ get our target PC 9128 add rINST,r14,#-5 @ save start of chain branch 9129#ifdef EXIT_STATS 9130 bl dvmBumpNormal 9131#endif 9132 mov r0,rPC 9133 bl dvmJitGetCodeAddr @ Is there a translation? 9134 cmp r0,#0 9135 beq toInterpreter @ go if not, otherwise do chain 9136 mov r1,rINST 9137 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9138 cmp r0,#0 @ successful chain? 9139 bxne r0 @ continue native execution 9140 b toInterpreter @ didn't chain - resume with interpreter 9141 9142/* 9143 * Return from the translation cache to the interpreter to do method invocation. 9144 * Check if translation exists for the callee, but don't chain to it. 9145 */ 9146 .global dvmJitToInterpNoChain 9147dvmJitToInterpNoChain: 9148#ifdef EXIT_STATS 9149 bl dvmBumpNoChain 9150#endif 9151 mov r0,rPC 9152 bl dvmJitGetCodeAddr @ Is there a translation? 9153 cmp r0,#0 9154 bxne r0 @ continue native execution if so 9155#endif 9156 9157/* 9158 * No translation, restore interpreter regs and start interpreting. 9159 * rGLUE & rFP were preserved in the translated code, and rPC has 9160 * already been restored by the time we get here. We'll need to set 9161 * up rIBASE & rINST, and load the address of the JitTable into r0. 9162 */ 9163toInterpreter: 9164 EXPORT_PC() 9165 adrl rIBASE, dvmAsmInstructionStart 9166 FETCH_INST() 9167 GET_JIT_PROF_TABLE(r0) 9168 @ NOTE: intended fallthrough 9169/* 9170 * Common code to update potential trace start counter, and initiate 9171 * a trace-build if appropriate. On entry, rPC should point to the 9172 * next instruction to execute, and rINST should be already loaded with 9173 * the next opcode word, and r0 holds a pointer to the jit profile 9174 * table (pJitProfTable). 9175 */ 9176common_testUpdateProfile: 9177 cmp r0,#0 9178 GET_INST_OPCODE(ip) 9179 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9180 9181common_updateProfile: 9182 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9183 lsl r3,r3,#23 @ shift out excess 511 9184 ldrb r1,[r0,r3,lsr #23] @ get counter 9185 GET_INST_OPCODE(ip) 9186 subs r1,r1,#1 @ decrement counter 9187 strb r1,[r0,r3,lsr #23] @ and store it 9188 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9189 9190/* 9191 * Here, we switch to the debug interpreter to request 9192 * trace selection. First, though, check to see if there 9193 * is already a native translation in place (and, if so, 9194 * jump to it now). 9195 */ 9196 mov r1,#255 9197 strb r1,[r0,r3,lsr #23] @ reset counter 9198 EXPORT_PC() 9199 mov r0,rPC 9200 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9201 cmp r0,#0 9202 beq common_selectTrace 9203#if !defined(WITH_SELF_VERIFICATION) 9204 bxne r0 @ jump to the translation 9205#else 9206 bne dvmJitSelfVerificationStart @ set up self verification 9207#endif 9208common_selectTrace: 9209 mov r2,#kJitTSelectRequest @ ask for trace selection 9210 str r2,[rGLUE,#offGlue_jitState] 9211 mov r2,#kInterpEntryInstr @ normal entry reason 9212 str r2,[rGLUE,#offGlue_entryPoint] 9213 mov r1,#1 @ set changeInterp 9214 b common_gotoBail 9215 9216#if defined(WITH_SELF_VERIFICATION) 9217/* 9218 * Save PC and registers to shadow memory for self verification mode 9219 * before jumping to native translation. 9220 */ 9221dvmJitSelfVerificationStart: 9222 mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC) 9223 mov r0,rPC @ r0<- program counter 9224 mov r1,rFP @ r1<- frame pointer 9225 mov r2,rGLUE @ r2<- InterpState pointer 9226 bl dvmSelfVerificationSaveState @ save registers to shadow space 9227 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9228 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9229 bx r10 @ jump to the translation 9230 9231/* 9232 * Restore PC, registers, and interpState to original values 9233 * before jumping back to the interpreter. 9234 */ 9235dvmJitSelfVerificationEnd: 9236 mov r1,rFP @ pass ending fp 9237 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9238 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9239 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9240 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9241 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9242 cmp r1,#0 @ check for punt condition 9243 beq 1f 9244 mov r2,#kJitSelfVerification @ ask for self verification 9245 str r2,[rGLUE,#offGlue_jitState] 9246 mov r2,#kInterpEntryInstr @ normal entry reason 9247 str r2,[rGLUE,#offGlue_entryPoint] 9248 mov r1,#1 @ set changeInterp 9249 b common_gotoBail 9250 92511: @ exit to interpreter without check 9252 EXPORT_PC() 9253 adrl rIBASE, dvmAsmInstructionStart 9254 FETCH_INST() 9255 GET_INST_OPCODE(ip) 9256 GOTO_OPCODE(ip) 9257#endif 9258 9259#endif 9260 9261/* 9262 * Common code when a backward branch is taken. 9263 * 9264 * On entry: 9265 * r9 is PC adjustment *in bytes* 9266 */ 9267common_backwardBranch: 9268 mov r0, #kInterpEntryInstr 9269 bl common_periodicChecks 9270#if defined(WITH_JIT) 9271 GET_JIT_PROF_TABLE(r0) 9272 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9273 cmp r0,#0 9274 bne common_updateProfile 9275 GET_INST_OPCODE(ip) 9276 GOTO_OPCODE(ip) 9277#else 9278 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9279 GET_INST_OPCODE(ip) @ extract opcode from rINST 9280 GOTO_OPCODE(ip) @ jump to next instruction 9281#endif 9282 9283 9284/* 9285 * Need to see if the thread needs to be suspended or debugger/profiler 9286 * activity has begun. 9287 * 9288 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9289 * have to do the second ldr. 9290 * 9291 * TODO: reduce this so we're just checking a single location. 9292 * 9293 * On entry: 9294 * r0 is reentry type, e.g. kInterpEntryInstr 9295 * r9 is trampoline PC adjustment *in bytes* 9296 */ 9297common_periodicChecks: 9298 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9299 9300 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9301 str r0, [rGLUE, #offGlue_entryPoint] 9302 9303#if defined(WITH_DEBUGGER) 9304 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9305#endif 9306#if defined(WITH_PROFILER) 9307 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9308#endif 9309 9310 ldr r3, [r3] @ r3<- suspendCount (int) 9311 9312#if defined(WITH_DEBUGGER) 9313 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9314#endif 9315#if defined (WITH_PROFILER) 9316 ldr r2, [r2] @ r2<- activeProfilers (int) 9317#endif 9318 9319 cmp r3, #0 @ suspend pending? 9320 bne 2f @ yes, do full suspension check 9321 9322#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9323# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9324 orrs r1, r1, r2 @ r1<- r1 | r2 9325 cmp r1, #0 @ debugger attached or profiler started? 9326# elif defined(WITH_DEBUGGER) 9327 cmp r1, #0 @ debugger attached? 9328# elif defined(WITH_PROFILER) 9329 cmp r2, #0 @ profiler started? 9330# endif 9331 bne 3f @ debugger/profiler, switch interp 9332#endif 9333 9334 bx lr @ nothing to do, return 9335 93362: @ check suspend 9337 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9338 EXPORT_PC() @ need for precise GC 9339 b dvmCheckSuspendPending @ suspend if necessary, then return 9340 93413: @ debugger/profiler enabled, bail out 9342 add rPC, rPC, r9 @ update rPC 9343 mov r1, #1 @ "want switch" = true 9344 b common_gotoBail 9345 9346 9347/* 9348 * The equivalent of "goto bail", this calls through the "bail handler". 9349 * 9350 * State registers will be saved to the "glue" area before bailing. 9351 * 9352 * On entry: 9353 * r1 is "bool changeInterp", indicating if we want to switch to the 9354 * other interpreter or just bail all the way out 9355 */ 9356common_gotoBail: 9357 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9358 mov r0, rGLUE @ r0<- glue ptr 9359 b dvmMterpStdBail @ call(glue, changeInterp) 9360 9361 @add r1, r1, #1 @ using (boolean+1) 9362 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9363 @bl _longjmp @ does not return 9364 @bl common_abort 9365 9366 9367/* 9368 * Common code for method invocation with range. 9369 * 9370 * On entry: 9371 * r0 is "Method* methodToCall", the method we're trying to call 9372 */ 9373common_invokeMethodRange: 9374.LinvokeNewRange: 9375 @ prepare to copy args to "outs" area of current frame 9376 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9377 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9378 beq .LinvokeArgsDone @ if no args, skip the rest 9379 FETCH(r1, 2) @ r1<- CCCC 9380 9381 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9382 @ (very few methods have > 10 args; could unroll for common cases) 9383 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9384 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9385 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 93861: ldr r1, [r3], #4 @ val = *fp++ 9387 subs r2, r2, #1 @ count-- 9388 str r1, [r10], #4 @ *outs++ = val 9389 bne 1b @ ...while count != 0 9390 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9391 b .LinvokeArgsDone 9392 9393/* 9394 * Common code for method invocation without range. 9395 * 9396 * On entry: 9397 * r0 is "Method* methodToCall", the method we're trying to call 9398 */ 9399common_invokeMethodNoRange: 9400.LinvokeNewNoRange: 9401 @ prepare to copy args to "outs" area of current frame 9402 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9403 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9404 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9405 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9406 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9407 beq .LinvokeArgsDone 9408 9409 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9410.LinvokeNonRange: 9411 rsb r2, r2, #5 @ r2<- 5-r2 9412 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9413 bl common_abort @ (skipped due to ARM prefetch) 94145: and ip, rINST, #0x0f00 @ isolate A 9415 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9416 mov r0, r0 @ nop 9417 str r2, [r10, #-4]! @ *--outs = vA 94184: and ip, r1, #0xf000 @ isolate G 9419 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9420 mov r0, r0 @ nop 9421 str r2, [r10, #-4]! @ *--outs = vG 94223: and ip, r1, #0x0f00 @ isolate F 9423 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9424 mov r0, r0 @ nop 9425 str r2, [r10, #-4]! @ *--outs = vF 94262: and ip, r1, #0x00f0 @ isolate E 9427 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9428 mov r0, r0 @ nop 9429 str r2, [r10, #-4]! @ *--outs = vE 94301: and ip, r1, #0x000f @ isolate D 9431 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9432 mov r0, r0 @ nop 9433 str r2, [r10, #-4]! @ *--outs = vD 94340: @ fall through to .LinvokeArgsDone 9435 9436.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9437 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9438 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9439 @ find space for the new stack frame, check for overflow 9440 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9441 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9442 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9443@ bl common_dumpRegs 9444 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9445 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9446 cmp r3, r9 @ bottom < interpStackEnd? 9447 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9448 blt .LstackOverflow @ yes, this frame will overflow stack 9449 9450 @ set up newSaveArea 9451#ifdef EASY_GDB 9452 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9453 str ip, [r10, #offStackSaveArea_prevSave] 9454#endif 9455 str rFP, [r10, #offStackSaveArea_prevFrame] 9456 str rPC, [r10, #offStackSaveArea_savedPc] 9457#if defined(WITH_JIT) 9458 mov r9, #0 9459 str r9, [r10, #offStackSaveArea_returnAddr] 9460#endif 9461 str r0, [r10, #offStackSaveArea_method] 9462 tst r3, #ACC_NATIVE 9463 bne .LinvokeNative 9464 9465 /* 9466 stmfd sp!, {r0-r3} 9467 bl common_printNewline 9468 mov r0, rFP 9469 mov r1, #0 9470 bl dvmDumpFp 9471 ldmfd sp!, {r0-r3} 9472 stmfd sp!, {r0-r3} 9473 mov r0, r1 9474 mov r1, r10 9475 bl dvmDumpFp 9476 bl common_printNewline 9477 ldmfd sp!, {r0-r3} 9478 */ 9479 9480 ldrh r9, [r2] @ r9 <- load INST from new PC 9481 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9482 mov rPC, r2 @ publish new rPC 9483 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9484 9485 @ Update "glue" values for the new method 9486 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9487 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9488 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9489#if defined(WITH_JIT) 9490 GET_JIT_PROF_TABLE(r0) 9491 mov rFP, r1 @ fp = newFp 9492 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9493 mov rINST, r9 @ publish new rINST 9494 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9495 cmp r0,#0 9496 bne common_updateProfile 9497 GOTO_OPCODE(ip) @ jump to next instruction 9498#else 9499 mov rFP, r1 @ fp = newFp 9500 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9501 mov rINST, r9 @ publish new rINST 9502 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9503 GOTO_OPCODE(ip) @ jump to next instruction 9504#endif 9505 9506.LinvokeNative: 9507 @ Prep for the native call 9508 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9509 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9510 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9511 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9512 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9513 mov r9, r3 @ r9<- glue->self (preserve) 9514 9515 mov r2, r0 @ r2<- methodToCall 9516 mov r0, r1 @ r0<- newFp (points to args) 9517 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9518 9519#ifdef ASSIST_DEBUGGER 9520 /* insert fake function header to help gdb find the stack frame */ 9521 b .Lskip 9522 .type dalvik_mterp, %function 9523dalvik_mterp: 9524 .fnstart 9525 MTERP_ENTRY1 9526 MTERP_ENTRY2 9527.Lskip: 9528#endif 9529 9530 @mov lr, pc @ set return addr 9531 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9532 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9533 9534 @ native return; r9=self, r10=newSaveArea 9535 @ equivalent to dvmPopJniLocals 9536 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9537 ldr r1, [r9, #offThread_exception] @ check for exception 9538 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9539 cmp r1, #0 @ null? 9540 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9541 bne common_exceptionThrown @ no, handle exception 9542 9543 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9544 GET_INST_OPCODE(ip) @ extract opcode from rINST 9545 GOTO_OPCODE(ip) @ jump to next instruction 9546 9547.LstackOverflow: @ r0=methodToCall 9548 mov r1, r0 @ r1<- methodToCall 9549 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9550 bl dvmHandleStackOverflow 9551 b common_exceptionThrown 9552#ifdef ASSIST_DEBUGGER 9553 .fnend 9554#endif 9555 9556 9557 /* 9558 * Common code for method invocation, calling through "glue code". 9559 * 9560 * TODO: now that we have range and non-range invoke handlers, this 9561 * needs to be split into two. Maybe just create entry points 9562 * that set r9 and jump here? 9563 * 9564 * On entry: 9565 * r0 is "Method* methodToCall", the method we're trying to call 9566 * r9 is "bool methodCallRange", indicating if this is a /range variant 9567 */ 9568 .if 0 9569.LinvokeOld: 9570 sub sp, sp, #8 @ space for args + pad 9571 FETCH(ip, 2) @ ip<- FEDC or CCCC 9572 mov r2, r0 @ A2<- methodToCall 9573 mov r0, rGLUE @ A0<- glue 9574 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9575 mov r1, r9 @ A1<- methodCallRange 9576 mov r3, rINST, lsr #8 @ A3<- AA 9577 str ip, [sp, #0] @ A4<- ip 9578 bl dvmMterp_invokeMethod @ call the C invokeMethod 9579 add sp, sp, #8 @ remove arg area 9580 b common_resumeAfterGlueCall @ continue to next instruction 9581 .endif 9582 9583 9584 9585/* 9586 * Common code for handling a return instruction. 9587 * 9588 * This does not return. 9589 */ 9590common_returnFromMethod: 9591.LreturnNew: 9592 mov r0, #kInterpEntryReturn 9593 mov r9, #0 9594 bl common_periodicChecks 9595 9596 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9597 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9598 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9599 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9600 @ r2<- method we're returning to 9601 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9602 cmp r2, #0 @ is this a break frame? 9603 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9604 mov r1, #0 @ "want switch" = false 9605 beq common_gotoBail @ break frame, bail out completely 9606 9607 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9608 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9609 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9610 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9611#if defined(WITH_JIT) 9612 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr 9613 GET_JIT_PROF_TABLE(r0) 9614 mov rPC, r9 @ publish new rPC 9615 str r1, [rGLUE, #offGlue_methodClassDex] 9616 cmp r3, #0 @ caller is compiled code 9617 blxne r3 9618 GET_INST_OPCODE(ip) @ extract opcode from rINST 9619 cmp r0,#0 9620 bne common_updateProfile 9621 GOTO_OPCODE(ip) @ jump to next instruction 9622#else 9623 GET_INST_OPCODE(ip) @ extract opcode from rINST 9624 mov rPC, r9 @ publish new rPC 9625 str r1, [rGLUE, #offGlue_methodClassDex] 9626 GOTO_OPCODE(ip) @ jump to next instruction 9627#endif 9628 9629 /* 9630 * Return handling, calls through "glue code". 9631 */ 9632 .if 0 9633.LreturnOld: 9634 SAVE_PC_FP_TO_GLUE() @ export state 9635 mov r0, rGLUE @ arg to function 9636 bl dvmMterp_returnFromMethod 9637 b common_resumeAfterGlueCall 9638 .endif 9639 9640 9641/* 9642 * Somebody has thrown an exception. Handle it. 9643 * 9644 * If the exception processing code returns to us (instead of falling 9645 * out of the interpreter), continue with whatever the next instruction 9646 * now happens to be. 9647 * 9648 * This does not return. 9649 */ 9650 .global dvmMterpCommonExceptionThrown 9651dvmMterpCommonExceptionThrown: 9652common_exceptionThrown: 9653.LexceptionNew: 9654 mov r0, #kInterpEntryThrow 9655 mov r9, #0 9656 bl common_periodicChecks 9657 9658#if defined(WITH_JIT) 9659 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9660 str r2,[rGLUE,#offGlue_jitState] 9661#endif 9662 9663 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9664 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9665 mov r1, r10 @ r1<- self 9666 mov r0, r9 @ r0<- exception 9667 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9668 mov r3, #0 @ r3<- NULL 9669 str r3, [r10, #offThread_exception] @ self->exception = NULL 9670 9671 /* set up args and a local for "&fp" */ 9672 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9673 str rFP, [sp, #-4]! @ *--sp = fp 9674 mov ip, sp @ ip<- &fp 9675 mov r3, #0 @ r3<- false 9676 str ip, [sp, #-4]! @ *--sp = &fp 9677 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9678 mov r0, r10 @ r0<- self 9679 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9680 mov r2, r9 @ r2<- exception 9681 sub r1, rPC, r1 @ r1<- pc - method->insns 9682 mov r1, r1, asr #1 @ r1<- offset in code units 9683 9684 /* call, r0 gets catchRelPc (a code-unit offset) */ 9685 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9686 9687 /* fix earlier stack overflow if necessary; may trash rFP */ 9688 ldrb r1, [r10, #offThread_stackOverflowed] 9689 cmp r1, #0 @ did we overflow earlier? 9690 beq 1f @ no, skip ahead 9691 mov rFP, r0 @ save relPc result in rFP 9692 mov r0, r10 @ r0<- self 9693 bl dvmCleanupStackOverflow @ call(self) 9694 mov r0, rFP @ restore result 96951: 9696 9697 /* update frame pointer and check result from dvmFindCatchBlock */ 9698 ldr rFP, [sp, #4] @ retrieve the updated rFP 9699 cmp r0, #0 @ is catchRelPc < 0? 9700 add sp, sp, #8 @ restore stack 9701 bmi .LnotCaughtLocally 9702 9703 /* adjust locals to match self->curFrame and updated PC */ 9704 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9705 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9706 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9707 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9708 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9709 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9710 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9711 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9712 9713 /* release the tracked alloc on the exception */ 9714 mov r0, r9 @ r0<- exception 9715 mov r1, r10 @ r1<- self 9716 bl dvmReleaseTrackedAlloc @ release the exception 9717 9718 /* restore the exception if the handler wants it */ 9719 FETCH_INST() @ load rINST from rPC 9720 GET_INST_OPCODE(ip) @ extract opcode from rINST 9721 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9722 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9723 GOTO_OPCODE(ip) @ jump to next instruction 9724 9725.LnotCaughtLocally: @ r9=exception, r10=self 9726 /* fix stack overflow if necessary */ 9727 ldrb r1, [r10, #offThread_stackOverflowed] 9728 cmp r1, #0 @ did we overflow earlier? 9729 movne r0, r10 @ if yes: r0<- self 9730 blne dvmCleanupStackOverflow @ if yes: call(self) 9731 9732 @ may want to show "not caught locally" debug messages here 9733#if DVM_SHOW_EXCEPTION >= 2 9734 /* call __android_log_print(prio, tag, format, ...) */ 9735 /* "Exception %s from %s:%d not caught locally" */ 9736 @ dvmLineNumFromPC(method, pc - method->insns) 9737 ldr r0, [rGLUE, #offGlue_method] 9738 ldr r1, [r0, #offMethod_insns] 9739 sub r1, rPC, r1 9740 asr r1, r1, #1 9741 bl dvmLineNumFromPC 9742 str r0, [sp, #-4]! 9743 @ dvmGetMethodSourceFile(method) 9744 ldr r0, [rGLUE, #offGlue_method] 9745 bl dvmGetMethodSourceFile 9746 str r0, [sp, #-4]! 9747 @ exception->clazz->descriptor 9748 ldr r3, [r9, #offObject_clazz] 9749 ldr r3, [r3, #offClassObject_descriptor] 9750 @ 9751 ldr r2, strExceptionNotCaughtLocally 9752 ldr r1, strLogTag 9753 mov r0, #3 @ LOG_DEBUG 9754 bl __android_log_print 9755#endif 9756 str r9, [r10, #offThread_exception] @ restore exception 9757 mov r0, r9 @ r0<- exception 9758 mov r1, r10 @ r1<- self 9759 bl dvmReleaseTrackedAlloc @ release the exception 9760 mov r1, #0 @ "want switch" = false 9761 b common_gotoBail @ bail out 9762 9763 9764 /* 9765 * Exception handling, calls through "glue code". 9766 */ 9767 .if 0 9768.LexceptionOld: 9769 SAVE_PC_FP_TO_GLUE() @ export state 9770 mov r0, rGLUE @ arg to function 9771 bl dvmMterp_exceptionThrown 9772 b common_resumeAfterGlueCall 9773 .endif 9774 9775 9776/* 9777 * After returning from a "glued" function, pull out the updated 9778 * values and start executing at the next instruction. 9779 */ 9780common_resumeAfterGlueCall: 9781 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9782 FETCH_INST() @ load rINST from rPC 9783 GET_INST_OPCODE(ip) @ extract opcode from rINST 9784 GOTO_OPCODE(ip) @ jump to next instruction 9785 9786/* 9787 * Invalid array index. 9788 */ 9789common_errArrayIndex: 9790 EXPORT_PC() 9791 ldr r0, strArrayIndexException 9792 mov r1, #0 9793 bl dvmThrowException 9794 b common_exceptionThrown 9795 9796/* 9797 * Invalid array value. 9798 */ 9799common_errArrayStore: 9800 EXPORT_PC() 9801 ldr r0, strArrayStoreException 9802 mov r1, #0 9803 bl dvmThrowException 9804 b common_exceptionThrown 9805 9806/* 9807 * Integer divide or mod by zero. 9808 */ 9809common_errDivideByZero: 9810 EXPORT_PC() 9811 ldr r0, strArithmeticException 9812 ldr r1, strDivideByZero 9813 bl dvmThrowException 9814 b common_exceptionThrown 9815 9816/* 9817 * Attempt to allocate an array with a negative size. 9818 */ 9819common_errNegativeArraySize: 9820 EXPORT_PC() 9821 ldr r0, strNegativeArraySizeException 9822 mov r1, #0 9823 bl dvmThrowException 9824 b common_exceptionThrown 9825 9826/* 9827 * Invocation of a non-existent method. 9828 */ 9829common_errNoSuchMethod: 9830 EXPORT_PC() 9831 ldr r0, strNoSuchMethodError 9832 mov r1, #0 9833 bl dvmThrowException 9834 b common_exceptionThrown 9835 9836/* 9837 * We encountered a null object when we weren't expecting one. We 9838 * export the PC, throw a NullPointerException, and goto the exception 9839 * processing code. 9840 */ 9841common_errNullObject: 9842 EXPORT_PC() 9843 ldr r0, strNullPointerException 9844 mov r1, #0 9845 bl dvmThrowException 9846 b common_exceptionThrown 9847 9848/* 9849 * For debugging, cause an immediate fault. The source address will 9850 * be in lr (use a bl instruction to jump here). 9851 */ 9852common_abort: 9853 ldr pc, .LdeadFood 9854.LdeadFood: 9855 .word 0xdeadf00d 9856 9857/* 9858 * Spit out a "we were here", preserving all registers. (The attempt 9859 * to save ip won't work, but we need to save an even number of 9860 * registers for EABI 64-bit stack alignment.) 9861 */ 9862 .macro SQUEAK num 9863common_squeak\num: 9864 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9865 ldr r0, strSqueak 9866 mov r1, #\num 9867 bl printf 9868 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9869 bx lr 9870 .endm 9871 9872 SQUEAK 0 9873 SQUEAK 1 9874 SQUEAK 2 9875 SQUEAK 3 9876 SQUEAK 4 9877 SQUEAK 5 9878 9879/* 9880 * Spit out the number in r0, preserving registers. 9881 */ 9882common_printNum: 9883 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9884 mov r1, r0 9885 ldr r0, strSqueak 9886 bl printf 9887 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9888 bx lr 9889 9890/* 9891 * Print a newline, preserving registers. 9892 */ 9893common_printNewline: 9894 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9895 ldr r0, strNewline 9896 bl printf 9897 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9898 bx lr 9899 9900 /* 9901 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9902 */ 9903common_printHex: 9904 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9905 mov r1, r0 9906 ldr r0, strPrintHex 9907 bl printf 9908 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9909 bx lr 9910 9911/* 9912 * Print the 64-bit quantity in r0-r1, preserving registers. 9913 */ 9914common_printLong: 9915 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9916 mov r3, r1 9917 mov r2, r0 9918 ldr r0, strPrintLong 9919 bl printf 9920 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9921 bx lr 9922 9923/* 9924 * Print full method info. Pass the Method* in r0. Preserves regs. 9925 */ 9926common_printMethod: 9927 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9928 bl dvmMterpPrintMethod 9929 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9930 bx lr 9931 9932/* 9933 * Call a C helper function that dumps regs and possibly some 9934 * additional info. Requires the C function to be compiled in. 9935 */ 9936 .if 0 9937common_dumpRegs: 9938 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9939 bl dvmMterpDumpArmRegs 9940 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9941 bx lr 9942 .endif 9943 9944#if 0 9945/* 9946 * Experiment on VFP mode. 9947 * 9948 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 9949 * 9950 * Updates the bits specified by "mask", setting them to the values in "val". 9951 */ 9952setFPSCR: 9953 and r0, r0, r1 @ make sure no stray bits are set 9954 fmrx r2, fpscr @ get VFP reg 9955 mvn r1, r1 @ bit-invert mask 9956 and r2, r2, r1 @ clear masked bits 9957 orr r2, r2, r0 @ set specified bits 9958 fmxr fpscr, r2 @ set VFP reg 9959 mov r0, r2 @ return new value 9960 bx lr 9961 9962 .align 2 9963 .global dvmConfigureFP 9964 .type dvmConfigureFP, %function 9965dvmConfigureFP: 9966 stmfd sp!, {ip, lr} 9967 /* 0x03000000 sets DN/FZ */ 9968 /* 0x00009f00 clears the six exception enable flags */ 9969 bl common_squeak0 9970 mov r0, #0x03000000 @ r0<- 0x03000000 9971 add r1, r0, #0x9f00 @ r1<- 0x03009f00 9972 bl setFPSCR 9973 ldmfd sp!, {ip, pc} 9974#endif 9975 9976 9977/* 9978 * String references, must be close to the code that uses them. 9979 */ 9980 .align 2 9981strArithmeticException: 9982 .word .LstrArithmeticException 9983strArrayIndexException: 9984 .word .LstrArrayIndexException 9985strArrayStoreException: 9986 .word .LstrArrayStoreException 9987strDivideByZero: 9988 .word .LstrDivideByZero 9989strNegativeArraySizeException: 9990 .word .LstrNegativeArraySizeException 9991strNoSuchMethodError: 9992 .word .LstrNoSuchMethodError 9993strNullPointerException: 9994 .word .LstrNullPointerException 9995 9996strLogTag: 9997 .word .LstrLogTag 9998strExceptionNotCaughtLocally: 9999 .word .LstrExceptionNotCaughtLocally 10000 10001strNewline: 10002 .word .LstrNewline 10003strSqueak: 10004 .word .LstrSqueak 10005strPrintHex: 10006 .word .LstrPrintHex 10007strPrintLong: 10008 .word .LstrPrintLong 10009 10010/* 10011 * Zero-terminated ASCII string data. 10012 * 10013 * On ARM we have two choices: do like gcc does, and LDR from a .word 10014 * with the address, or use an ADR pseudo-op to get the address 10015 * directly. ADR saves 4 bytes and an indirection, but it's using a 10016 * PC-relative addressing mode and hence has a limited range, which 10017 * makes it not work well with mergeable string sections. 10018 */ 10019 .section .rodata.str1.4,"aMS",%progbits,1 10020 10021.LstrBadEntryPoint: 10022 .asciz "Bad entry point %d\n" 10023.LstrArithmeticException: 10024 .asciz "Ljava/lang/ArithmeticException;" 10025.LstrArrayIndexException: 10026 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10027.LstrArrayStoreException: 10028 .asciz "Ljava/lang/ArrayStoreException;" 10029.LstrClassCastException: 10030 .asciz "Ljava/lang/ClassCastException;" 10031.LstrDivideByZero: 10032 .asciz "divide by zero" 10033.LstrFilledNewArrayNotImpl: 10034 .asciz "filled-new-array only implemented for objects and 'int'" 10035.LstrInternalError: 10036 .asciz "Ljava/lang/InternalError;" 10037.LstrInstantiationError: 10038 .asciz "Ljava/lang/InstantiationError;" 10039.LstrNegativeArraySizeException: 10040 .asciz "Ljava/lang/NegativeArraySizeException;" 10041.LstrNoSuchMethodError: 10042 .asciz "Ljava/lang/NoSuchMethodError;" 10043.LstrNullPointerException: 10044 .asciz "Ljava/lang/NullPointerException;" 10045 10046.LstrLogTag: 10047 .asciz "mterp" 10048.LstrExceptionNotCaughtLocally: 10049 .asciz "Exception %s from %s:%d not caught locally\n" 10050 10051.LstrNewline: 10052 .asciz "\n" 10053.LstrSqueak: 10054 .asciz "<%d>" 10055.LstrPrintHex: 10056 .asciz "<0x%x>" 10057.LstrPrintLong: 10058 .asciz "<%lld>" 10059 10060 10061