InterpAsm-armv5te-vfp.S revision 9797a237b48e880c33e2a2f497f48fb6f67c7a16
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204 205/* File: armv5te/platform.S */ 206/* 207 * =========================================================================== 208 * CPU-version-specific defines 209 * =========================================================================== 210 */ 211 212/* 213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 214 * one-way branch. 215 * 216 * May modify IP. Does not modify LR. 217 */ 218.macro LDR_PC source 219 ldr pc, \source 220.endm 221 222/* 223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 224 * Jump to subroutine. 225 * 226 * May modify IP and LR. 227 */ 228.macro LDR_PC_LR source 229 mov lr, pc 230 ldr pc, \source 231.endm 232 233/* 234 * Macro for "LDMFD SP!, {...regs...,PC}". 235 * 236 * May modify IP and LR. 237 */ 238.macro LDMFD_PC regs 239 ldmfd sp!, {\regs,pc} 240.endm 241 242 243/* File: armv5te/entry.S */ 244/* 245 * Copyright (C) 2008 The Android Open Source Project 246 * 247 * Licensed under the Apache License, Version 2.0 (the "License"); 248 * you may not use this file except in compliance with the License. 249 * You may obtain a copy of the License at 250 * 251 * http://www.apache.org/licenses/LICENSE-2.0 252 * 253 * Unless required by applicable law or agreed to in writing, software 254 * distributed under the License is distributed on an "AS IS" BASIS, 255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 256 * See the License for the specific language governing permissions and 257 * limitations under the License. 258 */ 259/* 260 * Interpreter entry point. 261 */ 262 263/* 264 * We don't have formal stack frames, so gdb scans upward in the code 265 * to find the start of the function (a label with the %function type), 266 * and then looks at the next few instructions to figure out what 267 * got pushed onto the stack. From this it figures out how to restore 268 * the registers, including PC, for the previous stack frame. If gdb 269 * sees a non-function label, it stops scanning, so either we need to 270 * have nothing but assembler-local labels between the entry point and 271 * the break, or we need to fake it out. 272 * 273 * When this is defined, we add some stuff to make gdb less confused. 274 */ 275#define ASSIST_DEBUGGER 1 276 277 .text 278 .align 2 279 .global dvmMterpStdRun 280 .type dvmMterpStdRun, %function 281 282/* 283 * On entry: 284 * r0 MterpGlue* glue 285 * 286 * This function returns a boolean "changeInterp" value. The return comes 287 * via a call to dvmMterpStdBail(). 288 */ 289dvmMterpStdRun: 290#define MTERP_ENTRY1 \ 291 .save {r4-r10,fp,lr}; \ 292 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 293#define MTERP_ENTRY2 \ 294 .pad #4; \ 295 sub sp, sp, #4 @ align 64 296 297 .fnstart 298 MTERP_ENTRY1 299 MTERP_ENTRY2 300 301 /* save stack pointer, add magic word for debuggerd */ 302 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 303 304 /* set up "named" registers, figure out entry point */ 305 mov rGLUE, r0 @ set rGLUE 306 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 307 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 308 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 309 cmp r1, #kInterpEntryInstr @ usual case? 310 bne .Lnot_instr @ no, handle it 311 312#if defined(WITH_JIT) 313.Lno_singleStep: 314 /* 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_BREAKPOINT: /* 0xec */ 7281/* File: armv5te/OP_BREAKPOINT.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 an InlineOp4Func: 7313 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7314 * 7315 * The first four args are in r0-r3, pointer to return value storage 7316 * is on the stack. The function's return value is a flag that tells 7317 * us if an exception was thrown. 7318 */ 7319 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7320 FETCH(r10, 1) @ r10<- BBBB 7321 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7322 EXPORT_PC() @ can throw 7323 sub sp, sp, #8 @ make room for arg, +64 bit align 7324 mov r0, rINST, lsr #12 @ r0<- B 7325 str r1, [sp] @ push &glue->retval 7326 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7327 add sp, sp, #8 @ pop stack 7328 cmp r0, #0 @ test boolean result of inline 7329 beq common_exceptionThrown @ returned false, handle exception 7330 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7331 GET_INST_OPCODE(ip) @ extract opcode from rINST 7332 GOTO_OPCODE(ip) @ jump to next instruction 7333 7334/* ------------------------------ */ 7335 .balign 64 7336.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7337/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7338 /* 7339 * Execute a "native inline" instruction, using "/range" semantics. 7340 * Same idea as execute-inline, but we get the args differently. 7341 * 7342 * We need to call an InlineOp4Func: 7343 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7344 * 7345 * The first four args are in r0-r3, pointer to return value storage 7346 * is on the stack. The function's return value is a flag that tells 7347 * us if an exception was thrown. 7348 */ 7349 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7350 FETCH(r10, 1) @ r10<- BBBB 7351 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7352 EXPORT_PC() @ can throw 7353 sub sp, sp, #8 @ make room for arg, +64 bit align 7354 mov r0, rINST, lsr #8 @ r0<- AA 7355 str r1, [sp] @ push &glue->retval 7356 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7357 add sp, sp, #8 @ pop stack 7358 cmp r0, #0 @ test boolean result of inline 7359 beq common_exceptionThrown @ returned false, handle exception 7360 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7361 GET_INST_OPCODE(ip) @ extract opcode from rINST 7362 GOTO_OPCODE(ip) @ jump to next instruction 7363 7364/* ------------------------------ */ 7365 .balign 64 7366.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7367/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7368 /* 7369 * invoke-direct-empty is a no-op in a "standard" interpreter. 7370 */ 7371 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7372 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7373 GOTO_OPCODE(ip) @ execute it 7374 7375/* ------------------------------ */ 7376 .balign 64 7377.L_OP_UNUSED_F1: /* 0xf1 */ 7378/* File: armv5te/OP_UNUSED_F1.S */ 7379/* File: armv5te/unused.S */ 7380 bl common_abort 7381 7382 7383 7384/* ------------------------------ */ 7385 .balign 64 7386.L_OP_IGET_QUICK: /* 0xf2 */ 7387/* File: armv5te/OP_IGET_QUICK.S */ 7388 /* For: iget-quick, iget-object-quick */ 7389 /* op vA, vB, offset@CCCC */ 7390 mov r2, rINST, lsr #12 @ r2<- B 7391 GET_VREG(r3, r2) @ r3<- object we're operating on 7392 FETCH(r1, 1) @ r1<- field byte offset 7393 cmp r3, #0 @ check object for null 7394 mov r2, rINST, lsr #8 @ r2<- A(+) 7395 beq common_errNullObject @ object was null 7396 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7397 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7398 and r2, r2, #15 7399 GET_INST_OPCODE(ip) @ extract opcode from rINST 7400 SET_VREG(r0, r2) @ fp[A]<- r0 7401 GOTO_OPCODE(ip) @ jump to next instruction 7402 7403 7404/* ------------------------------ */ 7405 .balign 64 7406.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7407/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7408 /* iget-wide-quick 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 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7416 and r2, r2, #15 7417 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7418 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7419 GET_INST_OPCODE(ip) @ extract opcode from rINST 7420 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7421 GOTO_OPCODE(ip) @ jump to next instruction 7422 7423 7424/* ------------------------------ */ 7425 .balign 64 7426.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7427/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7428/* File: armv5te/OP_IGET_QUICK.S */ 7429 /* For: iget-quick, iget-object-quick */ 7430 /* op vA, vB, offset@CCCC */ 7431 mov r2, rINST, lsr #12 @ r2<- B 7432 GET_VREG(r3, r2) @ r3<- object we're operating on 7433 FETCH(r1, 1) @ r1<- field byte offset 7434 cmp r3, #0 @ check object for null 7435 mov r2, rINST, lsr #8 @ r2<- A(+) 7436 beq common_errNullObject @ object was null 7437 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7438 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7439 and r2, r2, #15 7440 GET_INST_OPCODE(ip) @ extract opcode from rINST 7441 SET_VREG(r0, r2) @ fp[A]<- r0 7442 GOTO_OPCODE(ip) @ jump to next instruction 7443 7444 7445 7446/* ------------------------------ */ 7447 .balign 64 7448.L_OP_IPUT_QUICK: /* 0xf5 */ 7449/* File: armv5te/OP_IPUT_QUICK.S */ 7450 /* For: iput-quick, iput-object-quick */ 7451 /* op vA, vB, offset@CCCC */ 7452 mov r2, rINST, lsr #12 @ r2<- B 7453 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7454 FETCH(r1, 1) @ r1<- field byte offset 7455 cmp r3, #0 @ check object for null 7456 mov r2, rINST, lsr #8 @ r2<- A(+) 7457 beq common_errNullObject @ object was null 7458 and r2, r2, #15 7459 GET_VREG(r0, r2) @ r0<- fp[A] 7460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7461 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7462 GET_INST_OPCODE(ip) @ extract opcode from rINST 7463 GOTO_OPCODE(ip) @ jump to next instruction 7464 7465 7466/* ------------------------------ */ 7467 .balign 64 7468.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7469/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7470 /* iput-wide-quick vA, vB, offset@CCCC */ 7471 mov r0, rINST, lsr #8 @ r0<- A(+) 7472 mov r1, rINST, lsr #12 @ r1<- B 7473 and r0, r0, #15 7474 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7475 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7476 cmp r2, #0 @ check object for null 7477 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7478 beq common_errNullObject @ object was null 7479 FETCH(r3, 1) @ r3<- field byte offset 7480 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7481 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7482 GET_INST_OPCODE(ip) @ extract opcode from rINST 7483 GOTO_OPCODE(ip) @ jump to next instruction 7484 7485 7486/* ------------------------------ */ 7487 .balign 64 7488.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7489/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7490/* File: armv5te/OP_IPUT_QUICK.S */ 7491 /* For: iput-quick, iput-object-quick */ 7492 /* op vA, vB, offset@CCCC */ 7493 mov r2, rINST, lsr #12 @ r2<- B 7494 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7495 FETCH(r1, 1) @ r1<- field byte offset 7496 cmp r3, #0 @ check object for null 7497 mov r2, rINST, lsr #8 @ r2<- A(+) 7498 beq common_errNullObject @ object was null 7499 and r2, r2, #15 7500 GET_VREG(r0, r2) @ r0<- fp[A] 7501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7502 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7503 GET_INST_OPCODE(ip) @ extract opcode from rINST 7504 GOTO_OPCODE(ip) @ jump to next instruction 7505 7506 7507 7508/* ------------------------------ */ 7509 .balign 64 7510.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7511/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7512 /* 7513 * Handle an optimized virtual method call. 7514 * 7515 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7516 */ 7517 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7518 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7519 FETCH(r3, 2) @ r3<- FEDC or CCCC 7520 FETCH(r1, 1) @ r1<- BBBB 7521 .if (!0) 7522 and r3, r3, #15 @ r3<- C (or stays CCCC) 7523 .endif 7524 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7525 cmp r2, #0 @ is "this" null? 7526 beq common_errNullObject @ null "this", throw exception 7527 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7528 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7529 EXPORT_PC() @ invoke must export 7530 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7531 bl common_invokeMethodNoRange @ continue on 7532 7533/* ------------------------------ */ 7534 .balign 64 7535.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7536/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7537/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7538 /* 7539 * Handle an optimized virtual method call. 7540 * 7541 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7542 */ 7543 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7544 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7545 FETCH(r3, 2) @ r3<- FEDC or CCCC 7546 FETCH(r1, 1) @ r1<- BBBB 7547 .if (!1) 7548 and r3, r3, #15 @ r3<- C (or stays CCCC) 7549 .endif 7550 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7551 cmp r2, #0 @ is "this" null? 7552 beq common_errNullObject @ null "this", throw exception 7553 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7554 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7555 EXPORT_PC() @ invoke must export 7556 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7557 bl common_invokeMethodRange @ continue on 7558 7559 7560/* ------------------------------ */ 7561 .balign 64 7562.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7563/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7564 /* 7565 * Handle an optimized "super" method call. 7566 * 7567 * for: [opt] invoke-super-quick, invoke-super-quick/range 7568 */ 7569 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7570 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7571 FETCH(r10, 2) @ r10<- GFED or CCCC 7572 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7573 .if (!0) 7574 and r10, r10, #15 @ r10<- D (or stays CCCC) 7575 .endif 7576 FETCH(r1, 1) @ r1<- BBBB 7577 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7578 EXPORT_PC() @ must export for invoke 7579 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7580 GET_VREG(r3, r10) @ r3<- "this" 7581 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7582 cmp r3, #0 @ null "this" ref? 7583 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7584 beq common_errNullObject @ "this" is null, throw exception 7585 bl common_invokeMethodNoRange @ continue on 7586 7587 7588/* ------------------------------ */ 7589 .balign 64 7590.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7591/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7592/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7593 /* 7594 * Handle an optimized "super" method call. 7595 * 7596 * for: [opt] invoke-super-quick, invoke-super-quick/range 7597 */ 7598 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7599 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7600 FETCH(r10, 2) @ r10<- GFED or CCCC 7601 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7602 .if (!1) 7603 and r10, r10, #15 @ r10<- D (or stays CCCC) 7604 .endif 7605 FETCH(r1, 1) @ r1<- BBBB 7606 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7607 EXPORT_PC() @ must export for invoke 7608 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7609 GET_VREG(r3, r10) @ r3<- "this" 7610 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7611 cmp r3, #0 @ null "this" ref? 7612 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7613 beq common_errNullObject @ "this" is null, throw exception 7614 bl common_invokeMethodRange @ continue on 7615 7616 7617 7618/* ------------------------------ */ 7619 .balign 64 7620.L_OP_UNUSED_FC: /* 0xfc */ 7621/* File: armv5te/OP_UNUSED_FC.S */ 7622/* File: armv5te/unused.S */ 7623 bl common_abort 7624 7625 7626 7627/* ------------------------------ */ 7628 .balign 64 7629.L_OP_UNUSED_FD: /* 0xfd */ 7630/* File: armv5te/OP_UNUSED_FD.S */ 7631/* File: armv5te/unused.S */ 7632 bl common_abort 7633 7634 7635 7636/* ------------------------------ */ 7637 .balign 64 7638.L_OP_UNUSED_FE: /* 0xfe */ 7639/* File: armv5te/OP_UNUSED_FE.S */ 7640/* File: armv5te/unused.S */ 7641 bl common_abort 7642 7643 7644 7645/* ------------------------------ */ 7646 .balign 64 7647.L_OP_UNUSED_FF: /* 0xff */ 7648/* File: armv5te/OP_UNUSED_FF.S */ 7649/* File: armv5te/unused.S */ 7650 bl common_abort 7651 7652 7653 7654 7655 .balign 64 7656 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7657 .global dvmAsmInstructionEnd 7658dvmAsmInstructionEnd: 7659 7660/* 7661 * =========================================================================== 7662 * Sister implementations 7663 * =========================================================================== 7664 */ 7665 .global dvmAsmSisterStart 7666 .type dvmAsmSisterStart, %function 7667 .text 7668 .balign 4 7669dvmAsmSisterStart: 7670 7671/* continuation for OP_CONST_STRING */ 7672 7673 /* 7674 * Continuation if the String has not yet been resolved. 7675 * r1: BBBB (String ref) 7676 * r9: target register 7677 */ 7678.LOP_CONST_STRING_resolve: 7679 EXPORT_PC() 7680 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7681 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7682 bl dvmResolveString @ r0<- String reference 7683 cmp r0, #0 @ failed? 7684 beq common_exceptionThrown @ yup, handle the exception 7685 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7686 GET_INST_OPCODE(ip) @ extract opcode from rINST 7687 SET_VREG(r0, r9) @ vAA<- r0 7688 GOTO_OPCODE(ip) @ jump to next instruction 7689 7690 7691/* continuation for OP_CONST_STRING_JUMBO */ 7692 7693 /* 7694 * Continuation if the String has not yet been resolved. 7695 * r1: BBBBBBBB (String ref) 7696 * r9: target register 7697 */ 7698.LOP_CONST_STRING_JUMBO_resolve: 7699 EXPORT_PC() 7700 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7701 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7702 bl dvmResolveString @ r0<- String reference 7703 cmp r0, #0 @ failed? 7704 beq common_exceptionThrown @ yup, handle the exception 7705 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7706 GET_INST_OPCODE(ip) @ extract opcode from rINST 7707 SET_VREG(r0, r9) @ vAA<- r0 7708 GOTO_OPCODE(ip) @ jump to next instruction 7709 7710 7711/* continuation for OP_CONST_CLASS */ 7712 7713 /* 7714 * Continuation if the Class has not yet been resolved. 7715 * r1: BBBB (Class ref) 7716 * r9: target register 7717 */ 7718.LOP_CONST_CLASS_resolve: 7719 EXPORT_PC() 7720 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7721 mov r2, #1 @ r2<- true 7722 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7723 bl dvmResolveClass @ r0<- Class reference 7724 cmp r0, #0 @ failed? 7725 beq common_exceptionThrown @ yup, handle the exception 7726 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7727 GET_INST_OPCODE(ip) @ extract opcode from rINST 7728 SET_VREG(r0, r9) @ vAA<- r0 7729 GOTO_OPCODE(ip) @ jump to next instruction 7730 7731 7732/* continuation for OP_CHECK_CAST */ 7733 7734 /* 7735 * Trivial test failed, need to perform full check. This is common. 7736 * r0 holds obj->clazz 7737 * r1 holds class resolved from BBBB 7738 * r9 holds object 7739 */ 7740.LOP_CHECK_CAST_fullcheck: 7741 bl dvmInstanceofNonTrivial @ r0<- boolean result 7742 cmp r0, #0 @ failed? 7743 bne .LOP_CHECK_CAST_okay @ no, success 7744 7745 @ A cast has failed. We need to throw a ClassCastException with the 7746 @ class of the object that failed to be cast. 7747 EXPORT_PC() @ about to throw 7748 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7749 ldr r0, .LstrClassCastExceptionPtr 7750 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7751 bl dvmThrowExceptionWithClassMessage 7752 b common_exceptionThrown 7753 7754 /* 7755 * Resolution required. This is the least-likely path. 7756 * 7757 * r2 holds BBBB 7758 * r9 holds object 7759 */ 7760.LOP_CHECK_CAST_resolve: 7761 EXPORT_PC() @ resolve() could throw 7762 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7763 mov r1, r2 @ r1<- BBBB 7764 mov r2, #0 @ r2<- false 7765 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7766 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7767 cmp r0, #0 @ got null? 7768 beq common_exceptionThrown @ yes, handle exception 7769 mov r1, r0 @ r1<- class resolved from BBB 7770 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7771 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7772 7773.LstrClassCastExceptionPtr: 7774 .word .LstrClassCastException 7775 7776 7777/* continuation for OP_INSTANCE_OF */ 7778 7779 /* 7780 * Trivial test failed, need to perform full check. This is common. 7781 * r0 holds obj->clazz 7782 * r1 holds class resolved from BBBB 7783 * r9 holds A 7784 */ 7785.LOP_INSTANCE_OF_fullcheck: 7786 bl dvmInstanceofNonTrivial @ r0<- boolean result 7787 @ fall through to OP_INSTANCE_OF_store 7788 7789 /* 7790 * r0 holds boolean result 7791 * r9 holds A 7792 */ 7793.LOP_INSTANCE_OF_store: 7794 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7795 SET_VREG(r0, r9) @ vA<- r0 7796 GET_INST_OPCODE(ip) @ extract opcode from rINST 7797 GOTO_OPCODE(ip) @ jump to next instruction 7798 7799 /* 7800 * Trivial test succeeded, save and bail. 7801 * r9 holds A 7802 */ 7803.LOP_INSTANCE_OF_trivial: 7804 mov r0, #1 @ indicate success 7805 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7807 SET_VREG(r0, r9) @ vA<- r0 7808 GET_INST_OPCODE(ip) @ extract opcode from rINST 7809 GOTO_OPCODE(ip) @ jump to next instruction 7810 7811 /* 7812 * Resolution required. This is the least-likely path. 7813 * 7814 * r3 holds BBBB 7815 * r9 holds A 7816 */ 7817.LOP_INSTANCE_OF_resolve: 7818 EXPORT_PC() @ resolve() could throw 7819 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7820 mov r1, r3 @ r1<- BBBB 7821 mov r2, #1 @ r2<- true 7822 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7823 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7824 cmp r0, #0 @ got null? 7825 beq common_exceptionThrown @ yes, handle exception 7826 mov r1, r0 @ r1<- class resolved from BBB 7827 mov r3, rINST, lsr #12 @ r3<- B 7828 GET_VREG(r0, r3) @ r0<- vB (object) 7829 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7830 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7831 7832 7833/* continuation for OP_NEW_INSTANCE */ 7834 7835 .balign 32 @ minimize cache lines 7836.LOP_NEW_INSTANCE_finish: @ r0=new object 7837 mov r3, rINST, lsr #8 @ r3<- AA 7838 cmp r0, #0 @ failed? 7839 beq common_exceptionThrown @ yes, handle the exception 7840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7841 GET_INST_OPCODE(ip) @ extract opcode from rINST 7842 SET_VREG(r0, r3) @ vAA<- r0 7843 GOTO_OPCODE(ip) @ jump to next instruction 7844 7845 /* 7846 * Class initialization required. 7847 * 7848 * r0 holds class object 7849 */ 7850.LOP_NEW_INSTANCE_needinit: 7851 mov r9, r0 @ save r0 7852 bl dvmInitClass @ initialize class 7853 cmp r0, #0 @ check boolean result 7854 mov r0, r9 @ restore r0 7855 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7856 b common_exceptionThrown @ failed, deal with init exception 7857 7858 /* 7859 * Resolution required. This is the least-likely path. 7860 * 7861 * r1 holds BBBB 7862 */ 7863.LOP_NEW_INSTANCE_resolve: 7864 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7865 mov r2, #0 @ r2<- false 7866 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7867 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7868 cmp r0, #0 @ got null? 7869 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7870 b common_exceptionThrown @ yes, handle exception 7871 7872.LstrInstantiationErrorPtr: 7873 .word .LstrInstantiationError 7874 7875 7876/* continuation for OP_NEW_ARRAY */ 7877 7878 7879 /* 7880 * Resolve class. (This is an uncommon case.) 7881 * 7882 * r1 holds array length 7883 * r2 holds class ref CCCC 7884 */ 7885.LOP_NEW_ARRAY_resolve: 7886 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7887 mov r9, r1 @ r9<- length (save) 7888 mov r1, r2 @ r1<- CCCC 7889 mov r2, #0 @ r2<- false 7890 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7891 bl dvmResolveClass @ r0<- call(clazz, ref) 7892 cmp r0, #0 @ got null? 7893 mov r1, r9 @ r1<- length (restore) 7894 beq common_exceptionThrown @ yes, handle exception 7895 @ fall through to OP_NEW_ARRAY_finish 7896 7897 /* 7898 * Finish allocation. 7899 * 7900 * r0 holds class 7901 * r1 holds array length 7902 */ 7903.LOP_NEW_ARRAY_finish: 7904 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7905 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7906 cmp r0, #0 @ failed? 7907 mov r2, rINST, lsr #8 @ r2<- A+ 7908 beq common_exceptionThrown @ yes, handle the exception 7909 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7910 and r2, r2, #15 @ r2<- A 7911 GET_INST_OPCODE(ip) @ extract opcode from rINST 7912 SET_VREG(r0, r2) @ vA<- r0 7913 GOTO_OPCODE(ip) @ jump to next instruction 7914 7915 7916/* continuation for OP_FILLED_NEW_ARRAY */ 7917 7918 /* 7919 * On entry: 7920 * r0 holds array class 7921 * r10 holds AA or BA 7922 */ 7923.LOP_FILLED_NEW_ARRAY_continue: 7924 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7925 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7926 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7927 .if 0 7928 mov r1, r10 @ r1<- AA (length) 7929 .else 7930 mov r1, r10, lsr #4 @ r1<- B (length) 7931 .endif 7932 cmp r3, #'I' @ array of ints? 7933 cmpne r3, #'L' @ array of objects? 7934 cmpne r3, #'[' @ array of arrays? 7935 mov r9, r1 @ save length in r9 7936 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7937 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7938 cmp r0, #0 @ null return? 7939 beq common_exceptionThrown @ alloc failed, handle exception 7940 7941 FETCH(r1, 2) @ r1<- FEDC or CCCC 7942 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7943 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7944 subs r9, r9, #1 @ length--, check for neg 7945 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7946 bmi 2f @ was zero, bail 7947 7948 @ copy values from registers into the array 7949 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7950 .if 0 7951 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79521: ldr r3, [r2], #4 @ r3<- *r2++ 7953 subs r9, r9, #1 @ count-- 7954 str r3, [r0], #4 @ *contents++ = vX 7955 bpl 1b 7956 @ continue at 2 7957 .else 7958 cmp r9, #4 @ length was initially 5? 7959 and r2, r10, #15 @ r2<- A 7960 bne 1f @ <= 4 args, branch 7961 GET_VREG(r3, r2) @ r3<- vA 7962 sub r9, r9, #1 @ count-- 7963 str r3, [r0, #16] @ contents[4] = vA 79641: and r2, r1, #15 @ r2<- F/E/D/C 7965 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7966 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7967 subs r9, r9, #1 @ count-- 7968 str r3, [r0], #4 @ *contents++ = vX 7969 bpl 1b 7970 @ continue at 2 7971 .endif 7972 79732: 7974 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7975 GOTO_OPCODE(ip) @ execute it 7976 7977 /* 7978 * Throw an exception indicating that we have not implemented this 7979 * mode of filled-new-array. 7980 */ 7981.LOP_FILLED_NEW_ARRAY_notimpl: 7982 ldr r0, .L_strInternalError 7983 ldr r1, .L_strFilledNewArrayNotImpl 7984 bl dvmThrowException 7985 b common_exceptionThrown 7986 7987 .if (!0) @ define in one or the other, not both 7988.L_strFilledNewArrayNotImpl: 7989 .word .LstrFilledNewArrayNotImpl 7990.L_strInternalError: 7991 .word .LstrInternalError 7992 .endif 7993 7994 7995/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7996 7997 /* 7998 * On entry: 7999 * r0 holds array class 8000 * r10 holds AA or BA 8001 */ 8002.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8003 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8004 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8005 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8006 .if 1 8007 mov r1, r10 @ r1<- AA (length) 8008 .else 8009 mov r1, r10, lsr #4 @ r1<- B (length) 8010 .endif 8011 cmp r3, #'I' @ array of ints? 8012 cmpne r3, #'L' @ array of objects? 8013 cmpne r3, #'[' @ array of arrays? 8014 mov r9, r1 @ save length in r9 8015 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8016 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8017 cmp r0, #0 @ null return? 8018 beq common_exceptionThrown @ alloc failed, handle exception 8019 8020 FETCH(r1, 2) @ r1<- FEDC or CCCC 8021 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8022 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8023 subs r9, r9, #1 @ length--, check for neg 8024 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8025 bmi 2f @ was zero, bail 8026 8027 @ copy values from registers into the array 8028 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8029 .if 1 8030 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80311: ldr r3, [r2], #4 @ r3<- *r2++ 8032 subs r9, r9, #1 @ count-- 8033 str r3, [r0], #4 @ *contents++ = vX 8034 bpl 1b 8035 @ continue at 2 8036 .else 8037 cmp r9, #4 @ length was initially 5? 8038 and r2, r10, #15 @ r2<- A 8039 bne 1f @ <= 4 args, branch 8040 GET_VREG(r3, r2) @ r3<- vA 8041 sub r9, r9, #1 @ count-- 8042 str r3, [r0, #16] @ contents[4] = vA 80431: and r2, r1, #15 @ r2<- F/E/D/C 8044 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8045 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8046 subs r9, r9, #1 @ count-- 8047 str r3, [r0], #4 @ *contents++ = vX 8048 bpl 1b 8049 @ continue at 2 8050 .endif 8051 80522: 8053 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8054 GOTO_OPCODE(ip) @ execute it 8055 8056 /* 8057 * Throw an exception indicating that we have not implemented this 8058 * mode of filled-new-array. 8059 */ 8060.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8061 ldr r0, .L_strInternalError 8062 ldr r1, .L_strFilledNewArrayNotImpl 8063 bl dvmThrowException 8064 b common_exceptionThrown 8065 8066 .if (!1) @ define in one or the other, not both 8067.L_strFilledNewArrayNotImpl: 8068 .word .LstrFilledNewArrayNotImpl 8069.L_strInternalError: 8070 .word .LstrInternalError 8071 .endif 8072 8073 8074/* continuation for OP_CMPL_FLOAT */ 8075.LOP_CMPL_FLOAT_finish: 8076 SET_VREG(r0, r9) @ vAA<- r0 8077 GOTO_OPCODE(ip) @ jump to next instruction 8078 8079 8080/* continuation for OP_CMPG_FLOAT */ 8081.LOP_CMPG_FLOAT_finish: 8082 SET_VREG(r0, r9) @ vAA<- r0 8083 GOTO_OPCODE(ip) @ jump to next instruction 8084 8085 8086/* continuation for OP_CMPL_DOUBLE */ 8087.LOP_CMPL_DOUBLE_finish: 8088 SET_VREG(r0, r9) @ vAA<- r0 8089 GOTO_OPCODE(ip) @ jump to next instruction 8090 8091 8092/* continuation for OP_CMPG_DOUBLE */ 8093.LOP_CMPG_DOUBLE_finish: 8094 SET_VREG(r0, r9) @ vAA<- r0 8095 GOTO_OPCODE(ip) @ jump to next instruction 8096 8097 8098/* continuation for OP_CMP_LONG */ 8099 8100.LOP_CMP_LONG_less: 8101 mvn r1, #0 @ r1<- -1 8102 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8103 @ instead, we just replicate the tail end. 8104 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8105 SET_VREG(r1, r9) @ vAA<- r1 8106 GET_INST_OPCODE(ip) @ extract opcode from rINST 8107 GOTO_OPCODE(ip) @ jump to next instruction 8108 8109.LOP_CMP_LONG_greater: 8110 mov r1, #1 @ r1<- 1 8111 @ fall through to _finish 8112 8113.LOP_CMP_LONG_finish: 8114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8115 SET_VREG(r1, r9) @ vAA<- r1 8116 GET_INST_OPCODE(ip) @ extract opcode from rINST 8117 GOTO_OPCODE(ip) @ jump to next instruction 8118 8119 8120/* continuation for OP_AGET_WIDE */ 8121 8122.LOP_AGET_WIDE_finish: 8123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8124 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8125 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8126 GET_INST_OPCODE(ip) @ extract opcode from rINST 8127 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8128 GOTO_OPCODE(ip) @ jump to next instruction 8129 8130 8131/* continuation for OP_APUT_WIDE */ 8132 8133.LOP_APUT_WIDE_finish: 8134 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8135 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8136 GET_INST_OPCODE(ip) @ extract opcode from rINST 8137 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8138 GOTO_OPCODE(ip) @ jump to next instruction 8139 8140 8141/* continuation for OP_APUT_OBJECT */ 8142 /* 8143 * On entry: 8144 * r1 = vBB (arrayObj) 8145 * r9 = vAA (obj) 8146 * r10 = offset into array (vBB + vCC * width) 8147 */ 8148.LOP_APUT_OBJECT_finish: 8149 cmp r9, #0 @ storing null reference? 8150 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8151 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8152 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8153 bl dvmCanPutArrayElement @ test object type vs. array type 8154 cmp r0, #0 @ okay? 8155 beq common_errArrayStore @ no 8156.LOP_APUT_OBJECT_skip_check: 8157 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8158 GET_INST_OPCODE(ip) @ extract opcode from rINST 8159 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8160 GOTO_OPCODE(ip) @ jump to next instruction 8161 8162 8163/* continuation for OP_IGET */ 8164 8165 /* 8166 * Currently: 8167 * r0 holds resolved field 8168 * r9 holds object 8169 */ 8170.LOP_IGET_finish: 8171 @bl common_squeak0 8172 cmp r9, #0 @ check object for null 8173 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8174 beq common_errNullObject @ object was null 8175 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8176 mov r2, rINST, lsr #8 @ r2<- A+ 8177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8178 and r2, r2, #15 @ r2<- A 8179 GET_INST_OPCODE(ip) @ extract opcode from rINST 8180 SET_VREG(r0, r2) @ fp[A]<- r0 8181 GOTO_OPCODE(ip) @ jump to next instruction 8182 8183 8184/* continuation for OP_IGET_WIDE */ 8185 8186 /* 8187 * Currently: 8188 * r0 holds resolved field 8189 * r9 holds object 8190 */ 8191.LOP_IGET_WIDE_finish: 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 mov r2, rINST, lsr #8 @ r2<- A+ 8196 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8197 and r2, r2, #15 @ r2<- A 8198 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8199 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8200 GET_INST_OPCODE(ip) @ extract opcode from rINST 8201 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8202 GOTO_OPCODE(ip) @ jump to next instruction 8203 8204 8205/* continuation for OP_IGET_OBJECT */ 8206 8207 /* 8208 * Currently: 8209 * r0 holds resolved field 8210 * r9 holds object 8211 */ 8212.LOP_IGET_OBJECT_finish: 8213 @bl common_squeak0 8214 cmp r9, #0 @ check object for null 8215 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8216 beq common_errNullObject @ object was null 8217 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8218 mov r2, rINST, lsr #8 @ r2<- A+ 8219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8220 and r2, r2, #15 @ r2<- A 8221 GET_INST_OPCODE(ip) @ extract opcode from rINST 8222 SET_VREG(r0, r2) @ fp[A]<- r0 8223 GOTO_OPCODE(ip) @ jump to next instruction 8224 8225 8226/* continuation for OP_IGET_BOOLEAN */ 8227 8228 /* 8229 * Currently: 8230 * r0 holds resolved field 8231 * r9 holds object 8232 */ 8233.LOP_IGET_BOOLEAN_finish: 8234 @bl common_squeak1 8235 cmp r9, #0 @ check object for null 8236 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8237 beq common_errNullObject @ object was null 8238 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8239 mov r2, rINST, lsr #8 @ r2<- A+ 8240 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8241 and r2, r2, #15 @ r2<- A 8242 GET_INST_OPCODE(ip) @ extract opcode from rINST 8243 SET_VREG(r0, r2) @ fp[A]<- r0 8244 GOTO_OPCODE(ip) @ jump to next instruction 8245 8246 8247/* continuation for OP_IGET_BYTE */ 8248 8249 /* 8250 * Currently: 8251 * r0 holds resolved field 8252 * r9 holds object 8253 */ 8254.LOP_IGET_BYTE_finish: 8255 @bl common_squeak2 8256 cmp r9, #0 @ check object for null 8257 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8258 beq common_errNullObject @ object was null 8259 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8260 mov r2, rINST, lsr #8 @ r2<- A+ 8261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8262 and r2, r2, #15 @ r2<- A 8263 GET_INST_OPCODE(ip) @ extract opcode from rINST 8264 SET_VREG(r0, r2) @ fp[A]<- r0 8265 GOTO_OPCODE(ip) @ jump to next instruction 8266 8267 8268/* continuation for OP_IGET_CHAR */ 8269 8270 /* 8271 * Currently: 8272 * r0 holds resolved field 8273 * r9 holds object 8274 */ 8275.LOP_IGET_CHAR_finish: 8276 @bl common_squeak3 8277 cmp r9, #0 @ check object for null 8278 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8279 beq common_errNullObject @ object was null 8280 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8281 mov r2, rINST, lsr #8 @ r2<- A+ 8282 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8283 and r2, r2, #15 @ r2<- A 8284 GET_INST_OPCODE(ip) @ extract opcode from rINST 8285 SET_VREG(r0, r2) @ fp[A]<- r0 8286 GOTO_OPCODE(ip) @ jump to next instruction 8287 8288 8289/* continuation for OP_IGET_SHORT */ 8290 8291 /* 8292 * Currently: 8293 * r0 holds resolved field 8294 * r9 holds object 8295 */ 8296.LOP_IGET_SHORT_finish: 8297 @bl common_squeak4 8298 cmp r9, #0 @ check object for null 8299 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8300 beq common_errNullObject @ object was null 8301 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8302 mov r2, rINST, lsr #8 @ r2<- A+ 8303 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8304 and r2, r2, #15 @ r2<- A 8305 GET_INST_OPCODE(ip) @ extract opcode from rINST 8306 SET_VREG(r0, r2) @ fp[A]<- r0 8307 GOTO_OPCODE(ip) @ jump to next instruction 8308 8309 8310/* continuation for OP_IPUT */ 8311 8312 /* 8313 * Currently: 8314 * r0 holds resolved field 8315 * r9 holds object 8316 */ 8317.LOP_IPUT_finish: 8318 @bl common_squeak0 8319 mov r1, rINST, lsr #8 @ r1<- A+ 8320 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8321 and r1, r1, #15 @ r1<- A 8322 cmp r9, #0 @ check object for null 8323 GET_VREG(r0, r1) @ r0<- fp[A] 8324 beq common_errNullObject @ object was null 8325 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8326 GET_INST_OPCODE(ip) @ extract opcode from rINST 8327 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8328 GOTO_OPCODE(ip) @ jump to next instruction 8329 8330 8331/* continuation for OP_IPUT_WIDE */ 8332 8333 /* 8334 * Currently: 8335 * r0 holds resolved field 8336 * r9 holds object 8337 */ 8338.LOP_IPUT_WIDE_finish: 8339 mov r2, rINST, lsr #8 @ r2<- A+ 8340 cmp r9, #0 @ check object for null 8341 and r2, r2, #15 @ r2<- A 8342 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8343 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8344 beq common_errNullObject @ object was null 8345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8346 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8347 GET_INST_OPCODE(ip) @ extract opcode from rINST 8348 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8349 GOTO_OPCODE(ip) @ jump to next instruction 8350 8351 8352/* continuation for OP_IPUT_OBJECT */ 8353 8354 /* 8355 * Currently: 8356 * r0 holds resolved field 8357 * r9 holds object 8358 */ 8359.LOP_IPUT_OBJECT_finish: 8360 @bl common_squeak0 8361 mov r1, rINST, lsr #8 @ r1<- A+ 8362 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8363 and r1, r1, #15 @ r1<- A 8364 cmp r9, #0 @ check object for null 8365 GET_VREG(r0, r1) @ r0<- fp[A] 8366 beq common_errNullObject @ object was null 8367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8368 GET_INST_OPCODE(ip) @ extract opcode from rINST 8369 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8370 GOTO_OPCODE(ip) @ jump to next instruction 8371 8372 8373/* continuation for OP_IPUT_BOOLEAN */ 8374 8375 /* 8376 * Currently: 8377 * r0 holds resolved field 8378 * r9 holds object 8379 */ 8380.LOP_IPUT_BOOLEAN_finish: 8381 @bl common_squeak1 8382 mov r1, rINST, lsr #8 @ r1<- A+ 8383 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8384 and r1, r1, #15 @ r1<- A 8385 cmp r9, #0 @ check object for null 8386 GET_VREG(r0, r1) @ r0<- fp[A] 8387 beq common_errNullObject @ object was null 8388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8389 GET_INST_OPCODE(ip) @ extract opcode from rINST 8390 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8391 GOTO_OPCODE(ip) @ jump to next instruction 8392 8393 8394/* continuation for OP_IPUT_BYTE */ 8395 8396 /* 8397 * Currently: 8398 * r0 holds resolved field 8399 * r9 holds object 8400 */ 8401.LOP_IPUT_BYTE_finish: 8402 @bl common_squeak2 8403 mov r1, rINST, lsr #8 @ r1<- A+ 8404 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8405 and r1, r1, #15 @ r1<- A 8406 cmp r9, #0 @ check object for null 8407 GET_VREG(r0, r1) @ r0<- fp[A] 8408 beq common_errNullObject @ object was null 8409 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8410 GET_INST_OPCODE(ip) @ extract opcode from rINST 8411 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8412 GOTO_OPCODE(ip) @ jump to next instruction 8413 8414 8415/* continuation for OP_IPUT_CHAR */ 8416 8417 /* 8418 * Currently: 8419 * r0 holds resolved field 8420 * r9 holds object 8421 */ 8422.LOP_IPUT_CHAR_finish: 8423 @bl common_squeak3 8424 mov r1, rINST, lsr #8 @ r1<- A+ 8425 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8426 and r1, r1, #15 @ r1<- A 8427 cmp r9, #0 @ check object for null 8428 GET_VREG(r0, r1) @ r0<- fp[A] 8429 beq common_errNullObject @ object was null 8430 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8431 GET_INST_OPCODE(ip) @ extract opcode from rINST 8432 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8433 GOTO_OPCODE(ip) @ jump to next instruction 8434 8435 8436/* continuation for OP_IPUT_SHORT */ 8437 8438 /* 8439 * Currently: 8440 * r0 holds resolved field 8441 * r9 holds object 8442 */ 8443.LOP_IPUT_SHORT_finish: 8444 @bl common_squeak4 8445 mov r1, rINST, lsr #8 @ r1<- A+ 8446 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8447 and r1, r1, #15 @ r1<- A 8448 cmp r9, #0 @ check object for null 8449 GET_VREG(r0, r1) @ r0<- fp[A] 8450 beq common_errNullObject @ object was null 8451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8452 GET_INST_OPCODE(ip) @ extract opcode from rINST 8453 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8454 GOTO_OPCODE(ip) @ jump to next instruction 8455 8456 8457/* continuation for OP_SGET */ 8458 8459 /* 8460 * Continuation if the field has not yet been resolved. 8461 * r1: BBBB field ref 8462 */ 8463.LOP_SGET_resolve: 8464 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8465 EXPORT_PC() @ resolve() could throw, so export now 8466 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8467 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8468 cmp r0, #0 @ success? 8469 bne .LOP_SGET_finish @ yes, finish 8470 b common_exceptionThrown @ no, handle exception 8471 8472 8473/* continuation for OP_SGET_WIDE */ 8474 8475 /* 8476 * Continuation if the field has not yet been resolved. 8477 * r1: BBBB field ref 8478 */ 8479.LOP_SGET_WIDE_resolve: 8480 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8481 EXPORT_PC() @ resolve() could throw, so export now 8482 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8483 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8484 cmp r0, #0 @ success? 8485 bne .LOP_SGET_WIDE_finish @ yes, finish 8486 b common_exceptionThrown @ no, handle exception 8487 8488 8489/* continuation for OP_SGET_OBJECT */ 8490 8491 /* 8492 * Continuation if the field has not yet been resolved. 8493 * r1: BBBB field ref 8494 */ 8495.LOP_SGET_OBJECT_resolve: 8496 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8497 EXPORT_PC() @ resolve() could throw, so export now 8498 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8499 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8500 cmp r0, #0 @ success? 8501 bne .LOP_SGET_OBJECT_finish @ yes, finish 8502 b common_exceptionThrown @ no, handle exception 8503 8504 8505/* continuation for OP_SGET_BOOLEAN */ 8506 8507 /* 8508 * Continuation if the field has not yet been resolved. 8509 * r1: BBBB field ref 8510 */ 8511.LOP_SGET_BOOLEAN_resolve: 8512 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8513 EXPORT_PC() @ resolve() could throw, so export now 8514 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8515 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8516 cmp r0, #0 @ success? 8517 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8518 b common_exceptionThrown @ no, handle exception 8519 8520 8521/* continuation for OP_SGET_BYTE */ 8522 8523 /* 8524 * Continuation if the field has not yet been resolved. 8525 * r1: BBBB field ref 8526 */ 8527.LOP_SGET_BYTE_resolve: 8528 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8529 EXPORT_PC() @ resolve() could throw, so export now 8530 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8531 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8532 cmp r0, #0 @ success? 8533 bne .LOP_SGET_BYTE_finish @ yes, finish 8534 b common_exceptionThrown @ no, handle exception 8535 8536 8537/* continuation for OP_SGET_CHAR */ 8538 8539 /* 8540 * Continuation if the field has not yet been resolved. 8541 * r1: BBBB field ref 8542 */ 8543.LOP_SGET_CHAR_resolve: 8544 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8545 EXPORT_PC() @ resolve() could throw, so export now 8546 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8547 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8548 cmp r0, #0 @ success? 8549 bne .LOP_SGET_CHAR_finish @ yes, finish 8550 b common_exceptionThrown @ no, handle exception 8551 8552 8553/* continuation for OP_SGET_SHORT */ 8554 8555 /* 8556 * Continuation if the field has not yet been resolved. 8557 * r1: BBBB field ref 8558 */ 8559.LOP_SGET_SHORT_resolve: 8560 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8561 EXPORT_PC() @ resolve() could throw, so export now 8562 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8563 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8564 cmp r0, #0 @ success? 8565 bne .LOP_SGET_SHORT_finish @ yes, finish 8566 b common_exceptionThrown @ no, handle exception 8567 8568 8569/* continuation for OP_SPUT */ 8570 8571 /* 8572 * Continuation if the field has not yet been resolved. 8573 * r1: BBBB field ref 8574 */ 8575.LOP_SPUT_resolve: 8576 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8577 EXPORT_PC() @ resolve() could throw, so export now 8578 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8579 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8580 cmp r0, #0 @ success? 8581 bne .LOP_SPUT_finish @ yes, finish 8582 b common_exceptionThrown @ no, handle exception 8583 8584 8585/* continuation for OP_SPUT_WIDE */ 8586 8587 /* 8588 * Continuation if the field has not yet been resolved. 8589 * r1: BBBB field ref 8590 * r9: &fp[AA] 8591 */ 8592.LOP_SPUT_WIDE_resolve: 8593 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8594 EXPORT_PC() @ resolve() could throw, so export now 8595 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8596 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8597 cmp r0, #0 @ success? 8598 bne .LOP_SPUT_WIDE_finish @ yes, finish 8599 b common_exceptionThrown @ no, handle exception 8600 8601 8602/* continuation for OP_SPUT_OBJECT */ 8603 8604 /* 8605 * Continuation if the field has not yet been resolved. 8606 * r1: BBBB field ref 8607 */ 8608.LOP_SPUT_OBJECT_resolve: 8609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8610 EXPORT_PC() @ resolve() could throw, so export now 8611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8613 cmp r0, #0 @ success? 8614 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8615 b common_exceptionThrown @ no, handle exception 8616 8617 8618/* continuation for OP_SPUT_BOOLEAN */ 8619 8620 /* 8621 * Continuation if the field has not yet been resolved. 8622 * r1: BBBB field ref 8623 */ 8624.LOP_SPUT_BOOLEAN_resolve: 8625 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8626 EXPORT_PC() @ resolve() could throw, so export now 8627 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8628 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8629 cmp r0, #0 @ success? 8630 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8631 b common_exceptionThrown @ no, handle exception 8632 8633 8634/* continuation for OP_SPUT_BYTE */ 8635 8636 /* 8637 * Continuation if the field has not yet been resolved. 8638 * r1: BBBB field ref 8639 */ 8640.LOP_SPUT_BYTE_resolve: 8641 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8642 EXPORT_PC() @ resolve() could throw, so export now 8643 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8644 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8645 cmp r0, #0 @ success? 8646 bne .LOP_SPUT_BYTE_finish @ yes, finish 8647 b common_exceptionThrown @ no, handle exception 8648 8649 8650/* continuation for OP_SPUT_CHAR */ 8651 8652 /* 8653 * Continuation if the field has not yet been resolved. 8654 * r1: BBBB field ref 8655 */ 8656.LOP_SPUT_CHAR_resolve: 8657 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8658 EXPORT_PC() @ resolve() could throw, so export now 8659 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8660 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8661 cmp r0, #0 @ success? 8662 bne .LOP_SPUT_CHAR_finish @ yes, finish 8663 b common_exceptionThrown @ no, handle exception 8664 8665 8666/* continuation for OP_SPUT_SHORT */ 8667 8668 /* 8669 * Continuation if the field has not yet been resolved. 8670 * r1: BBBB field ref 8671 */ 8672.LOP_SPUT_SHORT_resolve: 8673 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8674 EXPORT_PC() @ resolve() could throw, so export now 8675 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8676 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8677 cmp r0, #0 @ success? 8678 bne .LOP_SPUT_SHORT_finish @ yes, finish 8679 b common_exceptionThrown @ no, handle exception 8680 8681 8682/* continuation for OP_INVOKE_VIRTUAL */ 8683 8684 /* 8685 * At this point: 8686 * r0 = resolved base method 8687 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8688 */ 8689.LOP_INVOKE_VIRTUAL_continue: 8690 GET_VREG(r1, r10) @ r1<- "this" ptr 8691 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8692 cmp r1, #0 @ is "this" null? 8693 beq common_errNullObject @ null "this", throw exception 8694 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8695 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8696 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8697 bl common_invokeMethodNoRange @ continue on 8698 8699 8700/* continuation for OP_INVOKE_SUPER */ 8701 8702 /* 8703 * At this point: 8704 * r0 = resolved base method 8705 * r9 = method->clazz 8706 */ 8707.LOP_INVOKE_SUPER_continue: 8708 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8709 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8710 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8711 EXPORT_PC() @ must export for invoke 8712 cmp r2, r3 @ compare (methodIndex, vtableCount) 8713 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8714 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8715 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8716 bl common_invokeMethodNoRange @ continue on 8717 8718.LOP_INVOKE_SUPER_resolve: 8719 mov r0, r9 @ r0<- method->clazz 8720 mov r2, #METHOD_VIRTUAL @ resolver method type 8721 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8722 cmp r0, #0 @ got null? 8723 bne .LOP_INVOKE_SUPER_continue @ no, continue 8724 b common_exceptionThrown @ yes, handle exception 8725 8726 /* 8727 * Throw a NoSuchMethodError with the method name as the message. 8728 * r0 = resolved base method 8729 */ 8730.LOP_INVOKE_SUPER_nsm: 8731 ldr r1, [r0, #offMethod_name] @ r1<- method name 8732 b common_errNoSuchMethod 8733 8734 8735/* continuation for OP_INVOKE_DIRECT */ 8736 8737 /* 8738 * On entry: 8739 * r1 = reference (BBBB or CCCC) 8740 * r10 = "this" register 8741 */ 8742.LOP_INVOKE_DIRECT_resolve: 8743 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8744 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8745 mov r2, #METHOD_DIRECT @ resolver method type 8746 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8747 cmp r0, #0 @ got null? 8748 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8749 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8750 b common_exceptionThrown @ yes, handle exception 8751 8752 8753/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8754 8755 /* 8756 * At this point: 8757 * r0 = resolved base method 8758 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8759 */ 8760.LOP_INVOKE_VIRTUAL_RANGE_continue: 8761 GET_VREG(r1, r10) @ r1<- "this" ptr 8762 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8763 cmp r1, #0 @ is "this" null? 8764 beq common_errNullObject @ null "this", throw exception 8765 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8766 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8767 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8768 bl common_invokeMethodRange @ continue on 8769 8770 8771/* continuation for OP_INVOKE_SUPER_RANGE */ 8772 8773 /* 8774 * At this point: 8775 * r0 = resolved base method 8776 * r9 = method->clazz 8777 */ 8778.LOP_INVOKE_SUPER_RANGE_continue: 8779 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8780 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8781 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8782 EXPORT_PC() @ must export for invoke 8783 cmp r2, r3 @ compare (methodIndex, vtableCount) 8784 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8785 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8786 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8787 bl common_invokeMethodRange @ continue on 8788 8789.LOP_INVOKE_SUPER_RANGE_resolve: 8790 mov r0, r9 @ r0<- method->clazz 8791 mov r2, #METHOD_VIRTUAL @ resolver method type 8792 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8793 cmp r0, #0 @ got null? 8794 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8795 b common_exceptionThrown @ yes, handle exception 8796 8797 /* 8798 * Throw a NoSuchMethodError with the method name as the message. 8799 * r0 = resolved base method 8800 */ 8801.LOP_INVOKE_SUPER_RANGE_nsm: 8802 ldr r1, [r0, #offMethod_name] @ r1<- method name 8803 b common_errNoSuchMethod 8804 8805 8806/* continuation for OP_INVOKE_DIRECT_RANGE */ 8807 8808 /* 8809 * On entry: 8810 * r1 = reference (BBBB or CCCC) 8811 * r10 = "this" register 8812 */ 8813.LOP_INVOKE_DIRECT_RANGE_resolve: 8814 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8815 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8816 mov r2, #METHOD_DIRECT @ resolver method type 8817 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8818 cmp r0, #0 @ got null? 8819 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8820 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8821 b common_exceptionThrown @ yes, handle exception 8822 8823 8824/* continuation for OP_FLOAT_TO_LONG */ 8825/* 8826 * Convert the float in r0 to a long in r0/r1. 8827 * 8828 * We have to clip values to long min/max per the specification. The 8829 * expected common case is a "reasonable" value that converts directly 8830 * to modest integer. The EABI convert function isn't doing this for us. 8831 */ 8832f2l_doconv: 8833 stmfd sp!, {r4, lr} 8834 mov r1, #0x5f000000 @ (float)maxlong 8835 mov r4, r0 8836 bl __aeabi_fcmpge @ is arg >= maxlong? 8837 cmp r0, #0 @ nonzero == yes 8838 mvnne r0, #0 @ return maxlong (7fffffff) 8839 mvnne r1, #0x80000000 8840 ldmnefd sp!, {r4, pc} 8841 8842 mov r0, r4 @ recover arg 8843 mov r1, #0xdf000000 @ (float)minlong 8844 bl __aeabi_fcmple @ is arg <= minlong? 8845 cmp r0, #0 @ nonzero == yes 8846 movne r0, #0 @ return minlong (80000000) 8847 movne r1, #0x80000000 8848 ldmnefd sp!, {r4, pc} 8849 8850 mov r0, r4 @ recover arg 8851 mov r1, r4 8852 bl __aeabi_fcmpeq @ is arg == self? 8853 cmp r0, #0 @ zero == no 8854 moveq r1, #0 @ return zero for NaN 8855 ldmeqfd sp!, {r4, pc} 8856 8857 mov r0, r4 @ recover arg 8858 bl __aeabi_f2lz @ convert float to long 8859 ldmfd sp!, {r4, pc} 8860 8861 8862/* continuation for OP_DOUBLE_TO_LONG */ 8863/* 8864 * Convert the double in r0/r1 to a long in r0/r1. 8865 * 8866 * We have to clip values to long min/max per the specification. The 8867 * expected common case is a "reasonable" value that converts directly 8868 * to modest integer. The EABI convert function isn't doing this for us. 8869 */ 8870d2l_doconv: 8871 stmfd sp!, {r4, r5, lr} @ save regs 8872 mov r3, #0x43000000 @ maxlong, as a double (high word) 8873 add r3, #0x00e00000 @ 0x43e00000 8874 mov r2, #0 @ maxlong, as a double (low word) 8875 sub sp, sp, #4 @ align for EABI 8876 mov r4, r0 @ save a copy of r0 8877 mov r5, r1 @ and r1 8878 bl __aeabi_dcmpge @ is arg >= maxlong? 8879 cmp r0, #0 @ nonzero == yes 8880 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8881 mvnne r1, #0x80000000 8882 bne 1f 8883 8884 mov r0, r4 @ recover arg 8885 mov r1, r5 8886 mov r3, #0xc3000000 @ minlong, as a double (high word) 8887 add r3, #0x00e00000 @ 0xc3e00000 8888 mov r2, #0 @ minlong, as a double (low word) 8889 bl __aeabi_dcmple @ is arg <= minlong? 8890 cmp r0, #0 @ nonzero == yes 8891 movne r0, #0 @ return minlong (8000000000000000) 8892 movne r1, #0x80000000 8893 bne 1f 8894 8895 mov r0, r4 @ recover arg 8896 mov r1, r5 8897 mov r2, r4 @ compare against self 8898 mov r3, r5 8899 bl __aeabi_dcmpeq @ is arg == self? 8900 cmp r0, #0 @ zero == no 8901 moveq r1, #0 @ return zero for NaN 8902 beq 1f 8903 8904 mov r0, r4 @ recover arg 8905 mov r1, r5 8906 bl __aeabi_d2lz @ convert double to long 8907 89081: 8909 add sp, sp, #4 8910 ldmfd sp!, {r4, r5, pc} 8911 8912 8913/* continuation for OP_MUL_LONG */ 8914 8915.LOP_MUL_LONG_finish: 8916 GET_INST_OPCODE(ip) @ extract opcode from rINST 8917 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8918 GOTO_OPCODE(ip) @ jump to next instruction 8919 8920 8921/* continuation for OP_SHL_LONG */ 8922 8923.LOP_SHL_LONG_finish: 8924 mov r0, r0, asl r2 @ r0<- r0 << r2 8925 GET_INST_OPCODE(ip) @ extract opcode from rINST 8926 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8927 GOTO_OPCODE(ip) @ jump to next instruction 8928 8929 8930/* continuation for OP_SHR_LONG */ 8931 8932.LOP_SHR_LONG_finish: 8933 mov r1, r1, asr r2 @ r1<- r1 >> r2 8934 GET_INST_OPCODE(ip) @ extract opcode from rINST 8935 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8936 GOTO_OPCODE(ip) @ jump to next instruction 8937 8938 8939/* continuation for OP_USHR_LONG */ 8940 8941.LOP_USHR_LONG_finish: 8942 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8943 GET_INST_OPCODE(ip) @ extract opcode from rINST 8944 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8945 GOTO_OPCODE(ip) @ jump to next instruction 8946 8947 8948/* continuation for OP_SHL_LONG_2ADDR */ 8949 8950.LOP_SHL_LONG_2ADDR_finish: 8951 GET_INST_OPCODE(ip) @ extract opcode from rINST 8952 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8953 GOTO_OPCODE(ip) @ jump to next instruction 8954 8955 8956/* continuation for OP_SHR_LONG_2ADDR */ 8957 8958.LOP_SHR_LONG_2ADDR_finish: 8959 GET_INST_OPCODE(ip) @ extract opcode from rINST 8960 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8961 GOTO_OPCODE(ip) @ jump to next instruction 8962 8963 8964/* continuation for OP_USHR_LONG_2ADDR */ 8965 8966.LOP_USHR_LONG_2ADDR_finish: 8967 GET_INST_OPCODE(ip) @ extract opcode from rINST 8968 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8969 GOTO_OPCODE(ip) @ jump to next instruction 8970 8971 8972/* continuation for OP_EXECUTE_INLINE */ 8973 8974 /* 8975 * Extract args, call function. 8976 * r0 = #of args (0-4) 8977 * r10 = call index 8978 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8979 * 8980 * Other ideas: 8981 * - Use a jump table from the main piece to jump directly into the 8982 * AND/LDR pairs. Costs a data load, saves a branch. 8983 * - Have five separate pieces that do the loading, so we can work the 8984 * interleave a little better. Increases code size. 8985 */ 8986.LOP_EXECUTE_INLINE_continue: 8987 rsb r0, r0, #4 @ r0<- 4-r0 8988 FETCH(r9, 2) @ r9<- FEDC 8989 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8990 bl common_abort @ (skipped due to ARM prefetch) 89914: and ip, r9, #0xf000 @ isolate F 8992 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 89933: and ip, r9, #0x0f00 @ isolate E 8994 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 89952: and ip, r9, #0x00f0 @ isolate D 8996 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 89971: and ip, r9, #0x000f @ isolate C 8998 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 89990: 9000 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9001 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9002 @ (not reached) 9003 9004.LOP_EXECUTE_INLINE_table: 9005 .word gDvmInlineOpsTable 9006 9007 9008/* continuation for OP_EXECUTE_INLINE_RANGE */ 9009 9010 /* 9011 * Extract args, call function. 9012 * r0 = #of args (0-4) 9013 * r10 = call index 9014 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9015 */ 9016.LOP_EXECUTE_INLINE_RANGE_continue: 9017 rsb r0, r0, #4 @ r0<- 4-r0 9018 FETCH(r9, 2) @ r9<- CCCC 9019 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9020 bl common_abort @ (skipped due to ARM prefetch) 90214: add ip, r9, #3 @ base+3 9022 GET_VREG(r3, ip) @ r3<- vBase[3] 90233: add ip, r9, #2 @ base+2 9024 GET_VREG(r2, ip) @ r2<- vBase[2] 90252: add ip, r9, #1 @ base+1 9026 GET_VREG(r1, ip) @ r1<- vBase[1] 90271: add ip, r9, #0 @ (nop) 9028 GET_VREG(r0, ip) @ r0<- vBase[0] 90290: 9030 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9031 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9032 @ (not reached) 9033 9034.LOP_EXECUTE_INLINE_RANGE_table: 9035 .word gDvmInlineOpsTable 9036 9037 9038 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9039 .global dvmAsmSisterEnd 9040dvmAsmSisterEnd: 9041 9042/* File: armv5te/footer.S */ 9043 9044/* 9045 * =========================================================================== 9046 * Common subroutines and data 9047 * =========================================================================== 9048 */ 9049 9050 9051 9052 .text 9053 .align 2 9054 9055#if defined(WITH_JIT) 9056#if defined(WITH_SELF_VERIFICATION) 9057 .global dvmJitToInterpPunt 9058dvmJitToInterpPunt: 9059 mov r2,#kSVSPunt @ r2<- interpreter entry point 9060 b dvmJitSelfVerificationEnd @ doesn't return 9061 9062 .global dvmJitToInterpSingleStep 9063dvmJitToInterpSingleStep: 9064 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9065 b dvmJitSelfVerificationEnd @ doesn't return 9066 9067 .global dvmJitToTraceSelect 9068dvmJitToTraceSelect: 9069 ldr r0,[lr, #-1] @ pass our target PC 9070 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9071 b dvmJitSelfVerificationEnd @ doesn't return 9072 9073 .global dvmJitToBackwardBranch 9074dvmJitToBackwardBranch: 9075 ldr r0,[lr, #-1] @ pass our target PC 9076 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9077 b dvmJitSelfVerificationEnd @ doesn't return 9078 9079 .global dvmJitToInterpNormal 9080dvmJitToInterpNormal: 9081 ldr r0,[lr, #-1] @ pass our target PC 9082 mov r2,#kSVSNormal @ r2<- interpreter entry point 9083 b dvmJitSelfVerificationEnd @ doesn't return 9084 9085 .global dvmJitToInterpNoChain 9086dvmJitToInterpNoChain: 9087 mov r0,rPC @ pass our target PC 9088 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9089 b dvmJitSelfVerificationEnd @ doesn't return 9090#else 9091/* 9092 * Return from the translation cache to the interpreter when the compiler is 9093 * having issues translating/executing a Dalvik instruction. We have to skip 9094 * the code cache lookup otherwise it is possible to indefinitely bouce 9095 * between the interpreter and the code cache if the instruction that fails 9096 * to be compiled happens to be at a trace start. 9097 */ 9098 .global dvmJitToInterpPunt 9099dvmJitToInterpPunt: 9100 mov rPC, r0 9101#ifdef EXIT_STATS 9102 mov r0,lr 9103 bl dvmBumpPunt; 9104#endif 9105 EXPORT_PC() 9106 adrl rIBASE, dvmAsmInstructionStart 9107 FETCH_INST() 9108 GET_INST_OPCODE(ip) 9109 GOTO_OPCODE(ip) 9110 9111/* 9112 * Return to the interpreter to handle a single instruction. 9113 * On entry: 9114 * r0 <= PC 9115 * r1 <= PC of resume instruction 9116 * lr <= resume point in translation 9117 */ 9118 .global dvmJitToInterpSingleStep 9119dvmJitToInterpSingleStep: 9120 str lr,[rGLUE,#offGlue_jitResume] 9121 str r1,[rGLUE,#offGlue_jitResumePC] 9122 mov r1,#kInterpEntryInstr 9123 @ enum is 4 byte in aapcs-EABI 9124 str r1, [rGLUE, #offGlue_entryPoint] 9125 mov rPC,r0 9126 EXPORT_PC() 9127 adrl rIBASE, dvmAsmInstructionStart 9128 mov r2,#kJitSingleStep @ Ask for single step and then revert 9129 str r2,[rGLUE,#offGlue_jitState] 9130 mov r1,#1 @ set changeInterp to bail to debug interp 9131 b common_gotoBail 9132 9133 9134/* 9135 * Return from the translation cache and immediately request 9136 * a translation for the exit target. Commonly used following 9137 * invokes. 9138 */ 9139 .global dvmJitToTraceSelect 9140dvmJitToTraceSelect: 9141 ldr rPC,[lr, #-1] @ get our target PC 9142 add rINST,lr,#-5 @ save start of chain branch 9143 mov r0,rPC 9144 bl dvmJitGetCodeAddr @ Is there a translation? 9145 cmp r0,#0 9146 beq 2f 9147 mov r1,rINST 9148 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9149 mov r1, rPC @ arg1 of translation may need this 9150 mov lr, #0 @ in case target is HANDLER_INTERPRET 9151 cmp r0,#0 @ successful chain? 9152 bxne r0 @ continue native execution 9153 b toInterpreter @ didn't chain - resume with interpreter 9154 9155/* No translation, so request one if profiling isn't disabled*/ 91562: 9157 adrl rIBASE, dvmAsmInstructionStart 9158 GET_JIT_PROF_TABLE(r0) 9159 FETCH_INST() 9160 cmp r0, #0 9161 bne common_selectTrace 9162 GET_INST_OPCODE(ip) 9163 GOTO_OPCODE(ip) 9164 9165/* 9166 * Return from the translation cache to the interpreter. 9167 * The return was done with a BLX from thumb mode, and 9168 * the following 32-bit word contains the target rPC value. 9169 * Note that lr (r14) will have its low-order bit set to denote 9170 * its thumb-mode origin. 9171 * 9172 * We'll need to stash our lr origin away, recover the new 9173 * target and then check to see if there is a translation available 9174 * for our new target. If so, we do a translation chain and 9175 * go back to native execution. Otherwise, it's back to the 9176 * interpreter (after treating this entry as a potential 9177 * trace start). 9178 */ 9179 .global dvmJitToInterpNormal 9180dvmJitToInterpNormal: 9181 ldr rPC,[lr, #-1] @ get our target PC 9182 add rINST,lr,#-5 @ save start of chain branch 9183#ifdef EXIT_STATS 9184 bl dvmBumpNormal 9185#endif 9186 mov r0,rPC 9187 bl dvmJitGetCodeAddr @ Is there a translation? 9188 cmp r0,#0 9189 beq toInterpreter @ go if not, otherwise do chain 9190 mov r1,rINST 9191 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9192 mov r1, rPC @ arg1 of translation may need this 9193 mov lr, #0 @ in case target is HANDLER_INTERPRET 9194 cmp r0,#0 @ successful chain? 9195 bxne r0 @ continue native execution 9196 b toInterpreter @ didn't chain - resume with interpreter 9197 9198/* 9199 * Return from the translation cache to the interpreter to do method invocation. 9200 * Check if translation exists for the callee, but don't chain to it. 9201 */ 9202 .global dvmJitToInterpNoChain 9203dvmJitToInterpNoChain: 9204#ifdef EXIT_STATS 9205 bl dvmBumpNoChain 9206#endif 9207 mov r0,rPC 9208 bl dvmJitGetCodeAddr @ Is there a translation? 9209 mov r1, rPC @ arg1 of translation may need this 9210 mov lr, #0 @ in case target is HANDLER_INTERPRET 9211 cmp r0,#0 9212 bxne r0 @ continue native execution if so 9213#endif 9214 9215/* 9216 * No translation, restore interpreter regs and start interpreting. 9217 * rGLUE & rFP were preserved in the translated code, and rPC has 9218 * already been restored by the time we get here. We'll need to set 9219 * up rIBASE & rINST, and load the address of the JitTable into r0. 9220 */ 9221toInterpreter: 9222 EXPORT_PC() 9223 adrl rIBASE, dvmAsmInstructionStart 9224 FETCH_INST() 9225 GET_JIT_PROF_TABLE(r0) 9226 @ NOTE: intended fallthrough 9227/* 9228 * Common code to update potential trace start counter, and initiate 9229 * a trace-build if appropriate. On entry, rPC should point to the 9230 * next instruction to execute, and rINST should be already loaded with 9231 * the next opcode word, and r0 holds a pointer to the jit profile 9232 * table (pJitProfTable). 9233 */ 9234common_testUpdateProfile: 9235 cmp r0,#0 9236 GET_INST_OPCODE(ip) 9237 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9238 9239common_updateProfile: 9240 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9241 lsl r3,r3,#21 @ shift out excess 2047 9242 ldrb r1,[r0,r3,lsr #21] @ get counter 9243 GET_INST_OPCODE(ip) 9244 subs r1,r1,#1 @ decrement counter 9245 strb r1,[r0,r3,lsr #21] @ and store it 9246 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9247 9248/* 9249 * Here, we switch to the debug interpreter to request 9250 * trace selection. First, though, check to see if there 9251 * is already a native translation in place (and, if so, 9252 * jump to it now). 9253 */ 9254 GET_JIT_THRESHOLD(r1) 9255 strb r1,[r0,r3,lsr #21] @ reset counter 9256 EXPORT_PC() 9257 mov r0,rPC 9258 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9259 mov r1, rPC @ arg1 of translation may need this 9260 mov lr, #0 @ in case target is HANDLER_INTERPRET 9261 cmp r0,#0 9262#if !defined(WITH_SELF_VERIFICATION) 9263 bxne r0 @ jump to the translation 9264#else 9265 beq common_selectTrace 9266 /* 9267 * At this point, we have a target translation. However, if 9268 * that translation is actually the interpret-only pseudo-translation 9269 * we want to treat it the same as no translation. 9270 */ 9271 mov r10, r0 @ save target 9272 bl dvmCompilerGetInterpretTemplate 9273 cmp r0, r10 @ special case? 9274 bne dvmJitSelfVerificationStart @ set up self verification 9275 GET_INST_OPCODE(ip) 9276 GOTO_OPCODE(ip) 9277 /* no return */ 9278#endif 9279 9280common_selectTrace: 9281 mov r2,#kJitTSelectRequest @ ask for trace selection 9282 str r2,[rGLUE,#offGlue_jitState] 9283 mov r2,#kInterpEntryInstr @ normal entry reason 9284 str r2,[rGLUE,#offGlue_entryPoint] 9285 mov r1,#1 @ set changeInterp 9286 b common_gotoBail 9287 9288#if defined(WITH_SELF_VERIFICATION) 9289/* 9290 * Save PC and registers to shadow memory for self verification mode 9291 * before jumping to native translation. 9292 * On entry, r10 contains the address of the target translation. 9293 */ 9294dvmJitSelfVerificationStart: 9295 mov r0,rPC @ r0<- program counter 9296 mov r1,rFP @ r1<- frame pointer 9297 mov r2,rGLUE @ r2<- InterpState pointer 9298 mov r3,r10 @ r3<- target translation 9299 bl dvmSelfVerificationSaveState @ save registers to shadow space 9300 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9301 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9302 bx r10 @ jump to the translation 9303 9304/* 9305 * Restore PC, registers, and interpState to original values 9306 * before jumping back to the interpreter. 9307 */ 9308dvmJitSelfVerificationEnd: 9309 mov r1,rFP @ pass ending fp 9310 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9311 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9312 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9313 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9314 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9315 cmp r1,#0 @ check for punt condition 9316 beq 1f 9317 mov r2,#kJitSelfVerification @ ask for self verification 9318 str r2,[rGLUE,#offGlue_jitState] 9319 mov r2,#kInterpEntryInstr @ normal entry reason 9320 str r2,[rGLUE,#offGlue_entryPoint] 9321 mov r1,#1 @ set changeInterp 9322 b common_gotoBail 9323 93241: @ exit to interpreter without check 9325 EXPORT_PC() 9326 adrl rIBASE, dvmAsmInstructionStart 9327 FETCH_INST() 9328 GET_INST_OPCODE(ip) 9329 GOTO_OPCODE(ip) 9330#endif 9331 9332#endif 9333 9334/* 9335 * Common code when a backward branch is taken. 9336 * 9337 * On entry: 9338 * r9 is PC adjustment *in bytes* 9339 */ 9340common_backwardBranch: 9341 mov r0, #kInterpEntryInstr 9342 bl common_periodicChecks 9343#if defined(WITH_JIT) 9344 GET_JIT_PROF_TABLE(r0) 9345 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9346 cmp r0,#0 9347 bne common_updateProfile 9348 GET_INST_OPCODE(ip) 9349 GOTO_OPCODE(ip) 9350#else 9351 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9352 GET_INST_OPCODE(ip) @ extract opcode from rINST 9353 GOTO_OPCODE(ip) @ jump to next instruction 9354#endif 9355 9356 9357/* 9358 * Need to see if the thread needs to be suspended or debugger/profiler 9359 * activity has begun. 9360 * 9361 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9362 * have to do the second ldr. 9363 * 9364 * TODO: reduce this so we're just checking a single location. 9365 * 9366 * On entry: 9367 * r0 is reentry type, e.g. kInterpEntryInstr 9368 * r9 is trampoline PC adjustment *in bytes* 9369 */ 9370common_periodicChecks: 9371 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9372 9373 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9374 str r0, [rGLUE, #offGlue_entryPoint] 9375 9376#if defined(WITH_DEBUGGER) 9377 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9378#endif 9379#if defined(WITH_PROFILER) 9380 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9381#endif 9382 9383 ldr r3, [r3] @ r3<- suspendCount (int) 9384 9385#if defined(WITH_DEBUGGER) 9386 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9387#endif 9388#if defined (WITH_PROFILER) 9389 ldr r2, [r2] @ r2<- activeProfilers (int) 9390#endif 9391 9392 cmp r3, #0 @ suspend pending? 9393 bne 2f @ yes, do full suspension check 9394 9395#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9396# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9397 orrs r1, r1, r2 @ r1<- r1 | r2 9398 cmp r1, #0 @ debugger attached or profiler started? 9399# elif defined(WITH_DEBUGGER) 9400 cmp r1, #0 @ debugger attached? 9401# elif defined(WITH_PROFILER) 9402 cmp r2, #0 @ profiler started? 9403# endif 9404 bne 3f @ debugger/profiler, switch interp 9405#endif 9406 9407 bx lr @ nothing to do, return 9408 94092: @ check suspend 9410 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9411 EXPORT_PC() @ need for precise GC 9412 b dvmCheckSuspendPending @ suspend if necessary, then return 9413 94143: @ debugger/profiler enabled, bail out 9415 add rPC, rPC, r9 @ update rPC 9416 mov r1, #1 @ "want switch" = true 9417 b common_gotoBail 9418 9419 9420/* 9421 * The equivalent of "goto bail", this calls through the "bail handler". 9422 * 9423 * State registers will be saved to the "glue" area before bailing. 9424 * 9425 * On entry: 9426 * r1 is "bool changeInterp", indicating if we want to switch to the 9427 * other interpreter or just bail all the way out 9428 */ 9429common_gotoBail: 9430 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9431 mov r0, rGLUE @ r0<- glue ptr 9432 b dvmMterpStdBail @ call(glue, changeInterp) 9433 9434 @add r1, r1, #1 @ using (boolean+1) 9435 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9436 @bl _longjmp @ does not return 9437 @bl common_abort 9438 9439 9440/* 9441 * Common code for method invocation with range. 9442 * 9443 * On entry: 9444 * r0 is "Method* methodToCall", the method we're trying to call 9445 */ 9446common_invokeMethodRange: 9447.LinvokeNewRange: 9448 @ prepare to copy args to "outs" area of current frame 9449 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9450 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9451 beq .LinvokeArgsDone @ if no args, skip the rest 9452 FETCH(r1, 2) @ r1<- CCCC 9453 9454 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9455 @ (very few methods have > 10 args; could unroll for common cases) 9456 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9457 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9458 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94591: ldr r1, [r3], #4 @ val = *fp++ 9460 subs r2, r2, #1 @ count-- 9461 str r1, [r10], #4 @ *outs++ = val 9462 bne 1b @ ...while count != 0 9463 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9464 b .LinvokeArgsDone 9465 9466/* 9467 * Common code for method invocation without range. 9468 * 9469 * On entry: 9470 * r0 is "Method* methodToCall", the method we're trying to call 9471 */ 9472common_invokeMethodNoRange: 9473.LinvokeNewNoRange: 9474 @ prepare to copy args to "outs" area of current frame 9475 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9476 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9477 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9478 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9479 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9480 beq .LinvokeArgsDone 9481 9482 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9483.LinvokeNonRange: 9484 rsb r2, r2, #5 @ r2<- 5-r2 9485 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9486 bl common_abort @ (skipped due to ARM prefetch) 94875: and ip, rINST, #0x0f00 @ isolate A 9488 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9489 mov r0, r0 @ nop 9490 str r2, [r10, #-4]! @ *--outs = vA 94914: and ip, r1, #0xf000 @ isolate G 9492 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9493 mov r0, r0 @ nop 9494 str r2, [r10, #-4]! @ *--outs = vG 94953: and ip, r1, #0x0f00 @ isolate F 9496 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9497 mov r0, r0 @ nop 9498 str r2, [r10, #-4]! @ *--outs = vF 94992: and ip, r1, #0x00f0 @ isolate E 9500 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9501 mov r0, r0 @ nop 9502 str r2, [r10, #-4]! @ *--outs = vE 95031: and ip, r1, #0x000f @ isolate D 9504 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9505 mov r0, r0 @ nop 9506 str r2, [r10, #-4]! @ *--outs = vD 95070: @ fall through to .LinvokeArgsDone 9508 9509.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9510 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9511 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9512 @ find space for the new stack frame, check for overflow 9513 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9514 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9515 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9516@ bl common_dumpRegs 9517 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9518 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9519 cmp r3, r9 @ bottom < interpStackEnd? 9520 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9521 blt .LstackOverflow @ yes, this frame will overflow stack 9522 9523 @ set up newSaveArea 9524#ifdef EASY_GDB 9525 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9526 str ip, [r10, #offStackSaveArea_prevSave] 9527#endif 9528 str rFP, [r10, #offStackSaveArea_prevFrame] 9529 str rPC, [r10, #offStackSaveArea_savedPc] 9530#if defined(WITH_JIT) 9531 mov r9, #0 9532 str r9, [r10, #offStackSaveArea_returnAddr] 9533#endif 9534 str r0, [r10, #offStackSaveArea_method] 9535 tst r3, #ACC_NATIVE 9536 bne .LinvokeNative 9537 9538 /* 9539 stmfd sp!, {r0-r3} 9540 bl common_printNewline 9541 mov r0, rFP 9542 mov r1, #0 9543 bl dvmDumpFp 9544 ldmfd sp!, {r0-r3} 9545 stmfd sp!, {r0-r3} 9546 mov r0, r1 9547 mov r1, r10 9548 bl dvmDumpFp 9549 bl common_printNewline 9550 ldmfd sp!, {r0-r3} 9551 */ 9552 9553 ldrh r9, [r2] @ r9 <- load INST from new PC 9554 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9555 mov rPC, r2 @ publish new rPC 9556 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9557 9558 @ Update "glue" values for the new method 9559 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9560 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9561 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9562#if defined(WITH_JIT) 9563 GET_JIT_PROF_TABLE(r0) 9564 mov rFP, r1 @ fp = newFp 9565 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9566 mov rINST, r9 @ publish new rINST 9567 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9568 cmp r0,#0 9569 bne common_updateProfile 9570 GOTO_OPCODE(ip) @ jump to next instruction 9571#else 9572 mov rFP, r1 @ fp = newFp 9573 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9574 mov rINST, r9 @ publish new rINST 9575 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9576 GOTO_OPCODE(ip) @ jump to next instruction 9577#endif 9578 9579.LinvokeNative: 9580 @ Prep for the native call 9581 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9582 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9583 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9584 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9585 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9586 mov r9, r3 @ r9<- glue->self (preserve) 9587 9588 mov r2, r0 @ r2<- methodToCall 9589 mov r0, r1 @ r0<- newFp (points to args) 9590 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9591 9592#ifdef ASSIST_DEBUGGER 9593 /* insert fake function header to help gdb find the stack frame */ 9594 b .Lskip 9595 .type dalvik_mterp, %function 9596dalvik_mterp: 9597 .fnstart 9598 MTERP_ENTRY1 9599 MTERP_ENTRY2 9600.Lskip: 9601#endif 9602 9603 @mov lr, pc @ set return addr 9604 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9605 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9606 9607 @ native return; r9=self, r10=newSaveArea 9608 @ equivalent to dvmPopJniLocals 9609 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9610 ldr r1, [r9, #offThread_exception] @ check for exception 9611 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9612 cmp r1, #0 @ null? 9613 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9614 bne common_exceptionThrown @ no, handle exception 9615 9616 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9617 GET_INST_OPCODE(ip) @ extract opcode from rINST 9618 GOTO_OPCODE(ip) @ jump to next instruction 9619 9620.LstackOverflow: @ r0=methodToCall 9621 mov r1, r0 @ r1<- methodToCall 9622 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9623 bl dvmHandleStackOverflow 9624 b common_exceptionThrown 9625#ifdef ASSIST_DEBUGGER 9626 .fnend 9627#endif 9628 9629 9630 /* 9631 * Common code for method invocation, calling through "glue code". 9632 * 9633 * TODO: now that we have range and non-range invoke handlers, this 9634 * needs to be split into two. Maybe just create entry points 9635 * that set r9 and jump here? 9636 * 9637 * On entry: 9638 * r0 is "Method* methodToCall", the method we're trying to call 9639 * r9 is "bool methodCallRange", indicating if this is a /range variant 9640 */ 9641 .if 0 9642.LinvokeOld: 9643 sub sp, sp, #8 @ space for args + pad 9644 FETCH(ip, 2) @ ip<- FEDC or CCCC 9645 mov r2, r0 @ A2<- methodToCall 9646 mov r0, rGLUE @ A0<- glue 9647 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9648 mov r1, r9 @ A1<- methodCallRange 9649 mov r3, rINST, lsr #8 @ A3<- AA 9650 str ip, [sp, #0] @ A4<- ip 9651 bl dvmMterp_invokeMethod @ call the C invokeMethod 9652 add sp, sp, #8 @ remove arg area 9653 b common_resumeAfterGlueCall @ continue to next instruction 9654 .endif 9655 9656 9657 9658/* 9659 * Common code for handling a return instruction. 9660 * 9661 * This does not return. 9662 */ 9663common_returnFromMethod: 9664.LreturnNew: 9665 mov r0, #kInterpEntryReturn 9666 mov r9, #0 9667 bl common_periodicChecks 9668 9669 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9670 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9671 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9672 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9673 @ r2<- method we're returning to 9674 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9675 cmp r2, #0 @ is this a break frame? 9676 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9677 mov r1, #0 @ "want switch" = false 9678 beq common_gotoBail @ break frame, bail out completely 9679 9680 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9681 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9682 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9683 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9684#if defined(WITH_JIT) 9685 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr 9686 GET_JIT_PROF_TABLE(r0) 9687 mov rPC, r9 @ publish new rPC 9688 str r1, [rGLUE, #offGlue_methodClassDex] 9689 cmp r3, #0 @ caller is compiled code 9690 blxne r3 9691 GET_INST_OPCODE(ip) @ extract opcode from rINST 9692 cmp r0,#0 9693 bne common_updateProfile 9694 GOTO_OPCODE(ip) @ jump to next instruction 9695#else 9696 GET_INST_OPCODE(ip) @ extract opcode from rINST 9697 mov rPC, r9 @ publish new rPC 9698 str r1, [rGLUE, #offGlue_methodClassDex] 9699 GOTO_OPCODE(ip) @ jump to next instruction 9700#endif 9701 9702 /* 9703 * Return handling, calls through "glue code". 9704 */ 9705 .if 0 9706.LreturnOld: 9707 SAVE_PC_FP_TO_GLUE() @ export state 9708 mov r0, rGLUE @ arg to function 9709 bl dvmMterp_returnFromMethod 9710 b common_resumeAfterGlueCall 9711 .endif 9712 9713 9714/* 9715 * Somebody has thrown an exception. Handle it. 9716 * 9717 * If the exception processing code returns to us (instead of falling 9718 * out of the interpreter), continue with whatever the next instruction 9719 * now happens to be. 9720 * 9721 * This does not return. 9722 */ 9723 .global dvmMterpCommonExceptionThrown 9724dvmMterpCommonExceptionThrown: 9725common_exceptionThrown: 9726.LexceptionNew: 9727 mov r0, #kInterpEntryThrow 9728 mov r9, #0 9729 bl common_periodicChecks 9730 9731#if defined(WITH_JIT) 9732 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 9733 str r2,[rGLUE,#offGlue_jitState] 9734#endif 9735 9736 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9737 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9738 mov r1, r10 @ r1<- self 9739 mov r0, r9 @ r0<- exception 9740 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9741 mov r3, #0 @ r3<- NULL 9742 str r3, [r10, #offThread_exception] @ self->exception = NULL 9743 9744 /* set up args and a local for "&fp" */ 9745 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9746 str rFP, [sp, #-4]! @ *--sp = fp 9747 mov ip, sp @ ip<- &fp 9748 mov r3, #0 @ r3<- false 9749 str ip, [sp, #-4]! @ *--sp = &fp 9750 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9751 mov r0, r10 @ r0<- self 9752 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9753 mov r2, r9 @ r2<- exception 9754 sub r1, rPC, r1 @ r1<- pc - method->insns 9755 mov r1, r1, asr #1 @ r1<- offset in code units 9756 9757 /* call, r0 gets catchRelPc (a code-unit offset) */ 9758 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9759 9760 /* fix earlier stack overflow if necessary; may trash rFP */ 9761 ldrb r1, [r10, #offThread_stackOverflowed] 9762 cmp r1, #0 @ did we overflow earlier? 9763 beq 1f @ no, skip ahead 9764 mov rFP, r0 @ save relPc result in rFP 9765 mov r0, r10 @ r0<- self 9766 bl dvmCleanupStackOverflow @ call(self) 9767 mov r0, rFP @ restore result 97681: 9769 9770 /* update frame pointer and check result from dvmFindCatchBlock */ 9771 ldr rFP, [sp, #4] @ retrieve the updated rFP 9772 cmp r0, #0 @ is catchRelPc < 0? 9773 add sp, sp, #8 @ restore stack 9774 bmi .LnotCaughtLocally 9775 9776 /* adjust locals to match self->curFrame and updated PC */ 9777 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9778 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9779 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9780 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9781 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9782 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9783 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9784 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9785 9786 /* release the tracked alloc on the exception */ 9787 mov r0, r9 @ r0<- exception 9788 mov r1, r10 @ r1<- self 9789 bl dvmReleaseTrackedAlloc @ release the exception 9790 9791 /* restore the exception if the handler wants it */ 9792 FETCH_INST() @ load rINST from rPC 9793 GET_INST_OPCODE(ip) @ extract opcode from rINST 9794 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9795 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9796 GOTO_OPCODE(ip) @ jump to next instruction 9797 9798.LnotCaughtLocally: @ r9=exception, r10=self 9799 /* fix stack overflow if necessary */ 9800 ldrb r1, [r10, #offThread_stackOverflowed] 9801 cmp r1, #0 @ did we overflow earlier? 9802 movne r0, r10 @ if yes: r0<- self 9803 blne dvmCleanupStackOverflow @ if yes: call(self) 9804 9805 @ may want to show "not caught locally" debug messages here 9806#if DVM_SHOW_EXCEPTION >= 2 9807 /* call __android_log_print(prio, tag, format, ...) */ 9808 /* "Exception %s from %s:%d not caught locally" */ 9809 @ dvmLineNumFromPC(method, pc - method->insns) 9810 ldr r0, [rGLUE, #offGlue_method] 9811 ldr r1, [r0, #offMethod_insns] 9812 sub r1, rPC, r1 9813 asr r1, r1, #1 9814 bl dvmLineNumFromPC 9815 str r0, [sp, #-4]! 9816 @ dvmGetMethodSourceFile(method) 9817 ldr r0, [rGLUE, #offGlue_method] 9818 bl dvmGetMethodSourceFile 9819 str r0, [sp, #-4]! 9820 @ exception->clazz->descriptor 9821 ldr r3, [r9, #offObject_clazz] 9822 ldr r3, [r3, #offClassObject_descriptor] 9823 @ 9824 ldr r2, strExceptionNotCaughtLocally 9825 ldr r1, strLogTag 9826 mov r0, #3 @ LOG_DEBUG 9827 bl __android_log_print 9828#endif 9829 str r9, [r10, #offThread_exception] @ restore exception 9830 mov r0, r9 @ r0<- exception 9831 mov r1, r10 @ r1<- self 9832 bl dvmReleaseTrackedAlloc @ release the exception 9833 mov r1, #0 @ "want switch" = false 9834 b common_gotoBail @ bail out 9835 9836 9837 /* 9838 * Exception handling, calls through "glue code". 9839 */ 9840 .if 0 9841.LexceptionOld: 9842 SAVE_PC_FP_TO_GLUE() @ export state 9843 mov r0, rGLUE @ arg to function 9844 bl dvmMterp_exceptionThrown 9845 b common_resumeAfterGlueCall 9846 .endif 9847 9848 9849/* 9850 * After returning from a "glued" function, pull out the updated 9851 * values and start executing at the next instruction. 9852 */ 9853common_resumeAfterGlueCall: 9854 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9855 FETCH_INST() @ load rINST from rPC 9856 GET_INST_OPCODE(ip) @ extract opcode from rINST 9857 GOTO_OPCODE(ip) @ jump to next instruction 9858 9859/* 9860 * Invalid array index. 9861 */ 9862common_errArrayIndex: 9863 EXPORT_PC() 9864 ldr r0, strArrayIndexException 9865 mov r1, #0 9866 bl dvmThrowException 9867 b common_exceptionThrown 9868 9869/* 9870 * Invalid array value. 9871 */ 9872common_errArrayStore: 9873 EXPORT_PC() 9874 ldr r0, strArrayStoreException 9875 mov r1, #0 9876 bl dvmThrowException 9877 b common_exceptionThrown 9878 9879/* 9880 * Integer divide or mod by zero. 9881 */ 9882common_errDivideByZero: 9883 EXPORT_PC() 9884 ldr r0, strArithmeticException 9885 ldr r1, strDivideByZero 9886 bl dvmThrowException 9887 b common_exceptionThrown 9888 9889/* 9890 * Attempt to allocate an array with a negative size. 9891 */ 9892common_errNegativeArraySize: 9893 EXPORT_PC() 9894 ldr r0, strNegativeArraySizeException 9895 mov r1, #0 9896 bl dvmThrowException 9897 b common_exceptionThrown 9898 9899/* 9900 * Invocation of a non-existent method. 9901 */ 9902common_errNoSuchMethod: 9903 EXPORT_PC() 9904 ldr r0, strNoSuchMethodError 9905 mov r1, #0 9906 bl dvmThrowException 9907 b common_exceptionThrown 9908 9909/* 9910 * We encountered a null object when we weren't expecting one. We 9911 * export the PC, throw a NullPointerException, and goto the exception 9912 * processing code. 9913 */ 9914common_errNullObject: 9915 EXPORT_PC() 9916 ldr r0, strNullPointerException 9917 mov r1, #0 9918 bl dvmThrowException 9919 b common_exceptionThrown 9920 9921/* 9922 * For debugging, cause an immediate fault. The source address will 9923 * be in lr (use a bl instruction to jump here). 9924 */ 9925common_abort: 9926 ldr pc, .LdeadFood 9927.LdeadFood: 9928 .word 0xdeadf00d 9929 9930/* 9931 * Spit out a "we were here", preserving all registers. (The attempt 9932 * to save ip won't work, but we need to save an even number of 9933 * registers for EABI 64-bit stack alignment.) 9934 */ 9935 .macro SQUEAK num 9936common_squeak\num: 9937 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9938 ldr r0, strSqueak 9939 mov r1, #\num 9940 bl printf 9941 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9942 bx lr 9943 .endm 9944 9945 SQUEAK 0 9946 SQUEAK 1 9947 SQUEAK 2 9948 SQUEAK 3 9949 SQUEAK 4 9950 SQUEAK 5 9951 9952/* 9953 * Spit out the number in r0, preserving registers. 9954 */ 9955common_printNum: 9956 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9957 mov r1, r0 9958 ldr r0, strSqueak 9959 bl printf 9960 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9961 bx lr 9962 9963/* 9964 * Print a newline, preserving registers. 9965 */ 9966common_printNewline: 9967 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9968 ldr r0, strNewline 9969 bl printf 9970 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9971 bx lr 9972 9973 /* 9974 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9975 */ 9976common_printHex: 9977 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9978 mov r1, r0 9979 ldr r0, strPrintHex 9980 bl printf 9981 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9982 bx lr 9983 9984/* 9985 * Print the 64-bit quantity in r0-r1, preserving registers. 9986 */ 9987common_printLong: 9988 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9989 mov r3, r1 9990 mov r2, r0 9991 ldr r0, strPrintLong 9992 bl printf 9993 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9994 bx lr 9995 9996/* 9997 * Print full method info. Pass the Method* in r0. Preserves regs. 9998 */ 9999common_printMethod: 10000 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10001 bl dvmMterpPrintMethod 10002 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10003 bx lr 10004 10005/* 10006 * Call a C helper function that dumps regs and possibly some 10007 * additional info. Requires the C function to be compiled in. 10008 */ 10009 .if 0 10010common_dumpRegs: 10011 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10012 bl dvmMterpDumpArmRegs 10013 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10014 bx lr 10015 .endif 10016 10017#if 0 10018/* 10019 * Experiment on VFP mode. 10020 * 10021 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10022 * 10023 * Updates the bits specified by "mask", setting them to the values in "val". 10024 */ 10025setFPSCR: 10026 and r0, r0, r1 @ make sure no stray bits are set 10027 fmrx r2, fpscr @ get VFP reg 10028 mvn r1, r1 @ bit-invert mask 10029 and r2, r2, r1 @ clear masked bits 10030 orr r2, r2, r0 @ set specified bits 10031 fmxr fpscr, r2 @ set VFP reg 10032 mov r0, r2 @ return new value 10033 bx lr 10034 10035 .align 2 10036 .global dvmConfigureFP 10037 .type dvmConfigureFP, %function 10038dvmConfigureFP: 10039 stmfd sp!, {ip, lr} 10040 /* 0x03000000 sets DN/FZ */ 10041 /* 0x00009f00 clears the six exception enable flags */ 10042 bl common_squeak0 10043 mov r0, #0x03000000 @ r0<- 0x03000000 10044 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10045 bl setFPSCR 10046 ldmfd sp!, {ip, pc} 10047#endif 10048 10049 10050/* 10051 * String references, must be close to the code that uses them. 10052 */ 10053 .align 2 10054strArithmeticException: 10055 .word .LstrArithmeticException 10056strArrayIndexException: 10057 .word .LstrArrayIndexException 10058strArrayStoreException: 10059 .word .LstrArrayStoreException 10060strDivideByZero: 10061 .word .LstrDivideByZero 10062strNegativeArraySizeException: 10063 .word .LstrNegativeArraySizeException 10064strNoSuchMethodError: 10065 .word .LstrNoSuchMethodError 10066strNullPointerException: 10067 .word .LstrNullPointerException 10068 10069strLogTag: 10070 .word .LstrLogTag 10071strExceptionNotCaughtLocally: 10072 .word .LstrExceptionNotCaughtLocally 10073 10074strNewline: 10075 .word .LstrNewline 10076strSqueak: 10077 .word .LstrSqueak 10078strPrintHex: 10079 .word .LstrPrintHex 10080strPrintLong: 10081 .word .LstrPrintLong 10082 10083/* 10084 * Zero-terminated ASCII string data. 10085 * 10086 * On ARM we have two choices: do like gcc does, and LDR from a .word 10087 * with the address, or use an ADR pseudo-op to get the address 10088 * directly. ADR saves 4 bytes and an indirection, but it's using a 10089 * PC-relative addressing mode and hence has a limited range, which 10090 * makes it not work well with mergeable string sections. 10091 */ 10092 .section .rodata.str1.4,"aMS",%progbits,1 10093 10094.LstrBadEntryPoint: 10095 .asciz "Bad entry point %d\n" 10096.LstrArithmeticException: 10097 .asciz "Ljava/lang/ArithmeticException;" 10098.LstrArrayIndexException: 10099 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10100.LstrArrayStoreException: 10101 .asciz "Ljava/lang/ArrayStoreException;" 10102.LstrClassCastException: 10103 .asciz "Ljava/lang/ClassCastException;" 10104.LstrDivideByZero: 10105 .asciz "divide by zero" 10106.LstrFilledNewArrayNotImpl: 10107 .asciz "filled-new-array only implemented for objects and 'int'" 10108.LstrInternalError: 10109 .asciz "Ljava/lang/InternalError;" 10110.LstrInstantiationError: 10111 .asciz "Ljava/lang/InstantiationError;" 10112.LstrNegativeArraySizeException: 10113 .asciz "Ljava/lang/NegativeArraySizeException;" 10114.LstrNoSuchMethodError: 10115 .asciz "Ljava/lang/NoSuchMethodError;" 10116.LstrNullPointerException: 10117 .asciz "Ljava/lang/NullPointerException;" 10118 10119.LstrLogTag: 10120 .asciz "mterp" 10121.LstrExceptionNotCaughtLocally: 10122 .asciz "Exception %s from %s:%d not caught locally\n" 10123 10124.LstrNewline: 10125 .asciz "\n" 10126.LstrSqueak: 10127 .asciz "<%d>" 10128.LstrPrintHex: 10129 .asciz "<0x%x>" 10130.LstrPrintLong: 10131 .asciz "<%lld>" 10132 10133 10134