InterpAsm-armv5te.S revision 9a8c75adb2abf551d06dbf757bff558c1feded08
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_ENABLED(_reg) ldr _reg,[rGLUE,#offGlue_jitEnabled] 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204 205/* File: armv5te/platform.S */ 206/* 207 * =========================================================================== 208 * CPU-version-specific defines 209 * =========================================================================== 210 */ 211 212/* 213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 214 * one-way branch. 215 * 216 * May modify IP. Does not modify LR. 217 */ 218.macro LDR_PC source 219 ldr pc, \source 220.endm 221 222/* 223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 224 * Jump to subroutine. 225 * 226 * May modify IP and LR. 227 */ 228.macro LDR_PC_LR source 229 mov lr, pc 230 ldr pc, \source 231.endm 232 233/* 234 * Macro for "LDMFD SP!, {...regs...,PC}". 235 * 236 * May modify IP and LR. 237 */ 238.macro LDMFD_PC regs 239 ldmfd sp!, {\regs,pc} 240.endm 241 242 243/* File: armv5te/entry.S */ 244/* 245 * Copyright (C) 2008 The Android Open Source Project 246 * 247 * Licensed under the Apache License, Version 2.0 (the "License"); 248 * you may not use this file except in compliance with the License. 249 * You may obtain a copy of the License at 250 * 251 * http://www.apache.org/licenses/LICENSE-2.0 252 * 253 * Unless required by applicable law or agreed to in writing, software 254 * distributed under the License is distributed on an "AS IS" BASIS, 255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 256 * See the License for the specific language governing permissions and 257 * limitations under the License. 258 */ 259/* 260 * Interpreter entry point. 261 */ 262 263/* 264 * We don't have formal stack frames, so gdb scans upward in the code 265 * to find the start of the function (a label with the %function type), 266 * and then looks at the next few instructions to figure out what 267 * got pushed onto the stack. From this it figures out how to restore 268 * the registers, including PC, for the previous stack frame. If gdb 269 * sees a non-function label, it stops scanning, so either we need to 270 * have nothing but assembler-local labels between the entry point and 271 * the break, or we need to fake it out. 272 * 273 * When this is defined, we add some stuff to make gdb less confused. 274 */ 275#define ASSIST_DEBUGGER 1 276 277 .text 278 .align 2 279 .global dvmMterpStdRun 280 .type dvmMterpStdRun, %function 281 282/* 283 * On entry: 284 * r0 MterpGlue* glue 285 * 286 * This function returns a boolean "changeInterp" value. The return comes 287 * via a call to dvmMterpStdBail(). 288 */ 289dvmMterpStdRun: 290#define MTERP_ENTRY1 \ 291 .save {r4-r10,fp,lr}; \ 292 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 293#define MTERP_ENTRY2 \ 294 .pad #4; \ 295 sub sp, sp, #4 @ align 64 296 297 .fnstart 298 MTERP_ENTRY1 299 MTERP_ENTRY2 300 301 /* save stack pointer, add magic word for debuggerd */ 302 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 303 304 /* set up "named" registers, figure out entry point */ 305 mov rGLUE, r0 @ set rGLUE 306 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 307 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 308 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 309 cmp r1, #kInterpEntryInstr @ usual case? 310 bne .Lnot_instr @ no, handle it 311 312#if defined(WITH_JIT) 313.Lno_singleStep: 314 /* Entry is always a possible trace start */ 315 GET_JIT_PROF_TABLE(r0) 316 FETCH_INST() 317 cmp r0,#0 318 bne common_updateProfile 319 GET_INST_OPCODE(ip) 320 GOTO_OPCODE(ip) 321#else 322 /* start executing the instruction at rPC */ 323 FETCH_INST() @ load rINST from rPC 324 GET_INST_OPCODE(ip) @ extract opcode from rINST 325 GOTO_OPCODE(ip) @ jump to next instruction 326#endif 327 328.Lnot_instr: 329 cmp r1, #kInterpEntryReturn @ were we returning from a method? 330 beq common_returnFromMethod 331 332.Lnot_return: 333 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 334 beq common_exceptionThrown 335 336#if defined(WITH_JIT) 337.Lnot_throw: 338 ldr r0,[rGLUE, #offGlue_jitResume] 339 ldr r2,[rGLUE, #offGlue_jitResumePC] 340 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 341 bne .Lbad_arg 342 cmp rPC,r2 343 bne .Lno_singleStep @ must have branched, don't resume 344 mov r1, #kInterpEntryInstr 345 strb r1, [rGLUE, #offGlue_entryPoint] 346 ldr rINST, .LdvmCompilerTemplate 347 bx r0 @ re-enter the translation 348.LdvmCompilerTemplate: 349 .word dvmCompilerTemplateStart 350#endif 351 352.Lbad_arg: 353 ldr r0, strBadEntryPoint 354 @ r1 holds value of entryPoint 355 bl printf 356 bl dvmAbort 357 .fnend 358 359 360 .global dvmMterpStdBail 361 .type dvmMterpStdBail, %function 362 363/* 364 * Restore the stack pointer and PC from the save point established on entry. 365 * This is essentially the same as a longjmp, but should be cheaper. The 366 * last instruction causes us to return to whoever called dvmMterpStdRun. 367 * 368 * We pushed some registers on the stack in dvmMterpStdRun, then saved 369 * SP and LR. Here we restore SP, restore the registers, and then restore 370 * LR to PC. 371 * 372 * On entry: 373 * r0 MterpGlue* glue 374 * r1 bool changeInterp 375 */ 376dvmMterpStdBail: 377 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 378 mov r0, r1 @ return the changeInterp value 379 add sp, sp, #4 @ un-align 64 380 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 381 382 383/* 384 * String references. 385 */ 386strBadEntryPoint: 387 .word .LstrBadEntryPoint 388 389 390 391 .global dvmAsmInstructionStart 392 .type dvmAsmInstructionStart, %function 393dvmAsmInstructionStart = .L_OP_NOP 394 .text 395 396/* ------------------------------ */ 397 .balign 64 398.L_OP_NOP: /* 0x00 */ 399/* File: armv5te/OP_NOP.S */ 400 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 401 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 402 GOTO_OPCODE(ip) @ execute it 403 404#ifdef ASSIST_DEBUGGER 405 /* insert fake function header to help gdb find the stack frame */ 406 .type dalvik_inst, %function 407dalvik_inst: 408 .fnstart 409 MTERP_ENTRY1 410 MTERP_ENTRY2 411 .fnend 412#endif 413 414 415/* ------------------------------ */ 416 .balign 64 417.L_OP_MOVE: /* 0x01 */ 418/* File: armv5te/OP_MOVE.S */ 419 /* for move, move-object, long-to-int */ 420 /* op vA, vB */ 421 mov r1, rINST, lsr #12 @ r1<- B from 15:12 422 mov r0, rINST, lsr #8 @ r0<- A from 11:8 423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 424 GET_VREG(r2, r1) @ r2<- fp[B] 425 and r0, r0, #15 426 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 427 SET_VREG(r2, r0) @ fp[A]<- r2 428 GOTO_OPCODE(ip) @ execute next instruction 429 430 431/* ------------------------------ */ 432 .balign 64 433.L_OP_MOVE_FROM16: /* 0x02 */ 434/* File: armv5te/OP_MOVE_FROM16.S */ 435 /* for: move/from16, move-object/from16 */ 436 /* op vAA, vBBBB */ 437 FETCH(r1, 1) @ r1<- BBBB 438 mov r0, rINST, lsr #8 @ r0<- AA 439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 440 GET_VREG(r2, r1) @ r2<- fp[BBBB] 441 GET_INST_OPCODE(ip) @ extract opcode from rINST 442 SET_VREG(r2, r0) @ fp[AA]<- r2 443 GOTO_OPCODE(ip) @ jump to next instruction 444 445 446/* ------------------------------ */ 447 .balign 64 448.L_OP_MOVE_16: /* 0x03 */ 449/* File: armv5te/OP_MOVE_16.S */ 450 /* for: move/16, move-object/16 */ 451 /* op vAAAA, vBBBB */ 452 FETCH(r1, 2) @ r1<- BBBB 453 FETCH(r0, 1) @ r0<- AAAA 454 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 455 GET_VREG(r2, r1) @ r2<- fp[BBBB] 456 GET_INST_OPCODE(ip) @ extract opcode from rINST 457 SET_VREG(r2, r0) @ fp[AAAA]<- r2 458 GOTO_OPCODE(ip) @ jump to next instruction 459 460 461/* ------------------------------ */ 462 .balign 64 463.L_OP_MOVE_WIDE: /* 0x04 */ 464/* File: armv5te/OP_MOVE_WIDE.S */ 465 /* move-wide vA, vB */ 466 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 467 mov r2, rINST, lsr #8 @ r2<- A(+) 468 mov r3, rINST, lsr #12 @ r3<- B 469 and r2, r2, #15 470 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 471 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 472 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 473 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 474 GET_INST_OPCODE(ip) @ extract opcode from rINST 475 stmia r2, {r0-r1} @ fp[A]<- r0/r1 476 GOTO_OPCODE(ip) @ jump to next instruction 477 478 479/* ------------------------------ */ 480 .balign 64 481.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 482/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 483 /* move-wide/from16 vAA, vBBBB */ 484 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 485 FETCH(r3, 1) @ r3<- BBBB 486 mov r2, rINST, lsr #8 @ r2<- AA 487 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 488 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 489 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 490 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 491 GET_INST_OPCODE(ip) @ extract opcode from rINST 492 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 493 GOTO_OPCODE(ip) @ jump to next instruction 494 495 496/* ------------------------------ */ 497 .balign 64 498.L_OP_MOVE_WIDE_16: /* 0x06 */ 499/* File: armv5te/OP_MOVE_WIDE_16.S */ 500 /* move-wide/16 vAAAA, vBBBB */ 501 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 502 FETCH(r3, 2) @ r3<- BBBB 503 FETCH(r2, 1) @ r2<- AAAA 504 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 505 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 506 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 507 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 508 GET_INST_OPCODE(ip) @ extract opcode from rINST 509 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 510 GOTO_OPCODE(ip) @ jump to next instruction 511 512 513/* ------------------------------ */ 514 .balign 64 515.L_OP_MOVE_OBJECT: /* 0x07 */ 516/* File: armv5te/OP_MOVE_OBJECT.S */ 517/* File: armv5te/OP_MOVE.S */ 518 /* for move, move-object, long-to-int */ 519 /* op vA, vB */ 520 mov r1, rINST, lsr #12 @ r1<- B from 15:12 521 mov r0, rINST, lsr #8 @ r0<- A from 11:8 522 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 523 GET_VREG(r2, r1) @ r2<- fp[B] 524 and r0, r0, #15 525 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 526 SET_VREG(r2, r0) @ fp[A]<- r2 527 GOTO_OPCODE(ip) @ execute next instruction 528 529 530 531/* ------------------------------ */ 532 .balign 64 533.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 534/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 535/* File: armv5te/OP_MOVE_FROM16.S */ 536 /* for: move/from16, move-object/from16 */ 537 /* op vAA, vBBBB */ 538 FETCH(r1, 1) @ r1<- BBBB 539 mov r0, rINST, lsr #8 @ r0<- AA 540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 541 GET_VREG(r2, r1) @ r2<- fp[BBBB] 542 GET_INST_OPCODE(ip) @ extract opcode from rINST 543 SET_VREG(r2, r0) @ fp[AA]<- r2 544 GOTO_OPCODE(ip) @ jump to next instruction 545 546 547 548/* ------------------------------ */ 549 .balign 64 550.L_OP_MOVE_OBJECT_16: /* 0x09 */ 551/* File: armv5te/OP_MOVE_OBJECT_16.S */ 552/* File: armv5te/OP_MOVE_16.S */ 553 /* for: move/16, move-object/16 */ 554 /* op vAAAA, vBBBB */ 555 FETCH(r1, 2) @ r1<- BBBB 556 FETCH(r0, 1) @ r0<- AAAA 557 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 558 GET_VREG(r2, r1) @ r2<- fp[BBBB] 559 GET_INST_OPCODE(ip) @ extract opcode from rINST 560 SET_VREG(r2, r0) @ fp[AAAA]<- r2 561 GOTO_OPCODE(ip) @ jump to next instruction 562 563 564 565/* ------------------------------ */ 566 .balign 64 567.L_OP_MOVE_RESULT: /* 0x0a */ 568/* File: armv5te/OP_MOVE_RESULT.S */ 569 /* for: move-result, move-result-object */ 570 /* op vAA */ 571 mov r2, rINST, lsr #8 @ r2<- AA 572 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 573 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 574 GET_INST_OPCODE(ip) @ extract opcode from rINST 575 SET_VREG(r0, r2) @ fp[AA]<- r0 576 GOTO_OPCODE(ip) @ jump to next instruction 577 578 579/* ------------------------------ */ 580 .balign 64 581.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 582/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 583 /* move-result-wide vAA */ 584 mov r2, rINST, lsr #8 @ r2<- AA 585 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 586 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 587 ldmia r3, {r0-r1} @ r0/r1<- retval.j 588 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 589 GET_INST_OPCODE(ip) @ extract opcode from rINST 590 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 591 GOTO_OPCODE(ip) @ jump to next instruction 592 593 594/* ------------------------------ */ 595 .balign 64 596.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 597/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 598/* File: armv5te/OP_MOVE_RESULT.S */ 599 /* for: move-result, move-result-object */ 600 /* op vAA */ 601 mov r2, rINST, lsr #8 @ r2<- AA 602 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 603 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 604 GET_INST_OPCODE(ip) @ extract opcode from rINST 605 SET_VREG(r0, r2) @ fp[AA]<- r0 606 GOTO_OPCODE(ip) @ jump to next instruction 607 608 609 610/* ------------------------------ */ 611 .balign 64 612.L_OP_MOVE_EXCEPTION: /* 0x0d */ 613/* File: armv5te/OP_MOVE_EXCEPTION.S */ 614 /* move-exception vAA */ 615 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 616 mov r2, rINST, lsr #8 @ r2<- AA 617 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 618 mov r1, #0 @ r1<- 0 619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 620 SET_VREG(r3, r2) @ fp[AA]<- exception obj 621 GET_INST_OPCODE(ip) @ extract opcode from rINST 622 str r1, [r0, #offThread_exception] @ dvmClearException bypass 623 GOTO_OPCODE(ip) @ jump to next instruction 624 625 626/* ------------------------------ */ 627 .balign 64 628.L_OP_RETURN_VOID: /* 0x0e */ 629/* File: armv5te/OP_RETURN_VOID.S */ 630 b common_returnFromMethod 631 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN: /* 0x0f */ 636/* File: armv5te/OP_RETURN.S */ 637 /* 638 * Return a 32-bit value. Copies the return value into the "glue" 639 * structure, then jumps to the return handler. 640 * 641 * for: return, return-object 642 */ 643 /* op vAA */ 644 mov r2, rINST, lsr #8 @ r2<- AA 645 GET_VREG(r0, r2) @ r0<- vAA 646 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 647 b common_returnFromMethod 648 649 650/* ------------------------------ */ 651 .balign 64 652.L_OP_RETURN_WIDE: /* 0x10 */ 653/* File: armv5te/OP_RETURN_WIDE.S */ 654 /* 655 * Return a 64-bit value. Copies the return value into the "glue" 656 * structure, then jumps to the return handler. 657 */ 658 /* return-wide vAA */ 659 mov r2, rINST, lsr #8 @ r2<- AA 660 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 661 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 662 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 663 stmia r3, {r0-r1} @ retval<- r0/r1 664 b common_returnFromMethod 665 666 667/* ------------------------------ */ 668 .balign 64 669.L_OP_RETURN_OBJECT: /* 0x11 */ 670/* File: armv5te/OP_RETURN_OBJECT.S */ 671/* File: armv5te/OP_RETURN.S */ 672 /* 673 * Return a 32-bit value. Copies the return value into the "glue" 674 * structure, then jumps to the return handler. 675 * 676 * for: return, return-object 677 */ 678 /* op vAA */ 679 mov r2, rINST, lsr #8 @ r2<- AA 680 GET_VREG(r0, r2) @ r0<- vAA 681 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 682 b common_returnFromMethod 683 684 685 686/* ------------------------------ */ 687 .balign 64 688.L_OP_CONST_4: /* 0x12 */ 689/* File: armv5te/OP_CONST_4.S */ 690 /* const/4 vA, #+B */ 691 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 692 mov r0, rINST, lsr #8 @ r0<- A+ 693 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 694 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 695 and r0, r0, #15 696 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 697 SET_VREG(r1, r0) @ fp[A]<- r1 698 GOTO_OPCODE(ip) @ execute next instruction 699 700 701/* ------------------------------ */ 702 .balign 64 703.L_OP_CONST_16: /* 0x13 */ 704/* File: armv5te/OP_CONST_16.S */ 705 /* const/16 vAA, #+BBBB */ 706 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 707 mov r3, rINST, lsr #8 @ r3<- AA 708 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 709 SET_VREG(r0, r3) @ vAA<- r0 710 GET_INST_OPCODE(ip) @ extract opcode from rINST 711 GOTO_OPCODE(ip) @ jump to next instruction 712 713 714/* ------------------------------ */ 715 .balign 64 716.L_OP_CONST: /* 0x14 */ 717/* File: armv5te/OP_CONST.S */ 718 /* const vAA, #+BBBBbbbb */ 719 mov r3, rINST, lsr #8 @ r3<- AA 720 FETCH(r0, 1) @ r0<- bbbb (low) 721 FETCH(r1, 2) @ r1<- BBBB (high) 722 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 723 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 724 GET_INST_OPCODE(ip) @ extract opcode from rINST 725 SET_VREG(r0, r3) @ vAA<- r0 726 GOTO_OPCODE(ip) @ jump to next instruction 727 728 729/* ------------------------------ */ 730 .balign 64 731.L_OP_CONST_HIGH16: /* 0x15 */ 732/* File: armv5te/OP_CONST_HIGH16.S */ 733 /* const/high16 vAA, #+BBBB0000 */ 734 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 735 mov r3, rINST, lsr #8 @ r3<- AA 736 mov r0, r0, lsl #16 @ r0<- BBBB0000 737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 738 SET_VREG(r0, r3) @ vAA<- r0 739 GET_INST_OPCODE(ip) @ extract opcode from rINST 740 GOTO_OPCODE(ip) @ jump to next instruction 741 742 743/* ------------------------------ */ 744 .balign 64 745.L_OP_CONST_WIDE_16: /* 0x16 */ 746/* File: armv5te/OP_CONST_WIDE_16.S */ 747 /* const-wide/16 vAA, #+BBBB */ 748 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 749 mov r3, rINST, lsr #8 @ r3<- AA 750 mov r1, r0, asr #31 @ r1<- ssssssss 751 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 752 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 753 GET_INST_OPCODE(ip) @ extract opcode from rINST 754 stmia r3, {r0-r1} @ vAA<- r0/r1 755 GOTO_OPCODE(ip) @ jump to next instruction 756 757 758/* ------------------------------ */ 759 .balign 64 760.L_OP_CONST_WIDE_32: /* 0x17 */ 761/* File: armv5te/OP_CONST_WIDE_32.S */ 762 /* const-wide/32 vAA, #+BBBBbbbb */ 763 FETCH(r0, 1) @ r0<- 0000bbbb (low) 764 mov r3, rINST, lsr #8 @ r3<- AA 765 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 766 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 767 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 768 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 769 mov r1, r0, asr #31 @ r1<- ssssssss 770 GET_INST_OPCODE(ip) @ extract opcode from rINST 771 stmia r3, {r0-r1} @ vAA<- r0/r1 772 GOTO_OPCODE(ip) @ jump to next instruction 773 774 775/* ------------------------------ */ 776 .balign 64 777.L_OP_CONST_WIDE: /* 0x18 */ 778/* File: armv5te/OP_CONST_WIDE.S */ 779 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 780 FETCH(r0, 1) @ r0<- bbbb (low) 781 FETCH(r1, 2) @ r1<- BBBB (low middle) 782 FETCH(r2, 3) @ r2<- hhhh (high middle) 783 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 784 FETCH(r3, 4) @ r3<- HHHH (high) 785 mov r9, rINST, lsr #8 @ r9<- AA 786 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 787 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 788 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 789 GET_INST_OPCODE(ip) @ extract opcode from rINST 790 stmia r9, {r0-r1} @ vAA<- r0/r1 791 GOTO_OPCODE(ip) @ jump to next instruction 792 793 794/* ------------------------------ */ 795 .balign 64 796.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 797/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 798 /* const-wide/high16 vAA, #+BBBB000000000000 */ 799 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 800 mov r3, rINST, lsr #8 @ r3<- AA 801 mov r0, #0 @ r0<- 00000000 802 mov r1, r1, lsl #16 @ r1<- BBBB0000 803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 804 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 805 GET_INST_OPCODE(ip) @ extract opcode from rINST 806 stmia r3, {r0-r1} @ vAA<- r0/r1 807 GOTO_OPCODE(ip) @ jump to next instruction 808 809 810/* ------------------------------ */ 811 .balign 64 812.L_OP_CONST_STRING: /* 0x1a */ 813/* File: armv5te/OP_CONST_STRING.S */ 814 /* const/string vAA, String@BBBB */ 815 FETCH(r1, 1) @ r1<- BBBB 816 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 817 mov r9, rINST, lsr #8 @ r9<- AA 818 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 819 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 820 cmp r0, #0 @ not yet resolved? 821 beq .LOP_CONST_STRING_resolve 822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 823 GET_INST_OPCODE(ip) @ extract opcode from rINST 824 SET_VREG(r0, r9) @ vAA<- r0 825 GOTO_OPCODE(ip) @ jump to next instruction 826 827/* ------------------------------ */ 828 .balign 64 829.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 830/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 831 /* const/string vAA, String@BBBBBBBB */ 832 FETCH(r0, 1) @ r0<- bbbb (low) 833 FETCH(r1, 2) @ r1<- BBBB (high) 834 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 835 mov r9, rINST, lsr #8 @ r9<- AA 836 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 837 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 838 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 839 cmp r0, #0 840 beq .LOP_CONST_STRING_JUMBO_resolve 841 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 842 GET_INST_OPCODE(ip) @ extract opcode from rINST 843 SET_VREG(r0, r9) @ vAA<- r0 844 GOTO_OPCODE(ip) @ jump to next instruction 845 846/* ------------------------------ */ 847 .balign 64 848.L_OP_CONST_CLASS: /* 0x1c */ 849/* File: armv5te/OP_CONST_CLASS.S */ 850 /* const/class vAA, Class@BBBB */ 851 FETCH(r1, 1) @ r1<- BBBB 852 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 853 mov r9, rINST, lsr #8 @ r9<- AA 854 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 855 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 856 cmp r0, #0 @ not yet resolved? 857 beq .LOP_CONST_CLASS_resolve 858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 859 GET_INST_OPCODE(ip) @ extract opcode from rINST 860 SET_VREG(r0, r9) @ vAA<- r0 861 GOTO_OPCODE(ip) @ jump to next instruction 862 863/* ------------------------------ */ 864 .balign 64 865.L_OP_MONITOR_ENTER: /* 0x1d */ 866/* File: armv5te/OP_MONITOR_ENTER.S */ 867 /* 868 * Synchronize on an object. 869 */ 870 /* monitor-enter vAA */ 871 mov r2, rINST, lsr #8 @ r2<- AA 872 GET_VREG(r1, r2) @ r1<- vAA (object) 873 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 874 cmp r1, #0 @ null object? 875 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 876 beq common_errNullObject @ null object, throw an exception 877 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 878 bl dvmLockObject @ call(self, obj) 879#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 880 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 881 ldr r1, [r0, #offThread_exception] @ check for exception 882 cmp r1, #0 883 bne common_exceptionThrown @ exception raised, bail out 884#endif 885 GET_INST_OPCODE(ip) @ extract opcode from rINST 886 GOTO_OPCODE(ip) @ jump to next instruction 887 888 889/* ------------------------------ */ 890 .balign 64 891.L_OP_MONITOR_EXIT: /* 0x1e */ 892/* File: armv5te/OP_MONITOR_EXIT.S */ 893 /* 894 * Unlock an object. 895 * 896 * Exceptions that occur when unlocking a monitor need to appear as 897 * if they happened at the following instruction. See the Dalvik 898 * instruction spec. 899 */ 900 /* monitor-exit vAA */ 901 mov r2, rINST, lsr #8 @ r2<- AA 902 EXPORT_PC() @ before fetch: export the PC 903 GET_VREG(r1, r2) @ r1<- vAA (object) 904 cmp r1, #0 @ null object? 905 beq common_errNullObject @ yes 906 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 907 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 908 cmp r0, #0 @ failed? 909 beq common_exceptionThrown @ yes, exception is pending 910 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 911 GET_INST_OPCODE(ip) @ extract opcode from rINST 912 GOTO_OPCODE(ip) @ jump to next instruction 913 914 915/* ------------------------------ */ 916 .balign 64 917.L_OP_CHECK_CAST: /* 0x1f */ 918/* File: armv5te/OP_CHECK_CAST.S */ 919 /* 920 * Check to see if a cast from one class to another is allowed. 921 */ 922 /* check-cast vAA, class@BBBB */ 923 mov r3, rINST, lsr #8 @ r3<- AA 924 FETCH(r2, 1) @ r2<- BBBB 925 GET_VREG(r9, r3) @ r9<- object 926 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 927 cmp r9, #0 @ is object null? 928 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 929 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 930 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 931 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 932 cmp r1, #0 @ have we resolved this before? 933 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 934.LOP_CHECK_CAST_resolved: 935 cmp r0, r1 @ same class (trivial success)? 936 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 937.LOP_CHECK_CAST_okay: 938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 939 GET_INST_OPCODE(ip) @ extract opcode from rINST 940 GOTO_OPCODE(ip) @ jump to next instruction 941 942/* ------------------------------ */ 943 .balign 64 944.L_OP_INSTANCE_OF: /* 0x20 */ 945/* File: armv5te/OP_INSTANCE_OF.S */ 946 /* 947 * Check to see if an object reference is an instance of a class. 948 * 949 * Most common situation is a non-null object, being compared against 950 * an already-resolved class. 951 */ 952 /* instance-of vA, vB, class@CCCC */ 953 mov r3, rINST, lsr #12 @ r3<- B 954 mov r9, rINST, lsr #8 @ r9<- A+ 955 GET_VREG(r0, r3) @ r0<- vB (object) 956 and r9, r9, #15 @ r9<- A 957 cmp r0, #0 @ is object null? 958 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 959 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 960 FETCH(r3, 1) @ r3<- CCCC 961 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 962 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 963 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 964 cmp r1, #0 @ have we resolved this before? 965 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 966.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 967 cmp r0, r1 @ same class (trivial success)? 968 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 969 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 970 971/* ------------------------------ */ 972 .balign 64 973.L_OP_ARRAY_LENGTH: /* 0x21 */ 974/* File: armv5te/OP_ARRAY_LENGTH.S */ 975 /* 976 * Return the length of an array. 977 */ 978 mov r1, rINST, lsr #12 @ r1<- B 979 mov r2, rINST, lsr #8 @ r2<- A+ 980 GET_VREG(r0, r1) @ r0<- vB (object ref) 981 and r2, r2, #15 @ r2<- A 982 cmp r0, #0 @ is object null? 983 beq common_errNullObject @ yup, fail 984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 985 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 986 GET_INST_OPCODE(ip) @ extract opcode from rINST 987 SET_VREG(r3, r2) @ vB<- length 988 GOTO_OPCODE(ip) @ jump to next instruction 989 990 991/* ------------------------------ */ 992 .balign 64 993.L_OP_NEW_INSTANCE: /* 0x22 */ 994/* File: armv5te/OP_NEW_INSTANCE.S */ 995 /* 996 * Create a new instance of a class. 997 */ 998 /* new-instance vAA, class@BBBB */ 999 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1000 FETCH(r1, 1) @ r1<- BBBB 1001 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1002 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1003 EXPORT_PC() @ req'd for init, resolve, alloc 1004 cmp r0, #0 @ already resolved? 1005 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1006.LOP_NEW_INSTANCE_resolved: @ r0=class 1007 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1008 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1009 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1010.LOP_NEW_INSTANCE_initialized: @ r0=class 1011 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1012 bl dvmAllocObject @ r0<- new object 1013 b .LOP_NEW_INSTANCE_finish @ continue 1014 1015/* ------------------------------ */ 1016 .balign 64 1017.L_OP_NEW_ARRAY: /* 0x23 */ 1018/* File: armv5te/OP_NEW_ARRAY.S */ 1019 /* 1020 * Allocate an array of objects, specified with the array class 1021 * and a count. 1022 * 1023 * The verifier guarantees that this is an array class, so we don't 1024 * check for it here. 1025 */ 1026 /* new-array vA, vB, class@CCCC */ 1027 mov r0, rINST, lsr #12 @ r0<- B 1028 FETCH(r2, 1) @ r2<- CCCC 1029 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1030 GET_VREG(r1, r0) @ r1<- vB (array length) 1031 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1032 cmp r1, #0 @ check length 1033 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1034 bmi common_errNegativeArraySize @ negative length, bail 1035 cmp r0, #0 @ already resolved? 1036 EXPORT_PC() @ req'd for resolve, alloc 1037 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1038 b .LOP_NEW_ARRAY_resolve @ do resolve now 1039 1040/* ------------------------------ */ 1041 .balign 64 1042.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1043/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1044 /* 1045 * Create a new array with elements filled from registers. 1046 * 1047 * for: filled-new-array, filled-new-array/range 1048 */ 1049 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1050 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1051 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1052 FETCH(r1, 1) @ r1<- BBBB 1053 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1054 EXPORT_PC() @ need for resolve and alloc 1055 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1056 mov r10, rINST, lsr #8 @ r10<- AA or BA 1057 cmp r0, #0 @ already resolved? 1058 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10598: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1060 mov r2, #0 @ r2<- false 1061 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1062 bl dvmResolveClass @ r0<- call(clazz, ref) 1063 cmp r0, #0 @ got null? 1064 beq common_exceptionThrown @ yes, handle exception 1065 b .LOP_FILLED_NEW_ARRAY_continue 1066 1067/* ------------------------------ */ 1068 .balign 64 1069.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1070/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1071/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1072 /* 1073 * Create a new array with elements filled from registers. 1074 * 1075 * for: filled-new-array, filled-new-array/range 1076 */ 1077 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1078 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1079 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1080 FETCH(r1, 1) @ r1<- BBBB 1081 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1082 EXPORT_PC() @ need for resolve and alloc 1083 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1084 mov r10, rINST, lsr #8 @ r10<- AA or BA 1085 cmp r0, #0 @ already resolved? 1086 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10878: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1088 mov r2, #0 @ r2<- false 1089 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1090 bl dvmResolveClass @ r0<- call(clazz, ref) 1091 cmp r0, #0 @ got null? 1092 beq common_exceptionThrown @ yes, handle exception 1093 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1094 1095 1096/* ------------------------------ */ 1097 .balign 64 1098.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1099/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1100 /* fill-array-data vAA, +BBBBBBBB */ 1101 FETCH(r0, 1) @ r0<- bbbb (lo) 1102 FETCH(r1, 2) @ r1<- BBBB (hi) 1103 mov r3, rINST, lsr #8 @ r3<- AA 1104 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1105 GET_VREG(r0, r3) @ r0<- vAA (array object) 1106 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1107 EXPORT_PC(); 1108 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1109 cmp r0, #0 @ 0 means an exception is thrown 1110 beq common_exceptionThrown @ has exception 1111 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1112 GET_INST_OPCODE(ip) @ extract opcode from rINST 1113 GOTO_OPCODE(ip) @ jump to next instruction 1114 1115/* ------------------------------ */ 1116 .balign 64 1117.L_OP_THROW: /* 0x27 */ 1118/* File: armv5te/OP_THROW.S */ 1119 /* 1120 * Throw an exception object in the current thread. 1121 */ 1122 /* throw vAA */ 1123 mov r2, rINST, lsr #8 @ r2<- AA 1124 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1125 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1126 cmp r1, #0 @ null object? 1127 beq common_errNullObject @ yes, throw an NPE instead 1128 @ bypass dvmSetException, just store it 1129 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1130 b common_exceptionThrown 1131 1132 1133/* ------------------------------ */ 1134 .balign 64 1135.L_OP_GOTO: /* 0x28 */ 1136/* File: armv5te/OP_GOTO.S */ 1137 /* 1138 * Unconditional branch, 8-bit offset. 1139 * 1140 * The branch distance is a signed code-unit offset, which we need to 1141 * double to get a byte offset. 1142 */ 1143 /* goto +AA */ 1144 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1145 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1146 mov r9, r9, lsl #1 @ r9<- byte offset 1147 bmi common_backwardBranch @ backward branch, do periodic checks 1148#if defined(WITH_JIT) 1149 GET_JIT_PROF_TABLE(r0) 1150 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1151 cmp r0,#0 1152 bne common_updateProfile 1153 GET_INST_OPCODE(ip) @ extract opcode from rINST 1154 GOTO_OPCODE(ip) @ jump to next instruction 1155#else 1156 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1157 GET_INST_OPCODE(ip) @ extract opcode from rINST 1158 GOTO_OPCODE(ip) @ jump to next instruction 1159#endif 1160 1161/* ------------------------------ */ 1162 .balign 64 1163.L_OP_GOTO_16: /* 0x29 */ 1164/* File: armv5te/OP_GOTO_16.S */ 1165 /* 1166 * Unconditional branch, 16-bit offset. 1167 * 1168 * The branch distance is a signed code-unit offset, which we need to 1169 * double to get a byte offset. 1170 */ 1171 /* goto/16 +AAAA */ 1172 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1173 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1174 bmi common_backwardBranch @ backward branch, do periodic checks 1175#if defined(WITH_JIT) 1176 GET_JIT_PROF_TABLE(r0) 1177 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1178 cmp r0,#0 1179 bne common_updateProfile 1180 GET_INST_OPCODE(ip) @ extract opcode from rINST 1181 GOTO_OPCODE(ip) @ jump to next instruction 1182#else 1183 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1184 GET_INST_OPCODE(ip) @ extract opcode from rINST 1185 GOTO_OPCODE(ip) @ jump to next instruction 1186#endif 1187 1188 1189/* ------------------------------ */ 1190 .balign 64 1191.L_OP_GOTO_32: /* 0x2a */ 1192/* File: armv5te/OP_GOTO_32.S */ 1193 /* 1194 * Unconditional branch, 32-bit offset. 1195 * 1196 * The branch distance is a signed code-unit offset, which we need to 1197 * double to get a byte offset. 1198 * 1199 * Unlike most opcodes, this one is allowed to branch to itself, so 1200 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1201 * instruction doesn't affect the V flag, so we need to clear it 1202 * explicitly. 1203 */ 1204 /* goto/32 +AAAAAAAA */ 1205 FETCH(r0, 1) @ r0<- aaaa (lo) 1206 FETCH(r1, 2) @ r1<- AAAA (hi) 1207 cmp ip, ip @ (clear V flag during stall) 1208 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1209 mov r9, r0, asl #1 @ r9<- byte offset 1210 ble common_backwardBranch @ backward branch, do periodic checks 1211#if defined(WITH_JIT) 1212 GET_JIT_PROF_TABLE(r0) 1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1214 cmp r0,#0 1215 bne common_updateProfile 1216 GET_INST_OPCODE(ip) @ extract opcode from rINST 1217 GOTO_OPCODE(ip) @ jump to next instruction 1218#else 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 GET_INST_OPCODE(ip) @ extract opcode from rINST 1221 GOTO_OPCODE(ip) @ jump to next instruction 1222#endif 1223 1224/* ------------------------------ */ 1225 .balign 64 1226.L_OP_PACKED_SWITCH: /* 0x2b */ 1227/* File: armv5te/OP_PACKED_SWITCH.S */ 1228 /* 1229 * Handle a packed-switch or sparse-switch instruction. In both cases 1230 * we decode it and hand it off to a helper function. 1231 * 1232 * We don't really expect backward branches in a switch statement, but 1233 * they're perfectly legal, so we check for them here. 1234 * 1235 * for: packed-switch, sparse-switch 1236 */ 1237 /* op vAA, +BBBB */ 1238 FETCH(r0, 1) @ r0<- bbbb (lo) 1239 FETCH(r1, 2) @ r1<- BBBB (hi) 1240 mov r3, rINST, lsr #8 @ r3<- AA 1241 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1242 GET_VREG(r1, r3) @ r1<- vAA 1243 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1244 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1245 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1246 bmi common_backwardBranch @ backward branch, do periodic checks 1247 beq common_backwardBranch @ (want to use BLE but V is unknown) 1248#if defined(WITH_JIT) 1249 GET_JIT_PROF_TABLE(r0) 1250 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1251 cmp r0,#0 1252 bne common_updateProfile 1253 GET_INST_OPCODE(ip) @ extract opcode from rINST 1254 GOTO_OPCODE(ip) @ jump to next instruction 1255#else 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 GOTO_OPCODE(ip) @ jump to next instruction 1259#endif 1260 1261 1262/* ------------------------------ */ 1263 .balign 64 1264.L_OP_SPARSE_SWITCH: /* 0x2c */ 1265/* File: armv5te/OP_SPARSE_SWITCH.S */ 1266/* File: armv5te/OP_PACKED_SWITCH.S */ 1267 /* 1268 * Handle a packed-switch or sparse-switch instruction. In both cases 1269 * we decode it and hand it off to a helper function. 1270 * 1271 * We don't really expect backward branches in a switch statement, but 1272 * they're perfectly legal, so we check for them here. 1273 * 1274 * for: packed-switch, sparse-switch 1275 */ 1276 /* op vAA, +BBBB */ 1277 FETCH(r0, 1) @ r0<- bbbb (lo) 1278 FETCH(r1, 2) @ r1<- BBBB (hi) 1279 mov r3, rINST, lsr #8 @ r3<- AA 1280 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1281 GET_VREG(r1, r3) @ r1<- vAA 1282 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1283 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1284 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1285 bmi common_backwardBranch @ backward branch, do periodic checks 1286 beq common_backwardBranch @ (want to use BLE but V is unknown) 1287#if defined(WITH_JIT) 1288 GET_JIT_PROF_TABLE(r0) 1289 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1290 cmp r0,#0 1291 bne common_updateProfile 1292 GET_INST_OPCODE(ip) @ extract opcode from rINST 1293 GOTO_OPCODE(ip) @ jump to next instruction 1294#else 1295 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1296 GET_INST_OPCODE(ip) @ extract opcode from rINST 1297 GOTO_OPCODE(ip) @ jump to next instruction 1298#endif 1299 1300 1301 1302/* ------------------------------ */ 1303 .balign 64 1304.L_OP_CMPL_FLOAT: /* 0x2d */ 1305/* File: armv5te/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 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1311 * on what value we'd like to return when one of the operands is NaN. 1312 * 1313 * The operation we're implementing is: 1314 * if (x == y) 1315 * return 0; 1316 * else if (x < y) 1317 * return -1; 1318 * else if (x > y) 1319 * return 1; 1320 * else 1321 * return {-1,1}; // one or both operands was NaN 1322 * 1323 * The straightforward implementation requires 3 calls to functions 1324 * that return a result in r0. We can do it with two calls if our 1325 * EABI library supports __aeabi_cfcmple (only one if we want to check 1326 * for NaN directly): 1327 * check x <= y 1328 * if <, return -1 1329 * if ==, return 0 1330 * check y <= x 1331 * if <, return 1 1332 * return {-1,1} 1333 * 1334 * for: cmpl-float, cmpg-float 1335 */ 1336 /* op vAA, vBB, vCC */ 1337 FETCH(r0, 1) @ r0<- CCBB 1338 and r2, r0, #255 @ r2<- BB 1339 mov r3, r0, lsr #8 @ r3<- CC 1340 GET_VREG(r9, r2) @ r9<- vBB 1341 GET_VREG(r10, r3) @ r10<- vCC 1342 mov r0, r9 @ copy to arg registers 1343 mov r1, r10 1344 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1345 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1346 mvncc r1, #0 @ (less than) r1<- -1 1347 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1348.LOP_CMPL_FLOAT_finish: 1349 mov r3, rINST, lsr #8 @ r3<- AA 1350 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1351 SET_VREG(r1, r3) @ vAA<- r1 1352 GET_INST_OPCODE(ip) @ extract opcode from rINST 1353 GOTO_OPCODE(ip) @ jump to next instruction 1354 1355/* ------------------------------ */ 1356 .balign 64 1357.L_OP_CMPG_FLOAT: /* 0x2e */ 1358/* File: armv5te/OP_CMPG_FLOAT.S */ 1359/* File: armv5te/OP_CMPL_FLOAT.S */ 1360 /* 1361 * Compare two floating-point values. Puts 0, 1, or -1 into the 1362 * destination register based on the results of the comparison. 1363 * 1364 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1365 * on what value we'd like to return when one of the operands is NaN. 1366 * 1367 * The operation we're implementing is: 1368 * if (x == y) 1369 * return 0; 1370 * else if (x < y) 1371 * return -1; 1372 * else if (x > y) 1373 * return 1; 1374 * else 1375 * return {-1,1}; // one or both operands was NaN 1376 * 1377 * The straightforward implementation requires 3 calls to functions 1378 * that return a result in r0. We can do it with two calls if our 1379 * EABI library supports __aeabi_cfcmple (only one if we want to check 1380 * for NaN directly): 1381 * check x <= y 1382 * if <, return -1 1383 * if ==, return 0 1384 * check y <= x 1385 * if <, return 1 1386 * return {-1,1} 1387 * 1388 * for: cmpl-float, cmpg-float 1389 */ 1390 /* op vAA, vBB, vCC */ 1391 FETCH(r0, 1) @ r0<- CCBB 1392 and r2, r0, #255 @ r2<- BB 1393 mov r3, r0, lsr #8 @ r3<- CC 1394 GET_VREG(r9, r2) @ r9<- vBB 1395 GET_VREG(r10, r3) @ r10<- vCC 1396 mov r0, r9 @ copy to arg registers 1397 mov r1, r10 1398 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1399 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1400 mvncc r1, #0 @ (less than) r1<- -1 1401 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1402.LOP_CMPG_FLOAT_finish: 1403 mov r3, rINST, lsr #8 @ r3<- AA 1404 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1405 SET_VREG(r1, r3) @ vAA<- r1 1406 GET_INST_OPCODE(ip) @ extract opcode from rINST 1407 GOTO_OPCODE(ip) @ jump to next instruction 1408 1409 1410/* ------------------------------ */ 1411 .balign 64 1412.L_OP_CMPL_DOUBLE: /* 0x2f */ 1413/* File: armv5te/OP_CMPL_DOUBLE.S */ 1414 /* 1415 * Compare two floating-point values. Puts 0, 1, or -1 into the 1416 * destination register based on the results of the comparison. 1417 * 1418 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1419 * on what value we'd like to return when one of the operands is NaN. 1420 * 1421 * See OP_CMPL_FLOAT for an explanation. 1422 * 1423 * For: cmpl-double, cmpg-double 1424 */ 1425 /* op vAA, vBB, vCC */ 1426 FETCH(r0, 1) @ r0<- CCBB 1427 and r9, r0, #255 @ r9<- BB 1428 mov r10, r0, lsr #8 @ r10<- CC 1429 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1430 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1431 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1432 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1433 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1434 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1435 mvncc r1, #0 @ (less than) r1<- -1 1436 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1437.LOP_CMPL_DOUBLE_finish: 1438 mov r3, rINST, lsr #8 @ r3<- AA 1439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1440 SET_VREG(r1, r3) @ vAA<- r1 1441 GET_INST_OPCODE(ip) @ extract opcode from rINST 1442 GOTO_OPCODE(ip) @ jump to next instruction 1443 1444/* ------------------------------ */ 1445 .balign 64 1446.L_OP_CMPG_DOUBLE: /* 0x30 */ 1447/* File: armv5te/OP_CMPG_DOUBLE.S */ 1448/* File: armv5te/OP_CMPL_DOUBLE.S */ 1449 /* 1450 * Compare two floating-point values. Puts 0, 1, or -1 into the 1451 * destination register based on the results of the comparison. 1452 * 1453 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1454 * on what value we'd like to return when one of the operands is NaN. 1455 * 1456 * See OP_CMPL_FLOAT for an explanation. 1457 * 1458 * For: cmpl-double, cmpg-double 1459 */ 1460 /* op vAA, vBB, vCC */ 1461 FETCH(r0, 1) @ r0<- CCBB 1462 and r9, r0, #255 @ r9<- BB 1463 mov r10, r0, lsr #8 @ r10<- CC 1464 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1465 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1466 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1467 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1468 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1469 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1470 mvncc r1, #0 @ (less than) r1<- -1 1471 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1472.LOP_CMPG_DOUBLE_finish: 1473 mov r3, rINST, lsr #8 @ r3<- AA 1474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1475 SET_VREG(r1, r3) @ vAA<- r1 1476 GET_INST_OPCODE(ip) @ extract opcode from rINST 1477 GOTO_OPCODE(ip) @ jump to next instruction 1478 1479 1480/* ------------------------------ */ 1481 .balign 64 1482.L_OP_CMP_LONG: /* 0x31 */ 1483/* File: armv5te/OP_CMP_LONG.S */ 1484 /* 1485 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1486 * register based on the results of the comparison. 1487 * 1488 * We load the full values with LDM, but in practice many values could 1489 * be resolved by only looking at the high word. This could be made 1490 * faster or slower by splitting the LDM into a pair of LDRs. 1491 * 1492 * If we just wanted to set condition flags, we could do this: 1493 * subs ip, r0, r2 1494 * sbcs ip, r1, r3 1495 * subeqs ip, r0, r2 1496 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1497 * integer value, which we can do with 2 conditional mov/mvn instructions 1498 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1499 * us a constant 5-cycle path plus a branch at the end to the 1500 * instruction epilogue code. The multi-compare approach below needs 1501 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1502 * in the worst case (the 64-bit values are equal). 1503 */ 1504 /* cmp-long vAA, vBB, vCC */ 1505 FETCH(r0, 1) @ r0<- CCBB 1506 mov r9, rINST, lsr #8 @ r9<- AA 1507 and r2, r0, #255 @ r2<- BB 1508 mov r3, r0, lsr #8 @ r3<- CC 1509 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1510 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1511 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1512 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1513 cmp r1, r3 @ compare (vBB+1, vCC+1) 1514 blt .LOP_CMP_LONG_less @ signed compare on high part 1515 bgt .LOP_CMP_LONG_greater 1516 subs r1, r0, r2 @ r1<- r0 - r2 1517 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1518 bne .LOP_CMP_LONG_less 1519 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1520 1521/* ------------------------------ */ 1522 .balign 64 1523.L_OP_IF_EQ: /* 0x32 */ 1524/* File: armv5te/OP_IF_EQ.S */ 1525/* File: armv5te/bincmp.S */ 1526 /* 1527 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1528 * fragment that specifies the *reverse* comparison to perform, e.g. 1529 * for "if-le" you would use "gt". 1530 * 1531 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1532 */ 1533 /* if-cmp vA, vB, +CCCC */ 1534 mov r0, rINST, lsr #8 @ r0<- A+ 1535 mov r1, rINST, lsr #12 @ r1<- B 1536 and r0, r0, #15 1537 GET_VREG(r3, r1) @ r3<- vB 1538 GET_VREG(r2, r0) @ r2<- vA 1539 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1540 cmp r2, r3 @ compare (vA, vB) 1541 bne 1f @ branch to 1 if comparison failed 1542 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1543 movs r9, r9, asl #1 @ convert to bytes, check sign 1544 bmi common_backwardBranch @ yes, do periodic checks 15451: 1546#if defined(WITH_JIT) 1547 GET_JIT_PROF_TABLE(r0) 1548 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1549 b common_testUpdateProfile 1550#else 1551 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1552 GET_INST_OPCODE(ip) @ extract opcode from rINST 1553 GOTO_OPCODE(ip) @ jump to next instruction 1554#endif 1555 1556 1557 1558/* ------------------------------ */ 1559 .balign 64 1560.L_OP_IF_NE: /* 0x33 */ 1561/* File: armv5te/OP_IF_NE.S */ 1562/* File: armv5te/bincmp.S */ 1563 /* 1564 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1565 * fragment that specifies the *reverse* comparison to perform, e.g. 1566 * for "if-le" you would use "gt". 1567 * 1568 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1569 */ 1570 /* if-cmp vA, vB, +CCCC */ 1571 mov r0, rINST, lsr #8 @ r0<- A+ 1572 mov r1, rINST, lsr #12 @ r1<- B 1573 and r0, r0, #15 1574 GET_VREG(r3, r1) @ r3<- vB 1575 GET_VREG(r2, r0) @ r2<- vA 1576 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1577 cmp r2, r3 @ compare (vA, vB) 1578 beq 1f @ branch to 1 if comparison failed 1579 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1580 movs r9, r9, asl #1 @ convert to bytes, check sign 1581 bmi common_backwardBranch @ yes, do periodic checks 15821: 1583#if defined(WITH_JIT) 1584 GET_JIT_PROF_TABLE(r0) 1585 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1586 b common_testUpdateProfile 1587#else 1588 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1589 GET_INST_OPCODE(ip) @ extract opcode from rINST 1590 GOTO_OPCODE(ip) @ jump to next instruction 1591#endif 1592 1593 1594 1595/* ------------------------------ */ 1596 .balign 64 1597.L_OP_IF_LT: /* 0x34 */ 1598/* File: armv5te/OP_IF_LT.S */ 1599/* File: armv5te/bincmp.S */ 1600 /* 1601 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1602 * fragment that specifies the *reverse* comparison to perform, e.g. 1603 * for "if-le" you would use "gt". 1604 * 1605 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1606 */ 1607 /* if-cmp vA, vB, +CCCC */ 1608 mov r0, rINST, lsr #8 @ r0<- A+ 1609 mov r1, rINST, lsr #12 @ r1<- B 1610 and r0, r0, #15 1611 GET_VREG(r3, r1) @ r3<- vB 1612 GET_VREG(r2, r0) @ r2<- vA 1613 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1614 cmp r2, r3 @ compare (vA, vB) 1615 bge 1f @ branch to 1 if comparison failed 1616 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1617 movs r9, r9, asl #1 @ convert to bytes, check sign 1618 bmi common_backwardBranch @ yes, do periodic checks 16191: 1620#if defined(WITH_JIT) 1621 GET_JIT_PROF_TABLE(r0) 1622 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1623 b common_testUpdateProfile 1624#else 1625 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1626 GET_INST_OPCODE(ip) @ extract opcode from rINST 1627 GOTO_OPCODE(ip) @ jump to next instruction 1628#endif 1629 1630 1631 1632/* ------------------------------ */ 1633 .balign 64 1634.L_OP_IF_GE: /* 0x35 */ 1635/* File: armv5te/OP_IF_GE.S */ 1636/* File: armv5te/bincmp.S */ 1637 /* 1638 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1639 * fragment that specifies the *reverse* comparison to perform, e.g. 1640 * for "if-le" you would use "gt". 1641 * 1642 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1643 */ 1644 /* if-cmp vA, vB, +CCCC */ 1645 mov r0, rINST, lsr #8 @ r0<- A+ 1646 mov r1, rINST, lsr #12 @ r1<- B 1647 and r0, r0, #15 1648 GET_VREG(r3, r1) @ r3<- vB 1649 GET_VREG(r2, r0) @ r2<- vA 1650 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1651 cmp r2, r3 @ compare (vA, vB) 1652 blt 1f @ branch to 1 if comparison failed 1653 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1654 movs r9, r9, asl #1 @ convert to bytes, check sign 1655 bmi common_backwardBranch @ yes, do periodic checks 16561: 1657#if defined(WITH_JIT) 1658 GET_JIT_PROF_TABLE(r0) 1659 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1660 b common_testUpdateProfile 1661#else 1662 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1663 GET_INST_OPCODE(ip) @ extract opcode from rINST 1664 GOTO_OPCODE(ip) @ jump to next instruction 1665#endif 1666 1667 1668 1669/* ------------------------------ */ 1670 .balign 64 1671.L_OP_IF_GT: /* 0x36 */ 1672/* File: armv5te/OP_IF_GT.S */ 1673/* File: armv5te/bincmp.S */ 1674 /* 1675 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1676 * fragment that specifies the *reverse* comparison to perform, e.g. 1677 * for "if-le" you would use "gt". 1678 * 1679 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1680 */ 1681 /* if-cmp vA, vB, +CCCC */ 1682 mov r0, rINST, lsr #8 @ r0<- A+ 1683 mov r1, rINST, lsr #12 @ r1<- B 1684 and r0, r0, #15 1685 GET_VREG(r3, r1) @ r3<- vB 1686 GET_VREG(r2, r0) @ r2<- vA 1687 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1688 cmp r2, r3 @ compare (vA, vB) 1689 ble 1f @ branch to 1 if comparison failed 1690 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1691 movs r9, r9, asl #1 @ convert to bytes, check sign 1692 bmi common_backwardBranch @ yes, do periodic checks 16931: 1694#if defined(WITH_JIT) 1695 GET_JIT_PROF_TABLE(r0) 1696 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1697 b common_testUpdateProfile 1698#else 1699 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1700 GET_INST_OPCODE(ip) @ extract opcode from rINST 1701 GOTO_OPCODE(ip) @ jump to next instruction 1702#endif 1703 1704 1705 1706/* ------------------------------ */ 1707 .balign 64 1708.L_OP_IF_LE: /* 0x37 */ 1709/* File: armv5te/OP_IF_LE.S */ 1710/* File: armv5te/bincmp.S */ 1711 /* 1712 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1713 * fragment that specifies the *reverse* comparison to perform, e.g. 1714 * for "if-le" you would use "gt". 1715 * 1716 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1717 */ 1718 /* if-cmp vA, vB, +CCCC */ 1719 mov r0, rINST, lsr #8 @ r0<- A+ 1720 mov r1, rINST, lsr #12 @ r1<- B 1721 and r0, r0, #15 1722 GET_VREG(r3, r1) @ r3<- vB 1723 GET_VREG(r2, r0) @ r2<- vA 1724 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1725 cmp r2, r3 @ compare (vA, vB) 1726 bgt 1f @ branch to 1 if comparison failed 1727 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1728 movs r9, r9, asl #1 @ convert to bytes, check sign 1729 bmi common_backwardBranch @ yes, do periodic checks 17301: 1731#if defined(WITH_JIT) 1732 GET_JIT_PROF_TABLE(r0) 1733 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1734 b common_testUpdateProfile 1735#else 1736 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1737 GET_INST_OPCODE(ip) @ extract opcode from rINST 1738 GOTO_OPCODE(ip) @ jump to next instruction 1739#endif 1740 1741 1742 1743/* ------------------------------ */ 1744 .balign 64 1745.L_OP_IF_EQZ: /* 0x38 */ 1746/* File: armv5te/OP_IF_EQZ.S */ 1747/* File: armv5te/zcmp.S */ 1748 /* 1749 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1750 * fragment that specifies the *reverse* comparison to perform, e.g. 1751 * for "if-le" you would use "gt". 1752 * 1753 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1754 */ 1755 /* if-cmp vAA, +BBBB */ 1756 mov r0, rINST, lsr #8 @ r0<- AA 1757 GET_VREG(r2, r0) @ r2<- vAA 1758 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1759 cmp r2, #0 @ compare (vA, 0) 1760 bne 1f @ branch to 1 if comparison failed 1761 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1762 movs r9, r9, asl #1 @ convert to bytes, check sign 1763 bmi common_backwardBranch @ backward branch, do periodic checks 17641: 1765#if defined(WITH_JIT) 1766 GET_JIT_PROF_TABLE(r0) 1767 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1768 cmp r0,#0 1769 bne common_updateProfile 1770 GET_INST_OPCODE(ip) @ extract opcode from rINST 1771 GOTO_OPCODE(ip) @ jump to next instruction 1772#else 1773 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1774 GET_INST_OPCODE(ip) @ extract opcode from rINST 1775 GOTO_OPCODE(ip) @ jump to next instruction 1776#endif 1777 1778 1779 1780/* ------------------------------ */ 1781 .balign 64 1782.L_OP_IF_NEZ: /* 0x39 */ 1783/* File: armv5te/OP_IF_NEZ.S */ 1784/* File: armv5te/zcmp.S */ 1785 /* 1786 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1787 * fragment that specifies the *reverse* comparison to perform, e.g. 1788 * for "if-le" you would use "gt". 1789 * 1790 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1791 */ 1792 /* if-cmp vAA, +BBBB */ 1793 mov r0, rINST, lsr #8 @ r0<- AA 1794 GET_VREG(r2, r0) @ r2<- vAA 1795 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1796 cmp r2, #0 @ compare (vA, 0) 1797 beq 1f @ branch to 1 if comparison failed 1798 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1799 movs r9, r9, asl #1 @ convert to bytes, check sign 1800 bmi common_backwardBranch @ backward branch, do periodic checks 18011: 1802#if defined(WITH_JIT) 1803 GET_JIT_PROF_TABLE(r0) 1804 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1805 cmp r0,#0 1806 bne common_updateProfile 1807 GET_INST_OPCODE(ip) @ extract opcode from rINST 1808 GOTO_OPCODE(ip) @ jump to next instruction 1809#else 1810 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1811 GET_INST_OPCODE(ip) @ extract opcode from rINST 1812 GOTO_OPCODE(ip) @ jump to next instruction 1813#endif 1814 1815 1816 1817/* ------------------------------ */ 1818 .balign 64 1819.L_OP_IF_LTZ: /* 0x3a */ 1820/* File: armv5te/OP_IF_LTZ.S */ 1821/* File: armv5te/zcmp.S */ 1822 /* 1823 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1824 * fragment that specifies the *reverse* comparison to perform, e.g. 1825 * for "if-le" you would use "gt". 1826 * 1827 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1828 */ 1829 /* if-cmp vAA, +BBBB */ 1830 mov r0, rINST, lsr #8 @ r0<- AA 1831 GET_VREG(r2, r0) @ r2<- vAA 1832 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1833 cmp r2, #0 @ compare (vA, 0) 1834 bge 1f @ branch to 1 if comparison failed 1835 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1836 movs r9, r9, asl #1 @ convert to bytes, check sign 1837 bmi common_backwardBranch @ backward branch, do periodic checks 18381: 1839#if defined(WITH_JIT) 1840 GET_JIT_PROF_TABLE(r0) 1841 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1842 cmp r0,#0 1843 bne common_updateProfile 1844 GET_INST_OPCODE(ip) @ extract opcode from rINST 1845 GOTO_OPCODE(ip) @ jump to next instruction 1846#else 1847 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1848 GET_INST_OPCODE(ip) @ extract opcode from rINST 1849 GOTO_OPCODE(ip) @ jump to next instruction 1850#endif 1851 1852 1853 1854/* ------------------------------ */ 1855 .balign 64 1856.L_OP_IF_GEZ: /* 0x3b */ 1857/* File: armv5te/OP_IF_GEZ.S */ 1858/* File: armv5te/zcmp.S */ 1859 /* 1860 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1861 * fragment that specifies the *reverse* comparison to perform, e.g. 1862 * for "if-le" you would use "gt". 1863 * 1864 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1865 */ 1866 /* if-cmp vAA, +BBBB */ 1867 mov r0, rINST, lsr #8 @ r0<- AA 1868 GET_VREG(r2, r0) @ r2<- vAA 1869 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1870 cmp r2, #0 @ compare (vA, 0) 1871 blt 1f @ branch to 1 if comparison failed 1872 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1873 movs r9, r9, asl #1 @ convert to bytes, check sign 1874 bmi common_backwardBranch @ backward branch, do periodic checks 18751: 1876#if defined(WITH_JIT) 1877 GET_JIT_PROF_TABLE(r0) 1878 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1879 cmp r0,#0 1880 bne common_updateProfile 1881 GET_INST_OPCODE(ip) @ extract opcode from rINST 1882 GOTO_OPCODE(ip) @ jump to next instruction 1883#else 1884 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1885 GET_INST_OPCODE(ip) @ extract opcode from rINST 1886 GOTO_OPCODE(ip) @ jump to next instruction 1887#endif 1888 1889 1890 1891/* ------------------------------ */ 1892 .balign 64 1893.L_OP_IF_GTZ: /* 0x3c */ 1894/* File: armv5te/OP_IF_GTZ.S */ 1895/* File: armv5te/zcmp.S */ 1896 /* 1897 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1898 * fragment that specifies the *reverse* comparison to perform, e.g. 1899 * for "if-le" you would use "gt". 1900 * 1901 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1902 */ 1903 /* if-cmp vAA, +BBBB */ 1904 mov r0, rINST, lsr #8 @ r0<- AA 1905 GET_VREG(r2, r0) @ r2<- vAA 1906 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1907 cmp r2, #0 @ compare (vA, 0) 1908 ble 1f @ branch to 1 if comparison failed 1909 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1910 movs r9, r9, asl #1 @ convert to bytes, check sign 1911 bmi common_backwardBranch @ backward branch, do periodic checks 19121: 1913#if defined(WITH_JIT) 1914 GET_JIT_PROF_TABLE(r0) 1915 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1916 cmp r0,#0 1917 bne common_updateProfile 1918 GET_INST_OPCODE(ip) @ extract opcode from rINST 1919 GOTO_OPCODE(ip) @ jump to next instruction 1920#else 1921 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1922 GET_INST_OPCODE(ip) @ extract opcode from rINST 1923 GOTO_OPCODE(ip) @ jump to next instruction 1924#endif 1925 1926 1927 1928/* ------------------------------ */ 1929 .balign 64 1930.L_OP_IF_LEZ: /* 0x3d */ 1931/* File: armv5te/OP_IF_LEZ.S */ 1932/* File: armv5te/zcmp.S */ 1933 /* 1934 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1935 * fragment that specifies the *reverse* comparison to perform, e.g. 1936 * for "if-le" you would use "gt". 1937 * 1938 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1939 */ 1940 /* if-cmp vAA, +BBBB */ 1941 mov r0, rINST, lsr #8 @ r0<- AA 1942 GET_VREG(r2, r0) @ r2<- vAA 1943 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1944 cmp r2, #0 @ compare (vA, 0) 1945 bgt 1f @ branch to 1 if comparison failed 1946 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1947 movs r9, r9, asl #1 @ convert to bytes, check sign 1948 bmi common_backwardBranch @ backward branch, do periodic checks 19491: 1950#if defined(WITH_JIT) 1951 GET_JIT_PROF_TABLE(r0) 1952 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1953 cmp r0,#0 1954 bne common_updateProfile 1955 GET_INST_OPCODE(ip) @ extract opcode from rINST 1956 GOTO_OPCODE(ip) @ jump to next instruction 1957#else 1958 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1959 GET_INST_OPCODE(ip) @ extract opcode from rINST 1960 GOTO_OPCODE(ip) @ jump to next instruction 1961#endif 1962 1963 1964 1965/* ------------------------------ */ 1966 .balign 64 1967.L_OP_UNUSED_3E: /* 0x3e */ 1968/* File: armv5te/OP_UNUSED_3E.S */ 1969/* File: armv5te/unused.S */ 1970 bl common_abort 1971 1972 1973 1974/* ------------------------------ */ 1975 .balign 64 1976.L_OP_UNUSED_3F: /* 0x3f */ 1977/* File: armv5te/OP_UNUSED_3F.S */ 1978/* File: armv5te/unused.S */ 1979 bl common_abort 1980 1981 1982 1983/* ------------------------------ */ 1984 .balign 64 1985.L_OP_UNUSED_40: /* 0x40 */ 1986/* File: armv5te/OP_UNUSED_40.S */ 1987/* File: armv5te/unused.S */ 1988 bl common_abort 1989 1990 1991 1992/* ------------------------------ */ 1993 .balign 64 1994.L_OP_UNUSED_41: /* 0x41 */ 1995/* File: armv5te/OP_UNUSED_41.S */ 1996/* File: armv5te/unused.S */ 1997 bl common_abort 1998 1999 2000 2001/* ------------------------------ */ 2002 .balign 64 2003.L_OP_UNUSED_42: /* 0x42 */ 2004/* File: armv5te/OP_UNUSED_42.S */ 2005/* File: armv5te/unused.S */ 2006 bl common_abort 2007 2008 2009 2010/* ------------------------------ */ 2011 .balign 64 2012.L_OP_UNUSED_43: /* 0x43 */ 2013/* File: armv5te/OP_UNUSED_43.S */ 2014/* File: armv5te/unused.S */ 2015 bl common_abort 2016 2017 2018 2019/* ------------------------------ */ 2020 .balign 64 2021.L_OP_AGET: /* 0x44 */ 2022/* File: armv5te/OP_AGET.S */ 2023 /* 2024 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2025 * 2026 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2027 * instructions. We use a pair of FETCH_Bs instead. 2028 * 2029 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2030 */ 2031 /* op vAA, vBB, vCC */ 2032 FETCH_B(r2, 1, 0) @ r2<- BB 2033 mov r9, rINST, lsr #8 @ r9<- AA 2034 FETCH_B(r3, 1, 1) @ r3<- CC 2035 GET_VREG(r0, r2) @ r0<- vBB (array object) 2036 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2037 cmp r0, #0 @ null array object? 2038 beq common_errNullObject @ yes, bail 2039 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2040 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2041 cmp r1, r3 @ compare unsigned index, length 2042 bcs common_errArrayIndex @ index >= length, bail 2043 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2044 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2045 GET_INST_OPCODE(ip) @ extract opcode from rINST 2046 SET_VREG(r2, r9) @ vAA<- r2 2047 GOTO_OPCODE(ip) @ jump to next instruction 2048 2049 2050/* ------------------------------ */ 2051 .balign 64 2052.L_OP_AGET_WIDE: /* 0x45 */ 2053/* File: armv5te/OP_AGET_WIDE.S */ 2054 /* 2055 * Array get, 64 bits. vAA <- vBB[vCC]. 2056 * 2057 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2058 */ 2059 /* aget-wide vAA, vBB, vCC */ 2060 FETCH(r0, 1) @ r0<- CCBB 2061 mov r9, rINST, lsr #8 @ r9<- AA 2062 and r2, r0, #255 @ r2<- BB 2063 mov r3, r0, lsr #8 @ r3<- CC 2064 GET_VREG(r0, r2) @ r0<- vBB (array object) 2065 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2066 cmp r0, #0 @ null array object? 2067 beq common_errNullObject @ yes, bail 2068 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2069 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2070 cmp r1, r3 @ compare unsigned index, length 2071 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2072 b common_errArrayIndex @ index >= length, bail 2073 @ May want to swap the order of these two branches depending on how the 2074 @ branch prediction (if any) handles conditional forward branches vs. 2075 @ unconditional forward branches. 2076 2077/* ------------------------------ */ 2078 .balign 64 2079.L_OP_AGET_OBJECT: /* 0x46 */ 2080/* File: armv5te/OP_AGET_OBJECT.S */ 2081/* File: armv5te/OP_AGET.S */ 2082 /* 2083 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2084 * 2085 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2086 * instructions. We use a pair of FETCH_Bs instead. 2087 * 2088 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2089 */ 2090 /* op vAA, vBB, vCC */ 2091 FETCH_B(r2, 1, 0) @ r2<- BB 2092 mov r9, rINST, lsr #8 @ r9<- AA 2093 FETCH_B(r3, 1, 1) @ r3<- CC 2094 GET_VREG(r0, r2) @ r0<- vBB (array object) 2095 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2096 cmp r0, #0 @ null array object? 2097 beq common_errNullObject @ yes, bail 2098 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2099 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2100 cmp r1, r3 @ compare unsigned index, length 2101 bcs common_errArrayIndex @ index >= length, bail 2102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2103 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2104 GET_INST_OPCODE(ip) @ extract opcode from rINST 2105 SET_VREG(r2, r9) @ vAA<- r2 2106 GOTO_OPCODE(ip) @ jump to next instruction 2107 2108 2109 2110/* ------------------------------ */ 2111 .balign 64 2112.L_OP_AGET_BOOLEAN: /* 0x47 */ 2113/* File: armv5te/OP_AGET_BOOLEAN.S */ 2114/* File: armv5te/OP_AGET.S */ 2115 /* 2116 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2117 * 2118 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2119 * instructions. We use a pair of FETCH_Bs instead. 2120 * 2121 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2122 */ 2123 /* op vAA, vBB, vCC */ 2124 FETCH_B(r2, 1, 0) @ r2<- BB 2125 mov r9, rINST, lsr #8 @ r9<- AA 2126 FETCH_B(r3, 1, 1) @ r3<- CC 2127 GET_VREG(r0, r2) @ r0<- vBB (array object) 2128 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2129 cmp r0, #0 @ null array object? 2130 beq common_errNullObject @ yes, bail 2131 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2132 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2133 cmp r1, r3 @ compare unsigned index, length 2134 bcs common_errArrayIndex @ index >= length, bail 2135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2136 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2137 GET_INST_OPCODE(ip) @ extract opcode from rINST 2138 SET_VREG(r2, r9) @ vAA<- r2 2139 GOTO_OPCODE(ip) @ jump to next instruction 2140 2141 2142 2143/* ------------------------------ */ 2144 .balign 64 2145.L_OP_AGET_BYTE: /* 0x48 */ 2146/* File: armv5te/OP_AGET_BYTE.S */ 2147/* File: armv5te/OP_AGET.S */ 2148 /* 2149 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2150 * 2151 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2152 * instructions. We use a pair of FETCH_Bs instead. 2153 * 2154 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2155 */ 2156 /* op vAA, vBB, vCC */ 2157 FETCH_B(r2, 1, 0) @ r2<- BB 2158 mov r9, rINST, lsr #8 @ r9<- AA 2159 FETCH_B(r3, 1, 1) @ r3<- CC 2160 GET_VREG(r0, r2) @ r0<- vBB (array object) 2161 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2162 cmp r0, #0 @ null array object? 2163 beq common_errNullObject @ yes, bail 2164 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2165 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2166 cmp r1, r3 @ compare unsigned index, length 2167 bcs common_errArrayIndex @ index >= length, bail 2168 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2169 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2170 GET_INST_OPCODE(ip) @ extract opcode from rINST 2171 SET_VREG(r2, r9) @ vAA<- r2 2172 GOTO_OPCODE(ip) @ jump to next instruction 2173 2174 2175 2176/* ------------------------------ */ 2177 .balign 64 2178.L_OP_AGET_CHAR: /* 0x49 */ 2179/* File: armv5te/OP_AGET_CHAR.S */ 2180/* File: armv5te/OP_AGET.S */ 2181 /* 2182 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2183 * 2184 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2185 * instructions. We use a pair of FETCH_Bs instead. 2186 * 2187 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2188 */ 2189 /* op vAA, vBB, vCC */ 2190 FETCH_B(r2, 1, 0) @ r2<- BB 2191 mov r9, rINST, lsr #8 @ r9<- AA 2192 FETCH_B(r3, 1, 1) @ r3<- CC 2193 GET_VREG(r0, r2) @ r0<- vBB (array object) 2194 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2195 cmp r0, #0 @ null array object? 2196 beq common_errNullObject @ yes, bail 2197 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2198 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2199 cmp r1, r3 @ compare unsigned index, length 2200 bcs common_errArrayIndex @ index >= length, bail 2201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2202 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2203 GET_INST_OPCODE(ip) @ extract opcode from rINST 2204 SET_VREG(r2, r9) @ vAA<- r2 2205 GOTO_OPCODE(ip) @ jump to next instruction 2206 2207 2208 2209/* ------------------------------ */ 2210 .balign 64 2211.L_OP_AGET_SHORT: /* 0x4a */ 2212/* File: armv5te/OP_AGET_SHORT.S */ 2213/* File: armv5te/OP_AGET.S */ 2214 /* 2215 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2216 * 2217 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2218 * instructions. We use a pair of FETCH_Bs instead. 2219 * 2220 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2221 */ 2222 /* op vAA, vBB, vCC */ 2223 FETCH_B(r2, 1, 0) @ r2<- BB 2224 mov r9, rINST, lsr #8 @ r9<- AA 2225 FETCH_B(r3, 1, 1) @ r3<- CC 2226 GET_VREG(r0, r2) @ r0<- vBB (array object) 2227 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2228 cmp r0, #0 @ null array object? 2229 beq common_errNullObject @ yes, bail 2230 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2231 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2232 cmp r1, r3 @ compare unsigned index, length 2233 bcs common_errArrayIndex @ index >= length, bail 2234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2235 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2236 GET_INST_OPCODE(ip) @ extract opcode from rINST 2237 SET_VREG(r2, r9) @ vAA<- r2 2238 GOTO_OPCODE(ip) @ jump to next instruction 2239 2240 2241 2242/* ------------------------------ */ 2243 .balign 64 2244.L_OP_APUT: /* 0x4b */ 2245/* File: armv5te/OP_APUT.S */ 2246 /* 2247 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2248 * 2249 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2250 * instructions. We use a pair of FETCH_Bs instead. 2251 * 2252 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2253 */ 2254 /* op vAA, vBB, vCC */ 2255 FETCH_B(r2, 1, 0) @ r2<- BB 2256 mov r9, rINST, lsr #8 @ r9<- AA 2257 FETCH_B(r3, 1, 1) @ r3<- CC 2258 GET_VREG(r0, r2) @ r0<- vBB (array object) 2259 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2260 cmp r0, #0 @ null array object? 2261 beq common_errNullObject @ yes, bail 2262 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2263 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2264 cmp r1, r3 @ compare unsigned index, length 2265 bcs common_errArrayIndex @ index >= length, bail 2266 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2267 GET_VREG(r2, r9) @ r2<- vAA 2268 GET_INST_OPCODE(ip) @ extract opcode from rINST 2269 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2270 GOTO_OPCODE(ip) @ jump to next instruction 2271 2272 2273/* ------------------------------ */ 2274 .balign 64 2275.L_OP_APUT_WIDE: /* 0x4c */ 2276/* File: armv5te/OP_APUT_WIDE.S */ 2277 /* 2278 * Array put, 64 bits. vBB[vCC] <- vAA. 2279 * 2280 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2281 */ 2282 /* aput-wide vAA, vBB, vCC */ 2283 FETCH(r0, 1) @ r0<- CCBB 2284 mov r9, rINST, lsr #8 @ r9<- AA 2285 and r2, r0, #255 @ r2<- BB 2286 mov r3, r0, lsr #8 @ r3<- CC 2287 GET_VREG(r0, r2) @ r0<- vBB (array object) 2288 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2289 cmp r0, #0 @ null array object? 2290 beq common_errNullObject @ yes, bail 2291 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2292 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2293 cmp r1, r3 @ compare unsigned index, length 2294 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2295 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2296 b common_errArrayIndex @ index >= length, bail 2297 @ May want to swap the order of these two branches depending on how the 2298 @ branch prediction (if any) handles conditional forward branches vs. 2299 @ unconditional forward branches. 2300 2301/* ------------------------------ */ 2302 .balign 64 2303.L_OP_APUT_OBJECT: /* 0x4d */ 2304/* File: armv5te/OP_APUT_OBJECT.S */ 2305 /* 2306 * Store an object into an array. vBB[vCC] <- vAA. 2307 * 2308 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2309 * instructions. We use a pair of FETCH_Bs instead. 2310 */ 2311 /* op vAA, vBB, vCC */ 2312 FETCH(r0, 1) @ r0<- CCBB 2313 mov r9, rINST, lsr #8 @ r9<- AA 2314 and r2, r0, #255 @ r2<- BB 2315 mov r3, r0, lsr #8 @ r3<- CC 2316 GET_VREG(r1, r2) @ r1<- vBB (array object) 2317 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2318 cmp r1, #0 @ null array object? 2319 GET_VREG(r9, r9) @ r9<- vAA 2320 beq common_errNullObject @ yes, bail 2321 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2322 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2323 cmp r0, r3 @ compare unsigned index, length 2324 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2325 b common_errArrayIndex @ index >= length, bail 2326 2327 2328/* ------------------------------ */ 2329 .balign 64 2330.L_OP_APUT_BOOLEAN: /* 0x4e */ 2331/* File: armv5te/OP_APUT_BOOLEAN.S */ 2332/* File: armv5te/OP_APUT.S */ 2333 /* 2334 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2335 * 2336 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2337 * instructions. We use a pair of FETCH_Bs instead. 2338 * 2339 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2340 */ 2341 /* op vAA, vBB, vCC */ 2342 FETCH_B(r2, 1, 0) @ r2<- BB 2343 mov r9, rINST, lsr #8 @ r9<- AA 2344 FETCH_B(r3, 1, 1) @ r3<- CC 2345 GET_VREG(r0, r2) @ r0<- vBB (array object) 2346 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2347 cmp r0, #0 @ null array object? 2348 beq common_errNullObject @ yes, bail 2349 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2350 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2351 cmp r1, r3 @ compare unsigned index, length 2352 bcs common_errArrayIndex @ index >= length, bail 2353 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2354 GET_VREG(r2, r9) @ r2<- vAA 2355 GET_INST_OPCODE(ip) @ extract opcode from rINST 2356 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2357 GOTO_OPCODE(ip) @ jump to next instruction 2358 2359 2360 2361/* ------------------------------ */ 2362 .balign 64 2363.L_OP_APUT_BYTE: /* 0x4f */ 2364/* File: armv5te/OP_APUT_BYTE.S */ 2365/* File: armv5te/OP_APUT.S */ 2366 /* 2367 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2368 * 2369 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2370 * instructions. We use a pair of FETCH_Bs instead. 2371 * 2372 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2373 */ 2374 /* op vAA, vBB, vCC */ 2375 FETCH_B(r2, 1, 0) @ r2<- BB 2376 mov r9, rINST, lsr #8 @ r9<- AA 2377 FETCH_B(r3, 1, 1) @ r3<- CC 2378 GET_VREG(r0, r2) @ r0<- vBB (array object) 2379 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2380 cmp r0, #0 @ null array object? 2381 beq common_errNullObject @ yes, bail 2382 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2383 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2384 cmp r1, r3 @ compare unsigned index, length 2385 bcs common_errArrayIndex @ index >= length, bail 2386 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2387 GET_VREG(r2, r9) @ r2<- vAA 2388 GET_INST_OPCODE(ip) @ extract opcode from rINST 2389 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2390 GOTO_OPCODE(ip) @ jump to next instruction 2391 2392 2393 2394/* ------------------------------ */ 2395 .balign 64 2396.L_OP_APUT_CHAR: /* 0x50 */ 2397/* File: armv5te/OP_APUT_CHAR.S */ 2398/* File: armv5te/OP_APUT.S */ 2399 /* 2400 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2401 * 2402 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2403 * instructions. We use a pair of FETCH_Bs instead. 2404 * 2405 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2406 */ 2407 /* op vAA, vBB, vCC */ 2408 FETCH_B(r2, 1, 0) @ r2<- BB 2409 mov r9, rINST, lsr #8 @ r9<- AA 2410 FETCH_B(r3, 1, 1) @ r3<- CC 2411 GET_VREG(r0, r2) @ r0<- vBB (array object) 2412 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2413 cmp r0, #0 @ null array object? 2414 beq common_errNullObject @ yes, bail 2415 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2416 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2417 cmp r1, r3 @ compare unsigned index, length 2418 bcs common_errArrayIndex @ index >= length, bail 2419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2420 GET_VREG(r2, r9) @ r2<- vAA 2421 GET_INST_OPCODE(ip) @ extract opcode from rINST 2422 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2423 GOTO_OPCODE(ip) @ jump to next instruction 2424 2425 2426 2427/* ------------------------------ */ 2428 .balign 64 2429.L_OP_APUT_SHORT: /* 0x51 */ 2430/* File: armv5te/OP_APUT_SHORT.S */ 2431/* File: armv5te/OP_APUT.S */ 2432 /* 2433 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2434 * 2435 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2436 * instructions. We use a pair of FETCH_Bs instead. 2437 * 2438 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2439 */ 2440 /* op vAA, vBB, vCC */ 2441 FETCH_B(r2, 1, 0) @ r2<- BB 2442 mov r9, rINST, lsr #8 @ r9<- AA 2443 FETCH_B(r3, 1, 1) @ r3<- CC 2444 GET_VREG(r0, r2) @ r0<- vBB (array object) 2445 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2446 cmp r0, #0 @ null array object? 2447 beq common_errNullObject @ yes, bail 2448 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2449 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2450 cmp r1, r3 @ compare unsigned index, length 2451 bcs common_errArrayIndex @ index >= length, bail 2452 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2453 GET_VREG(r2, r9) @ r2<- vAA 2454 GET_INST_OPCODE(ip) @ extract opcode from rINST 2455 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2456 GOTO_OPCODE(ip) @ jump to next instruction 2457 2458 2459 2460/* ------------------------------ */ 2461 .balign 64 2462.L_OP_IGET: /* 0x52 */ 2463/* File: armv5te/OP_IGET.S */ 2464 /* 2465 * General 32-bit instance field get. 2466 * 2467 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2468 */ 2469 /* op vA, vB, field@CCCC */ 2470 mov r0, rINST, lsr #12 @ r0<- B 2471 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2472 FETCH(r1, 1) @ r1<- field ref CCCC 2473 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2474 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2475 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2476 cmp r0, #0 @ is resolved entry null? 2477 bne .LOP_IGET_finish @ no, already resolved 24788: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2479 EXPORT_PC() @ resolve() could throw 2480 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2481 bl dvmResolveInstField @ r0<- resolved InstField ptr 2482 cmp r0, #0 2483 bne .LOP_IGET_finish 2484 b common_exceptionThrown 2485 2486/* ------------------------------ */ 2487 .balign 64 2488.L_OP_IGET_WIDE: /* 0x53 */ 2489/* File: armv5te/OP_IGET_WIDE.S */ 2490 /* 2491 * Wide 32-bit instance field get. 2492 */ 2493 /* iget-wide vA, vB, field@CCCC */ 2494 mov r0, rINST, lsr #12 @ r0<- B 2495 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2496 FETCH(r1, 1) @ r1<- field ref CCCC 2497 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2498 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2499 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2500 cmp r0, #0 @ is resolved entry null? 2501 bne .LOP_IGET_WIDE_finish @ no, already resolved 25028: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2503 EXPORT_PC() @ resolve() could throw 2504 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2505 bl dvmResolveInstField @ r0<- resolved InstField ptr 2506 cmp r0, #0 2507 bne .LOP_IGET_WIDE_finish 2508 b common_exceptionThrown 2509 2510/* ------------------------------ */ 2511 .balign 64 2512.L_OP_IGET_OBJECT: /* 0x54 */ 2513/* File: armv5te/OP_IGET_OBJECT.S */ 2514/* File: armv5te/OP_IGET.S */ 2515 /* 2516 * General 32-bit instance field get. 2517 * 2518 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2519 */ 2520 /* op vA, vB, field@CCCC */ 2521 mov r0, rINST, lsr #12 @ r0<- B 2522 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2523 FETCH(r1, 1) @ r1<- field ref CCCC 2524 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2525 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2526 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2527 cmp r0, #0 @ is resolved entry null? 2528 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2530 EXPORT_PC() @ resolve() could throw 2531 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2532 bl dvmResolveInstField @ r0<- resolved InstField ptr 2533 cmp r0, #0 2534 bne .LOP_IGET_OBJECT_finish 2535 b common_exceptionThrown 2536 2537 2538/* ------------------------------ */ 2539 .balign 64 2540.L_OP_IGET_BOOLEAN: /* 0x55 */ 2541/* File: armv5te/OP_IGET_BOOLEAN.S */ 2542@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2543/* File: armv5te/OP_IGET.S */ 2544 /* 2545 * General 32-bit instance field get. 2546 * 2547 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2548 */ 2549 /* op vA, vB, field@CCCC */ 2550 mov r0, rINST, lsr #12 @ r0<- B 2551 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2552 FETCH(r1, 1) @ r1<- field ref CCCC 2553 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2554 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2555 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2556 cmp r0, #0 @ is resolved entry null? 2557 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2559 EXPORT_PC() @ resolve() could throw 2560 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2561 bl dvmResolveInstField @ r0<- resolved InstField ptr 2562 cmp r0, #0 2563 bne .LOP_IGET_BOOLEAN_finish 2564 b common_exceptionThrown 2565 2566 2567/* ------------------------------ */ 2568 .balign 64 2569.L_OP_IGET_BYTE: /* 0x56 */ 2570/* File: armv5te/OP_IGET_BYTE.S */ 2571@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2572/* File: armv5te/OP_IGET.S */ 2573 /* 2574 * General 32-bit instance field get. 2575 * 2576 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2577 */ 2578 /* op vA, vB, field@CCCC */ 2579 mov r0, rINST, lsr #12 @ r0<- B 2580 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2581 FETCH(r1, 1) @ r1<- field ref CCCC 2582 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2583 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2584 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2585 cmp r0, #0 @ is resolved entry null? 2586 bne .LOP_IGET_BYTE_finish @ no, already resolved 25878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2588 EXPORT_PC() @ resolve() could throw 2589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2590 bl dvmResolveInstField @ r0<- resolved InstField ptr 2591 cmp r0, #0 2592 bne .LOP_IGET_BYTE_finish 2593 b common_exceptionThrown 2594 2595 2596/* ------------------------------ */ 2597 .balign 64 2598.L_OP_IGET_CHAR: /* 0x57 */ 2599/* File: armv5te/OP_IGET_CHAR.S */ 2600@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2601/* File: armv5te/OP_IGET.S */ 2602 /* 2603 * General 32-bit instance field get. 2604 * 2605 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2606 */ 2607 /* op vA, vB, field@CCCC */ 2608 mov r0, rINST, lsr #12 @ r0<- B 2609 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2610 FETCH(r1, 1) @ r1<- field ref CCCC 2611 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2612 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2613 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2614 cmp r0, #0 @ is resolved entry null? 2615 bne .LOP_IGET_CHAR_finish @ no, already resolved 26168: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2617 EXPORT_PC() @ resolve() could throw 2618 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2619 bl dvmResolveInstField @ r0<- resolved InstField ptr 2620 cmp r0, #0 2621 bne .LOP_IGET_CHAR_finish 2622 b common_exceptionThrown 2623 2624 2625/* ------------------------------ */ 2626 .balign 64 2627.L_OP_IGET_SHORT: /* 0x58 */ 2628/* File: armv5te/OP_IGET_SHORT.S */ 2629@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2630/* File: armv5te/OP_IGET.S */ 2631 /* 2632 * General 32-bit instance field get. 2633 * 2634 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2635 */ 2636 /* op vA, vB, field@CCCC */ 2637 mov r0, rINST, lsr #12 @ r0<- B 2638 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2639 FETCH(r1, 1) @ r1<- field ref CCCC 2640 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2641 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2642 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2643 cmp r0, #0 @ is resolved entry null? 2644 bne .LOP_IGET_SHORT_finish @ no, already resolved 26458: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2646 EXPORT_PC() @ resolve() could throw 2647 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2648 bl dvmResolveInstField @ r0<- resolved InstField ptr 2649 cmp r0, #0 2650 bne .LOP_IGET_SHORT_finish 2651 b common_exceptionThrown 2652 2653 2654/* ------------------------------ */ 2655 .balign 64 2656.L_OP_IPUT: /* 0x59 */ 2657/* File: armv5te/OP_IPUT.S */ 2658 /* 2659 * General 32-bit instance field put. 2660 * 2661 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2662 */ 2663 /* op vA, vB, field@CCCC */ 2664 mov r0, rINST, lsr #12 @ r0<- B 2665 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2666 FETCH(r1, 1) @ r1<- field ref CCCC 2667 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2668 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2669 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2670 cmp r0, #0 @ is resolved entry null? 2671 bne .LOP_IPUT_finish @ no, already resolved 26728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2673 EXPORT_PC() @ resolve() could throw 2674 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2675 bl dvmResolveInstField @ r0<- resolved InstField ptr 2676 cmp r0, #0 @ success? 2677 bne .LOP_IPUT_finish @ yes, finish up 2678 b common_exceptionThrown 2679 2680/* ------------------------------ */ 2681 .balign 64 2682.L_OP_IPUT_WIDE: /* 0x5a */ 2683/* File: armv5te/OP_IPUT_WIDE.S */ 2684 /* iput-wide vA, vB, field@CCCC */ 2685 mov r0, rINST, lsr #12 @ r0<- B 2686 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2687 FETCH(r1, 1) @ r1<- field ref CCCC 2688 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2689 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2690 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2691 cmp r0, #0 @ is resolved entry null? 2692 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26938: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2694 EXPORT_PC() @ resolve() could throw 2695 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2696 bl dvmResolveInstField @ r0<- resolved InstField ptr 2697 cmp r0, #0 @ success? 2698 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2699 b common_exceptionThrown 2700 2701/* ------------------------------ */ 2702 .balign 64 2703.L_OP_IPUT_OBJECT: /* 0x5b */ 2704/* File: armv5te/OP_IPUT_OBJECT.S */ 2705/* File: armv5te/OP_IPUT.S */ 2706 /* 2707 * General 32-bit instance field put. 2708 * 2709 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2710 */ 2711 /* op vA, vB, field@CCCC */ 2712 mov r0, rINST, lsr #12 @ r0<- B 2713 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2714 FETCH(r1, 1) @ r1<- field ref CCCC 2715 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2716 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2717 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2718 cmp r0, #0 @ is resolved entry null? 2719 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2721 EXPORT_PC() @ resolve() could throw 2722 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2723 bl dvmResolveInstField @ r0<- resolved InstField ptr 2724 cmp r0, #0 @ success? 2725 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2726 b common_exceptionThrown 2727 2728 2729/* ------------------------------ */ 2730 .balign 64 2731.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2732/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2733@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2734/* File: armv5te/OP_IPUT.S */ 2735 /* 2736 * General 32-bit instance field put. 2737 * 2738 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2739 */ 2740 /* op vA, vB, field@CCCC */ 2741 mov r0, rINST, lsr #12 @ r0<- B 2742 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2743 FETCH(r1, 1) @ r1<- field ref CCCC 2744 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2745 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2746 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2747 cmp r0, #0 @ is resolved entry null? 2748 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2750 EXPORT_PC() @ resolve() could throw 2751 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2752 bl dvmResolveInstField @ r0<- resolved InstField ptr 2753 cmp r0, #0 @ success? 2754 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2755 b common_exceptionThrown 2756 2757 2758/* ------------------------------ */ 2759 .balign 64 2760.L_OP_IPUT_BYTE: /* 0x5d */ 2761/* File: armv5te/OP_IPUT_BYTE.S */ 2762@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2763/* File: armv5te/OP_IPUT.S */ 2764 /* 2765 * General 32-bit instance field put. 2766 * 2767 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2768 */ 2769 /* op vA, vB, field@CCCC */ 2770 mov r0, rINST, lsr #12 @ r0<- B 2771 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2772 FETCH(r1, 1) @ r1<- field ref CCCC 2773 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2774 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2775 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2776 cmp r0, #0 @ is resolved entry null? 2777 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27788: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2779 EXPORT_PC() @ resolve() could throw 2780 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2781 bl dvmResolveInstField @ r0<- resolved InstField ptr 2782 cmp r0, #0 @ success? 2783 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2784 b common_exceptionThrown 2785 2786 2787/* ------------------------------ */ 2788 .balign 64 2789.L_OP_IPUT_CHAR: /* 0x5e */ 2790/* File: armv5te/OP_IPUT_CHAR.S */ 2791@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2792/* File: armv5te/OP_IPUT.S */ 2793 /* 2794 * General 32-bit instance field put. 2795 * 2796 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2797 */ 2798 /* op vA, vB, field@CCCC */ 2799 mov r0, rINST, lsr #12 @ r0<- B 2800 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2801 FETCH(r1, 1) @ r1<- field ref CCCC 2802 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2803 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2804 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2805 cmp r0, #0 @ is resolved entry null? 2806 bne .LOP_IPUT_CHAR_finish @ no, already resolved 28078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2808 EXPORT_PC() @ resolve() could throw 2809 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2810 bl dvmResolveInstField @ r0<- resolved InstField ptr 2811 cmp r0, #0 @ success? 2812 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2813 b common_exceptionThrown 2814 2815 2816/* ------------------------------ */ 2817 .balign 64 2818.L_OP_IPUT_SHORT: /* 0x5f */ 2819/* File: armv5te/OP_IPUT_SHORT.S */ 2820@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2821/* File: armv5te/OP_IPUT.S */ 2822 /* 2823 * General 32-bit instance field put. 2824 * 2825 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2826 */ 2827 /* op vA, vB, field@CCCC */ 2828 mov r0, rINST, lsr #12 @ r0<- B 2829 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2830 FETCH(r1, 1) @ r1<- field ref CCCC 2831 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2832 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2833 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2834 cmp r0, #0 @ is resolved entry null? 2835 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2837 EXPORT_PC() @ resolve() could throw 2838 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2839 bl dvmResolveInstField @ r0<- resolved InstField ptr 2840 cmp r0, #0 @ success? 2841 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2842 b common_exceptionThrown 2843 2844 2845/* ------------------------------ */ 2846 .balign 64 2847.L_OP_SGET: /* 0x60 */ 2848/* File: armv5te/OP_SGET.S */ 2849 /* 2850 * General 32-bit SGET handler. 2851 * 2852 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2853 */ 2854 /* op 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_resolve @ yes, do resolve 2861.LOP_SGET_finish: @ field ptr in r0 2862 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2863 mov r2, rINST, lsr #8 @ r2<- AA 2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2865 SET_VREG(r1, r2) @ fp[AA]<- r1 2866 GET_INST_OPCODE(ip) @ extract opcode from rINST 2867 GOTO_OPCODE(ip) @ jump to next instruction 2868 2869/* ------------------------------ */ 2870 .balign 64 2871.L_OP_SGET_WIDE: /* 0x61 */ 2872/* File: armv5te/OP_SGET_WIDE.S */ 2873 /* 2874 * 64-bit SGET handler. 2875 */ 2876 /* sget-wide vAA, field@BBBB */ 2877 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2878 FETCH(r1, 1) @ r1<- field ref BBBB 2879 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2880 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2881 cmp r0, #0 @ is resolved entry null? 2882 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2883.LOP_SGET_WIDE_finish: 2884 mov r1, rINST, lsr #8 @ r1<- AA 2885 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2886 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2887 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2888 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2889 GET_INST_OPCODE(ip) @ extract opcode from rINST 2890 GOTO_OPCODE(ip) @ jump to next instruction 2891 2892/* ------------------------------ */ 2893 .balign 64 2894.L_OP_SGET_OBJECT: /* 0x62 */ 2895/* File: armv5te/OP_SGET_OBJECT.S */ 2896/* File: armv5te/OP_SGET.S */ 2897 /* 2898 * General 32-bit SGET handler. 2899 * 2900 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2901 */ 2902 /* op vAA, field@BBBB */ 2903 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2904 FETCH(r1, 1) @ r1<- field ref BBBB 2905 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2906 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2907 cmp r0, #0 @ is resolved entry null? 2908 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2909.LOP_SGET_OBJECT_finish: @ field ptr in r0 2910 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2911 mov r2, rINST, lsr #8 @ r2<- AA 2912 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2913 SET_VREG(r1, r2) @ fp[AA]<- r1 2914 GET_INST_OPCODE(ip) @ extract opcode from rINST 2915 GOTO_OPCODE(ip) @ jump to next instruction 2916 2917 2918/* ------------------------------ */ 2919 .balign 64 2920.L_OP_SGET_BOOLEAN: /* 0x63 */ 2921/* File: armv5te/OP_SGET_BOOLEAN.S */ 2922/* File: armv5te/OP_SGET.S */ 2923 /* 2924 * General 32-bit SGET handler. 2925 * 2926 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2927 */ 2928 /* op vAA, field@BBBB */ 2929 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2930 FETCH(r1, 1) @ r1<- field ref BBBB 2931 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2932 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2933 cmp r0, #0 @ is resolved entry null? 2934 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2935.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2936 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2937 mov r2, rINST, lsr #8 @ r2<- AA 2938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2939 SET_VREG(r1, r2) @ fp[AA]<- r1 2940 GET_INST_OPCODE(ip) @ extract opcode from rINST 2941 GOTO_OPCODE(ip) @ jump to next instruction 2942 2943 2944/* ------------------------------ */ 2945 .balign 64 2946.L_OP_SGET_BYTE: /* 0x64 */ 2947/* File: armv5te/OP_SGET_BYTE.S */ 2948/* File: armv5te/OP_SGET.S */ 2949 /* 2950 * General 32-bit SGET handler. 2951 * 2952 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2953 */ 2954 /* op vAA, field@BBBB */ 2955 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2956 FETCH(r1, 1) @ r1<- field ref BBBB 2957 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2958 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2959 cmp r0, #0 @ is resolved entry null? 2960 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2961.LOP_SGET_BYTE_finish: @ field ptr in r0 2962 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2963 mov r2, rINST, lsr #8 @ r2<- AA 2964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2965 SET_VREG(r1, r2) @ fp[AA]<- r1 2966 GET_INST_OPCODE(ip) @ extract opcode from rINST 2967 GOTO_OPCODE(ip) @ jump to next instruction 2968 2969 2970/* ------------------------------ */ 2971 .balign 64 2972.L_OP_SGET_CHAR: /* 0x65 */ 2973/* File: armv5te/OP_SGET_CHAR.S */ 2974/* File: armv5te/OP_SGET.S */ 2975 /* 2976 * General 32-bit SGET handler. 2977 * 2978 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2979 */ 2980 /* op vAA, field@BBBB */ 2981 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2982 FETCH(r1, 1) @ r1<- field ref BBBB 2983 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2984 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2985 cmp r0, #0 @ is resolved entry null? 2986 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2987.LOP_SGET_CHAR_finish: @ field ptr in r0 2988 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2989 mov r2, rINST, lsr #8 @ r2<- AA 2990 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2991 SET_VREG(r1, r2) @ fp[AA]<- r1 2992 GET_INST_OPCODE(ip) @ extract opcode from rINST 2993 GOTO_OPCODE(ip) @ jump to next instruction 2994 2995 2996/* ------------------------------ */ 2997 .balign 64 2998.L_OP_SGET_SHORT: /* 0x66 */ 2999/* File: armv5te/OP_SGET_SHORT.S */ 3000/* File: armv5te/OP_SGET.S */ 3001 /* 3002 * General 32-bit SGET handler. 3003 * 3004 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 3005 */ 3006 /* op vAA, field@BBBB */ 3007 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3008 FETCH(r1, 1) @ r1<- field ref BBBB 3009 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3010 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3011 cmp r0, #0 @ is resolved entry null? 3012 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 3013.LOP_SGET_SHORT_finish: @ field ptr in r0 3014 ldr r1, [r0, #offStaticField_value] @ r1<- field value 3015 mov r2, rINST, lsr #8 @ r2<- AA 3016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3017 SET_VREG(r1, r2) @ fp[AA]<- r1 3018 GET_INST_OPCODE(ip) @ extract opcode from rINST 3019 GOTO_OPCODE(ip) @ jump to next instruction 3020 3021 3022/* ------------------------------ */ 3023 .balign 64 3024.L_OP_SPUT: /* 0x67 */ 3025/* File: armv5te/OP_SPUT.S */ 3026 /* 3027 * General 32-bit SPUT handler. 3028 * 3029 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3030 */ 3031 /* op 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 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3036 cmp r0, #0 @ is resolved entry null? 3037 beq .LOP_SPUT_resolve @ yes, do resolve 3038.LOP_SPUT_finish: @ field ptr in r0 3039 mov r2, rINST, lsr #8 @ r2<- AA 3040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3041 GET_VREG(r1, r2) @ r1<- fp[AA] 3042 GET_INST_OPCODE(ip) @ extract opcode from rINST 3043 str r1, [r0, #offStaticField_value] @ field<- vAA 3044 GOTO_OPCODE(ip) @ jump to next instruction 3045 3046/* ------------------------------ */ 3047 .balign 64 3048.L_OP_SPUT_WIDE: /* 0x68 */ 3049/* File: armv5te/OP_SPUT_WIDE.S */ 3050 /* 3051 * 64-bit SPUT handler. 3052 */ 3053 /* sput-wide vAA, field@BBBB */ 3054 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3055 FETCH(r1, 1) @ r1<- field ref BBBB 3056 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3057 mov r9, rINST, lsr #8 @ r9<- AA 3058 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3059 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3060 cmp r0, #0 @ is resolved entry null? 3061 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3062.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 3063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3064 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 3065 GET_INST_OPCODE(ip) @ extract opcode from rINST 3066 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 3067 GOTO_OPCODE(ip) @ jump to next instruction 3068 3069/* ------------------------------ */ 3070 .balign 64 3071.L_OP_SPUT_OBJECT: /* 0x69 */ 3072/* File: armv5te/OP_SPUT_OBJECT.S */ 3073/* File: armv5te/OP_SPUT.S */ 3074 /* 3075 * General 32-bit SPUT handler. 3076 * 3077 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3078 */ 3079 /* op vAA, field@BBBB */ 3080 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3081 FETCH(r1, 1) @ r1<- field ref BBBB 3082 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3083 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3084 cmp r0, #0 @ is resolved entry null? 3085 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3086.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3087 mov r2, rINST, lsr #8 @ r2<- AA 3088 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3089 GET_VREG(r1, r2) @ r1<- fp[AA] 3090 GET_INST_OPCODE(ip) @ extract opcode from rINST 3091 str r1, [r0, #offStaticField_value] @ field<- vAA 3092 GOTO_OPCODE(ip) @ jump to next instruction 3093 3094 3095/* ------------------------------ */ 3096 .balign 64 3097.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3098/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3099/* File: armv5te/OP_SPUT.S */ 3100 /* 3101 * General 32-bit SPUT handler. 3102 * 3103 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3104 */ 3105 /* op vAA, field@BBBB */ 3106 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3107 FETCH(r1, 1) @ r1<- field ref BBBB 3108 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3109 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3110 cmp r0, #0 @ is resolved entry null? 3111 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3112.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3113 mov r2, rINST, lsr #8 @ r2<- AA 3114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3115 GET_VREG(r1, r2) @ r1<- fp[AA] 3116 GET_INST_OPCODE(ip) @ extract opcode from rINST 3117 str r1, [r0, #offStaticField_value] @ field<- vAA 3118 GOTO_OPCODE(ip) @ jump to next instruction 3119 3120 3121/* ------------------------------ */ 3122 .balign 64 3123.L_OP_SPUT_BYTE: /* 0x6b */ 3124/* File: armv5te/OP_SPUT_BYTE.S */ 3125/* File: armv5te/OP_SPUT.S */ 3126 /* 3127 * General 32-bit SPUT handler. 3128 * 3129 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3130 */ 3131 /* op vAA, field@BBBB */ 3132 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3133 FETCH(r1, 1) @ r1<- field ref BBBB 3134 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3135 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3136 cmp r0, #0 @ is resolved entry null? 3137 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3138.LOP_SPUT_BYTE_finish: @ field ptr in r0 3139 mov r2, rINST, lsr #8 @ r2<- AA 3140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3141 GET_VREG(r1, r2) @ r1<- fp[AA] 3142 GET_INST_OPCODE(ip) @ extract opcode from rINST 3143 str r1, [r0, #offStaticField_value] @ field<- vAA 3144 GOTO_OPCODE(ip) @ jump to next instruction 3145 3146 3147/* ------------------------------ */ 3148 .balign 64 3149.L_OP_SPUT_CHAR: /* 0x6c */ 3150/* File: armv5te/OP_SPUT_CHAR.S */ 3151/* File: armv5te/OP_SPUT.S */ 3152 /* 3153 * General 32-bit SPUT handler. 3154 * 3155 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3156 */ 3157 /* op vAA, field@BBBB */ 3158 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3159 FETCH(r1, 1) @ r1<- field ref BBBB 3160 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3161 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3162 cmp r0, #0 @ is resolved entry null? 3163 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3164.LOP_SPUT_CHAR_finish: @ field ptr in r0 3165 mov r2, rINST, lsr #8 @ r2<- AA 3166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3167 GET_VREG(r1, r2) @ r1<- fp[AA] 3168 GET_INST_OPCODE(ip) @ extract opcode from rINST 3169 str r1, [r0, #offStaticField_value] @ field<- vAA 3170 GOTO_OPCODE(ip) @ jump to next instruction 3171 3172 3173/* ------------------------------ */ 3174 .balign 64 3175.L_OP_SPUT_SHORT: /* 0x6d */ 3176/* File: armv5te/OP_SPUT_SHORT.S */ 3177/* File: armv5te/OP_SPUT.S */ 3178 /* 3179 * General 32-bit SPUT handler. 3180 * 3181 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3182 */ 3183 /* op vAA, field@BBBB */ 3184 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3185 FETCH(r1, 1) @ r1<- field ref BBBB 3186 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3187 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3188 cmp r0, #0 @ is resolved entry null? 3189 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3190.LOP_SPUT_SHORT_finish: @ field ptr in r0 3191 mov r2, rINST, lsr #8 @ r2<- AA 3192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3193 GET_VREG(r1, r2) @ r1<- fp[AA] 3194 GET_INST_OPCODE(ip) @ extract opcode from rINST 3195 str r1, [r0, #offStaticField_value] @ field<- vAA 3196 GOTO_OPCODE(ip) @ jump to next instruction 3197 3198 3199/* ------------------------------ */ 3200 .balign 64 3201.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3202/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3203 /* 3204 * Handle a virtual method call. 3205 * 3206 * for: invoke-virtual, invoke-virtual/range 3207 */ 3208 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3209 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3210 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3211 FETCH(r1, 1) @ r1<- BBBB 3212 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3213 FETCH(r10, 2) @ r10<- GFED or CCCC 3214 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3215 .if (!0) 3216 and r10, r10, #15 @ r10<- D (or stays CCCC) 3217 .endif 3218 cmp r0, #0 @ already resolved? 3219 EXPORT_PC() @ must export for invoke 3220 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3221 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3222 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3223 mov r2, #METHOD_VIRTUAL @ resolver method type 3224 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3225 cmp r0, #0 @ got null? 3226 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3227 b common_exceptionThrown @ yes, handle exception 3228 3229/* ------------------------------ */ 3230 .balign 64 3231.L_OP_INVOKE_SUPER: /* 0x6f */ 3232/* File: armv5te/OP_INVOKE_SUPER.S */ 3233 /* 3234 * Handle a "super" method call. 3235 * 3236 * for: invoke-super, invoke-super/range 3237 */ 3238 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3239 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3240 FETCH(r10, 2) @ r10<- GFED or CCCC 3241 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3242 .if (!0) 3243 and r10, r10, #15 @ r10<- D (or stays CCCC) 3244 .endif 3245 FETCH(r1, 1) @ r1<- BBBB 3246 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3247 GET_VREG(r2, r10) @ r2<- "this" ptr 3248 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3249 cmp r2, #0 @ null "this"? 3250 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3251 beq common_errNullObject @ null "this", throw exception 3252 cmp r0, #0 @ already resolved? 3253 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3254 EXPORT_PC() @ must export for invoke 3255 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3256 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3257 3258/* ------------------------------ */ 3259 .balign 64 3260.L_OP_INVOKE_DIRECT: /* 0x70 */ 3261/* File: armv5te/OP_INVOKE_DIRECT.S */ 3262 /* 3263 * Handle a direct method call. 3264 * 3265 * (We could defer the "is 'this' pointer null" test to the common 3266 * method invocation code, and use a flag to indicate that static 3267 * calls don't count. If we do this as part of copying the arguments 3268 * out we could avoiding loading the first arg twice.) 3269 * 3270 * for: invoke-direct, invoke-direct/range 3271 */ 3272 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3273 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3274 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3275 FETCH(r1, 1) @ r1<- BBBB 3276 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3277 FETCH(r10, 2) @ r10<- GFED or CCCC 3278 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3279 .if (!0) 3280 and r10, r10, #15 @ r10<- D (or stays CCCC) 3281 .endif 3282 cmp r0, #0 @ already resolved? 3283 EXPORT_PC() @ must export for invoke 3284 GET_VREG(r2, r10) @ r2<- "this" ptr 3285 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3286.LOP_INVOKE_DIRECT_finish: 3287 cmp r2, #0 @ null "this" ref? 3288 bne common_invokeMethodNoRange @ no, continue on 3289 b common_errNullObject @ yes, throw exception 3290 3291/* ------------------------------ */ 3292 .balign 64 3293.L_OP_INVOKE_STATIC: /* 0x71 */ 3294/* File: armv5te/OP_INVOKE_STATIC.S */ 3295 /* 3296 * Handle a static method call. 3297 * 3298 * for: invoke-static, invoke-static/range 3299 */ 3300 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3301 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3302 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3303 FETCH(r1, 1) @ r1<- BBBB 3304 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3305 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3306 cmp r0, #0 @ already resolved? 3307 EXPORT_PC() @ must export for invoke 3308 bne common_invokeMethodNoRange @ yes, continue on 33090: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3310 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3311 mov r2, #METHOD_STATIC @ resolver method type 3312 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3313 cmp r0, #0 @ got null? 3314 bne common_invokeMethodNoRange @ no, continue 3315 b common_exceptionThrown @ yes, handle exception 3316 3317 3318/* ------------------------------ */ 3319 .balign 64 3320.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3321/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3322 /* 3323 * Handle an interface method call. 3324 * 3325 * for: invoke-interface, invoke-interface/range 3326 */ 3327 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3328 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3329 FETCH(r2, 2) @ r2<- FEDC or CCCC 3330 FETCH(r1, 1) @ r1<- BBBB 3331 .if (!0) 3332 and r2, r2, #15 @ r2<- C (or stays CCCC) 3333 .endif 3334 EXPORT_PC() @ must export for invoke 3335 GET_VREG(r0, r2) @ r0<- first arg ("this") 3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3337 cmp r0, #0 @ null obj? 3338 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3339 beq common_errNullObject @ yes, fail 3340 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3341 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3342 cmp r0, #0 @ failed? 3343 beq common_exceptionThrown @ yes, handle exception 3344 b common_invokeMethodNoRange @ jump to common handler 3345 3346 3347/* ------------------------------ */ 3348 .balign 64 3349.L_OP_UNUSED_73: /* 0x73 */ 3350/* File: armv5te/OP_UNUSED_73.S */ 3351/* File: armv5te/unused.S */ 3352 bl common_abort 3353 3354 3355 3356/* ------------------------------ */ 3357 .balign 64 3358.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3359/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3360/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3361 /* 3362 * Handle a virtual method call. 3363 * 3364 * for: invoke-virtual, invoke-virtual/range 3365 */ 3366 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3367 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3368 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3369 FETCH(r1, 1) @ r1<- BBBB 3370 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3371 FETCH(r10, 2) @ r10<- GFED or CCCC 3372 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3373 .if (!1) 3374 and r10, r10, #15 @ r10<- D (or stays CCCC) 3375 .endif 3376 cmp r0, #0 @ already resolved? 3377 EXPORT_PC() @ must export for invoke 3378 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3379 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3380 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3381 mov r2, #METHOD_VIRTUAL @ resolver method type 3382 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3383 cmp r0, #0 @ got null? 3384 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3385 b common_exceptionThrown @ yes, handle exception 3386 3387 3388/* ------------------------------ */ 3389 .balign 64 3390.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3391/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3392/* File: armv5te/OP_INVOKE_SUPER.S */ 3393 /* 3394 * Handle a "super" method call. 3395 * 3396 * for: invoke-super, invoke-super/range 3397 */ 3398 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3399 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3400 FETCH(r10, 2) @ r10<- GFED or CCCC 3401 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3402 .if (!1) 3403 and r10, r10, #15 @ r10<- D (or stays CCCC) 3404 .endif 3405 FETCH(r1, 1) @ r1<- BBBB 3406 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3407 GET_VREG(r2, r10) @ r2<- "this" ptr 3408 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3409 cmp r2, #0 @ null "this"? 3410 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3411 beq common_errNullObject @ null "this", throw exception 3412 cmp r0, #0 @ already resolved? 3413 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3414 EXPORT_PC() @ must export for invoke 3415 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3416 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3417 3418 3419/* ------------------------------ */ 3420 .balign 64 3421.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3422/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3423/* File: armv5te/OP_INVOKE_DIRECT.S */ 3424 /* 3425 * Handle a direct method call. 3426 * 3427 * (We could defer the "is 'this' pointer null" test to the common 3428 * method invocation code, and use a flag to indicate that static 3429 * calls don't count. If we do this as part of copying the arguments 3430 * out we could avoiding loading the first arg twice.) 3431 * 3432 * for: invoke-direct, invoke-direct/range 3433 */ 3434 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3435 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3436 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3437 FETCH(r1, 1) @ r1<- BBBB 3438 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3439 FETCH(r10, 2) @ r10<- GFED or CCCC 3440 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3441 .if (!1) 3442 and r10, r10, #15 @ r10<- D (or stays CCCC) 3443 .endif 3444 cmp r0, #0 @ already resolved? 3445 EXPORT_PC() @ must export for invoke 3446 GET_VREG(r2, r10) @ r2<- "this" ptr 3447 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3448.LOP_INVOKE_DIRECT_RANGE_finish: 3449 cmp r2, #0 @ null "this" ref? 3450 bne common_invokeMethodRange @ no, continue on 3451 b common_errNullObject @ yes, throw exception 3452 3453 3454/* ------------------------------ */ 3455 .balign 64 3456.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3457/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3458/* File: armv5te/OP_INVOKE_STATIC.S */ 3459 /* 3460 * Handle a static method call. 3461 * 3462 * for: invoke-static, invoke-static/range 3463 */ 3464 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3465 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3466 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3467 FETCH(r1, 1) @ r1<- BBBB 3468 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3469 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3470 cmp r0, #0 @ already resolved? 3471 EXPORT_PC() @ must export for invoke 3472 bne common_invokeMethodRange @ yes, continue on 34730: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3474 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3475 mov r2, #METHOD_STATIC @ resolver method type 3476 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3477 cmp r0, #0 @ got null? 3478 bne common_invokeMethodRange @ no, continue 3479 b common_exceptionThrown @ yes, handle exception 3480 3481 3482 3483/* ------------------------------ */ 3484 .balign 64 3485.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3486/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3487/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3488 /* 3489 * Handle an interface method call. 3490 * 3491 * for: invoke-interface, invoke-interface/range 3492 */ 3493 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3494 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3495 FETCH(r2, 2) @ r2<- FEDC or CCCC 3496 FETCH(r1, 1) @ r1<- BBBB 3497 .if (!1) 3498 and r2, r2, #15 @ r2<- C (or stays CCCC) 3499 .endif 3500 EXPORT_PC() @ must export for invoke 3501 GET_VREG(r0, r2) @ r0<- first arg ("this") 3502 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3503 cmp r0, #0 @ null obj? 3504 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3505 beq common_errNullObject @ yes, fail 3506 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3507 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3508 cmp r0, #0 @ failed? 3509 beq common_exceptionThrown @ yes, handle exception 3510 b common_invokeMethodRange @ jump to common handler 3511 3512 3513 3514/* ------------------------------ */ 3515 .balign 64 3516.L_OP_UNUSED_79: /* 0x79 */ 3517/* File: armv5te/OP_UNUSED_79.S */ 3518/* File: armv5te/unused.S */ 3519 bl common_abort 3520 3521 3522 3523/* ------------------------------ */ 3524 .balign 64 3525.L_OP_UNUSED_7A: /* 0x7a */ 3526/* File: armv5te/OP_UNUSED_7A.S */ 3527/* File: armv5te/unused.S */ 3528 bl common_abort 3529 3530 3531 3532/* ------------------------------ */ 3533 .balign 64 3534.L_OP_NEG_INT: /* 0x7b */ 3535/* File: armv5te/OP_NEG_INT.S */ 3536/* File: armv5te/unop.S */ 3537 /* 3538 * Generic 32-bit unary operation. Provide an "instr" line that 3539 * specifies an instruction that performs "result = op r0". 3540 * This could be an ARM instruction or a function call. 3541 * 3542 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3543 * int-to-byte, int-to-char, int-to-short 3544 */ 3545 /* unop vA, vB */ 3546 mov r3, rINST, lsr #12 @ r3<- B 3547 mov r9, rINST, lsr #8 @ r9<- A+ 3548 GET_VREG(r0, r3) @ r0<- vB 3549 and r9, r9, #15 3550 @ optional op; may set condition codes 3551 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3552 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3553 GET_INST_OPCODE(ip) @ extract opcode from rINST 3554 SET_VREG(r0, r9) @ vAA<- r0 3555 GOTO_OPCODE(ip) @ jump to next instruction 3556 /* 9-10 instructions */ 3557 3558 3559/* ------------------------------ */ 3560 .balign 64 3561.L_OP_NOT_INT: /* 0x7c */ 3562/* File: armv5te/OP_NOT_INT.S */ 3563/* File: armv5te/unop.S */ 3564 /* 3565 * Generic 32-bit unary operation. Provide an "instr" line that 3566 * specifies an instruction that performs "result = op r0". 3567 * This could be an ARM instruction or a function call. 3568 * 3569 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3570 * int-to-byte, int-to-char, int-to-short 3571 */ 3572 /* unop vA, vB */ 3573 mov r3, rINST, lsr #12 @ r3<- B 3574 mov r9, rINST, lsr #8 @ r9<- A+ 3575 GET_VREG(r0, r3) @ r0<- vB 3576 and r9, r9, #15 3577 @ optional op; may set condition codes 3578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3579 mvn r0, r0 @ r0<- op, r0-r3 changed 3580 GET_INST_OPCODE(ip) @ extract opcode from rINST 3581 SET_VREG(r0, r9) @ vAA<- r0 3582 GOTO_OPCODE(ip) @ jump to next instruction 3583 /* 9-10 instructions */ 3584 3585 3586/* ------------------------------ */ 3587 .balign 64 3588.L_OP_NEG_LONG: /* 0x7d */ 3589/* File: armv5te/OP_NEG_LONG.S */ 3590/* File: armv5te/unopWide.S */ 3591 /* 3592 * Generic 64-bit unary operation. Provide an "instr" line that 3593 * specifies an instruction that performs "result = op r0/r1". 3594 * This could be an ARM instruction or a function call. 3595 * 3596 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3597 */ 3598 /* unop vA, vB */ 3599 mov r9, rINST, lsr #8 @ r9<- A+ 3600 mov r3, rINST, lsr #12 @ r3<- B 3601 and r9, r9, #15 3602 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3603 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3604 ldmia r3, {r0-r1} @ r0/r1<- vAA 3605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3606 rsbs r0, r0, #0 @ optional op; may set condition codes 3607 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3608 GET_INST_OPCODE(ip) @ extract opcode from rINST 3609 stmia r9, {r0-r1} @ vAA<- r0/r1 3610 GOTO_OPCODE(ip) @ jump to next instruction 3611 /* 12-13 instructions */ 3612 3613 3614 3615/* ------------------------------ */ 3616 .balign 64 3617.L_OP_NOT_LONG: /* 0x7e */ 3618/* File: armv5te/OP_NOT_LONG.S */ 3619/* File: armv5te/unopWide.S */ 3620 /* 3621 * Generic 64-bit unary operation. Provide an "instr" line that 3622 * specifies an instruction that performs "result = op r0/r1". 3623 * This could be an ARM instruction or a function call. 3624 * 3625 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3626 */ 3627 /* unop vA, vB */ 3628 mov r9, rINST, lsr #8 @ r9<- A+ 3629 mov r3, rINST, lsr #12 @ r3<- B 3630 and r9, r9, #15 3631 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3632 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3633 ldmia r3, {r0-r1} @ r0/r1<- vAA 3634 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3635 mvn r0, r0 @ optional op; may set condition codes 3636 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3637 GET_INST_OPCODE(ip) @ extract opcode from rINST 3638 stmia r9, {r0-r1} @ vAA<- r0/r1 3639 GOTO_OPCODE(ip) @ jump to next instruction 3640 /* 12-13 instructions */ 3641 3642 3643 3644/* ------------------------------ */ 3645 .balign 64 3646.L_OP_NEG_FLOAT: /* 0x7f */ 3647/* File: armv5te/OP_NEG_FLOAT.S */ 3648/* File: armv5te/unop.S */ 3649 /* 3650 * Generic 32-bit unary operation. Provide an "instr" line that 3651 * specifies an instruction that performs "result = op r0". 3652 * This could be an ARM instruction or a function call. 3653 * 3654 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3655 * int-to-byte, int-to-char, int-to-short 3656 */ 3657 /* unop vA, vB */ 3658 mov r3, rINST, lsr #12 @ r3<- B 3659 mov r9, rINST, lsr #8 @ r9<- A+ 3660 GET_VREG(r0, r3) @ r0<- vB 3661 and r9, r9, #15 3662 @ optional op; may set condition codes 3663 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3664 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3665 GET_INST_OPCODE(ip) @ extract opcode from rINST 3666 SET_VREG(r0, r9) @ vAA<- r0 3667 GOTO_OPCODE(ip) @ jump to next instruction 3668 /* 9-10 instructions */ 3669 3670 3671/* ------------------------------ */ 3672 .balign 64 3673.L_OP_NEG_DOUBLE: /* 0x80 */ 3674/* File: armv5te/OP_NEG_DOUBLE.S */ 3675/* File: armv5te/unopWide.S */ 3676 /* 3677 * Generic 64-bit unary operation. Provide an "instr" line that 3678 * specifies an instruction that performs "result = op r0/r1". 3679 * This could be an ARM instruction or a function call. 3680 * 3681 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3682 */ 3683 /* unop vA, vB */ 3684 mov r9, rINST, lsr #8 @ r9<- A+ 3685 mov r3, rINST, lsr #12 @ r3<- B 3686 and r9, r9, #15 3687 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3688 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3689 ldmia r3, {r0-r1} @ r0/r1<- vAA 3690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3691 @ optional op; may set condition codes 3692 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3693 GET_INST_OPCODE(ip) @ extract opcode from rINST 3694 stmia r9, {r0-r1} @ vAA<- r0/r1 3695 GOTO_OPCODE(ip) @ jump to next instruction 3696 /* 12-13 instructions */ 3697 3698 3699 3700/* ------------------------------ */ 3701 .balign 64 3702.L_OP_INT_TO_LONG: /* 0x81 */ 3703/* File: armv5te/OP_INT_TO_LONG.S */ 3704/* File: armv5te/unopWider.S */ 3705 /* 3706 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3707 * that specifies an instruction that performs "result = op r0", where 3708 * "result" is a 64-bit quantity in r0/r1. 3709 * 3710 * For: int-to-long, int-to-double, float-to-long, float-to-double 3711 */ 3712 /* unop vA, vB */ 3713 mov r9, rINST, lsr #8 @ r9<- A+ 3714 mov r3, rINST, lsr #12 @ r3<- B 3715 and r9, r9, #15 3716 GET_VREG(r0, r3) @ r0<- vB 3717 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3718 @ optional op; may set condition codes 3719 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3720 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3721 GET_INST_OPCODE(ip) @ extract opcode from rINST 3722 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3723 GOTO_OPCODE(ip) @ jump to next instruction 3724 /* 10-11 instructions */ 3725 3726 3727/* ------------------------------ */ 3728 .balign 64 3729.L_OP_INT_TO_FLOAT: /* 0x82 */ 3730/* File: armv5te/OP_INT_TO_FLOAT.S */ 3731/* File: armv5te/unop.S */ 3732 /* 3733 * Generic 32-bit unary operation. Provide an "instr" line that 3734 * specifies an instruction that performs "result = op r0". 3735 * This could be an ARM instruction or a function call. 3736 * 3737 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3738 * int-to-byte, int-to-char, int-to-short 3739 */ 3740 /* unop vA, vB */ 3741 mov r3, rINST, lsr #12 @ r3<- B 3742 mov r9, rINST, lsr #8 @ r9<- A+ 3743 GET_VREG(r0, r3) @ r0<- vB 3744 and r9, r9, #15 3745 @ optional op; may set condition codes 3746 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3747 bl __aeabi_i2f @ r0<- op, r0-r3 changed 3748 GET_INST_OPCODE(ip) @ extract opcode from rINST 3749 SET_VREG(r0, r9) @ vAA<- r0 3750 GOTO_OPCODE(ip) @ jump to next instruction 3751 /* 9-10 instructions */ 3752 3753 3754/* ------------------------------ */ 3755 .balign 64 3756.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3757/* File: armv5te/OP_INT_TO_DOUBLE.S */ 3758/* File: armv5te/unopWider.S */ 3759 /* 3760 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3761 * that specifies an instruction that performs "result = op r0", where 3762 * "result" is a 64-bit quantity in r0/r1. 3763 * 3764 * For: int-to-long, int-to-double, float-to-long, float-to-double 3765 */ 3766 /* unop vA, vB */ 3767 mov r9, rINST, lsr #8 @ r9<- A+ 3768 mov r3, rINST, lsr #12 @ r3<- B 3769 and r9, r9, #15 3770 GET_VREG(r0, r3) @ r0<- vB 3771 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3772 @ optional op; may set condition codes 3773 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3774 bl __aeabi_i2d @ r0<- op, r0-r3 changed 3775 GET_INST_OPCODE(ip) @ extract opcode from rINST 3776 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3777 GOTO_OPCODE(ip) @ jump to next instruction 3778 /* 10-11 instructions */ 3779 3780 3781/* ------------------------------ */ 3782 .balign 64 3783.L_OP_LONG_TO_INT: /* 0x84 */ 3784/* File: armv5te/OP_LONG_TO_INT.S */ 3785/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3786/* File: armv5te/OP_MOVE.S */ 3787 /* for move, move-object, long-to-int */ 3788 /* op vA, vB */ 3789 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3790 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3791 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3792 GET_VREG(r2, r1) @ r2<- fp[B] 3793 and r0, r0, #15 3794 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3795 SET_VREG(r2, r0) @ fp[A]<- r2 3796 GOTO_OPCODE(ip) @ execute next instruction 3797 3798 3799 3800/* ------------------------------ */ 3801 .balign 64 3802.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3803/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3804/* File: armv5te/unopNarrower.S */ 3805 /* 3806 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3807 * that specifies an instruction that performs "result = op r0/r1", where 3808 * "result" is a 32-bit quantity in r0. 3809 * 3810 * For: long-to-float, double-to-int, double-to-float 3811 * 3812 * (This would work for long-to-int, but that instruction is actually 3813 * an exact match for OP_MOVE.) 3814 */ 3815 /* unop vA, vB */ 3816 mov r3, rINST, lsr #12 @ r3<- B 3817 mov r9, rINST, lsr #8 @ r9<- A+ 3818 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3819 and r9, r9, #15 3820 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3821 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3822 @ optional op; may set condition codes 3823 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3824 GET_INST_OPCODE(ip) @ extract opcode from rINST 3825 SET_VREG(r0, r9) @ vA<- r0 3826 GOTO_OPCODE(ip) @ jump to next instruction 3827 /* 10-11 instructions */ 3828 3829 3830/* ------------------------------ */ 3831 .balign 64 3832.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3833/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3834/* File: armv5te/unopWide.S */ 3835 /* 3836 * Generic 64-bit unary operation. Provide an "instr" line that 3837 * specifies an instruction that performs "result = op r0/r1". 3838 * This could be an ARM instruction or a function call. 3839 * 3840 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3841 */ 3842 /* unop vA, vB */ 3843 mov r9, rINST, lsr #8 @ r9<- A+ 3844 mov r3, rINST, lsr #12 @ r3<- B 3845 and r9, r9, #15 3846 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3847 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3848 ldmia r3, {r0-r1} @ r0/r1<- vAA 3849 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3850 @ optional op; may set condition codes 3851 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3852 GET_INST_OPCODE(ip) @ extract opcode from rINST 3853 stmia r9, {r0-r1} @ vAA<- r0/r1 3854 GOTO_OPCODE(ip) @ jump to next instruction 3855 /* 12-13 instructions */ 3856 3857 3858 3859/* ------------------------------ */ 3860 .balign 64 3861.L_OP_FLOAT_TO_INT: /* 0x87 */ 3862/* File: armv5te/OP_FLOAT_TO_INT.S */ 3863/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3864/* File: armv5te/unop.S */ 3865 /* 3866 * Generic 32-bit unary operation. Provide an "instr" line that 3867 * specifies an instruction that performs "result = op r0". 3868 * This could be an ARM instruction or a function call. 3869 * 3870 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3871 * int-to-byte, int-to-char, int-to-short 3872 */ 3873 /* unop vA, vB */ 3874 mov r3, rINST, lsr #12 @ r3<- B 3875 mov r9, rINST, lsr #8 @ r9<- A+ 3876 GET_VREG(r0, r3) @ r0<- vB 3877 and r9, r9, #15 3878 @ optional op; may set condition codes 3879 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3880 bl __aeabi_f2iz @ r0<- op, r0-r3 changed 3881 GET_INST_OPCODE(ip) @ extract opcode from rINST 3882 SET_VREG(r0, r9) @ vAA<- r0 3883 GOTO_OPCODE(ip) @ jump to next instruction 3884 /* 9-10 instructions */ 3885 3886 3887#if 0 3888@include "armv5te/unop.S" {"instr":"bl f2i_doconv"} 3889@break 3890/* 3891 * Convert the float in r0 to an int in r0. 3892 * 3893 * We have to clip values to int min/max per the specification. The 3894 * expected common case is a "reasonable" value that converts directly 3895 * to modest integer. The EABI convert function isn't doing this for us. 3896 */ 3897f2i_doconv: 3898 stmfd sp!, {r4, lr} 3899 mov r1, #0x4f000000 @ (float)maxint 3900 mov r4, r0 3901 bl __aeabi_fcmpge @ is arg >= maxint? 3902 cmp r0, #0 @ nonzero == yes 3903 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3904 ldmnefd sp!, {r4, pc} 3905 3906 mov r0, r4 @ recover arg 3907 mov r1, #0xcf000000 @ (float)minint 3908 bl __aeabi_fcmple @ is arg <= minint? 3909 cmp r0, #0 @ nonzero == yes 3910 movne r0, #0x80000000 @ return minint (80000000) 3911 ldmnefd sp!, {r4, pc} 3912 3913 mov r0, r4 @ recover arg 3914 mov r1, r4 3915 bl __aeabi_fcmpeq @ is arg == self? 3916 cmp r0, #0 @ zero == no 3917 ldmeqfd sp!, {r4, pc} @ return zero for NaN 3918 3919 mov r0, r4 @ recover arg 3920 bl __aeabi_f2iz @ convert float to int 3921 ldmfd sp!, {r4, pc} 3922#endif 3923 3924 3925/* ------------------------------ */ 3926 .balign 64 3927.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3928/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3929@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3930/* File: armv5te/unopWider.S */ 3931 /* 3932 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3933 * that specifies an instruction that performs "result = op r0", where 3934 * "result" is a 64-bit quantity in r0/r1. 3935 * 3936 * For: int-to-long, int-to-double, float-to-long, float-to-double 3937 */ 3938 /* unop vA, vB */ 3939 mov r9, rINST, lsr #8 @ r9<- A+ 3940 mov r3, rINST, lsr #12 @ r3<- B 3941 and r9, r9, #15 3942 GET_VREG(r0, r3) @ r0<- vB 3943 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3944 @ optional op; may set condition codes 3945 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3946 bl f2l_doconv @ r0<- op, r0-r3 changed 3947 GET_INST_OPCODE(ip) @ extract opcode from rINST 3948 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3949 GOTO_OPCODE(ip) @ jump to next instruction 3950 /* 10-11 instructions */ 3951 3952 3953 3954/* ------------------------------ */ 3955 .balign 64 3956.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3957/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */ 3958/* File: armv5te/unopWider.S */ 3959 /* 3960 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3961 * that specifies an instruction that performs "result = op r0", where 3962 * "result" is a 64-bit quantity in r0/r1. 3963 * 3964 * For: int-to-long, int-to-double, float-to-long, float-to-double 3965 */ 3966 /* unop vA, vB */ 3967 mov r9, rINST, lsr #8 @ r9<- A+ 3968 mov r3, rINST, lsr #12 @ r3<- B 3969 and r9, r9, #15 3970 GET_VREG(r0, r3) @ r0<- vB 3971 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3972 @ optional op; may set condition codes 3973 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3974 bl __aeabi_f2d @ r0<- op, r0-r3 changed 3975 GET_INST_OPCODE(ip) @ extract opcode from rINST 3976 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3977 GOTO_OPCODE(ip) @ jump to next instruction 3978 /* 10-11 instructions */ 3979 3980 3981/* ------------------------------ */ 3982 .balign 64 3983.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3984/* File: armv5te/OP_DOUBLE_TO_INT.S */ 3985/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3986/* File: armv5te/unopNarrower.S */ 3987 /* 3988 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3989 * that specifies an instruction that performs "result = op r0/r1", where 3990 * "result" is a 32-bit quantity in r0. 3991 * 3992 * For: long-to-float, double-to-int, double-to-float 3993 * 3994 * (This would work for long-to-int, but that instruction is actually 3995 * an exact match for OP_MOVE.) 3996 */ 3997 /* unop vA, vB */ 3998 mov r3, rINST, lsr #12 @ r3<- B 3999 mov r9, rINST, lsr #8 @ r9<- A+ 4000 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4001 and r9, r9, #15 4002 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 4003 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4004 @ optional op; may set condition codes 4005 bl __aeabi_d2iz @ r0<- op, r0-r3 changed 4006 GET_INST_OPCODE(ip) @ extract opcode from rINST 4007 SET_VREG(r0, r9) @ vA<- r0 4008 GOTO_OPCODE(ip) @ jump to next instruction 4009 /* 10-11 instructions */ 4010 4011 4012#if 0 4013@include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"} 4014@break 4015/* 4016 * Convert the double in r0/r1 to an int in r0. 4017 * 4018 * We have to clip values to int min/max per the specification. The 4019 * expected common case is a "reasonable" value that converts directly 4020 * to modest integer. The EABI convert function isn't doing this for us. 4021 */ 4022d2i_doconv: 4023 stmfd sp!, {r4, r5, lr} @ save regs 4024 mov r2, #0x80000000 @ maxint, as a double (low word) 4025 mov r2, r2, asr #9 @ 0xffc00000 4026 sub sp, sp, #4 @ align for EABI 4027 mvn r3, #0xbe000000 @ maxint, as a double (high word) 4028 sub r3, r3, #0x00200000 @ 0x41dfffff 4029 mov r4, r0 @ save a copy of r0 4030 mov r5, r1 @ and r1 4031 bl __aeabi_dcmpge @ is arg >= maxint? 4032 cmp r0, #0 @ nonzero == yes 4033 mvnne r0, #0x80000000 @ return maxint (0x7fffffff) 4034 bne 1f 4035 4036 mov r0, r4 @ recover arg 4037 mov r1, r5 4038 mov r3, #0xc1000000 @ minint, as a double (high word) 4039 add r3, r3, #0x00e00000 @ 0xc1e00000 4040 mov r2, #0 @ minint, as a double (low word) 4041 bl __aeabi_dcmple @ is arg <= minint? 4042 cmp r0, #0 @ nonzero == yes 4043 movne r0, #0x80000000 @ return minint (80000000) 4044 bne 1f 4045 4046 mov r0, r4 @ recover arg 4047 mov r1, r5 4048 mov r2, r4 @ compare against self 4049 mov r3, r5 4050 bl __aeabi_dcmpeq @ is arg == self? 4051 cmp r0, #0 @ zero == no 4052 beq 1f @ return zero for NaN 4053 4054 mov r0, r4 @ recover arg 4055 mov r1, r5 4056 bl __aeabi_d2iz @ convert double to int 4057 40581: 4059 add sp, sp, #4 4060 ldmfd sp!, {r4, r5, pc} 4061#endif 4062 4063 4064/* ------------------------------ */ 4065 .balign 64 4066.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 4067/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 4068@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 4069/* File: armv5te/unopWide.S */ 4070 /* 4071 * Generic 64-bit unary operation. Provide an "instr" line that 4072 * specifies an instruction that performs "result = op r0/r1". 4073 * This could be an ARM instruction or a function call. 4074 * 4075 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 4076 */ 4077 /* unop vA, vB */ 4078 mov r9, rINST, lsr #8 @ r9<- A+ 4079 mov r3, rINST, lsr #12 @ r3<- B 4080 and r9, r9, #15 4081 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4082 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 4083 ldmia r3, {r0-r1} @ r0/r1<- vAA 4084 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4085 @ optional op; may set condition codes 4086 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 4087 GET_INST_OPCODE(ip) @ extract opcode from rINST 4088 stmia r9, {r0-r1} @ vAA<- r0/r1 4089 GOTO_OPCODE(ip) @ jump to next instruction 4090 /* 12-13 instructions */ 4091 4092 4093 4094 4095/* ------------------------------ */ 4096 .balign 64 4097.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 4098/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */ 4099/* File: armv5te/unopNarrower.S */ 4100 /* 4101 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 4102 * that specifies an instruction that performs "result = op r0/r1", where 4103 * "result" is a 32-bit quantity in r0. 4104 * 4105 * For: long-to-float, double-to-int, double-to-float 4106 * 4107 * (This would work for long-to-int, but that instruction is actually 4108 * an exact match for OP_MOVE.) 4109 */ 4110 /* unop vA, vB */ 4111 mov r3, rINST, lsr #12 @ r3<- B 4112 mov r9, rINST, lsr #8 @ r9<- A+ 4113 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4114 and r9, r9, #15 4115 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 4116 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4117 @ optional op; may set condition codes 4118 bl __aeabi_d2f @ r0<- op, r0-r3 changed 4119 GET_INST_OPCODE(ip) @ extract opcode from rINST 4120 SET_VREG(r0, r9) @ vA<- r0 4121 GOTO_OPCODE(ip) @ jump to next instruction 4122 /* 10-11 instructions */ 4123 4124 4125/* ------------------------------ */ 4126 .balign 64 4127.L_OP_INT_TO_BYTE: /* 0x8d */ 4128/* File: armv5te/OP_INT_TO_BYTE.S */ 4129/* File: armv5te/unop.S */ 4130 /* 4131 * Generic 32-bit unary operation. Provide an "instr" line that 4132 * specifies an instruction that performs "result = op r0". 4133 * This could be an ARM instruction or a function call. 4134 * 4135 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4136 * int-to-byte, int-to-char, int-to-short 4137 */ 4138 /* unop vA, vB */ 4139 mov r3, rINST, lsr #12 @ r3<- B 4140 mov r9, rINST, lsr #8 @ r9<- A+ 4141 GET_VREG(r0, r3) @ r0<- vB 4142 and r9, r9, #15 4143 mov r0, r0, asl #24 @ optional op; may set condition codes 4144 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4145 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4146 GET_INST_OPCODE(ip) @ extract opcode from rINST 4147 SET_VREG(r0, r9) @ vAA<- r0 4148 GOTO_OPCODE(ip) @ jump to next instruction 4149 /* 9-10 instructions */ 4150 4151 4152/* ------------------------------ */ 4153 .balign 64 4154.L_OP_INT_TO_CHAR: /* 0x8e */ 4155/* File: armv5te/OP_INT_TO_CHAR.S */ 4156/* File: armv5te/unop.S */ 4157 /* 4158 * Generic 32-bit unary operation. Provide an "instr" line that 4159 * specifies an instruction that performs "result = op r0". 4160 * This could be an ARM instruction or a function call. 4161 * 4162 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4163 * int-to-byte, int-to-char, int-to-short 4164 */ 4165 /* unop vA, vB */ 4166 mov r3, rINST, lsr #12 @ r3<- B 4167 mov r9, rINST, lsr #8 @ r9<- A+ 4168 GET_VREG(r0, r3) @ r0<- vB 4169 and r9, r9, #15 4170 mov r0, r0, asl #16 @ optional op; may set condition codes 4171 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4172 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4173 GET_INST_OPCODE(ip) @ extract opcode from rINST 4174 SET_VREG(r0, r9) @ vAA<- r0 4175 GOTO_OPCODE(ip) @ jump to next instruction 4176 /* 9-10 instructions */ 4177 4178 4179/* ------------------------------ */ 4180 .balign 64 4181.L_OP_INT_TO_SHORT: /* 0x8f */ 4182/* File: armv5te/OP_INT_TO_SHORT.S */ 4183/* File: armv5te/unop.S */ 4184 /* 4185 * Generic 32-bit unary operation. Provide an "instr" line that 4186 * specifies an instruction that performs "result = op r0". 4187 * This could be an ARM instruction or a function call. 4188 * 4189 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4190 * int-to-byte, int-to-char, int-to-short 4191 */ 4192 /* unop vA, vB */ 4193 mov r3, rINST, lsr #12 @ r3<- B 4194 mov r9, rINST, lsr #8 @ r9<- A+ 4195 GET_VREG(r0, r3) @ r0<- vB 4196 and r9, r9, #15 4197 mov r0, r0, asl #16 @ optional op; may set condition codes 4198 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4199 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4200 GET_INST_OPCODE(ip) @ extract opcode from rINST 4201 SET_VREG(r0, r9) @ vAA<- r0 4202 GOTO_OPCODE(ip) @ jump to next instruction 4203 /* 9-10 instructions */ 4204 4205 4206/* ------------------------------ */ 4207 .balign 64 4208.L_OP_ADD_INT: /* 0x90 */ 4209/* File: armv5te/OP_ADD_INT.S */ 4210/* File: armv5te/binop.S */ 4211 /* 4212 * Generic 32-bit binary operation. Provide an "instr" line that 4213 * specifies an instruction that performs "result = r0 op r1". 4214 * This could be an ARM instruction or a function call. (If the result 4215 * comes back in a register other than r0, you can override "result".) 4216 * 4217 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4218 * vCC (r1). Useful for integer division and modulus. Note that we 4219 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4220 * handles it correctly. 4221 * 4222 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4223 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4224 * mul-float, div-float, rem-float 4225 */ 4226 /* binop vAA, vBB, vCC */ 4227 FETCH(r0, 1) @ r0<- CCBB 4228 mov r9, rINST, lsr #8 @ r9<- AA 4229 mov r3, r0, lsr #8 @ r3<- CC 4230 and r2, r0, #255 @ r2<- BB 4231 GET_VREG(r1, r3) @ r1<- vCC 4232 GET_VREG(r0, r2) @ r0<- vBB 4233 .if 0 4234 cmp r1, #0 @ is second operand zero? 4235 beq common_errDivideByZero 4236 .endif 4237 4238 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4239 @ optional op; may set condition codes 4240 add r0, r0, r1 @ r0<- op, r0-r3 changed 4241 GET_INST_OPCODE(ip) @ extract opcode from rINST 4242 SET_VREG(r0, r9) @ vAA<- r0 4243 GOTO_OPCODE(ip) @ jump to next instruction 4244 /* 11-14 instructions */ 4245 4246 4247 4248/* ------------------------------ */ 4249 .balign 64 4250.L_OP_SUB_INT: /* 0x91 */ 4251/* File: armv5te/OP_SUB_INT.S */ 4252/* File: armv5te/binop.S */ 4253 /* 4254 * Generic 32-bit binary operation. Provide an "instr" line that 4255 * specifies an instruction that performs "result = r0 op r1". 4256 * This could be an ARM instruction or a function call. (If the result 4257 * comes back in a register other than r0, you can override "result".) 4258 * 4259 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4260 * vCC (r1). Useful for integer division and modulus. Note that we 4261 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4262 * handles it correctly. 4263 * 4264 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4265 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4266 * mul-float, div-float, rem-float 4267 */ 4268 /* binop vAA, vBB, vCC */ 4269 FETCH(r0, 1) @ r0<- CCBB 4270 mov r9, rINST, lsr #8 @ r9<- AA 4271 mov r3, r0, lsr #8 @ r3<- CC 4272 and r2, r0, #255 @ r2<- BB 4273 GET_VREG(r1, r3) @ r1<- vCC 4274 GET_VREG(r0, r2) @ r0<- vBB 4275 .if 0 4276 cmp r1, #0 @ is second operand zero? 4277 beq common_errDivideByZero 4278 .endif 4279 4280 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4281 @ optional op; may set condition codes 4282 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4283 GET_INST_OPCODE(ip) @ extract opcode from rINST 4284 SET_VREG(r0, r9) @ vAA<- r0 4285 GOTO_OPCODE(ip) @ jump to next instruction 4286 /* 11-14 instructions */ 4287 4288 4289 4290/* ------------------------------ */ 4291 .balign 64 4292.L_OP_MUL_INT: /* 0x92 */ 4293/* File: armv5te/OP_MUL_INT.S */ 4294/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4295/* File: armv5te/binop.S */ 4296 /* 4297 * Generic 32-bit binary operation. Provide an "instr" line that 4298 * specifies an instruction that performs "result = r0 op r1". 4299 * This could be an ARM instruction or a function call. (If the result 4300 * comes back in a register other than r0, you can override "result".) 4301 * 4302 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4303 * vCC (r1). Useful for integer division and modulus. Note that we 4304 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4305 * handles it correctly. 4306 * 4307 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4308 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4309 * mul-float, div-float, rem-float 4310 */ 4311 /* binop vAA, vBB, vCC */ 4312 FETCH(r0, 1) @ r0<- CCBB 4313 mov r9, rINST, lsr #8 @ r9<- AA 4314 mov r3, r0, lsr #8 @ r3<- CC 4315 and r2, r0, #255 @ r2<- BB 4316 GET_VREG(r1, r3) @ r1<- vCC 4317 GET_VREG(r0, r2) @ r0<- vBB 4318 .if 0 4319 cmp r1, #0 @ is second operand zero? 4320 beq common_errDivideByZero 4321 .endif 4322 4323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4324 @ optional op; may set condition codes 4325 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4326 GET_INST_OPCODE(ip) @ extract opcode from rINST 4327 SET_VREG(r0, r9) @ vAA<- r0 4328 GOTO_OPCODE(ip) @ jump to next instruction 4329 /* 11-14 instructions */ 4330 4331 4332 4333/* ------------------------------ */ 4334 .balign 64 4335.L_OP_DIV_INT: /* 0x93 */ 4336/* File: armv5te/OP_DIV_INT.S */ 4337/* File: armv5te/binop.S */ 4338 /* 4339 * Generic 32-bit binary operation. Provide an "instr" line that 4340 * specifies an instruction that performs "result = r0 op r1". 4341 * This could be an ARM instruction or a function call. (If the result 4342 * comes back in a register other than r0, you can override "result".) 4343 * 4344 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4345 * vCC (r1). Useful for integer division and modulus. Note that we 4346 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4347 * handles it correctly. 4348 * 4349 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4350 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4351 * mul-float, div-float, rem-float 4352 */ 4353 /* binop vAA, vBB, vCC */ 4354 FETCH(r0, 1) @ r0<- CCBB 4355 mov r9, rINST, lsr #8 @ r9<- AA 4356 mov r3, r0, lsr #8 @ r3<- CC 4357 and r2, r0, #255 @ r2<- BB 4358 GET_VREG(r1, r3) @ r1<- vCC 4359 GET_VREG(r0, r2) @ r0<- vBB 4360 .if 1 4361 cmp r1, #0 @ is second operand zero? 4362 beq common_errDivideByZero 4363 .endif 4364 4365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4366 @ optional op; may set condition codes 4367 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4368 GET_INST_OPCODE(ip) @ extract opcode from rINST 4369 SET_VREG(r0, r9) @ vAA<- r0 4370 GOTO_OPCODE(ip) @ jump to next instruction 4371 /* 11-14 instructions */ 4372 4373 4374 4375/* ------------------------------ */ 4376 .balign 64 4377.L_OP_REM_INT: /* 0x94 */ 4378/* File: armv5te/OP_REM_INT.S */ 4379/* idivmod returns quotient in r0 and remainder in r1 */ 4380/* File: armv5te/binop.S */ 4381 /* 4382 * Generic 32-bit binary operation. Provide an "instr" line that 4383 * specifies an instruction that performs "result = r0 op r1". 4384 * This could be an ARM instruction or a function call. (If the result 4385 * comes back in a register other than r0, you can override "result".) 4386 * 4387 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4388 * vCC (r1). Useful for integer division and modulus. Note that we 4389 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4390 * handles it correctly. 4391 * 4392 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4393 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4394 * mul-float, div-float, rem-float 4395 */ 4396 /* binop vAA, vBB, vCC */ 4397 FETCH(r0, 1) @ r0<- CCBB 4398 mov r9, rINST, lsr #8 @ r9<- AA 4399 mov r3, r0, lsr #8 @ r3<- CC 4400 and r2, r0, #255 @ r2<- BB 4401 GET_VREG(r1, r3) @ r1<- vCC 4402 GET_VREG(r0, r2) @ r0<- vBB 4403 .if 1 4404 cmp r1, #0 @ is second operand zero? 4405 beq common_errDivideByZero 4406 .endif 4407 4408 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4409 @ optional op; may set condition codes 4410 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4411 GET_INST_OPCODE(ip) @ extract opcode from rINST 4412 SET_VREG(r1, r9) @ vAA<- r1 4413 GOTO_OPCODE(ip) @ jump to next instruction 4414 /* 11-14 instructions */ 4415 4416 4417 4418/* ------------------------------ */ 4419 .balign 64 4420.L_OP_AND_INT: /* 0x95 */ 4421/* File: armv5te/OP_AND_INT.S */ 4422/* File: armv5te/binop.S */ 4423 /* 4424 * Generic 32-bit binary operation. Provide an "instr" line that 4425 * specifies an instruction that performs "result = r0 op r1". 4426 * This could be an ARM instruction or a function call. (If the result 4427 * comes back in a register other than r0, you can override "result".) 4428 * 4429 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4430 * vCC (r1). Useful for integer division and modulus. Note that we 4431 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4432 * handles it correctly. 4433 * 4434 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4435 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4436 * mul-float, div-float, rem-float 4437 */ 4438 /* binop vAA, vBB, vCC */ 4439 FETCH(r0, 1) @ r0<- CCBB 4440 mov r9, rINST, lsr #8 @ r9<- AA 4441 mov r3, r0, lsr #8 @ r3<- CC 4442 and r2, r0, #255 @ r2<- BB 4443 GET_VREG(r1, r3) @ r1<- vCC 4444 GET_VREG(r0, r2) @ r0<- vBB 4445 .if 0 4446 cmp r1, #0 @ is second operand zero? 4447 beq common_errDivideByZero 4448 .endif 4449 4450 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4451 @ optional op; may set condition codes 4452 and r0, r0, r1 @ r0<- op, r0-r3 changed 4453 GET_INST_OPCODE(ip) @ extract opcode from rINST 4454 SET_VREG(r0, r9) @ vAA<- r0 4455 GOTO_OPCODE(ip) @ jump to next instruction 4456 /* 11-14 instructions */ 4457 4458 4459 4460/* ------------------------------ */ 4461 .balign 64 4462.L_OP_OR_INT: /* 0x96 */ 4463/* File: armv5te/OP_OR_INT.S */ 4464/* File: armv5te/binop.S */ 4465 /* 4466 * Generic 32-bit binary operation. Provide an "instr" line that 4467 * specifies an instruction that performs "result = r0 op r1". 4468 * This could be an ARM instruction or a function call. (If the result 4469 * comes back in a register other than r0, you can override "result".) 4470 * 4471 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4472 * vCC (r1). Useful for integer division and modulus. Note that we 4473 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4474 * handles it correctly. 4475 * 4476 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4477 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4478 * mul-float, div-float, rem-float 4479 */ 4480 /* binop vAA, vBB, vCC */ 4481 FETCH(r0, 1) @ r0<- CCBB 4482 mov r9, rINST, lsr #8 @ r9<- AA 4483 mov r3, r0, lsr #8 @ r3<- CC 4484 and r2, r0, #255 @ r2<- BB 4485 GET_VREG(r1, r3) @ r1<- vCC 4486 GET_VREG(r0, r2) @ r0<- vBB 4487 .if 0 4488 cmp r1, #0 @ is second operand zero? 4489 beq common_errDivideByZero 4490 .endif 4491 4492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4493 @ optional op; may set condition codes 4494 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4495 GET_INST_OPCODE(ip) @ extract opcode from rINST 4496 SET_VREG(r0, r9) @ vAA<- r0 4497 GOTO_OPCODE(ip) @ jump to next instruction 4498 /* 11-14 instructions */ 4499 4500 4501 4502/* ------------------------------ */ 4503 .balign 64 4504.L_OP_XOR_INT: /* 0x97 */ 4505/* File: armv5te/OP_XOR_INT.S */ 4506/* File: armv5te/binop.S */ 4507 /* 4508 * Generic 32-bit binary operation. Provide an "instr" line that 4509 * specifies an instruction that performs "result = r0 op r1". 4510 * This could be an ARM instruction or a function call. (If the result 4511 * comes back in a register other than r0, you can override "result".) 4512 * 4513 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4514 * vCC (r1). Useful for integer division and modulus. Note that we 4515 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4516 * handles it correctly. 4517 * 4518 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4519 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4520 * mul-float, div-float, rem-float 4521 */ 4522 /* binop vAA, vBB, vCC */ 4523 FETCH(r0, 1) @ r0<- CCBB 4524 mov r9, rINST, lsr #8 @ r9<- AA 4525 mov r3, r0, lsr #8 @ r3<- CC 4526 and r2, r0, #255 @ r2<- BB 4527 GET_VREG(r1, r3) @ r1<- vCC 4528 GET_VREG(r0, r2) @ r0<- vBB 4529 .if 0 4530 cmp r1, #0 @ is second operand zero? 4531 beq common_errDivideByZero 4532 .endif 4533 4534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4535 @ optional op; may set condition codes 4536 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4537 GET_INST_OPCODE(ip) @ extract opcode from rINST 4538 SET_VREG(r0, r9) @ vAA<- r0 4539 GOTO_OPCODE(ip) @ jump to next instruction 4540 /* 11-14 instructions */ 4541 4542 4543 4544/* ------------------------------ */ 4545 .balign 64 4546.L_OP_SHL_INT: /* 0x98 */ 4547/* File: armv5te/OP_SHL_INT.S */ 4548/* File: armv5te/binop.S */ 4549 /* 4550 * Generic 32-bit binary operation. Provide an "instr" line that 4551 * specifies an instruction that performs "result = r0 op r1". 4552 * This could be an ARM instruction or a function call. (If the result 4553 * comes back in a register other than r0, you can override "result".) 4554 * 4555 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4556 * vCC (r1). Useful for integer division and modulus. Note that we 4557 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4558 * handles it correctly. 4559 * 4560 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4561 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4562 * mul-float, div-float, rem-float 4563 */ 4564 /* binop vAA, vBB, vCC */ 4565 FETCH(r0, 1) @ r0<- CCBB 4566 mov r9, rINST, lsr #8 @ r9<- AA 4567 mov r3, r0, lsr #8 @ r3<- CC 4568 and r2, r0, #255 @ r2<- BB 4569 GET_VREG(r1, r3) @ r1<- vCC 4570 GET_VREG(r0, r2) @ r0<- vBB 4571 .if 0 4572 cmp r1, #0 @ is second operand zero? 4573 beq common_errDivideByZero 4574 .endif 4575 4576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4577 and r1, r1, #31 @ optional op; may set condition codes 4578 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4579 GET_INST_OPCODE(ip) @ extract opcode from rINST 4580 SET_VREG(r0, r9) @ vAA<- r0 4581 GOTO_OPCODE(ip) @ jump to next instruction 4582 /* 11-14 instructions */ 4583 4584 4585 4586/* ------------------------------ */ 4587 .balign 64 4588.L_OP_SHR_INT: /* 0x99 */ 4589/* File: armv5te/OP_SHR_INT.S */ 4590/* File: armv5te/binop.S */ 4591 /* 4592 * Generic 32-bit binary operation. Provide an "instr" line that 4593 * specifies an instruction that performs "result = r0 op r1". 4594 * This could be an ARM instruction or a function call. (If the result 4595 * comes back in a register other than r0, you can override "result".) 4596 * 4597 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4598 * vCC (r1). Useful for integer division and modulus. Note that we 4599 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4600 * handles it correctly. 4601 * 4602 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4603 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4604 * mul-float, div-float, rem-float 4605 */ 4606 /* binop vAA, vBB, vCC */ 4607 FETCH(r0, 1) @ r0<- CCBB 4608 mov r9, rINST, lsr #8 @ r9<- AA 4609 mov r3, r0, lsr #8 @ r3<- CC 4610 and r2, r0, #255 @ r2<- BB 4611 GET_VREG(r1, r3) @ r1<- vCC 4612 GET_VREG(r0, r2) @ r0<- vBB 4613 .if 0 4614 cmp r1, #0 @ is second operand zero? 4615 beq common_errDivideByZero 4616 .endif 4617 4618 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4619 and r1, r1, #31 @ optional op; may set condition codes 4620 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4621 GET_INST_OPCODE(ip) @ extract opcode from rINST 4622 SET_VREG(r0, r9) @ vAA<- r0 4623 GOTO_OPCODE(ip) @ jump to next instruction 4624 /* 11-14 instructions */ 4625 4626 4627 4628/* ------------------------------ */ 4629 .balign 64 4630.L_OP_USHR_INT: /* 0x9a */ 4631/* File: armv5te/OP_USHR_INT.S */ 4632/* File: armv5te/binop.S */ 4633 /* 4634 * Generic 32-bit binary operation. Provide an "instr" line that 4635 * specifies an instruction that performs "result = r0 op r1". 4636 * This could be an ARM instruction or a function call. (If the result 4637 * comes back in a register other than r0, you can override "result".) 4638 * 4639 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4640 * vCC (r1). Useful for integer division and modulus. Note that we 4641 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4642 * handles it correctly. 4643 * 4644 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4645 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4646 * mul-float, div-float, rem-float 4647 */ 4648 /* binop vAA, vBB, vCC */ 4649 FETCH(r0, 1) @ r0<- CCBB 4650 mov r9, rINST, lsr #8 @ r9<- AA 4651 mov r3, r0, lsr #8 @ r3<- CC 4652 and r2, r0, #255 @ r2<- BB 4653 GET_VREG(r1, r3) @ r1<- vCC 4654 GET_VREG(r0, r2) @ r0<- vBB 4655 .if 0 4656 cmp r1, #0 @ is second operand zero? 4657 beq common_errDivideByZero 4658 .endif 4659 4660 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4661 and r1, r1, #31 @ optional op; may set condition codes 4662 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4663 GET_INST_OPCODE(ip) @ extract opcode from rINST 4664 SET_VREG(r0, r9) @ vAA<- r0 4665 GOTO_OPCODE(ip) @ jump to next instruction 4666 /* 11-14 instructions */ 4667 4668 4669 4670/* ------------------------------ */ 4671 .balign 64 4672.L_OP_ADD_LONG: /* 0x9b */ 4673/* File: armv5te/OP_ADD_LONG.S */ 4674/* File: armv5te/binopWide.S */ 4675 /* 4676 * Generic 64-bit binary operation. Provide an "instr" line that 4677 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4678 * This could be an ARM instruction or a function call. (If the result 4679 * comes back in a register other than r0, you can override "result".) 4680 * 4681 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4682 * vCC (r1). Useful for integer division and modulus. 4683 * 4684 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4685 * xor-long, add-double, sub-double, mul-double, div-double, 4686 * rem-double 4687 * 4688 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4689 */ 4690 /* binop vAA, vBB, vCC */ 4691 FETCH(r0, 1) @ r0<- CCBB 4692 mov r9, rINST, lsr #8 @ r9<- AA 4693 and r2, r0, #255 @ r2<- BB 4694 mov r3, r0, lsr #8 @ r3<- CC 4695 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4696 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4697 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4698 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4699 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4700 .if 0 4701 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4702 beq common_errDivideByZero 4703 .endif 4704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4705 4706 adds r0, r0, r2 @ optional op; may set condition codes 4707 adc r1, r1, r3 @ result<- op, r0-r3 changed 4708 GET_INST_OPCODE(ip) @ extract opcode from rINST 4709 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4710 GOTO_OPCODE(ip) @ jump to next instruction 4711 /* 14-17 instructions */ 4712 4713 4714 4715/* ------------------------------ */ 4716 .balign 64 4717.L_OP_SUB_LONG: /* 0x9c */ 4718/* File: armv5te/OP_SUB_LONG.S */ 4719/* File: armv5te/binopWide.S */ 4720 /* 4721 * Generic 64-bit binary operation. Provide an "instr" line that 4722 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4723 * This could be an ARM instruction or a function call. (If the result 4724 * comes back in a register other than r0, you can override "result".) 4725 * 4726 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4727 * vCC (r1). Useful for integer division and modulus. 4728 * 4729 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4730 * xor-long, add-double, sub-double, mul-double, div-double, 4731 * rem-double 4732 * 4733 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4734 */ 4735 /* binop vAA, vBB, vCC */ 4736 FETCH(r0, 1) @ r0<- CCBB 4737 mov r9, rINST, lsr #8 @ r9<- AA 4738 and r2, r0, #255 @ r2<- BB 4739 mov r3, r0, lsr #8 @ r3<- CC 4740 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4741 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4742 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4743 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4744 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4745 .if 0 4746 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4747 beq common_errDivideByZero 4748 .endif 4749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4750 4751 subs r0, r0, r2 @ optional op; may set condition codes 4752 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4753 GET_INST_OPCODE(ip) @ extract opcode from rINST 4754 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4755 GOTO_OPCODE(ip) @ jump to next instruction 4756 /* 14-17 instructions */ 4757 4758 4759 4760/* ------------------------------ */ 4761 .balign 64 4762.L_OP_MUL_LONG: /* 0x9d */ 4763/* File: armv5te/OP_MUL_LONG.S */ 4764 /* 4765 * Signed 64-bit integer multiply. 4766 * 4767 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4768 * WX 4769 * x YZ 4770 * -------- 4771 * ZW ZX 4772 * YW YX 4773 * 4774 * The low word of the result holds ZX, the high word holds 4775 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4776 * it doesn't fit in the low 64 bits. 4777 * 4778 * Unlike most ARM math operations, multiply instructions have 4779 * restrictions on using the same register more than once (Rd and Rm 4780 * cannot be the same). 4781 */ 4782 /* mul-long vAA, vBB, vCC */ 4783 FETCH(r0, 1) @ r0<- CCBB 4784 and r2, r0, #255 @ r2<- BB 4785 mov r3, r0, lsr #8 @ r3<- CC 4786 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4787 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4788 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4789 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4790 mul ip, r2, r1 @ ip<- ZxW 4791 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4792 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4793 mov r0, rINST, lsr #8 @ r0<- AA 4794 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4795 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4796 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4797 b .LOP_MUL_LONG_finish 4798 4799/* ------------------------------ */ 4800 .balign 64 4801.L_OP_DIV_LONG: /* 0x9e */ 4802/* File: armv5te/OP_DIV_LONG.S */ 4803/* File: armv5te/binopWide.S */ 4804 /* 4805 * Generic 64-bit binary operation. Provide an "instr" line that 4806 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4807 * This could be an ARM instruction or a function call. (If the result 4808 * comes back in a register other than r0, you can override "result".) 4809 * 4810 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4811 * vCC (r1). Useful for integer division and modulus. 4812 * 4813 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4814 * xor-long, add-double, sub-double, mul-double, div-double, 4815 * rem-double 4816 * 4817 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4818 */ 4819 /* binop vAA, vBB, vCC */ 4820 FETCH(r0, 1) @ r0<- CCBB 4821 mov r9, rINST, lsr #8 @ r9<- AA 4822 and r2, r0, #255 @ r2<- BB 4823 mov r3, r0, lsr #8 @ r3<- CC 4824 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4825 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4826 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4827 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4828 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4829 .if 1 4830 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4831 beq common_errDivideByZero 4832 .endif 4833 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4834 4835 @ optional op; may set condition codes 4836 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4837 GET_INST_OPCODE(ip) @ extract opcode from rINST 4838 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4839 GOTO_OPCODE(ip) @ jump to next instruction 4840 /* 14-17 instructions */ 4841 4842 4843 4844/* ------------------------------ */ 4845 .balign 64 4846.L_OP_REM_LONG: /* 0x9f */ 4847/* File: armv5te/OP_REM_LONG.S */ 4848/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4849/* File: armv5te/binopWide.S */ 4850 /* 4851 * Generic 64-bit binary operation. Provide an "instr" line that 4852 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4853 * This could be an ARM instruction or a function call. (If the result 4854 * comes back in a register other than r0, you can override "result".) 4855 * 4856 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4857 * vCC (r1). Useful for integer division and modulus. 4858 * 4859 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4860 * xor-long, add-double, sub-double, mul-double, div-double, 4861 * rem-double 4862 * 4863 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4864 */ 4865 /* binop vAA, vBB, vCC */ 4866 FETCH(r0, 1) @ r0<- CCBB 4867 mov r9, rINST, lsr #8 @ r9<- AA 4868 and r2, r0, #255 @ r2<- BB 4869 mov r3, r0, lsr #8 @ r3<- CC 4870 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4871 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4872 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4873 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4874 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4875 .if 1 4876 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4877 beq common_errDivideByZero 4878 .endif 4879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4880 4881 @ optional op; may set condition codes 4882 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4883 GET_INST_OPCODE(ip) @ extract opcode from rINST 4884 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4885 GOTO_OPCODE(ip) @ jump to next instruction 4886 /* 14-17 instructions */ 4887 4888 4889 4890/* ------------------------------ */ 4891 .balign 64 4892.L_OP_AND_LONG: /* 0xa0 */ 4893/* File: armv5te/OP_AND_LONG.S */ 4894/* File: armv5te/binopWide.S */ 4895 /* 4896 * Generic 64-bit binary operation. Provide an "instr" line that 4897 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4898 * This could be an ARM instruction or a function call. (If the result 4899 * comes back in a register other than r0, you can override "result".) 4900 * 4901 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4902 * vCC (r1). Useful for integer division and modulus. 4903 * 4904 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4905 * xor-long, add-double, sub-double, mul-double, div-double, 4906 * rem-double 4907 * 4908 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4909 */ 4910 /* binop vAA, vBB, vCC */ 4911 FETCH(r0, 1) @ r0<- CCBB 4912 mov r9, rINST, lsr #8 @ r9<- AA 4913 and r2, r0, #255 @ r2<- BB 4914 mov r3, r0, lsr #8 @ r3<- CC 4915 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4916 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4917 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4918 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4919 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4920 .if 0 4921 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4922 beq common_errDivideByZero 4923 .endif 4924 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4925 4926 and r0, r0, r2 @ optional op; may set condition codes 4927 and r1, r1, r3 @ result<- op, r0-r3 changed 4928 GET_INST_OPCODE(ip) @ extract opcode from rINST 4929 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4930 GOTO_OPCODE(ip) @ jump to next instruction 4931 /* 14-17 instructions */ 4932 4933 4934 4935/* ------------------------------ */ 4936 .balign 64 4937.L_OP_OR_LONG: /* 0xa1 */ 4938/* File: armv5te/OP_OR_LONG.S */ 4939/* File: armv5te/binopWide.S */ 4940 /* 4941 * Generic 64-bit binary operation. Provide an "instr" line that 4942 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4943 * This could be an ARM instruction or a function call. (If the result 4944 * comes back in a register other than r0, you can override "result".) 4945 * 4946 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4947 * vCC (r1). Useful for integer division and modulus. 4948 * 4949 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4950 * xor-long, add-double, sub-double, mul-double, div-double, 4951 * rem-double 4952 * 4953 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4954 */ 4955 /* binop vAA, vBB, vCC */ 4956 FETCH(r0, 1) @ r0<- CCBB 4957 mov r9, rINST, lsr #8 @ r9<- AA 4958 and r2, r0, #255 @ r2<- BB 4959 mov r3, r0, lsr #8 @ r3<- CC 4960 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4961 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4962 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4963 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4964 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4965 .if 0 4966 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4967 beq common_errDivideByZero 4968 .endif 4969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4970 4971 orr r0, r0, r2 @ optional op; may set condition codes 4972 orr r1, r1, r3 @ result<- op, r0-r3 changed 4973 GET_INST_OPCODE(ip) @ extract opcode from rINST 4974 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4975 GOTO_OPCODE(ip) @ jump to next instruction 4976 /* 14-17 instructions */ 4977 4978 4979 4980/* ------------------------------ */ 4981 .balign 64 4982.L_OP_XOR_LONG: /* 0xa2 */ 4983/* File: armv5te/OP_XOR_LONG.S */ 4984/* File: armv5te/binopWide.S */ 4985 /* 4986 * Generic 64-bit binary operation. Provide an "instr" line that 4987 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4988 * This could be an ARM instruction or a function call. (If the result 4989 * comes back in a register other than r0, you can override "result".) 4990 * 4991 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4992 * vCC (r1). Useful for integer division and modulus. 4993 * 4994 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4995 * xor-long, add-double, sub-double, mul-double, div-double, 4996 * rem-double 4997 * 4998 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4999 */ 5000 /* binop vAA, vBB, vCC */ 5001 FETCH(r0, 1) @ r0<- CCBB 5002 mov r9, rINST, lsr #8 @ r9<- AA 5003 and r2, r0, #255 @ r2<- BB 5004 mov r3, r0, lsr #8 @ r3<- CC 5005 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5006 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5007 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5008 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5009 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5010 .if 0 5011 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5012 beq common_errDivideByZero 5013 .endif 5014 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5015 5016 eor r0, r0, r2 @ optional op; may set condition codes 5017 eor r1, r1, r3 @ result<- op, r0-r3 changed 5018 GET_INST_OPCODE(ip) @ extract opcode from rINST 5019 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5020 GOTO_OPCODE(ip) @ jump to next instruction 5021 /* 14-17 instructions */ 5022 5023 5024 5025/* ------------------------------ */ 5026 .balign 64 5027.L_OP_SHL_LONG: /* 0xa3 */ 5028/* File: armv5te/OP_SHL_LONG.S */ 5029 /* 5030 * Long integer shift. This is different from the generic 32/64-bit 5031 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5032 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5033 * 6 bits of the shift distance. 5034 */ 5035 /* shl-long vAA, vBB, vCC */ 5036 FETCH(r0, 1) @ r0<- CCBB 5037 mov r9, rINST, lsr #8 @ r9<- AA 5038 and r3, r0, #255 @ r3<- BB 5039 mov r0, r0, lsr #8 @ r0<- CC 5040 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5041 GET_VREG(r2, r0) @ r2<- vCC 5042 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5043 and r2, r2, #63 @ r2<- r2 & 0x3f 5044 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5045 5046 mov r1, r1, asl r2 @ r1<- r1 << r2 5047 rsb r3, r2, #32 @ r3<- 32 - r2 5048 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5049 subs ip, r2, #32 @ ip<- r2 - 32 5050 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5051 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5052 b .LOP_SHL_LONG_finish 5053 5054/* ------------------------------ */ 5055 .balign 64 5056.L_OP_SHR_LONG: /* 0xa4 */ 5057/* File: armv5te/OP_SHR_LONG.S */ 5058 /* 5059 * Long integer shift. This is different from the generic 32/64-bit 5060 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5061 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5062 * 6 bits of the shift distance. 5063 */ 5064 /* shr-long vAA, vBB, vCC */ 5065 FETCH(r0, 1) @ r0<- CCBB 5066 mov r9, rINST, lsr #8 @ r9<- AA 5067 and r3, r0, #255 @ r3<- BB 5068 mov r0, r0, lsr #8 @ r0<- CC 5069 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5070 GET_VREG(r2, r0) @ r2<- vCC 5071 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5072 and r2, r2, #63 @ r0<- r0 & 0x3f 5073 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5074 5075 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5076 rsb r3, r2, #32 @ r3<- 32 - r2 5077 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5078 subs ip, r2, #32 @ ip<- r2 - 32 5079 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 5080 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5081 b .LOP_SHR_LONG_finish 5082 5083/* ------------------------------ */ 5084 .balign 64 5085.L_OP_USHR_LONG: /* 0xa5 */ 5086/* File: armv5te/OP_USHR_LONG.S */ 5087 /* 5088 * Long integer shift. This is different from the generic 32/64-bit 5089 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5090 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5091 * 6 bits of the shift distance. 5092 */ 5093 /* ushr-long vAA, vBB, vCC */ 5094 FETCH(r0, 1) @ r0<- CCBB 5095 mov r9, rINST, lsr #8 @ r9<- AA 5096 and r3, r0, #255 @ r3<- BB 5097 mov r0, r0, lsr #8 @ r0<- CC 5098 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5099 GET_VREG(r2, r0) @ r2<- vCC 5100 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5101 and r2, r2, #63 @ r0<- r0 & 0x3f 5102 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5103 5104 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5105 rsb r3, r2, #32 @ r3<- 32 - r2 5106 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5107 subs ip, r2, #32 @ ip<- r2 - 32 5108 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 5109 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5110 b .LOP_USHR_LONG_finish 5111 5112/* ------------------------------ */ 5113 .balign 64 5114.L_OP_ADD_FLOAT: /* 0xa6 */ 5115/* File: armv5te/OP_ADD_FLOAT.S */ 5116/* File: armv5te/binop.S */ 5117 /* 5118 * Generic 32-bit binary operation. Provide an "instr" line that 5119 * specifies an instruction that performs "result = r0 op r1". 5120 * This could be an ARM instruction or a function call. (If the result 5121 * comes back in a register other than r0, you can override "result".) 5122 * 5123 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5124 * vCC (r1). Useful for integer division and modulus. Note that we 5125 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5126 * handles it correctly. 5127 * 5128 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5129 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5130 * mul-float, div-float, rem-float 5131 */ 5132 /* binop vAA, vBB, vCC */ 5133 FETCH(r0, 1) @ r0<- CCBB 5134 mov r9, rINST, lsr #8 @ r9<- AA 5135 mov r3, r0, lsr #8 @ r3<- CC 5136 and r2, r0, #255 @ r2<- BB 5137 GET_VREG(r1, r3) @ r1<- vCC 5138 GET_VREG(r0, r2) @ r0<- vBB 5139 .if 0 5140 cmp r1, #0 @ is second operand zero? 5141 beq common_errDivideByZero 5142 .endif 5143 5144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5145 @ optional op; may set condition codes 5146 bl __aeabi_fadd @ r0<- op, r0-r3 changed 5147 GET_INST_OPCODE(ip) @ extract opcode from rINST 5148 SET_VREG(r0, r9) @ vAA<- r0 5149 GOTO_OPCODE(ip) @ jump to next instruction 5150 /* 11-14 instructions */ 5151 5152 5153 5154/* ------------------------------ */ 5155 .balign 64 5156.L_OP_SUB_FLOAT: /* 0xa7 */ 5157/* File: armv5te/OP_SUB_FLOAT.S */ 5158/* File: armv5te/binop.S */ 5159 /* 5160 * Generic 32-bit binary operation. Provide an "instr" line that 5161 * specifies an instruction that performs "result = r0 op r1". 5162 * This could be an ARM instruction or a function call. (If the result 5163 * comes back in a register other than r0, you can override "result".) 5164 * 5165 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5166 * vCC (r1). Useful for integer division and modulus. Note that we 5167 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5168 * handles it correctly. 5169 * 5170 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5171 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5172 * mul-float, div-float, rem-float 5173 */ 5174 /* binop vAA, vBB, vCC */ 5175 FETCH(r0, 1) @ r0<- CCBB 5176 mov r9, rINST, lsr #8 @ r9<- AA 5177 mov r3, r0, lsr #8 @ r3<- CC 5178 and r2, r0, #255 @ r2<- BB 5179 GET_VREG(r1, r3) @ r1<- vCC 5180 GET_VREG(r0, r2) @ r0<- vBB 5181 .if 0 5182 cmp r1, #0 @ is second operand zero? 5183 beq common_errDivideByZero 5184 .endif 5185 5186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5187 @ optional op; may set condition codes 5188 bl __aeabi_fsub @ r0<- op, r0-r3 changed 5189 GET_INST_OPCODE(ip) @ extract opcode from rINST 5190 SET_VREG(r0, r9) @ vAA<- r0 5191 GOTO_OPCODE(ip) @ jump to next instruction 5192 /* 11-14 instructions */ 5193 5194 5195 5196/* ------------------------------ */ 5197 .balign 64 5198.L_OP_MUL_FLOAT: /* 0xa8 */ 5199/* File: armv5te/OP_MUL_FLOAT.S */ 5200/* File: armv5te/binop.S */ 5201 /* 5202 * Generic 32-bit binary operation. Provide an "instr" line that 5203 * specifies an instruction that performs "result = r0 op r1". 5204 * This could be an ARM instruction or a function call. (If the result 5205 * comes back in a register other than r0, you can override "result".) 5206 * 5207 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5208 * vCC (r1). Useful for integer division and modulus. Note that we 5209 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5210 * handles it correctly. 5211 * 5212 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5213 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5214 * mul-float, div-float, rem-float 5215 */ 5216 /* binop vAA, vBB, vCC */ 5217 FETCH(r0, 1) @ r0<- CCBB 5218 mov r9, rINST, lsr #8 @ r9<- AA 5219 mov r3, r0, lsr #8 @ r3<- CC 5220 and r2, r0, #255 @ r2<- BB 5221 GET_VREG(r1, r3) @ r1<- vCC 5222 GET_VREG(r0, r2) @ r0<- vBB 5223 .if 0 5224 cmp r1, #0 @ is second operand zero? 5225 beq common_errDivideByZero 5226 .endif 5227 5228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5229 @ optional op; may set condition codes 5230 bl __aeabi_fmul @ r0<- op, r0-r3 changed 5231 GET_INST_OPCODE(ip) @ extract opcode from rINST 5232 SET_VREG(r0, r9) @ vAA<- r0 5233 GOTO_OPCODE(ip) @ jump to next instruction 5234 /* 11-14 instructions */ 5235 5236 5237 5238/* ------------------------------ */ 5239 .balign 64 5240.L_OP_DIV_FLOAT: /* 0xa9 */ 5241/* File: armv5te/OP_DIV_FLOAT.S */ 5242/* File: armv5te/binop.S */ 5243 /* 5244 * Generic 32-bit binary operation. Provide an "instr" line that 5245 * specifies an instruction that performs "result = r0 op r1". 5246 * This could be an ARM instruction or a function call. (If the result 5247 * comes back in a register other than r0, you can override "result".) 5248 * 5249 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5250 * vCC (r1). Useful for integer division and modulus. Note that we 5251 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5252 * handles it correctly. 5253 * 5254 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5255 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5256 * mul-float, div-float, rem-float 5257 */ 5258 /* binop vAA, vBB, vCC */ 5259 FETCH(r0, 1) @ r0<- CCBB 5260 mov r9, rINST, lsr #8 @ r9<- AA 5261 mov r3, r0, lsr #8 @ r3<- CC 5262 and r2, r0, #255 @ r2<- BB 5263 GET_VREG(r1, r3) @ r1<- vCC 5264 GET_VREG(r0, r2) @ r0<- vBB 5265 .if 0 5266 cmp r1, #0 @ is second operand zero? 5267 beq common_errDivideByZero 5268 .endif 5269 5270 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5271 @ optional op; may set condition codes 5272 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 5273 GET_INST_OPCODE(ip) @ extract opcode from rINST 5274 SET_VREG(r0, r9) @ vAA<- r0 5275 GOTO_OPCODE(ip) @ jump to next instruction 5276 /* 11-14 instructions */ 5277 5278 5279 5280/* ------------------------------ */ 5281 .balign 64 5282.L_OP_REM_FLOAT: /* 0xaa */ 5283/* File: armv5te/OP_REM_FLOAT.S */ 5284/* EABI doesn't define a float remainder function, but libm does */ 5285/* File: armv5te/binop.S */ 5286 /* 5287 * Generic 32-bit binary operation. Provide an "instr" line that 5288 * specifies an instruction that performs "result = r0 op r1". 5289 * This could be an ARM instruction or a function call. (If the result 5290 * comes back in a register other than r0, you can override "result".) 5291 * 5292 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5293 * vCC (r1). Useful for integer division and modulus. Note that we 5294 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5295 * handles it correctly. 5296 * 5297 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5298 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5299 * mul-float, div-float, rem-float 5300 */ 5301 /* binop vAA, vBB, vCC */ 5302 FETCH(r0, 1) @ r0<- CCBB 5303 mov r9, rINST, lsr #8 @ r9<- AA 5304 mov r3, r0, lsr #8 @ r3<- CC 5305 and r2, r0, #255 @ r2<- BB 5306 GET_VREG(r1, r3) @ r1<- vCC 5307 GET_VREG(r0, r2) @ r0<- vBB 5308 .if 0 5309 cmp r1, #0 @ is second operand zero? 5310 beq common_errDivideByZero 5311 .endif 5312 5313 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5314 @ optional op; may set condition codes 5315 bl fmodf @ r0<- op, r0-r3 changed 5316 GET_INST_OPCODE(ip) @ extract opcode from rINST 5317 SET_VREG(r0, r9) @ vAA<- r0 5318 GOTO_OPCODE(ip) @ jump to next instruction 5319 /* 11-14 instructions */ 5320 5321 5322 5323/* ------------------------------ */ 5324 .balign 64 5325.L_OP_ADD_DOUBLE: /* 0xab */ 5326/* File: armv5te/OP_ADD_DOUBLE.S */ 5327/* File: armv5te/binopWide.S */ 5328 /* 5329 * Generic 64-bit binary operation. Provide an "instr" line that 5330 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5331 * This could be an ARM instruction or a function call. (If the result 5332 * comes back in a register other than r0, you can override "result".) 5333 * 5334 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5335 * vCC (r1). Useful for integer division and modulus. 5336 * 5337 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5338 * xor-long, add-double, sub-double, mul-double, div-double, 5339 * rem-double 5340 * 5341 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5342 */ 5343 /* binop vAA, vBB, vCC */ 5344 FETCH(r0, 1) @ r0<- CCBB 5345 mov r9, rINST, lsr #8 @ r9<- AA 5346 and r2, r0, #255 @ r2<- BB 5347 mov r3, r0, lsr #8 @ r3<- CC 5348 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5349 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5350 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5351 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5352 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5353 .if 0 5354 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5355 beq common_errDivideByZero 5356 .endif 5357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5358 5359 @ optional op; may set condition codes 5360 bl __aeabi_dadd @ result<- op, r0-r3 changed 5361 GET_INST_OPCODE(ip) @ extract opcode from rINST 5362 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5363 GOTO_OPCODE(ip) @ jump to next instruction 5364 /* 14-17 instructions */ 5365 5366 5367 5368/* ------------------------------ */ 5369 .balign 64 5370.L_OP_SUB_DOUBLE: /* 0xac */ 5371/* File: armv5te/OP_SUB_DOUBLE.S */ 5372/* File: armv5te/binopWide.S */ 5373 /* 5374 * Generic 64-bit binary operation. Provide an "instr" line that 5375 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5376 * This could be an ARM instruction or a function call. (If the result 5377 * comes back in a register other than r0, you can override "result".) 5378 * 5379 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5380 * vCC (r1). Useful for integer division and modulus. 5381 * 5382 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5383 * xor-long, add-double, sub-double, mul-double, div-double, 5384 * rem-double 5385 * 5386 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5387 */ 5388 /* binop vAA, vBB, vCC */ 5389 FETCH(r0, 1) @ r0<- CCBB 5390 mov r9, rINST, lsr #8 @ r9<- AA 5391 and r2, r0, #255 @ r2<- BB 5392 mov r3, r0, lsr #8 @ r3<- CC 5393 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5394 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5395 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5396 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5397 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5398 .if 0 5399 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5400 beq common_errDivideByZero 5401 .endif 5402 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5403 5404 @ optional op; may set condition codes 5405 bl __aeabi_dsub @ result<- op, r0-r3 changed 5406 GET_INST_OPCODE(ip) @ extract opcode from rINST 5407 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5408 GOTO_OPCODE(ip) @ jump to next instruction 5409 /* 14-17 instructions */ 5410 5411 5412 5413/* ------------------------------ */ 5414 .balign 64 5415.L_OP_MUL_DOUBLE: /* 0xad */ 5416/* File: armv5te/OP_MUL_DOUBLE.S */ 5417/* File: armv5te/binopWide.S */ 5418 /* 5419 * Generic 64-bit binary operation. Provide an "instr" line that 5420 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5421 * This could be an ARM instruction or a function call. (If the result 5422 * comes back in a register other than r0, you can override "result".) 5423 * 5424 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5425 * vCC (r1). Useful for integer division and modulus. 5426 * 5427 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5428 * xor-long, add-double, sub-double, mul-double, div-double, 5429 * rem-double 5430 * 5431 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5432 */ 5433 /* binop vAA, vBB, vCC */ 5434 FETCH(r0, 1) @ r0<- CCBB 5435 mov r9, rINST, lsr #8 @ r9<- AA 5436 and r2, r0, #255 @ r2<- BB 5437 mov r3, r0, lsr #8 @ r3<- CC 5438 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5439 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5440 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5441 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5442 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5443 .if 0 5444 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5445 beq common_errDivideByZero 5446 .endif 5447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5448 5449 @ optional op; may set condition codes 5450 bl __aeabi_dmul @ result<- op, r0-r3 changed 5451 GET_INST_OPCODE(ip) @ extract opcode from rINST 5452 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5453 GOTO_OPCODE(ip) @ jump to next instruction 5454 /* 14-17 instructions */ 5455 5456 5457 5458/* ------------------------------ */ 5459 .balign 64 5460.L_OP_DIV_DOUBLE: /* 0xae */ 5461/* File: armv5te/OP_DIV_DOUBLE.S */ 5462/* File: armv5te/binopWide.S */ 5463 /* 5464 * Generic 64-bit binary operation. Provide an "instr" line that 5465 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5466 * This could be an ARM instruction or a function call. (If the result 5467 * comes back in a register other than r0, you can override "result".) 5468 * 5469 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5470 * vCC (r1). Useful for integer division and modulus. 5471 * 5472 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5473 * xor-long, add-double, sub-double, mul-double, div-double, 5474 * rem-double 5475 * 5476 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5477 */ 5478 /* binop vAA, vBB, vCC */ 5479 FETCH(r0, 1) @ r0<- CCBB 5480 mov r9, rINST, lsr #8 @ r9<- AA 5481 and r2, r0, #255 @ r2<- BB 5482 mov r3, r0, lsr #8 @ r3<- CC 5483 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5484 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5485 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5486 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5487 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5488 .if 0 5489 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5490 beq common_errDivideByZero 5491 .endif 5492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5493 5494 @ optional op; may set condition codes 5495 bl __aeabi_ddiv @ result<- op, r0-r3 changed 5496 GET_INST_OPCODE(ip) @ extract opcode from rINST 5497 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5498 GOTO_OPCODE(ip) @ jump to next instruction 5499 /* 14-17 instructions */ 5500 5501 5502 5503/* ------------------------------ */ 5504 .balign 64 5505.L_OP_REM_DOUBLE: /* 0xaf */ 5506/* File: armv5te/OP_REM_DOUBLE.S */ 5507/* EABI doesn't define a double remainder function, but libm does */ 5508/* File: armv5te/binopWide.S */ 5509 /* 5510 * Generic 64-bit binary operation. Provide an "instr" line that 5511 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5512 * This could be an ARM instruction or a function call. (If the result 5513 * comes back in a register other than r0, you can override "result".) 5514 * 5515 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5516 * vCC (r1). Useful for integer division and modulus. 5517 * 5518 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5519 * xor-long, add-double, sub-double, mul-double, div-double, 5520 * rem-double 5521 * 5522 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5523 */ 5524 /* binop vAA, vBB, vCC */ 5525 FETCH(r0, 1) @ r0<- CCBB 5526 mov r9, rINST, lsr #8 @ r9<- AA 5527 and r2, r0, #255 @ r2<- BB 5528 mov r3, r0, lsr #8 @ r3<- CC 5529 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5530 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5531 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5532 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5533 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5534 .if 0 5535 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5536 beq common_errDivideByZero 5537 .endif 5538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5539 5540 @ optional op; may set condition codes 5541 bl fmod @ result<- op, r0-r3 changed 5542 GET_INST_OPCODE(ip) @ extract opcode from rINST 5543 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5544 GOTO_OPCODE(ip) @ jump to next instruction 5545 /* 14-17 instructions */ 5546 5547 5548 5549/* ------------------------------ */ 5550 .balign 64 5551.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5552/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5553/* File: armv5te/binop2addr.S */ 5554 /* 5555 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5556 * that specifies an instruction that performs "result = r0 op r1". 5557 * This could be an ARM instruction or a function call. (If the result 5558 * comes back in a register other than r0, you can override "result".) 5559 * 5560 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5561 * vCC (r1). Useful for integer division and modulus. 5562 * 5563 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5564 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5565 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5566 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5567 */ 5568 /* binop/2addr vA, vB */ 5569 mov r9, rINST, lsr #8 @ r9<- A+ 5570 mov r3, rINST, lsr #12 @ r3<- B 5571 and r9, r9, #15 5572 GET_VREG(r1, r3) @ r1<- vB 5573 GET_VREG(r0, r9) @ r0<- vA 5574 .if 0 5575 cmp r1, #0 @ is second operand zero? 5576 beq common_errDivideByZero 5577 .endif 5578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5579 5580 @ optional op; may set condition codes 5581 add r0, r0, r1 @ r0<- op, r0-r3 changed 5582 GET_INST_OPCODE(ip) @ extract opcode from rINST 5583 SET_VREG(r0, r9) @ vAA<- r0 5584 GOTO_OPCODE(ip) @ jump to next instruction 5585 /* 10-13 instructions */ 5586 5587 5588 5589/* ------------------------------ */ 5590 .balign 64 5591.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5592/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5593/* File: armv5te/binop2addr.S */ 5594 /* 5595 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5596 * that specifies an instruction that performs "result = r0 op r1". 5597 * This could be an ARM instruction or a function call. (If the result 5598 * comes back in a register other than r0, you can override "result".) 5599 * 5600 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5601 * vCC (r1). Useful for integer division and modulus. 5602 * 5603 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5604 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5605 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5606 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5607 */ 5608 /* binop/2addr vA, vB */ 5609 mov r9, rINST, lsr #8 @ r9<- A+ 5610 mov r3, rINST, lsr #12 @ r3<- B 5611 and r9, r9, #15 5612 GET_VREG(r1, r3) @ r1<- vB 5613 GET_VREG(r0, r9) @ r0<- vA 5614 .if 0 5615 cmp r1, #0 @ is second operand zero? 5616 beq common_errDivideByZero 5617 .endif 5618 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5619 5620 @ optional op; may set condition codes 5621 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5622 GET_INST_OPCODE(ip) @ extract opcode from rINST 5623 SET_VREG(r0, r9) @ vAA<- r0 5624 GOTO_OPCODE(ip) @ jump to next instruction 5625 /* 10-13 instructions */ 5626 5627 5628 5629/* ------------------------------ */ 5630 .balign 64 5631.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5632/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5633/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5634/* File: armv5te/binop2addr.S */ 5635 /* 5636 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5637 * that specifies an instruction that performs "result = r0 op r1". 5638 * This could be an ARM instruction or a function call. (If the result 5639 * comes back in a register other than r0, you can override "result".) 5640 * 5641 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5642 * vCC (r1). Useful for integer division and modulus. 5643 * 5644 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5645 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5646 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5647 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5648 */ 5649 /* binop/2addr vA, vB */ 5650 mov r9, rINST, lsr #8 @ r9<- A+ 5651 mov r3, rINST, lsr #12 @ r3<- B 5652 and r9, r9, #15 5653 GET_VREG(r1, r3) @ r1<- vB 5654 GET_VREG(r0, r9) @ r0<- vA 5655 .if 0 5656 cmp r1, #0 @ is second operand zero? 5657 beq common_errDivideByZero 5658 .endif 5659 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5660 5661 @ optional op; may set condition codes 5662 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5663 GET_INST_OPCODE(ip) @ extract opcode from rINST 5664 SET_VREG(r0, r9) @ vAA<- r0 5665 GOTO_OPCODE(ip) @ jump to next instruction 5666 /* 10-13 instructions */ 5667 5668 5669 5670/* ------------------------------ */ 5671 .balign 64 5672.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5673/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5674/* File: armv5te/binop2addr.S */ 5675 /* 5676 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5677 * that specifies an instruction that performs "result = r0 op r1". 5678 * This could be an ARM instruction or a function call. (If the result 5679 * comes back in a register other than r0, you can override "result".) 5680 * 5681 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5682 * vCC (r1). Useful for integer division and modulus. 5683 * 5684 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5685 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5686 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5687 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5688 */ 5689 /* binop/2addr vA, vB */ 5690 mov r9, rINST, lsr #8 @ r9<- A+ 5691 mov r3, rINST, lsr #12 @ r3<- B 5692 and r9, r9, #15 5693 GET_VREG(r1, r3) @ r1<- vB 5694 GET_VREG(r0, r9) @ r0<- vA 5695 .if 1 5696 cmp r1, #0 @ is second operand zero? 5697 beq common_errDivideByZero 5698 .endif 5699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5700 5701 @ optional op; may set condition codes 5702 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5703 GET_INST_OPCODE(ip) @ extract opcode from rINST 5704 SET_VREG(r0, r9) @ vAA<- r0 5705 GOTO_OPCODE(ip) @ jump to next instruction 5706 /* 10-13 instructions */ 5707 5708 5709 5710/* ------------------------------ */ 5711 .balign 64 5712.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5713/* File: armv5te/OP_REM_INT_2ADDR.S */ 5714/* idivmod returns quotient in r0 and remainder in r1 */ 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 1 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 @ optional op; may set condition codes 5743 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5744 GET_INST_OPCODE(ip) @ extract opcode from rINST 5745 SET_VREG(r1, r9) @ vAA<- r1 5746 GOTO_OPCODE(ip) @ jump to next instruction 5747 /* 10-13 instructions */ 5748 5749 5750 5751/* ------------------------------ */ 5752 .balign 64 5753.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5754/* File: armv5te/OP_AND_INT_2ADDR.S */ 5755/* File: armv5te/binop2addr.S */ 5756 /* 5757 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5758 * that specifies an instruction that performs "result = r0 op r1". 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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5766 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5767 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5768 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5769 */ 5770 /* binop/2addr vA, vB */ 5771 mov r9, rINST, lsr #8 @ r9<- A+ 5772 mov r3, rINST, lsr #12 @ r3<- B 5773 and r9, r9, #15 5774 GET_VREG(r1, r3) @ r1<- vB 5775 GET_VREG(r0, r9) @ r0<- vA 5776 .if 0 5777 cmp r1, #0 @ is second operand zero? 5778 beq common_errDivideByZero 5779 .endif 5780 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5781 5782 @ optional op; may set condition codes 5783 and r0, r0, r1 @ r0<- op, r0-r3 changed 5784 GET_INST_OPCODE(ip) @ extract opcode from rINST 5785 SET_VREG(r0, r9) @ vAA<- r0 5786 GOTO_OPCODE(ip) @ jump to next instruction 5787 /* 10-13 instructions */ 5788 5789 5790 5791/* ------------------------------ */ 5792 .balign 64 5793.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5794/* File: armv5te/OP_OR_INT_2ADDR.S */ 5795/* File: armv5te/binop2addr.S */ 5796 /* 5797 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5798 * that specifies an instruction that performs "result = r0 op r1". 5799 * This could be an ARM instruction or a function call. (If the result 5800 * comes back in a register other than r0, you can override "result".) 5801 * 5802 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5803 * vCC (r1). Useful for integer division and modulus. 5804 * 5805 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5806 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5807 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5808 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5809 */ 5810 /* binop/2addr vA, vB */ 5811 mov r9, rINST, lsr #8 @ r9<- A+ 5812 mov r3, rINST, lsr #12 @ r3<- B 5813 and r9, r9, #15 5814 GET_VREG(r1, r3) @ r1<- vB 5815 GET_VREG(r0, r9) @ r0<- vA 5816 .if 0 5817 cmp r1, #0 @ is second operand zero? 5818 beq common_errDivideByZero 5819 .endif 5820 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5821 5822 @ optional op; may set condition codes 5823 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5824 GET_INST_OPCODE(ip) @ extract opcode from rINST 5825 SET_VREG(r0, r9) @ vAA<- r0 5826 GOTO_OPCODE(ip) @ jump to next instruction 5827 /* 10-13 instructions */ 5828 5829 5830 5831/* ------------------------------ */ 5832 .balign 64 5833.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5834/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5835/* File: armv5te/binop2addr.S */ 5836 /* 5837 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5838 * that specifies an instruction that performs "result = r0 op r1". 5839 * This could be an ARM instruction or a function call. (If the result 5840 * comes back in a register other than r0, you can override "result".) 5841 * 5842 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5843 * vCC (r1). Useful for integer division and modulus. 5844 * 5845 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5846 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5847 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5848 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5849 */ 5850 /* binop/2addr vA, vB */ 5851 mov r9, rINST, lsr #8 @ r9<- A+ 5852 mov r3, rINST, lsr #12 @ r3<- B 5853 and r9, r9, #15 5854 GET_VREG(r1, r3) @ r1<- vB 5855 GET_VREG(r0, r9) @ r0<- vA 5856 .if 0 5857 cmp r1, #0 @ is second operand zero? 5858 beq common_errDivideByZero 5859 .endif 5860 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5861 5862 @ optional op; may set condition codes 5863 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5864 GET_INST_OPCODE(ip) @ extract opcode from rINST 5865 SET_VREG(r0, r9) @ vAA<- r0 5866 GOTO_OPCODE(ip) @ jump to next instruction 5867 /* 10-13 instructions */ 5868 5869 5870 5871/* ------------------------------ */ 5872 .balign 64 5873.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5874/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5875/* File: armv5te/binop2addr.S */ 5876 /* 5877 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5878 * that specifies an instruction that performs "result = r0 op r1". 5879 * This could be an ARM instruction or a function call. (If the result 5880 * comes back in a register other than r0, you can override "result".) 5881 * 5882 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5883 * vCC (r1). Useful for integer division and modulus. 5884 * 5885 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5886 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5887 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5888 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5889 */ 5890 /* binop/2addr vA, vB */ 5891 mov r9, rINST, lsr #8 @ r9<- A+ 5892 mov r3, rINST, lsr #12 @ r3<- B 5893 and r9, r9, #15 5894 GET_VREG(r1, r3) @ r1<- vB 5895 GET_VREG(r0, r9) @ r0<- vA 5896 .if 0 5897 cmp r1, #0 @ is second operand zero? 5898 beq common_errDivideByZero 5899 .endif 5900 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5901 5902 and r1, r1, #31 @ optional op; may set condition codes 5903 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5904 GET_INST_OPCODE(ip) @ extract opcode from rINST 5905 SET_VREG(r0, r9) @ vAA<- r0 5906 GOTO_OPCODE(ip) @ jump to next instruction 5907 /* 10-13 instructions */ 5908 5909 5910 5911/* ------------------------------ */ 5912 .balign 64 5913.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5914/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5915/* File: armv5te/binop2addr.S */ 5916 /* 5917 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5918 * that specifies an instruction that performs "result = r0 op r1". 5919 * This could be an ARM instruction or a function call. (If the result 5920 * comes back in a register other than r0, you can override "result".) 5921 * 5922 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5923 * vCC (r1). Useful for integer division and modulus. 5924 * 5925 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5926 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5927 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5928 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5929 */ 5930 /* binop/2addr vA, vB */ 5931 mov r9, rINST, lsr #8 @ r9<- A+ 5932 mov r3, rINST, lsr #12 @ r3<- B 5933 and r9, r9, #15 5934 GET_VREG(r1, r3) @ r1<- vB 5935 GET_VREG(r0, r9) @ r0<- vA 5936 .if 0 5937 cmp r1, #0 @ is second operand zero? 5938 beq common_errDivideByZero 5939 .endif 5940 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5941 5942 and r1, r1, #31 @ optional op; may set condition codes 5943 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5944 GET_INST_OPCODE(ip) @ extract opcode from rINST 5945 SET_VREG(r0, r9) @ vAA<- r0 5946 GOTO_OPCODE(ip) @ jump to next instruction 5947 /* 10-13 instructions */ 5948 5949 5950 5951/* ------------------------------ */ 5952 .balign 64 5953.L_OP_USHR_INT_2ADDR: /* 0xba */ 5954/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5955/* File: armv5te/binop2addr.S */ 5956 /* 5957 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5958 * that specifies an instruction that performs "result = r0 op r1". 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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5966 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5967 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5968 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5969 */ 5970 /* binop/2addr vA, vB */ 5971 mov r9, rINST, lsr #8 @ r9<- A+ 5972 mov r3, rINST, lsr #12 @ r3<- B 5973 and r9, r9, #15 5974 GET_VREG(r1, r3) @ r1<- vB 5975 GET_VREG(r0, r9) @ r0<- vA 5976 .if 0 5977 cmp r1, #0 @ is second operand zero? 5978 beq common_errDivideByZero 5979 .endif 5980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5981 5982 and r1, r1, #31 @ optional op; may set condition codes 5983 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5984 GET_INST_OPCODE(ip) @ extract opcode from rINST 5985 SET_VREG(r0, r9) @ vAA<- r0 5986 GOTO_OPCODE(ip) @ jump to next instruction 5987 /* 10-13 instructions */ 5988 5989 5990 5991/* ------------------------------ */ 5992 .balign 64 5993.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5994/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5995/* File: armv5te/binopWide2addr.S */ 5996 /* 5997 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5998 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5999 * This could be an ARM instruction or a function call. (If the result 6000 * comes back in a register other than r0, you can override "result".) 6001 * 6002 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6003 * vCC (r1). Useful for integer division and modulus. 6004 * 6005 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6006 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6007 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6008 * rem-double/2addr 6009 */ 6010 /* binop/2addr vA, vB */ 6011 mov r9, rINST, lsr #8 @ r9<- A+ 6012 mov r1, rINST, lsr #12 @ r1<- B 6013 and r9, r9, #15 6014 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6015 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6016 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6017 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6018 .if 0 6019 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6020 beq common_errDivideByZero 6021 .endif 6022 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6023 6024 adds r0, r0, r2 @ optional op; may set condition codes 6025 adc r1, r1, r3 @ result<- op, r0-r3 changed 6026 GET_INST_OPCODE(ip) @ extract opcode from rINST 6027 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6028 GOTO_OPCODE(ip) @ jump to next instruction 6029 /* 12-15 instructions */ 6030 6031 6032 6033/* ------------------------------ */ 6034 .balign 64 6035.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 6036/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 6037/* File: armv5te/binopWide2addr.S */ 6038 /* 6039 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6040 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6041 * This could be an ARM instruction or a function call. (If the result 6042 * comes back in a register other than r0, you can override "result".) 6043 * 6044 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6045 * vCC (r1). Useful for integer division and modulus. 6046 * 6047 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6048 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6049 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6050 * rem-double/2addr 6051 */ 6052 /* binop/2addr vA, vB */ 6053 mov r9, rINST, lsr #8 @ r9<- A+ 6054 mov r1, rINST, lsr #12 @ r1<- B 6055 and r9, r9, #15 6056 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6057 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6058 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6059 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6060 .if 0 6061 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6062 beq common_errDivideByZero 6063 .endif 6064 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6065 6066 subs r0, r0, r2 @ optional op; may set condition codes 6067 sbc r1, r1, r3 @ result<- op, r0-r3 changed 6068 GET_INST_OPCODE(ip) @ extract opcode from rINST 6069 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6070 GOTO_OPCODE(ip) @ jump to next instruction 6071 /* 12-15 instructions */ 6072 6073 6074 6075/* ------------------------------ */ 6076 .balign 64 6077.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 6078/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 6079 /* 6080 * Signed 64-bit integer multiply, "/2addr" version. 6081 * 6082 * See OP_MUL_LONG for an explanation. 6083 * 6084 * We get a little tight on registers, so to avoid looking up &fp[A] 6085 * again we stuff it into rINST. 6086 */ 6087 /* mul-long/2addr vA, vB */ 6088 mov r9, rINST, lsr #8 @ r9<- A+ 6089 mov r1, rINST, lsr #12 @ r1<- B 6090 and r9, r9, #15 6091 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6092 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 6093 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6094 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 6095 mul ip, r2, r1 @ ip<- ZxW 6096 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 6097 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 6098 mov r0, rINST @ r0<- &fp[A] (free up rINST) 6099 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6100 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 6101 GET_INST_OPCODE(ip) @ extract opcode from rINST 6102 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 6103 GOTO_OPCODE(ip) @ jump to next instruction 6104 6105 6106/* ------------------------------ */ 6107 .balign 64 6108.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 6109/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 6110/* File: armv5te/binopWide2addr.S */ 6111 /* 6112 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6113 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6114 * This could be an ARM instruction or a function call. (If the result 6115 * comes back in a register other than r0, you can override "result".) 6116 * 6117 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6118 * vCC (r1). Useful for integer division and modulus. 6119 * 6120 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6121 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6122 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6123 * rem-double/2addr 6124 */ 6125 /* binop/2addr vA, vB */ 6126 mov r9, rINST, lsr #8 @ r9<- A+ 6127 mov r1, rINST, lsr #12 @ r1<- B 6128 and r9, r9, #15 6129 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6130 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6131 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6132 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6133 .if 1 6134 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6135 beq common_errDivideByZero 6136 .endif 6137 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6138 6139 @ optional op; may set condition codes 6140 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6141 GET_INST_OPCODE(ip) @ extract opcode from rINST 6142 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6143 GOTO_OPCODE(ip) @ jump to next instruction 6144 /* 12-15 instructions */ 6145 6146 6147 6148/* ------------------------------ */ 6149 .balign 64 6150.L_OP_REM_LONG_2ADDR: /* 0xbf */ 6151/* File: armv5te/OP_REM_LONG_2ADDR.S */ 6152/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 6153/* File: armv5te/binopWide2addr.S */ 6154 /* 6155 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6156 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6157 * This could be an ARM instruction or a function call. (If the result 6158 * comes back in a register other than r0, you can override "result".) 6159 * 6160 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6161 * vCC (r1). Useful for integer division and modulus. 6162 * 6163 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6164 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6165 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6166 * rem-double/2addr 6167 */ 6168 /* binop/2addr vA, vB */ 6169 mov r9, rINST, lsr #8 @ r9<- A+ 6170 mov r1, rINST, lsr #12 @ r1<- B 6171 and r9, r9, #15 6172 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6173 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6174 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6175 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6176 .if 1 6177 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6178 beq common_errDivideByZero 6179 .endif 6180 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6181 6182 @ optional op; may set condition codes 6183 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6184 GET_INST_OPCODE(ip) @ extract opcode from rINST 6185 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 6186 GOTO_OPCODE(ip) @ jump to next instruction 6187 /* 12-15 instructions */ 6188 6189 6190 6191/* ------------------------------ */ 6192 .balign 64 6193.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 6194/* File: armv5te/OP_AND_LONG_2ADDR.S */ 6195/* File: armv5te/binopWide2addr.S */ 6196 /* 6197 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6198 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6199 * This could be an ARM instruction or a function call. (If the result 6200 * comes back in a register other than r0, you can override "result".) 6201 * 6202 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6203 * vCC (r1). Useful for integer division and modulus. 6204 * 6205 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6206 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6207 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6208 * rem-double/2addr 6209 */ 6210 /* binop/2addr vA, vB */ 6211 mov r9, rINST, lsr #8 @ r9<- A+ 6212 mov r1, rINST, lsr #12 @ r1<- B 6213 and r9, r9, #15 6214 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6215 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6216 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6217 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6218 .if 0 6219 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6220 beq common_errDivideByZero 6221 .endif 6222 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6223 6224 and r0, r0, r2 @ optional op; may set condition codes 6225 and r1, r1, r3 @ result<- op, r0-r3 changed 6226 GET_INST_OPCODE(ip) @ extract opcode from rINST 6227 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6228 GOTO_OPCODE(ip) @ jump to next instruction 6229 /* 12-15 instructions */ 6230 6231 6232 6233/* ------------------------------ */ 6234 .balign 64 6235.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6236/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6237/* File: armv5te/binopWide2addr.S */ 6238 /* 6239 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6240 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6241 * This could be an ARM instruction or a function call. (If the result 6242 * comes back in a register other than r0, you can override "result".) 6243 * 6244 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6245 * vCC (r1). Useful for integer division and modulus. 6246 * 6247 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6248 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6249 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6250 * rem-double/2addr 6251 */ 6252 /* binop/2addr vA, vB */ 6253 mov r9, rINST, lsr #8 @ r9<- A+ 6254 mov r1, rINST, lsr #12 @ r1<- B 6255 and r9, r9, #15 6256 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6257 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6258 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6259 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6260 .if 0 6261 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6262 beq common_errDivideByZero 6263 .endif 6264 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6265 6266 orr r0, r0, r2 @ optional op; may set condition codes 6267 orr r1, r1, r3 @ result<- op, r0-r3 changed 6268 GET_INST_OPCODE(ip) @ extract opcode from rINST 6269 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6270 GOTO_OPCODE(ip) @ jump to next instruction 6271 /* 12-15 instructions */ 6272 6273 6274 6275/* ------------------------------ */ 6276 .balign 64 6277.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6278/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6279/* File: armv5te/binopWide2addr.S */ 6280 /* 6281 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6282 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6283 * This could be an ARM instruction or a function call. (If the result 6284 * comes back in a register other than r0, you can override "result".) 6285 * 6286 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6287 * vCC (r1). Useful for integer division and modulus. 6288 * 6289 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6290 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6291 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6292 * rem-double/2addr 6293 */ 6294 /* binop/2addr vA, vB */ 6295 mov r9, rINST, lsr #8 @ r9<- A+ 6296 mov r1, rINST, lsr #12 @ r1<- B 6297 and r9, r9, #15 6298 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6299 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6300 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6301 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6302 .if 0 6303 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6304 beq common_errDivideByZero 6305 .endif 6306 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6307 6308 eor r0, r0, r2 @ optional op; may set condition codes 6309 eor r1, r1, r3 @ result<- op, r0-r3 changed 6310 GET_INST_OPCODE(ip) @ extract opcode from rINST 6311 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6312 GOTO_OPCODE(ip) @ jump to next instruction 6313 /* 12-15 instructions */ 6314 6315 6316 6317/* ------------------------------ */ 6318 .balign 64 6319.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6320/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6321 /* 6322 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6323 * 32-bit shift distance. 6324 */ 6325 /* shl-long/2addr vA, vB */ 6326 mov r9, rINST, lsr #8 @ r9<- A+ 6327 mov r3, rINST, lsr #12 @ r3<- B 6328 and r9, r9, #15 6329 GET_VREG(r2, r3) @ r2<- vB 6330 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6331 and r2, r2, #63 @ r2<- r2 & 0x3f 6332 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6333 6334 mov r1, r1, asl r2 @ r1<- r1 << r2 6335 rsb r3, r2, #32 @ r3<- 32 - r2 6336 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6337 subs ip, r2, #32 @ ip<- r2 - 32 6338 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6339 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6340 mov r0, r0, asl r2 @ r0<- r0 << r2 6341 b .LOP_SHL_LONG_2ADDR_finish 6342 6343/* ------------------------------ */ 6344 .balign 64 6345.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6346/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6347 /* 6348 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6349 * 32-bit shift distance. 6350 */ 6351 /* shr-long/2addr vA, vB */ 6352 mov r9, rINST, lsr #8 @ r9<- A+ 6353 mov r3, rINST, lsr #12 @ r3<- B 6354 and r9, r9, #15 6355 GET_VREG(r2, r3) @ r2<- vB 6356 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6357 and r2, r2, #63 @ r2<- r2 & 0x3f 6358 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6359 6360 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6361 rsb r3, r2, #32 @ r3<- 32 - r2 6362 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6363 subs ip, r2, #32 @ ip<- r2 - 32 6364 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6365 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6366 mov r1, r1, asr r2 @ r1<- r1 >> r2 6367 b .LOP_SHR_LONG_2ADDR_finish 6368 6369/* ------------------------------ */ 6370 .balign 64 6371.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6372/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6373 /* 6374 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6375 * 32-bit shift distance. 6376 */ 6377 /* ushr-long/2addr vA, vB */ 6378 mov r9, rINST, lsr #8 @ r9<- A+ 6379 mov r3, rINST, lsr #12 @ r3<- B 6380 and r9, r9, #15 6381 GET_VREG(r2, r3) @ r2<- vB 6382 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6383 and r2, r2, #63 @ r2<- r2 & 0x3f 6384 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6385 6386 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6387 rsb r3, r2, #32 @ r3<- 32 - r2 6388 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6389 subs ip, r2, #32 @ ip<- r2 - 32 6390 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6391 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6392 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6393 b .LOP_USHR_LONG_2ADDR_finish 6394 6395/* ------------------------------ */ 6396 .balign 64 6397.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6398/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */ 6399/* File: armv5te/binop2addr.S */ 6400 /* 6401 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6402 * that specifies an instruction that performs "result = r0 op r1". 6403 * This could be an ARM instruction or a function call. (If the result 6404 * comes back in a register other than r0, you can override "result".) 6405 * 6406 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6407 * vCC (r1). Useful for integer division and modulus. 6408 * 6409 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6410 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6411 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6412 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6413 */ 6414 /* binop/2addr vA, vB */ 6415 mov r9, rINST, lsr #8 @ r9<- A+ 6416 mov r3, rINST, lsr #12 @ r3<- B 6417 and r9, r9, #15 6418 GET_VREG(r1, r3) @ r1<- vB 6419 GET_VREG(r0, r9) @ r0<- vA 6420 .if 0 6421 cmp r1, #0 @ is second operand zero? 6422 beq common_errDivideByZero 6423 .endif 6424 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6425 6426 @ optional op; may set condition codes 6427 bl __aeabi_fadd @ r0<- op, r0-r3 changed 6428 GET_INST_OPCODE(ip) @ extract opcode from rINST 6429 SET_VREG(r0, r9) @ vAA<- r0 6430 GOTO_OPCODE(ip) @ jump to next instruction 6431 /* 10-13 instructions */ 6432 6433 6434 6435/* ------------------------------ */ 6436 .balign 64 6437.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6438/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */ 6439/* File: armv5te/binop2addr.S */ 6440 /* 6441 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6442 * that specifies an instruction that performs "result = r0 op r1". 6443 * This could be an ARM instruction or a function call. (If the result 6444 * comes back in a register other than r0, you can override "result".) 6445 * 6446 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6447 * vCC (r1). Useful for integer division and modulus. 6448 * 6449 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6450 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6451 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6452 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6453 */ 6454 /* binop/2addr vA, vB */ 6455 mov r9, rINST, lsr #8 @ r9<- A+ 6456 mov r3, rINST, lsr #12 @ r3<- B 6457 and r9, r9, #15 6458 GET_VREG(r1, r3) @ r1<- vB 6459 GET_VREG(r0, r9) @ r0<- vA 6460 .if 0 6461 cmp r1, #0 @ is second operand zero? 6462 beq common_errDivideByZero 6463 .endif 6464 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6465 6466 @ optional op; may set condition codes 6467 bl __aeabi_fsub @ r0<- op, r0-r3 changed 6468 GET_INST_OPCODE(ip) @ extract opcode from rINST 6469 SET_VREG(r0, r9) @ vAA<- r0 6470 GOTO_OPCODE(ip) @ jump to next instruction 6471 /* 10-13 instructions */ 6472 6473 6474 6475/* ------------------------------ */ 6476 .balign 64 6477.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6478/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */ 6479/* File: armv5te/binop2addr.S */ 6480 /* 6481 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6482 * that specifies an instruction that performs "result = r0 op r1". 6483 * This could be an ARM instruction or a function call. (If the result 6484 * comes back in a register other than r0, you can override "result".) 6485 * 6486 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6487 * vCC (r1). Useful for integer division and modulus. 6488 * 6489 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6490 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6491 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6492 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6493 */ 6494 /* binop/2addr vA, vB */ 6495 mov r9, rINST, lsr #8 @ r9<- A+ 6496 mov r3, rINST, lsr #12 @ r3<- B 6497 and r9, r9, #15 6498 GET_VREG(r1, r3) @ r1<- vB 6499 GET_VREG(r0, r9) @ r0<- vA 6500 .if 0 6501 cmp r1, #0 @ is second operand zero? 6502 beq common_errDivideByZero 6503 .endif 6504 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6505 6506 @ optional op; may set condition codes 6507 bl __aeabi_fmul @ r0<- op, r0-r3 changed 6508 GET_INST_OPCODE(ip) @ extract opcode from rINST 6509 SET_VREG(r0, r9) @ vAA<- r0 6510 GOTO_OPCODE(ip) @ jump to next instruction 6511 /* 10-13 instructions */ 6512 6513 6514 6515/* ------------------------------ */ 6516 .balign 64 6517.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6518/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */ 6519/* File: armv5te/binop2addr.S */ 6520 /* 6521 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6522 * that specifies an instruction that performs "result = r0 op r1". 6523 * This could be an ARM instruction or a function call. (If the result 6524 * comes back in a register other than r0, you can override "result".) 6525 * 6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6527 * vCC (r1). Useful for integer division and modulus. 6528 * 6529 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6530 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6531 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6532 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6533 */ 6534 /* binop/2addr vA, vB */ 6535 mov r9, rINST, lsr #8 @ r9<- A+ 6536 mov r3, rINST, lsr #12 @ r3<- B 6537 and r9, r9, #15 6538 GET_VREG(r1, r3) @ r1<- vB 6539 GET_VREG(r0, r9) @ r0<- vA 6540 .if 0 6541 cmp r1, #0 @ is second operand zero? 6542 beq common_errDivideByZero 6543 .endif 6544 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6545 6546 @ optional op; may set condition codes 6547 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 6548 GET_INST_OPCODE(ip) @ extract opcode from rINST 6549 SET_VREG(r0, r9) @ vAA<- r0 6550 GOTO_OPCODE(ip) @ jump to next instruction 6551 /* 10-13 instructions */ 6552 6553 6554 6555/* ------------------------------ */ 6556 .balign 64 6557.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6558/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6559/* EABI doesn't define a float remainder function, but libm does */ 6560/* File: armv5te/binop2addr.S */ 6561 /* 6562 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6563 * that specifies an instruction that performs "result = r0 op r1". 6564 * This could be an ARM instruction or a function call. (If the result 6565 * comes back in a register other than r0, you can override "result".) 6566 * 6567 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6568 * vCC (r1). Useful for integer division and modulus. 6569 * 6570 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6571 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6572 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6573 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6574 */ 6575 /* binop/2addr vA, vB */ 6576 mov r9, rINST, lsr #8 @ r9<- A+ 6577 mov r3, rINST, lsr #12 @ r3<- B 6578 and r9, r9, #15 6579 GET_VREG(r1, r3) @ r1<- vB 6580 GET_VREG(r0, r9) @ r0<- vA 6581 .if 0 6582 cmp r1, #0 @ is second operand zero? 6583 beq common_errDivideByZero 6584 .endif 6585 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6586 6587 @ optional op; may set condition codes 6588 bl fmodf @ r0<- op, r0-r3 changed 6589 GET_INST_OPCODE(ip) @ extract opcode from rINST 6590 SET_VREG(r0, r9) @ vAA<- r0 6591 GOTO_OPCODE(ip) @ jump to next instruction 6592 /* 10-13 instructions */ 6593 6594 6595 6596/* ------------------------------ */ 6597 .balign 64 6598.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6599/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */ 6600/* File: armv5te/binopWide2addr.S */ 6601 /* 6602 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6603 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6604 * This could be an ARM instruction or a function call. (If the result 6605 * comes back in a register other than r0, you can override "result".) 6606 * 6607 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6608 * vCC (r1). Useful for integer division and modulus. 6609 * 6610 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6611 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6612 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6613 * rem-double/2addr 6614 */ 6615 /* binop/2addr vA, vB */ 6616 mov r9, rINST, lsr #8 @ r9<- A+ 6617 mov r1, rINST, lsr #12 @ r1<- B 6618 and r9, r9, #15 6619 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6620 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6621 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6622 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6623 .if 0 6624 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6625 beq common_errDivideByZero 6626 .endif 6627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6628 6629 @ optional op; may set condition codes 6630 bl __aeabi_dadd @ result<- op, r0-r3 changed 6631 GET_INST_OPCODE(ip) @ extract opcode from rINST 6632 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6633 GOTO_OPCODE(ip) @ jump to next instruction 6634 /* 12-15 instructions */ 6635 6636 6637 6638/* ------------------------------ */ 6639 .balign 64 6640.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6641/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */ 6642/* File: armv5te/binopWide2addr.S */ 6643 /* 6644 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6645 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6646 * This could be an ARM instruction or a function call. (If the result 6647 * comes back in a register other than r0, you can override "result".) 6648 * 6649 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6650 * vCC (r1). Useful for integer division and modulus. 6651 * 6652 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6653 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6654 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6655 * rem-double/2addr 6656 */ 6657 /* binop/2addr vA, vB */ 6658 mov r9, rINST, lsr #8 @ r9<- A+ 6659 mov r1, rINST, lsr #12 @ r1<- B 6660 and r9, r9, #15 6661 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6662 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6663 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6664 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6665 .if 0 6666 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6667 beq common_errDivideByZero 6668 .endif 6669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6670 6671 @ optional op; may set condition codes 6672 bl __aeabi_dsub @ result<- op, r0-r3 changed 6673 GET_INST_OPCODE(ip) @ extract opcode from rINST 6674 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6675 GOTO_OPCODE(ip) @ jump to next instruction 6676 /* 12-15 instructions */ 6677 6678 6679 6680/* ------------------------------ */ 6681 .balign 64 6682.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6683/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */ 6684/* File: armv5te/binopWide2addr.S */ 6685 /* 6686 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6687 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6688 * This could be an ARM instruction or a function call. (If the result 6689 * comes back in a register other than r0, you can override "result".) 6690 * 6691 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6692 * vCC (r1). Useful for integer division and modulus. 6693 * 6694 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6695 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6696 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6697 * rem-double/2addr 6698 */ 6699 /* binop/2addr vA, vB */ 6700 mov r9, rINST, lsr #8 @ r9<- A+ 6701 mov r1, rINST, lsr #12 @ r1<- B 6702 and r9, r9, #15 6703 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6704 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6705 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6706 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6707 .if 0 6708 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6709 beq common_errDivideByZero 6710 .endif 6711 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6712 6713 @ optional op; may set condition codes 6714 bl __aeabi_dmul @ result<- op, r0-r3 changed 6715 GET_INST_OPCODE(ip) @ extract opcode from rINST 6716 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6717 GOTO_OPCODE(ip) @ jump to next instruction 6718 /* 12-15 instructions */ 6719 6720 6721 6722/* ------------------------------ */ 6723 .balign 64 6724.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6725/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */ 6726/* File: armv5te/binopWide2addr.S */ 6727 /* 6728 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6729 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6730 * This could be an ARM instruction or a function call. (If the result 6731 * comes back in a register other than r0, you can override "result".) 6732 * 6733 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6734 * vCC (r1). Useful for integer division and modulus. 6735 * 6736 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6737 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6738 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6739 * rem-double/2addr 6740 */ 6741 /* binop/2addr vA, vB */ 6742 mov r9, rINST, lsr #8 @ r9<- A+ 6743 mov r1, rINST, lsr #12 @ r1<- B 6744 and r9, r9, #15 6745 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6746 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6747 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6748 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6749 .if 0 6750 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6751 beq common_errDivideByZero 6752 .endif 6753 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6754 6755 @ optional op; may set condition codes 6756 bl __aeabi_ddiv @ result<- op, r0-r3 changed 6757 GET_INST_OPCODE(ip) @ extract opcode from rINST 6758 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6759 GOTO_OPCODE(ip) @ jump to next instruction 6760 /* 12-15 instructions */ 6761 6762 6763 6764/* ------------------------------ */ 6765 .balign 64 6766.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6767/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6768/* EABI doesn't define a double remainder function, but libm does */ 6769/* File: armv5te/binopWide2addr.S */ 6770 /* 6771 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6772 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6773 * This could be an ARM instruction or a function call. (If the result 6774 * comes back in a register other than r0, you can override "result".) 6775 * 6776 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6777 * vCC (r1). Useful for integer division and modulus. 6778 * 6779 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6780 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6781 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6782 * rem-double/2addr 6783 */ 6784 /* binop/2addr vA, vB */ 6785 mov r9, rINST, lsr #8 @ r9<- A+ 6786 mov r1, rINST, lsr #12 @ r1<- B 6787 and r9, r9, #15 6788 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6789 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6790 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6791 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6792 .if 0 6793 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6794 beq common_errDivideByZero 6795 .endif 6796 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6797 6798 @ optional op; may set condition codes 6799 bl fmod @ result<- op, r0-r3 changed 6800 GET_INST_OPCODE(ip) @ extract opcode from rINST 6801 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6802 GOTO_OPCODE(ip) @ jump to next instruction 6803 /* 12-15 instructions */ 6804 6805 6806 6807/* ------------------------------ */ 6808 .balign 64 6809.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6810/* File: armv5te/OP_ADD_INT_LIT16.S */ 6811/* File: armv5te/binopLit16.S */ 6812 /* 6813 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6814 * that specifies an instruction that performs "result = r0 op r1". 6815 * This could be an ARM instruction or a function call. (If the result 6816 * comes back in a register other than r0, you can override "result".) 6817 * 6818 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6819 * vCC (r1). Useful for integer division and modulus. 6820 * 6821 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6822 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6823 */ 6824 /* binop/lit16 vA, vB, #+CCCC */ 6825 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6826 mov r2, rINST, lsr #12 @ r2<- B 6827 mov r9, rINST, lsr #8 @ r9<- A+ 6828 GET_VREG(r0, r2) @ r0<- vB 6829 and r9, r9, #15 6830 .if 0 6831 cmp r1, #0 @ is second operand zero? 6832 beq common_errDivideByZero 6833 .endif 6834 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6835 6836 add 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-13 instructions */ 6841 6842 6843 6844/* ------------------------------ */ 6845 .balign 64 6846.L_OP_RSUB_INT: /* 0xd1 */ 6847/* File: armv5te/OP_RSUB_INT.S */ 6848/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6849/* File: armv5te/binopLit16.S */ 6850 /* 6851 * Generic 32-bit "lit16" 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/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6860 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6861 */ 6862 /* binop/lit16 vA, vB, #+CCCC */ 6863 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6864 mov r2, rINST, lsr #12 @ r2<- B 6865 mov r9, rINST, lsr #8 @ r9<- A+ 6866 GET_VREG(r0, r2) @ r0<- vB 6867 and r9, r9, #15 6868 .if 0 6869 cmp r1, #0 @ is second operand zero? 6870 beq common_errDivideByZero 6871 .endif 6872 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6873 6874 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6875 GET_INST_OPCODE(ip) @ extract opcode from rINST 6876 SET_VREG(r0, r9) @ vAA<- r0 6877 GOTO_OPCODE(ip) @ jump to next instruction 6878 /* 10-13 instructions */ 6879 6880 6881 6882/* ------------------------------ */ 6883 .balign 64 6884.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6885/* File: armv5te/OP_MUL_INT_LIT16.S */ 6886/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6887/* File: armv5te/binopLit16.S */ 6888 /* 6889 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6890 * that specifies an instruction that performs "result = r0 op r1". 6891 * This could be an ARM instruction or a function call. (If the result 6892 * comes back in a register other than r0, you can override "result".) 6893 * 6894 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6895 * vCC (r1). Useful for integer division and modulus. 6896 * 6897 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6898 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6899 */ 6900 /* binop/lit16 vA, vB, #+CCCC */ 6901 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6902 mov r2, rINST, lsr #12 @ r2<- B 6903 mov r9, rINST, lsr #8 @ r9<- A+ 6904 GET_VREG(r0, r2) @ r0<- vB 6905 and r9, r9, #15 6906 .if 0 6907 cmp r1, #0 @ is second operand zero? 6908 beq common_errDivideByZero 6909 .endif 6910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6911 6912 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6913 GET_INST_OPCODE(ip) @ extract opcode from rINST 6914 SET_VREG(r0, r9) @ vAA<- r0 6915 GOTO_OPCODE(ip) @ jump to next instruction 6916 /* 10-13 instructions */ 6917 6918 6919 6920/* ------------------------------ */ 6921 .balign 64 6922.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6923/* File: armv5te/OP_DIV_INT_LIT16.S */ 6924/* File: armv5te/binopLit16.S */ 6925 /* 6926 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6927 * that specifies an instruction that performs "result = r0 op r1". 6928 * This could be an ARM instruction or a function call. (If the result 6929 * comes back in a register other than r0, you can override "result".) 6930 * 6931 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6932 * vCC (r1). Useful for integer division and modulus. 6933 * 6934 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6935 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6936 */ 6937 /* binop/lit16 vA, vB, #+CCCC */ 6938 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6939 mov r2, rINST, lsr #12 @ r2<- B 6940 mov r9, rINST, lsr #8 @ r9<- A+ 6941 GET_VREG(r0, r2) @ r0<- vB 6942 and r9, r9, #15 6943 .if 1 6944 cmp r1, #0 @ is second operand zero? 6945 beq common_errDivideByZero 6946 .endif 6947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6948 6949 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6950 GET_INST_OPCODE(ip) @ extract opcode from rINST 6951 SET_VREG(r0, r9) @ vAA<- r0 6952 GOTO_OPCODE(ip) @ jump to next instruction 6953 /* 10-13 instructions */ 6954 6955 6956 6957/* ------------------------------ */ 6958 .balign 64 6959.L_OP_REM_INT_LIT16: /* 0xd4 */ 6960/* File: armv5te/OP_REM_INT_LIT16.S */ 6961/* idivmod returns quotient in r0 and remainder in r1 */ 6962/* File: armv5te/binopLit16.S */ 6963 /* 6964 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6965 * that specifies an instruction that performs "result = r0 op r1". 6966 * This could be an ARM instruction or a function call. (If the result 6967 * comes back in a register other than r0, you can override "result".) 6968 * 6969 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6970 * vCC (r1). Useful for integer division and modulus. 6971 * 6972 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6973 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6974 */ 6975 /* binop/lit16 vA, vB, #+CCCC */ 6976 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6977 mov r2, rINST, lsr #12 @ r2<- B 6978 mov r9, rINST, lsr #8 @ r9<- A+ 6979 GET_VREG(r0, r2) @ r0<- vB 6980 and r9, r9, #15 6981 .if 1 6982 cmp r1, #0 @ is second operand zero? 6983 beq common_errDivideByZero 6984 .endif 6985 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6986 6987 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6988 GET_INST_OPCODE(ip) @ extract opcode from rINST 6989 SET_VREG(r1, r9) @ vAA<- r1 6990 GOTO_OPCODE(ip) @ jump to next instruction 6991 /* 10-13 instructions */ 6992 6993 6994 6995/* ------------------------------ */ 6996 .balign 64 6997.L_OP_AND_INT_LIT16: /* 0xd5 */ 6998/* File: armv5te/OP_AND_INT_LIT16.S */ 6999/* File: armv5te/binopLit16.S */ 7000 /* 7001 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7002 * that specifies an instruction that performs "result = r0 op r1". 7003 * This could be an ARM instruction or a function call. (If the result 7004 * comes back in a register other than r0, you can override "result".) 7005 * 7006 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7007 * vCC (r1). Useful for integer division and modulus. 7008 * 7009 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7010 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7011 */ 7012 /* binop/lit16 vA, vB, #+CCCC */ 7013 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7014 mov r2, rINST, lsr #12 @ r2<- B 7015 mov r9, rINST, lsr #8 @ r9<- A+ 7016 GET_VREG(r0, r2) @ r0<- vB 7017 and r9, r9, #15 7018 .if 0 7019 cmp r1, #0 @ is second operand zero? 7020 beq common_errDivideByZero 7021 .endif 7022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7023 7024 and r0, r0, r1 @ r0<- op, r0-r3 changed 7025 GET_INST_OPCODE(ip) @ extract opcode from rINST 7026 SET_VREG(r0, r9) @ vAA<- r0 7027 GOTO_OPCODE(ip) @ jump to next instruction 7028 /* 10-13 instructions */ 7029 7030 7031 7032/* ------------------------------ */ 7033 .balign 64 7034.L_OP_OR_INT_LIT16: /* 0xd6 */ 7035/* File: armv5te/OP_OR_INT_LIT16.S */ 7036/* File: armv5te/binopLit16.S */ 7037 /* 7038 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7039 * that specifies an instruction that performs "result = r0 op r1". 7040 * This could be an ARM instruction or a function call. (If the result 7041 * comes back in a register other than r0, you can override "result".) 7042 * 7043 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7044 * vCC (r1). Useful for integer division and modulus. 7045 * 7046 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7047 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7048 */ 7049 /* binop/lit16 vA, vB, #+CCCC */ 7050 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7051 mov r2, rINST, lsr #12 @ r2<- B 7052 mov r9, rINST, lsr #8 @ r9<- A+ 7053 GET_VREG(r0, r2) @ r0<- vB 7054 and r9, r9, #15 7055 .if 0 7056 cmp r1, #0 @ is second operand zero? 7057 beq common_errDivideByZero 7058 .endif 7059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7060 7061 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7062 GET_INST_OPCODE(ip) @ extract opcode from rINST 7063 SET_VREG(r0, r9) @ vAA<- r0 7064 GOTO_OPCODE(ip) @ jump to next instruction 7065 /* 10-13 instructions */ 7066 7067 7068 7069/* ------------------------------ */ 7070 .balign 64 7071.L_OP_XOR_INT_LIT16: /* 0xd7 */ 7072/* File: armv5te/OP_XOR_INT_LIT16.S */ 7073/* File: armv5te/binopLit16.S */ 7074 /* 7075 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7076 * that specifies an instruction that performs "result = r0 op r1". 7077 * This could be an ARM instruction or a function call. (If the result 7078 * comes back in a register other than r0, you can override "result".) 7079 * 7080 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7081 * vCC (r1). Useful for integer division and modulus. 7082 * 7083 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7084 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7085 */ 7086 /* binop/lit16 vA, vB, #+CCCC */ 7087 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7088 mov r2, rINST, lsr #12 @ r2<- B 7089 mov r9, rINST, lsr #8 @ r9<- A+ 7090 GET_VREG(r0, r2) @ r0<- vB 7091 and r9, r9, #15 7092 .if 0 7093 cmp r1, #0 @ is second operand zero? 7094 beq common_errDivideByZero 7095 .endif 7096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7097 7098 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7099 GET_INST_OPCODE(ip) @ extract opcode from rINST 7100 SET_VREG(r0, r9) @ vAA<- r0 7101 GOTO_OPCODE(ip) @ jump to next instruction 7102 /* 10-13 instructions */ 7103 7104 7105 7106/* ------------------------------ */ 7107 .balign 64 7108.L_OP_ADD_INT_LIT8: /* 0xd8 */ 7109/* File: armv5te/OP_ADD_INT_LIT8.S */ 7110/* File: armv5te/binopLit8.S */ 7111 /* 7112 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7113 * that specifies an instruction that performs "result = r0 op r1". 7114 * This could be an ARM instruction or a function call. (If the result 7115 * comes back in a register other than r0, you can override "result".) 7116 * 7117 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7118 * vCC (r1). Useful for integer division and modulus. 7119 * 7120 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7121 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7122 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7123 */ 7124 /* binop/lit8 vAA, vBB, #+CC */ 7125 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7126 mov r9, rINST, lsr #8 @ r9<- AA 7127 and r2, r3, #255 @ r2<- BB 7128 GET_VREG(r0, r2) @ r0<- vBB 7129 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7130 .if 0 7131 @cmp r1, #0 @ is second operand zero? 7132 beq common_errDivideByZero 7133 .endif 7134 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7135 7136 @ optional op; may set condition codes 7137 add r0, r0, r1 @ r0<- op, r0-r3 changed 7138 GET_INST_OPCODE(ip) @ extract opcode from rINST 7139 SET_VREG(r0, r9) @ vAA<- r0 7140 GOTO_OPCODE(ip) @ jump to next instruction 7141 /* 10-12 instructions */ 7142 7143 7144 7145/* ------------------------------ */ 7146 .balign 64 7147.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 7148/* File: armv5te/OP_RSUB_INT_LIT8.S */ 7149/* File: armv5te/binopLit8.S */ 7150 /* 7151 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7152 * that specifies an instruction that performs "result = r0 op r1". 7153 * This could be an ARM instruction or a function call. (If the result 7154 * comes back in a register other than r0, you can override "result".) 7155 * 7156 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7157 * vCC (r1). Useful for integer division and modulus. 7158 * 7159 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7160 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7161 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7162 */ 7163 /* binop/lit8 vAA, vBB, #+CC */ 7164 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7165 mov r9, rINST, lsr #8 @ r9<- AA 7166 and r2, r3, #255 @ r2<- BB 7167 GET_VREG(r0, r2) @ r0<- vBB 7168 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7169 .if 0 7170 @cmp r1, #0 @ is second operand zero? 7171 beq common_errDivideByZero 7172 .endif 7173 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7174 7175 @ optional op; may set condition codes 7176 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 7177 GET_INST_OPCODE(ip) @ extract opcode from rINST 7178 SET_VREG(r0, r9) @ vAA<- r0 7179 GOTO_OPCODE(ip) @ jump to next instruction 7180 /* 10-12 instructions */ 7181 7182 7183 7184/* ------------------------------ */ 7185 .balign 64 7186.L_OP_MUL_INT_LIT8: /* 0xda */ 7187/* File: armv5te/OP_MUL_INT_LIT8.S */ 7188/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 7189/* File: armv5te/binopLit8.S */ 7190 /* 7191 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7192 * that specifies an instruction that performs "result = r0 op r1". 7193 * This could be an ARM instruction or a function call. (If the result 7194 * comes back in a register other than r0, you can override "result".) 7195 * 7196 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7197 * vCC (r1). Useful for integer division and modulus. 7198 * 7199 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7200 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7201 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7202 */ 7203 /* binop/lit8 vAA, vBB, #+CC */ 7204 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7205 mov r9, rINST, lsr #8 @ r9<- AA 7206 and r2, r3, #255 @ r2<- BB 7207 GET_VREG(r0, r2) @ r0<- vBB 7208 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7209 .if 0 7210 @cmp r1, #0 @ is second operand zero? 7211 beq common_errDivideByZero 7212 .endif 7213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7214 7215 @ optional op; may set condition codes 7216 mul r0, r1, r0 @ r0<- op, r0-r3 changed 7217 GET_INST_OPCODE(ip) @ extract opcode from rINST 7218 SET_VREG(r0, r9) @ vAA<- r0 7219 GOTO_OPCODE(ip) @ jump to next instruction 7220 /* 10-12 instructions */ 7221 7222 7223 7224/* ------------------------------ */ 7225 .balign 64 7226.L_OP_DIV_INT_LIT8: /* 0xdb */ 7227/* File: armv5te/OP_DIV_INT_LIT8.S */ 7228/* File: armv5te/binopLit8.S */ 7229 /* 7230 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7231 * that specifies an instruction that performs "result = r0 op r1". 7232 * This could be an ARM instruction or a function call. (If the result 7233 * comes back in a register other than r0, you can override "result".) 7234 * 7235 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7236 * vCC (r1). Useful for integer division and modulus. 7237 * 7238 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7239 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7240 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7241 */ 7242 /* binop/lit8 vAA, vBB, #+CC */ 7243 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7244 mov r9, rINST, lsr #8 @ r9<- AA 7245 and r2, r3, #255 @ r2<- BB 7246 GET_VREG(r0, r2) @ r0<- vBB 7247 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7248 .if 1 7249 @cmp r1, #0 @ is second operand zero? 7250 beq common_errDivideByZero 7251 .endif 7252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7253 7254 @ optional op; may set condition codes 7255 bl __aeabi_idiv @ r0<- op, r0-r3 changed 7256 GET_INST_OPCODE(ip) @ extract opcode from rINST 7257 SET_VREG(r0, r9) @ vAA<- r0 7258 GOTO_OPCODE(ip) @ jump to next instruction 7259 /* 10-12 instructions */ 7260 7261 7262 7263/* ------------------------------ */ 7264 .balign 64 7265.L_OP_REM_INT_LIT8: /* 0xdc */ 7266/* File: armv5te/OP_REM_INT_LIT8.S */ 7267/* idivmod returns quotient in r0 and remainder in r1 */ 7268/* File: armv5te/binopLit8.S */ 7269 /* 7270 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7271 * that specifies an instruction that performs "result = r0 op r1". 7272 * This could be an ARM instruction or a function call. (If the result 7273 * comes back in a register other than r0, you can override "result".) 7274 * 7275 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7276 * vCC (r1). Useful for integer division and modulus. 7277 * 7278 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7279 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7280 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7281 */ 7282 /* binop/lit8 vAA, vBB, #+CC */ 7283 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7284 mov r9, rINST, lsr #8 @ r9<- AA 7285 and r2, r3, #255 @ r2<- BB 7286 GET_VREG(r0, r2) @ r0<- vBB 7287 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7288 .if 1 7289 @cmp r1, #0 @ is second operand zero? 7290 beq common_errDivideByZero 7291 .endif 7292 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7293 7294 @ optional op; may set condition codes 7295 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 7296 GET_INST_OPCODE(ip) @ extract opcode from rINST 7297 SET_VREG(r1, r9) @ vAA<- r1 7298 GOTO_OPCODE(ip) @ jump to next instruction 7299 /* 10-12 instructions */ 7300 7301 7302 7303/* ------------------------------ */ 7304 .balign 64 7305.L_OP_AND_INT_LIT8: /* 0xdd */ 7306/* File: armv5te/OP_AND_INT_LIT8.S */ 7307/* File: armv5te/binopLit8.S */ 7308 /* 7309 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7310 * that specifies an instruction that performs "result = r0 op r1". 7311 * This could be an ARM instruction or a function call. (If the result 7312 * comes back in a register other than r0, you can override "result".) 7313 * 7314 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7315 * vCC (r1). Useful for integer division and modulus. 7316 * 7317 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7318 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7319 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7320 */ 7321 /* binop/lit8 vAA, vBB, #+CC */ 7322 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7323 mov r9, rINST, lsr #8 @ r9<- AA 7324 and r2, r3, #255 @ r2<- BB 7325 GET_VREG(r0, r2) @ r0<- vBB 7326 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7327 .if 0 7328 @cmp r1, #0 @ is second operand zero? 7329 beq common_errDivideByZero 7330 .endif 7331 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7332 7333 @ optional op; may set condition codes 7334 and r0, r0, r1 @ r0<- op, r0-r3 changed 7335 GET_INST_OPCODE(ip) @ extract opcode from rINST 7336 SET_VREG(r0, r9) @ vAA<- r0 7337 GOTO_OPCODE(ip) @ jump to next instruction 7338 /* 10-12 instructions */ 7339 7340 7341 7342/* ------------------------------ */ 7343 .balign 64 7344.L_OP_OR_INT_LIT8: /* 0xde */ 7345/* File: armv5te/OP_OR_INT_LIT8.S */ 7346/* File: armv5te/binopLit8.S */ 7347 /* 7348 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7349 * that specifies an instruction that performs "result = r0 op r1". 7350 * This could be an ARM instruction or a function call. (If the result 7351 * comes back in a register other than r0, you can override "result".) 7352 * 7353 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7354 * vCC (r1). Useful for integer division and modulus. 7355 * 7356 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7357 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7358 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7359 */ 7360 /* binop/lit8 vAA, vBB, #+CC */ 7361 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7362 mov r9, rINST, lsr #8 @ r9<- AA 7363 and r2, r3, #255 @ r2<- BB 7364 GET_VREG(r0, r2) @ r0<- vBB 7365 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7366 .if 0 7367 @cmp r1, #0 @ is second operand zero? 7368 beq common_errDivideByZero 7369 .endif 7370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7371 7372 @ optional op; may set condition codes 7373 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7374 GET_INST_OPCODE(ip) @ extract opcode from rINST 7375 SET_VREG(r0, r9) @ vAA<- r0 7376 GOTO_OPCODE(ip) @ jump to next instruction 7377 /* 10-12 instructions */ 7378 7379 7380 7381/* ------------------------------ */ 7382 .balign 64 7383.L_OP_XOR_INT_LIT8: /* 0xdf */ 7384/* File: armv5te/OP_XOR_INT_LIT8.S */ 7385/* File: armv5te/binopLit8.S */ 7386 /* 7387 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7388 * that specifies an instruction that performs "result = r0 op r1". 7389 * This could be an ARM instruction or a function call. (If the result 7390 * comes back in a register other than r0, you can override "result".) 7391 * 7392 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7393 * vCC (r1). Useful for integer division and modulus. 7394 * 7395 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7396 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7397 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7398 */ 7399 /* binop/lit8 vAA, vBB, #+CC */ 7400 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7401 mov r9, rINST, lsr #8 @ r9<- AA 7402 and r2, r3, #255 @ r2<- BB 7403 GET_VREG(r0, r2) @ r0<- vBB 7404 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7405 .if 0 7406 @cmp r1, #0 @ is second operand zero? 7407 beq common_errDivideByZero 7408 .endif 7409 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7410 7411 @ optional op; may set condition codes 7412 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7413 GET_INST_OPCODE(ip) @ extract opcode from rINST 7414 SET_VREG(r0, r9) @ vAA<- r0 7415 GOTO_OPCODE(ip) @ jump to next instruction 7416 /* 10-12 instructions */ 7417 7418 7419 7420/* ------------------------------ */ 7421 .balign 64 7422.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7423/* File: armv5te/OP_SHL_INT_LIT8.S */ 7424/* File: armv5te/binopLit8.S */ 7425 /* 7426 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7427 * that specifies an instruction that performs "result = r0 op r1". 7428 * This could be an ARM instruction or a function call. (If the result 7429 * comes back in a register other than r0, you can override "result".) 7430 * 7431 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7432 * vCC (r1). Useful for integer division and modulus. 7433 * 7434 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7435 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7436 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7437 */ 7438 /* binop/lit8 vAA, vBB, #+CC */ 7439 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7440 mov r9, rINST, lsr #8 @ r9<- AA 7441 and r2, r3, #255 @ r2<- BB 7442 GET_VREG(r0, r2) @ r0<- vBB 7443 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7444 .if 0 7445 @cmp r1, #0 @ is second operand zero? 7446 beq common_errDivideByZero 7447 .endif 7448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7449 7450 and r1, r1, #31 @ optional op; may set condition codes 7451 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7452 GET_INST_OPCODE(ip) @ extract opcode from rINST 7453 SET_VREG(r0, r9) @ vAA<- r0 7454 GOTO_OPCODE(ip) @ jump to next instruction 7455 /* 10-12 instructions */ 7456 7457 7458 7459/* ------------------------------ */ 7460 .balign 64 7461.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7462/* File: armv5te/OP_SHR_INT_LIT8.S */ 7463/* File: armv5te/binopLit8.S */ 7464 /* 7465 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7466 * that specifies an instruction that performs "result = r0 op r1". 7467 * This could be an ARM instruction or a function call. (If the result 7468 * comes back in a register other than r0, you can override "result".) 7469 * 7470 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7471 * vCC (r1). Useful for integer division and modulus. 7472 * 7473 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7474 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7475 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7476 */ 7477 /* binop/lit8 vAA, vBB, #+CC */ 7478 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7479 mov r9, rINST, lsr #8 @ r9<- AA 7480 and r2, r3, #255 @ r2<- BB 7481 GET_VREG(r0, r2) @ r0<- vBB 7482 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7483 .if 0 7484 @cmp r1, #0 @ is second operand zero? 7485 beq common_errDivideByZero 7486 .endif 7487 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7488 7489 and r1, r1, #31 @ optional op; may set condition codes 7490 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7491 GET_INST_OPCODE(ip) @ extract opcode from rINST 7492 SET_VREG(r0, r9) @ vAA<- r0 7493 GOTO_OPCODE(ip) @ jump to next instruction 7494 /* 10-12 instructions */ 7495 7496 7497 7498/* ------------------------------ */ 7499 .balign 64 7500.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7501/* File: armv5te/OP_USHR_INT_LIT8.S */ 7502/* File: armv5te/binopLit8.S */ 7503 /* 7504 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7505 * that specifies an instruction that performs "result = r0 op r1". 7506 * This could be an ARM instruction or a function call. (If the result 7507 * comes back in a register other than r0, you can override "result".) 7508 * 7509 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7510 * vCC (r1). Useful for integer division and modulus. 7511 * 7512 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7513 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7514 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7515 */ 7516 /* binop/lit8 vAA, vBB, #+CC */ 7517 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7518 mov r9, rINST, lsr #8 @ r9<- AA 7519 and r2, r3, #255 @ r2<- BB 7520 GET_VREG(r0, r2) @ r0<- vBB 7521 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7522 .if 0 7523 @cmp r1, #0 @ is second operand zero? 7524 beq common_errDivideByZero 7525 .endif 7526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7527 7528 and r1, r1, #31 @ optional op; may set condition codes 7529 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7530 GET_INST_OPCODE(ip) @ extract opcode from rINST 7531 SET_VREG(r0, r9) @ vAA<- r0 7532 GOTO_OPCODE(ip) @ jump to next instruction 7533 /* 10-12 instructions */ 7534 7535 7536 7537/* ------------------------------ */ 7538 .balign 64 7539.L_OP_UNUSED_E3: /* 0xe3 */ 7540/* File: armv5te/OP_UNUSED_E3.S */ 7541/* File: armv5te/unused.S */ 7542 bl common_abort 7543 7544 7545 7546/* ------------------------------ */ 7547 .balign 64 7548.L_OP_UNUSED_E4: /* 0xe4 */ 7549/* File: armv5te/OP_UNUSED_E4.S */ 7550/* File: armv5te/unused.S */ 7551 bl common_abort 7552 7553 7554 7555/* ------------------------------ */ 7556 .balign 64 7557.L_OP_UNUSED_E5: /* 0xe5 */ 7558/* File: armv5te/OP_UNUSED_E5.S */ 7559/* File: armv5te/unused.S */ 7560 bl common_abort 7561 7562 7563 7564/* ------------------------------ */ 7565 .balign 64 7566.L_OP_UNUSED_E6: /* 0xe6 */ 7567/* File: armv5te/OP_UNUSED_E6.S */ 7568/* File: armv5te/unused.S */ 7569 bl common_abort 7570 7571 7572 7573/* ------------------------------ */ 7574 .balign 64 7575.L_OP_UNUSED_E7: /* 0xe7 */ 7576/* File: armv5te/OP_UNUSED_E7.S */ 7577/* File: armv5te/unused.S */ 7578 bl common_abort 7579 7580 7581 7582/* ------------------------------ */ 7583 .balign 64 7584.L_OP_UNUSED_E8: /* 0xe8 */ 7585/* File: armv5te/OP_UNUSED_E8.S */ 7586/* File: armv5te/unused.S */ 7587 bl common_abort 7588 7589 7590 7591/* ------------------------------ */ 7592 .balign 64 7593.L_OP_UNUSED_E9: /* 0xe9 */ 7594/* File: armv5te/OP_UNUSED_E9.S */ 7595/* File: armv5te/unused.S */ 7596 bl common_abort 7597 7598 7599 7600/* ------------------------------ */ 7601 .balign 64 7602.L_OP_UNUSED_EA: /* 0xea */ 7603/* File: armv5te/OP_UNUSED_EA.S */ 7604/* File: armv5te/unused.S */ 7605 bl common_abort 7606 7607 7608 7609/* ------------------------------ */ 7610 .balign 64 7611.L_OP_UNUSED_EB: /* 0xeb */ 7612/* File: armv5te/OP_UNUSED_EB.S */ 7613/* File: armv5te/unused.S */ 7614 bl common_abort 7615 7616 7617 7618/* ------------------------------ */ 7619 .balign 64 7620.L_OP_UNUSED_EC: /* 0xec */ 7621/* File: armv5te/OP_UNUSED_EC.S */ 7622/* File: armv5te/unused.S */ 7623 bl common_abort 7624 7625 7626 7627/* ------------------------------ */ 7628 .balign 64 7629.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7630/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7631 /* 7632 * Handle a throw-verification-error instruction. This throws an 7633 * exception for an error discovered during verification. The 7634 * exception is indicated by AA, with some detail provided by BBBB. 7635 */ 7636 /* op AA, ref@BBBB */ 7637 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7638 FETCH(r2, 1) @ r2<- BBBB 7639 EXPORT_PC() @ export the PC 7640 mov r1, rINST, lsr #8 @ r1<- AA 7641 bl dvmThrowVerificationError @ always throws 7642 b common_exceptionThrown @ handle exception 7643 7644 7645/* ------------------------------ */ 7646 .balign 64 7647.L_OP_EXECUTE_INLINE: /* 0xee */ 7648/* File: armv5te/OP_EXECUTE_INLINE.S */ 7649 /* 7650 * Execute a "native inline" instruction. 7651 * 7652 * We need to call: 7653 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7654 * 7655 * The first four args are in r0-r3, but the last two must be pushed 7656 * onto the stack. 7657 */ 7658 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7659 FETCH(r10, 1) @ r10<- BBBB 7660 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7661 EXPORT_PC() @ can throw 7662 sub sp, sp, #8 @ make room for arg(s) 7663 mov r0, rINST, lsr #12 @ r0<- B 7664 str r1, [sp] @ push &glue->retval 7665 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7666 add sp, sp, #8 @ pop stack 7667 cmp r0, #0 @ test boolean result of inline 7668 beq common_exceptionThrown @ returned false, handle exception 7669 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7670 GET_INST_OPCODE(ip) @ extract opcode from rINST 7671 GOTO_OPCODE(ip) @ jump to next instruction 7672 7673/* ------------------------------ */ 7674 .balign 64 7675.L_OP_UNUSED_EF: /* 0xef */ 7676/* File: armv5te/OP_UNUSED_EF.S */ 7677/* File: armv5te/unused.S */ 7678 bl common_abort 7679 7680 7681 7682/* ------------------------------ */ 7683 .balign 64 7684.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7685/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7686 /* 7687 * invoke-direct-empty is a no-op in a "standard" interpreter. 7688 */ 7689 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7690 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7691 GOTO_OPCODE(ip) @ execute it 7692 7693/* ------------------------------ */ 7694 .balign 64 7695.L_OP_UNUSED_F1: /* 0xf1 */ 7696/* File: armv5te/OP_UNUSED_F1.S */ 7697/* File: armv5te/unused.S */ 7698 bl common_abort 7699 7700 7701 7702/* ------------------------------ */ 7703 .balign 64 7704.L_OP_IGET_QUICK: /* 0xf2 */ 7705/* File: armv5te/OP_IGET_QUICK.S */ 7706 /* For: iget-quick, iget-object-quick */ 7707 /* op vA, vB, offset@CCCC */ 7708 mov r2, rINST, lsr #12 @ r2<- B 7709 GET_VREG(r3, r2) @ r3<- object we're operating on 7710 FETCH(r1, 1) @ r1<- field byte offset 7711 cmp r3, #0 @ check object for null 7712 mov r2, rINST, lsr #8 @ r2<- A(+) 7713 beq common_errNullObject @ object was null 7714 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7715 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7716 and r2, r2, #15 7717 GET_INST_OPCODE(ip) @ extract opcode from rINST 7718 SET_VREG(r0, r2) @ fp[A]<- r0 7719 GOTO_OPCODE(ip) @ jump to next instruction 7720 7721 7722/* ------------------------------ */ 7723 .balign 64 7724.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7725/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7726 /* iget-wide-quick vA, vB, offset@CCCC */ 7727 mov r2, rINST, lsr #12 @ r2<- B 7728 GET_VREG(r3, r2) @ r3<- object we're operating on 7729 FETCH(r1, 1) @ r1<- field byte offset 7730 cmp r3, #0 @ check object for null 7731 mov r2, rINST, lsr #8 @ r2<- A(+) 7732 beq common_errNullObject @ object was null 7733 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7734 and r2, r2, #15 7735 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7736 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7737 GET_INST_OPCODE(ip) @ extract opcode from rINST 7738 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7739 GOTO_OPCODE(ip) @ jump to next instruction 7740 7741 7742/* ------------------------------ */ 7743 .balign 64 7744.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7745/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7746/* File: armv5te/OP_IGET_QUICK.S */ 7747 /* For: iget-quick, iget-object-quick */ 7748 /* op vA, vB, offset@CCCC */ 7749 mov r2, rINST, lsr #12 @ r2<- B 7750 GET_VREG(r3, r2) @ r3<- object we're operating on 7751 FETCH(r1, 1) @ r1<- field byte offset 7752 cmp r3, #0 @ check object for null 7753 mov r2, rINST, lsr #8 @ r2<- A(+) 7754 beq common_errNullObject @ object was null 7755 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7757 and r2, r2, #15 7758 GET_INST_OPCODE(ip) @ extract opcode from rINST 7759 SET_VREG(r0, r2) @ fp[A]<- r0 7760 GOTO_OPCODE(ip) @ jump to next instruction 7761 7762 7763 7764/* ------------------------------ */ 7765 .balign 64 7766.L_OP_IPUT_QUICK: /* 0xf5 */ 7767/* File: armv5te/OP_IPUT_QUICK.S */ 7768 /* For: iput-quick, iput-object-quick */ 7769 /* op vA, vB, offset@CCCC */ 7770 mov r2, rINST, lsr #12 @ r2<- B 7771 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7772 FETCH(r1, 1) @ r1<- field byte offset 7773 cmp r3, #0 @ check object for null 7774 mov r2, rINST, lsr #8 @ r2<- A(+) 7775 beq common_errNullObject @ object was null 7776 and r2, r2, #15 7777 GET_VREG(r0, r2) @ r0<- fp[A] 7778 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7779 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7780 GET_INST_OPCODE(ip) @ extract opcode from rINST 7781 GOTO_OPCODE(ip) @ jump to next instruction 7782 7783 7784/* ------------------------------ */ 7785 .balign 64 7786.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7787/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7788 /* iput-wide-quick vA, vB, offset@CCCC */ 7789 mov r0, rINST, lsr #8 @ r0<- A(+) 7790 mov r1, rINST, lsr #12 @ r1<- B 7791 and r0, r0, #15 7792 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7793 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7794 cmp r2, #0 @ check object for null 7795 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7796 beq common_errNullObject @ object was null 7797 FETCH(r3, 1) @ r3<- field byte offset 7798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7799 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7800 GET_INST_OPCODE(ip) @ extract opcode from rINST 7801 GOTO_OPCODE(ip) @ jump to next instruction 7802 7803 7804/* ------------------------------ */ 7805 .balign 64 7806.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7807/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7808/* File: armv5te/OP_IPUT_QUICK.S */ 7809 /* For: iput-quick, iput-object-quick */ 7810 /* op vA, vB, offset@CCCC */ 7811 mov r2, rINST, lsr #12 @ r2<- B 7812 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7813 FETCH(r1, 1) @ r1<- field byte offset 7814 cmp r3, #0 @ check object for null 7815 mov r2, rINST, lsr #8 @ r2<- A(+) 7816 beq common_errNullObject @ object was null 7817 and r2, r2, #15 7818 GET_VREG(r0, r2) @ r0<- fp[A] 7819 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7820 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7821 GET_INST_OPCODE(ip) @ extract opcode from rINST 7822 GOTO_OPCODE(ip) @ jump to next instruction 7823 7824 7825 7826/* ------------------------------ */ 7827 .balign 64 7828.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7829/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7830 /* 7831 * Handle an optimized virtual method call. 7832 * 7833 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7834 */ 7835 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7836 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7837 FETCH(r3, 2) @ r3<- FEDC or CCCC 7838 FETCH(r1, 1) @ r1<- BBBB 7839 .if (!0) 7840 and r3, r3, #15 @ r3<- C (or stays CCCC) 7841 .endif 7842 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7843 cmp r2, #0 @ is "this" null? 7844 beq common_errNullObject @ null "this", throw exception 7845 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7846 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7847 EXPORT_PC() @ invoke must export 7848 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7849 bl common_invokeMethodNoRange @ continue on 7850 7851/* ------------------------------ */ 7852 .balign 64 7853.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7854/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7855/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7856 /* 7857 * Handle an optimized virtual method call. 7858 * 7859 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7860 */ 7861 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7862 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7863 FETCH(r3, 2) @ r3<- FEDC or CCCC 7864 FETCH(r1, 1) @ r1<- BBBB 7865 .if (!1) 7866 and r3, r3, #15 @ r3<- C (or stays CCCC) 7867 .endif 7868 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7869 cmp r2, #0 @ is "this" null? 7870 beq common_errNullObject @ null "this", throw exception 7871 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7872 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7873 EXPORT_PC() @ invoke must export 7874 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7875 bl common_invokeMethodRange @ continue on 7876 7877 7878/* ------------------------------ */ 7879 .balign 64 7880.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7881/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7882 /* 7883 * Handle an optimized "super" method call. 7884 * 7885 * for: [opt] invoke-super-quick, invoke-super-quick/range 7886 */ 7887 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7888 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7889 FETCH(r10, 2) @ r10<- GFED or CCCC 7890 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7891 .if (!0) 7892 and r10, r10, #15 @ r10<- D (or stays CCCC) 7893 .endif 7894 FETCH(r1, 1) @ r1<- BBBB 7895 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7896 EXPORT_PC() @ must export for invoke 7897 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7898 GET_VREG(r3, r10) @ r3<- "this" 7899 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7900 cmp r3, #0 @ null "this" ref? 7901 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7902 beq common_errNullObject @ "this" is null, throw exception 7903 bl common_invokeMethodNoRange @ continue on 7904 7905 7906/* ------------------------------ */ 7907 .balign 64 7908.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7909/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7910/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7911 /* 7912 * Handle an optimized "super" method call. 7913 * 7914 * for: [opt] invoke-super-quick, invoke-super-quick/range 7915 */ 7916 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7917 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7918 FETCH(r10, 2) @ r10<- GFED or CCCC 7919 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7920 .if (!1) 7921 and r10, r10, #15 @ r10<- D (or stays CCCC) 7922 .endif 7923 FETCH(r1, 1) @ r1<- BBBB 7924 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7925 EXPORT_PC() @ must export for invoke 7926 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7927 GET_VREG(r3, r10) @ r3<- "this" 7928 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7929 cmp r3, #0 @ null "this" ref? 7930 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7931 beq common_errNullObject @ "this" is null, throw exception 7932 bl common_invokeMethodRange @ continue on 7933 7934 7935 7936/* ------------------------------ */ 7937 .balign 64 7938.L_OP_UNUSED_FC: /* 0xfc */ 7939/* File: armv5te/OP_UNUSED_FC.S */ 7940/* File: armv5te/unused.S */ 7941 bl common_abort 7942 7943 7944 7945/* ------------------------------ */ 7946 .balign 64 7947.L_OP_UNUSED_FD: /* 0xfd */ 7948/* File: armv5te/OP_UNUSED_FD.S */ 7949/* File: armv5te/unused.S */ 7950 bl common_abort 7951 7952 7953 7954/* ------------------------------ */ 7955 .balign 64 7956.L_OP_UNUSED_FE: /* 0xfe */ 7957/* File: armv5te/OP_UNUSED_FE.S */ 7958/* File: armv5te/unused.S */ 7959 bl common_abort 7960 7961 7962 7963/* ------------------------------ */ 7964 .balign 64 7965.L_OP_UNUSED_FF: /* 0xff */ 7966/* File: armv5te/OP_UNUSED_FF.S */ 7967/* File: armv5te/unused.S */ 7968 bl common_abort 7969 7970 7971 7972 7973 .balign 64 7974 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7975 .global dvmAsmInstructionEnd 7976dvmAsmInstructionEnd: 7977 7978/* 7979 * =========================================================================== 7980 * Sister implementations 7981 * =========================================================================== 7982 */ 7983 .global dvmAsmSisterStart 7984 .type dvmAsmSisterStart, %function 7985 .text 7986 .balign 4 7987dvmAsmSisterStart: 7988 7989/* continuation for OP_CONST_STRING */ 7990 7991 /* 7992 * Continuation if the String has not yet been resolved. 7993 * r1: BBBB (String ref) 7994 * r9: target register 7995 */ 7996.LOP_CONST_STRING_resolve: 7997 EXPORT_PC() 7998 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7999 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8000 bl dvmResolveString @ r0<- String reference 8001 cmp r0, #0 @ failed? 8002 beq common_exceptionThrown @ yup, handle the exception 8003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8004 GET_INST_OPCODE(ip) @ extract opcode from rINST 8005 SET_VREG(r0, r9) @ vAA<- r0 8006 GOTO_OPCODE(ip) @ jump to next instruction 8007 8008 8009/* continuation for OP_CONST_STRING_JUMBO */ 8010 8011 /* 8012 * Continuation if the String has not yet been resolved. 8013 * r1: BBBBBBBB (String ref) 8014 * r9: target register 8015 */ 8016.LOP_CONST_STRING_JUMBO_resolve: 8017 EXPORT_PC() 8018 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8019 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8020 bl dvmResolveString @ r0<- String reference 8021 cmp r0, #0 @ failed? 8022 beq common_exceptionThrown @ yup, handle the exception 8023 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 8024 GET_INST_OPCODE(ip) @ extract opcode from rINST 8025 SET_VREG(r0, r9) @ vAA<- r0 8026 GOTO_OPCODE(ip) @ jump to next instruction 8027 8028 8029/* continuation for OP_CONST_CLASS */ 8030 8031 /* 8032 * Continuation if the Class has not yet been resolved. 8033 * r1: BBBB (Class ref) 8034 * r9: target register 8035 */ 8036.LOP_CONST_CLASS_resolve: 8037 EXPORT_PC() 8038 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8039 mov r2, #1 @ r2<- true 8040 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8041 bl dvmResolveClass @ r0<- Class reference 8042 cmp r0, #0 @ failed? 8043 beq common_exceptionThrown @ yup, handle the exception 8044 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8045 GET_INST_OPCODE(ip) @ extract opcode from rINST 8046 SET_VREG(r0, r9) @ vAA<- r0 8047 GOTO_OPCODE(ip) @ jump to next instruction 8048 8049 8050/* continuation for OP_CHECK_CAST */ 8051 8052 /* 8053 * Trivial test failed, need to perform full check. This is common. 8054 * r0 holds obj->clazz 8055 * r1 holds class resolved from BBBB 8056 * r9 holds object 8057 */ 8058.LOP_CHECK_CAST_fullcheck: 8059 bl dvmInstanceofNonTrivial @ r0<- boolean result 8060 cmp r0, #0 @ failed? 8061 bne .LOP_CHECK_CAST_okay @ no, success 8062 8063 @ A cast has failed. We need to throw a ClassCastException with the 8064 @ class of the object that failed to be cast. 8065 EXPORT_PC() @ about to throw 8066 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 8067 ldr r0, .LstrClassCastExceptionPtr 8068 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 8069 bl dvmThrowExceptionWithClassMessage 8070 b common_exceptionThrown 8071 8072 /* 8073 * Resolution required. This is the least-likely path. 8074 * 8075 * r2 holds BBBB 8076 * r9 holds object 8077 */ 8078.LOP_CHECK_CAST_resolve: 8079 EXPORT_PC() @ resolve() could throw 8080 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8081 mov r1, r2 @ r1<- BBBB 8082 mov r2, #0 @ r2<- false 8083 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8084 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8085 cmp r0, #0 @ got null? 8086 beq common_exceptionThrown @ yes, handle exception 8087 mov r1, r0 @ r1<- class resolved from BBB 8088 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8089 b .LOP_CHECK_CAST_resolved @ pick up where we left off 8090 8091.LstrClassCastExceptionPtr: 8092 .word .LstrClassCastException 8093 8094 8095/* continuation for OP_INSTANCE_OF */ 8096 8097 /* 8098 * Trivial test failed, need to perform full check. This is common. 8099 * r0 holds obj->clazz 8100 * r1 holds class resolved from BBBB 8101 * r9 holds A 8102 */ 8103.LOP_INSTANCE_OF_fullcheck: 8104 bl dvmInstanceofNonTrivial @ r0<- boolean result 8105 @ fall through to OP_INSTANCE_OF_store 8106 8107 /* 8108 * r0 holds boolean result 8109 * r9 holds A 8110 */ 8111.LOP_INSTANCE_OF_store: 8112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8113 SET_VREG(r0, r9) @ vA<- r0 8114 GET_INST_OPCODE(ip) @ extract opcode from rINST 8115 GOTO_OPCODE(ip) @ jump to next instruction 8116 8117 /* 8118 * Trivial test succeeded, save and bail. 8119 * r9 holds A 8120 */ 8121.LOP_INSTANCE_OF_trivial: 8122 mov r0, #1 @ indicate success 8123 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 8124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8125 SET_VREG(r0, r9) @ vA<- r0 8126 GET_INST_OPCODE(ip) @ extract opcode from rINST 8127 GOTO_OPCODE(ip) @ jump to next instruction 8128 8129 /* 8130 * Resolution required. This is the least-likely path. 8131 * 8132 * r3 holds BBBB 8133 * r9 holds A 8134 */ 8135.LOP_INSTANCE_OF_resolve: 8136 EXPORT_PC() @ resolve() could throw 8137 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8138 mov r1, r3 @ r1<- BBBB 8139 mov r2, #1 @ r2<- true 8140 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8141 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8142 cmp r0, #0 @ got null? 8143 beq common_exceptionThrown @ yes, handle exception 8144 mov r1, r0 @ r1<- class resolved from BBB 8145 mov r3, rINST, lsr #12 @ r3<- B 8146 GET_VREG(r0, r3) @ r0<- vB (object) 8147 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 8148 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 8149 8150 8151/* continuation for OP_NEW_INSTANCE */ 8152 8153 .balign 32 @ minimize cache lines 8154.LOP_NEW_INSTANCE_finish: @ r0=new object 8155 mov r3, rINST, lsr #8 @ r3<- AA 8156 cmp r0, #0 @ failed? 8157 beq common_exceptionThrown @ yes, handle the exception 8158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8159 GET_INST_OPCODE(ip) @ extract opcode from rINST 8160 SET_VREG(r0, r3) @ vAA<- r0 8161 GOTO_OPCODE(ip) @ jump to next instruction 8162 8163 /* 8164 * Class initialization required. 8165 * 8166 * r0 holds class object 8167 */ 8168.LOP_NEW_INSTANCE_needinit: 8169 mov r9, r0 @ save r0 8170 bl dvmInitClass @ initialize class 8171 cmp r0, #0 @ check boolean result 8172 mov r0, r9 @ restore r0 8173 bne .LOP_NEW_INSTANCE_initialized @ success, continue 8174 b common_exceptionThrown @ failed, deal with init exception 8175 8176 /* 8177 * Resolution required. This is the least-likely path. 8178 * 8179 * r1 holds BBBB 8180 */ 8181.LOP_NEW_INSTANCE_resolve: 8182 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8183 mov r2, #0 @ r2<- false 8184 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8185 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8186 cmp r0, #0 @ got null? 8187 bne .LOP_NEW_INSTANCE_resolved @ no, continue 8188 b common_exceptionThrown @ yes, handle exception 8189 8190.LstrInstantiationErrorPtr: 8191 .word .LstrInstantiationError 8192 8193 8194/* continuation for OP_NEW_ARRAY */ 8195 8196 8197 /* 8198 * Resolve class. (This is an uncommon case.) 8199 * 8200 * r1 holds array length 8201 * r2 holds class ref CCCC 8202 */ 8203.LOP_NEW_ARRAY_resolve: 8204 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8205 mov r9, r1 @ r9<- length (save) 8206 mov r1, r2 @ r1<- CCCC 8207 mov r2, #0 @ r2<- false 8208 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8209 bl dvmResolveClass @ r0<- call(clazz, ref) 8210 cmp r0, #0 @ got null? 8211 mov r1, r9 @ r1<- length (restore) 8212 beq common_exceptionThrown @ yes, handle exception 8213 @ fall through to OP_NEW_ARRAY_finish 8214 8215 /* 8216 * Finish allocation. 8217 * 8218 * r0 holds class 8219 * r1 holds array length 8220 */ 8221.LOP_NEW_ARRAY_finish: 8222 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8223 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8224 cmp r0, #0 @ failed? 8225 mov r2, rINST, lsr #8 @ r2<- A+ 8226 beq common_exceptionThrown @ yes, handle the exception 8227 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8228 and r2, r2, #15 @ r2<- A 8229 GET_INST_OPCODE(ip) @ extract opcode from rINST 8230 SET_VREG(r0, r2) @ vA<- r0 8231 GOTO_OPCODE(ip) @ jump to next instruction 8232 8233 8234/* continuation for OP_FILLED_NEW_ARRAY */ 8235 8236 /* 8237 * On entry: 8238 * r0 holds array class 8239 * r10 holds AA or BA 8240 */ 8241.LOP_FILLED_NEW_ARRAY_continue: 8242 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8243 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8244 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8245 .if 0 8246 mov r1, r10 @ r1<- AA (length) 8247 .else 8248 mov r1, r10, lsr #4 @ r1<- B (length) 8249 .endif 8250 cmp r3, #'I' @ array of ints? 8251 cmpne r3, #'L' @ array of objects? 8252 cmpne r3, #'[' @ array of arrays? 8253 mov r9, r1 @ save length in r9 8254 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8255 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8256 cmp r0, #0 @ null return? 8257 beq common_exceptionThrown @ alloc failed, handle exception 8258 8259 FETCH(r1, 2) @ r1<- FEDC or CCCC 8260 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8261 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8262 subs r9, r9, #1 @ length--, check for neg 8263 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8264 bmi 2f @ was zero, bail 8265 8266 @ copy values from registers into the array 8267 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8268 .if 0 8269 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 82701: ldr r3, [r2], #4 @ r3<- *r2++ 8271 subs r9, r9, #1 @ count-- 8272 str r3, [r0], #4 @ *contents++ = vX 8273 bpl 1b 8274 @ continue at 2 8275 .else 8276 cmp r9, #4 @ length was initially 5? 8277 and r2, r10, #15 @ r2<- A 8278 bne 1f @ <= 4 args, branch 8279 GET_VREG(r3, r2) @ r3<- vA 8280 sub r9, r9, #1 @ count-- 8281 str r3, [r0, #16] @ contents[4] = vA 82821: and r2, r1, #15 @ r2<- F/E/D/C 8283 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8284 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8285 subs r9, r9, #1 @ count-- 8286 str r3, [r0], #4 @ *contents++ = vX 8287 bpl 1b 8288 @ continue at 2 8289 .endif 8290 82912: 8292 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8293 GOTO_OPCODE(ip) @ execute it 8294 8295 /* 8296 * Throw an exception indicating that we have not implemented this 8297 * mode of filled-new-array. 8298 */ 8299.LOP_FILLED_NEW_ARRAY_notimpl: 8300 ldr r0, .L_strInternalError 8301 ldr r1, .L_strFilledNewArrayNotImpl 8302 bl dvmThrowException 8303 b common_exceptionThrown 8304 8305 .if (!0) @ define in one or the other, not both 8306.L_strFilledNewArrayNotImpl: 8307 .word .LstrFilledNewArrayNotImpl 8308.L_strInternalError: 8309 .word .LstrInternalError 8310 .endif 8311 8312 8313/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8314 8315 /* 8316 * On entry: 8317 * r0 holds array class 8318 * r10 holds AA or BA 8319 */ 8320.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8321 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8322 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8323 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8324 .if 1 8325 mov r1, r10 @ r1<- AA (length) 8326 .else 8327 mov r1, r10, lsr #4 @ r1<- B (length) 8328 .endif 8329 cmp r3, #'I' @ array of ints? 8330 cmpne r3, #'L' @ array of objects? 8331 cmpne r3, #'[' @ array of arrays? 8332 mov r9, r1 @ save length in r9 8333 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8334 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8335 cmp r0, #0 @ null return? 8336 beq common_exceptionThrown @ alloc failed, handle exception 8337 8338 FETCH(r1, 2) @ r1<- FEDC or CCCC 8339 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8340 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8341 subs r9, r9, #1 @ length--, check for neg 8342 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8343 bmi 2f @ was zero, bail 8344 8345 @ copy values from registers into the array 8346 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8347 .if 1 8348 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 83491: ldr r3, [r2], #4 @ r3<- *r2++ 8350 subs r9, r9, #1 @ count-- 8351 str r3, [r0], #4 @ *contents++ = vX 8352 bpl 1b 8353 @ continue at 2 8354 .else 8355 cmp r9, #4 @ length was initially 5? 8356 and r2, r10, #15 @ r2<- A 8357 bne 1f @ <= 4 args, branch 8358 GET_VREG(r3, r2) @ r3<- vA 8359 sub r9, r9, #1 @ count-- 8360 str r3, [r0, #16] @ contents[4] = vA 83611: and r2, r1, #15 @ r2<- F/E/D/C 8362 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8363 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8364 subs r9, r9, #1 @ count-- 8365 str r3, [r0], #4 @ *contents++ = vX 8366 bpl 1b 8367 @ continue at 2 8368 .endif 8369 83702: 8371 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8372 GOTO_OPCODE(ip) @ execute it 8373 8374 /* 8375 * Throw an exception indicating that we have not implemented this 8376 * mode of filled-new-array. 8377 */ 8378.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8379 ldr r0, .L_strInternalError 8380 ldr r1, .L_strFilledNewArrayNotImpl 8381 bl dvmThrowException 8382 b common_exceptionThrown 8383 8384 .if (!1) @ define in one or the other, not both 8385.L_strFilledNewArrayNotImpl: 8386 .word .LstrFilledNewArrayNotImpl 8387.L_strInternalError: 8388 .word .LstrInternalError 8389 .endif 8390 8391 8392/* continuation for OP_CMPL_FLOAT */ 8393 8394 @ Test for NaN with a second comparison. EABI forbids testing bit 8395 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8396 @ make the library call. 8397.LOP_CMPL_FLOAT_gt_or_nan: 8398 mov r1, r9 @ reverse order 8399 mov r0, r10 8400 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8401 @bleq common_abort 8402 movcc r1, #1 @ (greater than) r1<- 1 8403 bcc .LOP_CMPL_FLOAT_finish 8404 mvn r1, #0 @ r1<- 1 or -1 for NaN 8405 b .LOP_CMPL_FLOAT_finish 8406 8407 8408#if 0 /* "clasic" form */ 8409 FETCH(r0, 1) @ r0<- CCBB 8410 and r2, r0, #255 @ r2<- BB 8411 mov r3, r0, lsr #8 @ r3<- CC 8412 GET_VREG(r9, r2) @ r9<- vBB 8413 GET_VREG(r10, r3) @ r10<- vCC 8414 mov r0, r9 @ r0<- vBB 8415 mov r1, r10 @ r1<- vCC 8416 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8417 cmp r0, #0 @ equal? 8418 movne r1, #0 @ yes, result is 0 8419 bne OP_CMPL_FLOAT_finish 8420 mov r0, r9 @ r0<- vBB 8421 mov r1, r10 @ r1<- vCC 8422 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8423 cmp r0, #0 @ less than? 8424 b OP_CMPL_FLOAT_continue 8425@%break 8426 8427OP_CMPL_FLOAT_continue: 8428 mvnne r1, #0 @ yes, result is -1 8429 bne OP_CMPL_FLOAT_finish 8430 mov r0, r9 @ r0<- vBB 8431 mov r1, r10 @ r1<- vCC 8432 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8433 cmp r0, #0 @ greater than? 8434 beq OP_CMPL_FLOAT_nan @ no, must be NaN 8435 mov r1, #1 @ yes, result is 1 8436 @ fall through to _finish 8437 8438OP_CMPL_FLOAT_finish: 8439 mov r3, rINST, lsr #8 @ r3<- AA 8440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8441 SET_VREG(r1, r3) @ vAA<- r1 8442 GET_INST_OPCODE(ip) @ extract opcode from rINST 8443 GOTO_OPCODE(ip) @ jump to next instruction 8444 8445 /* 8446 * This is expected to be uncommon, so we double-branch (once to here, 8447 * again back to _finish). 8448 */ 8449OP_CMPL_FLOAT_nan: 8450 mvn r1, #0 @ r1<- 1 or -1 for NaN 8451 b OP_CMPL_FLOAT_finish 8452 8453#endif 8454 8455 8456/* continuation for OP_CMPG_FLOAT */ 8457 8458 @ Test for NaN with a second comparison. EABI forbids testing bit 8459 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8460 @ make the library call. 8461.LOP_CMPG_FLOAT_gt_or_nan: 8462 mov r1, r9 @ reverse order 8463 mov r0, r10 8464 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8465 @bleq common_abort 8466 movcc r1, #1 @ (greater than) r1<- 1 8467 bcc .LOP_CMPG_FLOAT_finish 8468 mov r1, #1 @ r1<- 1 or -1 for NaN 8469 b .LOP_CMPG_FLOAT_finish 8470 8471 8472#if 0 /* "clasic" form */ 8473 FETCH(r0, 1) @ r0<- CCBB 8474 and r2, r0, #255 @ r2<- BB 8475 mov r3, r0, lsr #8 @ r3<- CC 8476 GET_VREG(r9, r2) @ r9<- vBB 8477 GET_VREG(r10, r3) @ r10<- vCC 8478 mov r0, r9 @ r0<- vBB 8479 mov r1, r10 @ r1<- vCC 8480 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8481 cmp r0, #0 @ equal? 8482 movne r1, #0 @ yes, result is 0 8483 bne OP_CMPG_FLOAT_finish 8484 mov r0, r9 @ r0<- vBB 8485 mov r1, r10 @ r1<- vCC 8486 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8487 cmp r0, #0 @ less than? 8488 b OP_CMPG_FLOAT_continue 8489@%break 8490 8491OP_CMPG_FLOAT_continue: 8492 mvnne r1, #0 @ yes, result is -1 8493 bne OP_CMPG_FLOAT_finish 8494 mov r0, r9 @ r0<- vBB 8495 mov r1, r10 @ r1<- vCC 8496 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8497 cmp r0, #0 @ greater than? 8498 beq OP_CMPG_FLOAT_nan @ no, must be NaN 8499 mov r1, #1 @ yes, result is 1 8500 @ fall through to _finish 8501 8502OP_CMPG_FLOAT_finish: 8503 mov r3, rINST, lsr #8 @ r3<- AA 8504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8505 SET_VREG(r1, r3) @ vAA<- r1 8506 GET_INST_OPCODE(ip) @ extract opcode from rINST 8507 GOTO_OPCODE(ip) @ jump to next instruction 8508 8509 /* 8510 * This is expected to be uncommon, so we double-branch (once to here, 8511 * again back to _finish). 8512 */ 8513OP_CMPG_FLOAT_nan: 8514 mov r1, #1 @ r1<- 1 or -1 for NaN 8515 b OP_CMPG_FLOAT_finish 8516 8517#endif 8518 8519 8520/* continuation for OP_CMPL_DOUBLE */ 8521 8522 @ Test for NaN with a second comparison. EABI forbids testing bit 8523 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8524 @ make the library call. 8525.LOP_CMPL_DOUBLE_gt_or_nan: 8526 ldmia r10, {r0-r1} @ reverse order 8527 ldmia r9, {r2-r3} 8528 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8529 @bleq common_abort 8530 movcc r1, #1 @ (greater than) r1<- 1 8531 bcc .LOP_CMPL_DOUBLE_finish 8532 mvn r1, #0 @ r1<- 1 or -1 for NaN 8533 b .LOP_CMPL_DOUBLE_finish 8534 8535 8536/* continuation for OP_CMPG_DOUBLE */ 8537 8538 @ Test for NaN with a second comparison. EABI forbids testing bit 8539 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8540 @ make the library call. 8541.LOP_CMPG_DOUBLE_gt_or_nan: 8542 ldmia r10, {r0-r1} @ reverse order 8543 ldmia r9, {r2-r3} 8544 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8545 @bleq common_abort 8546 movcc r1, #1 @ (greater than) r1<- 1 8547 bcc .LOP_CMPG_DOUBLE_finish 8548 mov r1, #1 @ r1<- 1 or -1 for NaN 8549 b .LOP_CMPG_DOUBLE_finish 8550 8551 8552/* continuation for OP_CMP_LONG */ 8553 8554.LOP_CMP_LONG_less: 8555 mvn r1, #0 @ r1<- -1 8556 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8557 @ instead, we just replicate the tail end. 8558 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8559 SET_VREG(r1, r9) @ vAA<- r1 8560 GET_INST_OPCODE(ip) @ extract opcode from rINST 8561 GOTO_OPCODE(ip) @ jump to next instruction 8562 8563.LOP_CMP_LONG_greater: 8564 mov r1, #1 @ r1<- 1 8565 @ fall through to _finish 8566 8567.LOP_CMP_LONG_finish: 8568 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8569 SET_VREG(r1, r9) @ vAA<- r1 8570 GET_INST_OPCODE(ip) @ extract opcode from rINST 8571 GOTO_OPCODE(ip) @ jump to next instruction 8572 8573 8574/* continuation for OP_AGET_WIDE */ 8575 8576.LOP_AGET_WIDE_finish: 8577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8578 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8579 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8580 GET_INST_OPCODE(ip) @ extract opcode from rINST 8581 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8582 GOTO_OPCODE(ip) @ jump to next instruction 8583 8584 8585/* continuation for OP_APUT_WIDE */ 8586 8587.LOP_APUT_WIDE_finish: 8588 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8589 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8590 GET_INST_OPCODE(ip) @ extract opcode from rINST 8591 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8592 GOTO_OPCODE(ip) @ jump to next instruction 8593 8594 8595/* continuation for OP_APUT_OBJECT */ 8596 /* 8597 * On entry: 8598 * r1 = vBB (arrayObj) 8599 * r9 = vAA (obj) 8600 * r10 = offset into array (vBB + vCC * width) 8601 */ 8602.LOP_APUT_OBJECT_finish: 8603 cmp r9, #0 @ storing null reference? 8604 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8605 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8606 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8607 bl dvmCanPutArrayElement @ test object type vs. array type 8608 cmp r0, #0 @ okay? 8609 beq common_errArrayStore @ no 8610.LOP_APUT_OBJECT_skip_check: 8611 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8612 GET_INST_OPCODE(ip) @ extract opcode from rINST 8613 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8614 GOTO_OPCODE(ip) @ jump to next instruction 8615 8616 8617/* continuation for OP_IGET */ 8618 8619 /* 8620 * Currently: 8621 * r0 holds resolved field 8622 * r9 holds object 8623 */ 8624.LOP_IGET_finish: 8625 @bl common_squeak0 8626 cmp r9, #0 @ check object for null 8627 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8628 beq common_errNullObject @ object was null 8629 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8630 mov r2, rINST, lsr #8 @ r2<- A+ 8631 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8632 and r2, r2, #15 @ r2<- A 8633 GET_INST_OPCODE(ip) @ extract opcode from rINST 8634 SET_VREG(r0, r2) @ fp[A]<- r0 8635 GOTO_OPCODE(ip) @ jump to next instruction 8636 8637 8638/* continuation for OP_IGET_WIDE */ 8639 8640 /* 8641 * Currently: 8642 * r0 holds resolved field 8643 * r9 holds object 8644 */ 8645.LOP_IGET_WIDE_finish: 8646 cmp r9, #0 @ check object for null 8647 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8648 beq common_errNullObject @ object was null 8649 mov r2, rINST, lsr #8 @ r2<- A+ 8650 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8651 and r2, r2, #15 @ r2<- A 8652 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8653 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8654 GET_INST_OPCODE(ip) @ extract opcode from rINST 8655 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8656 GOTO_OPCODE(ip) @ jump to next instruction 8657 8658 8659/* continuation for OP_IGET_OBJECT */ 8660 8661 /* 8662 * Currently: 8663 * r0 holds resolved field 8664 * r9 holds object 8665 */ 8666.LOP_IGET_OBJECT_finish: 8667 @bl common_squeak0 8668 cmp r9, #0 @ check object for null 8669 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8670 beq common_errNullObject @ object was null 8671 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8672 mov r2, rINST, lsr #8 @ r2<- A+ 8673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8674 and r2, r2, #15 @ r2<- A 8675 GET_INST_OPCODE(ip) @ extract opcode from rINST 8676 SET_VREG(r0, r2) @ fp[A]<- r0 8677 GOTO_OPCODE(ip) @ jump to next instruction 8678 8679 8680/* continuation for OP_IGET_BOOLEAN */ 8681 8682 /* 8683 * Currently: 8684 * r0 holds resolved field 8685 * r9 holds object 8686 */ 8687.LOP_IGET_BOOLEAN_finish: 8688 @bl common_squeak1 8689 cmp r9, #0 @ check object for null 8690 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8691 beq common_errNullObject @ object was null 8692 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8693 mov r2, rINST, lsr #8 @ r2<- A+ 8694 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8695 and r2, r2, #15 @ r2<- A 8696 GET_INST_OPCODE(ip) @ extract opcode from rINST 8697 SET_VREG(r0, r2) @ fp[A]<- r0 8698 GOTO_OPCODE(ip) @ jump to next instruction 8699 8700 8701/* continuation for OP_IGET_BYTE */ 8702 8703 /* 8704 * Currently: 8705 * r0 holds resolved field 8706 * r9 holds object 8707 */ 8708.LOP_IGET_BYTE_finish: 8709 @bl common_squeak2 8710 cmp r9, #0 @ check object for null 8711 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8712 beq common_errNullObject @ object was null 8713 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8714 mov r2, rINST, lsr #8 @ r2<- A+ 8715 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8716 and r2, r2, #15 @ r2<- A 8717 GET_INST_OPCODE(ip) @ extract opcode from rINST 8718 SET_VREG(r0, r2) @ fp[A]<- r0 8719 GOTO_OPCODE(ip) @ jump to next instruction 8720 8721 8722/* continuation for OP_IGET_CHAR */ 8723 8724 /* 8725 * Currently: 8726 * r0 holds resolved field 8727 * r9 holds object 8728 */ 8729.LOP_IGET_CHAR_finish: 8730 @bl common_squeak3 8731 cmp r9, #0 @ check object for null 8732 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8733 beq common_errNullObject @ object was null 8734 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8735 mov r2, rINST, lsr #8 @ r2<- A+ 8736 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8737 and r2, r2, #15 @ r2<- A 8738 GET_INST_OPCODE(ip) @ extract opcode from rINST 8739 SET_VREG(r0, r2) @ fp[A]<- r0 8740 GOTO_OPCODE(ip) @ jump to next instruction 8741 8742 8743/* continuation for OP_IGET_SHORT */ 8744 8745 /* 8746 * Currently: 8747 * r0 holds resolved field 8748 * r9 holds object 8749 */ 8750.LOP_IGET_SHORT_finish: 8751 @bl common_squeak4 8752 cmp r9, #0 @ check object for null 8753 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8754 beq common_errNullObject @ object was null 8755 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8756 mov r2, rINST, lsr #8 @ r2<- A+ 8757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8758 and r2, r2, #15 @ r2<- A 8759 GET_INST_OPCODE(ip) @ extract opcode from rINST 8760 SET_VREG(r0, r2) @ fp[A]<- r0 8761 GOTO_OPCODE(ip) @ jump to next instruction 8762 8763 8764/* continuation for OP_IPUT */ 8765 8766 /* 8767 * Currently: 8768 * r0 holds resolved field 8769 * r9 holds object 8770 */ 8771.LOP_IPUT_finish: 8772 @bl common_squeak0 8773 mov r1, rINST, lsr #8 @ r1<- A+ 8774 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8775 and r1, r1, #15 @ r1<- A 8776 cmp r9, #0 @ check object for null 8777 GET_VREG(r0, r1) @ r0<- fp[A] 8778 beq common_errNullObject @ object was null 8779 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8780 GET_INST_OPCODE(ip) @ extract opcode from rINST 8781 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8782 GOTO_OPCODE(ip) @ jump to next instruction 8783 8784 8785/* continuation for OP_IPUT_WIDE */ 8786 8787 /* 8788 * Currently: 8789 * r0 holds resolved field 8790 * r9 holds object 8791 */ 8792.LOP_IPUT_WIDE_finish: 8793 mov r2, rINST, lsr #8 @ r2<- A+ 8794 cmp r9, #0 @ check object for null 8795 and r2, r2, #15 @ r2<- A 8796 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8797 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8798 beq common_errNullObject @ object was null 8799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8800 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8801 GET_INST_OPCODE(ip) @ extract opcode from rINST 8802 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8803 GOTO_OPCODE(ip) @ jump to next instruction 8804 8805 8806/* continuation for OP_IPUT_OBJECT */ 8807 8808 /* 8809 * Currently: 8810 * r0 holds resolved field 8811 * r9 holds object 8812 */ 8813.LOP_IPUT_OBJECT_finish: 8814 @bl common_squeak0 8815 mov r1, rINST, lsr #8 @ r1<- A+ 8816 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8817 and r1, r1, #15 @ r1<- A 8818 cmp r9, #0 @ check object for null 8819 GET_VREG(r0, r1) @ r0<- fp[A] 8820 beq common_errNullObject @ object was null 8821 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8822 GET_INST_OPCODE(ip) @ extract opcode from rINST 8823 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8824 GOTO_OPCODE(ip) @ jump to next instruction 8825 8826 8827/* continuation for OP_IPUT_BOOLEAN */ 8828 8829 /* 8830 * Currently: 8831 * r0 holds resolved field 8832 * r9 holds object 8833 */ 8834.LOP_IPUT_BOOLEAN_finish: 8835 @bl common_squeak1 8836 mov r1, rINST, lsr #8 @ r1<- A+ 8837 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8838 and r1, r1, #15 @ r1<- A 8839 cmp r9, #0 @ check object for null 8840 GET_VREG(r0, r1) @ r0<- fp[A] 8841 beq common_errNullObject @ object was null 8842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8843 GET_INST_OPCODE(ip) @ extract opcode from rINST 8844 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8845 GOTO_OPCODE(ip) @ jump to next instruction 8846 8847 8848/* continuation for OP_IPUT_BYTE */ 8849 8850 /* 8851 * Currently: 8852 * r0 holds resolved field 8853 * r9 holds object 8854 */ 8855.LOP_IPUT_BYTE_finish: 8856 @bl common_squeak2 8857 mov r1, rINST, lsr #8 @ r1<- A+ 8858 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8859 and r1, r1, #15 @ r1<- A 8860 cmp r9, #0 @ check object for null 8861 GET_VREG(r0, r1) @ r0<- fp[A] 8862 beq common_errNullObject @ object was null 8863 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8864 GET_INST_OPCODE(ip) @ extract opcode from rINST 8865 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8866 GOTO_OPCODE(ip) @ jump to next instruction 8867 8868 8869/* continuation for OP_IPUT_CHAR */ 8870 8871 /* 8872 * Currently: 8873 * r0 holds resolved field 8874 * r9 holds object 8875 */ 8876.LOP_IPUT_CHAR_finish: 8877 @bl common_squeak3 8878 mov r1, rINST, lsr #8 @ r1<- A+ 8879 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8880 and r1, r1, #15 @ r1<- A 8881 cmp r9, #0 @ check object for null 8882 GET_VREG(r0, r1) @ r0<- fp[A] 8883 beq common_errNullObject @ object was null 8884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8885 GET_INST_OPCODE(ip) @ extract opcode from rINST 8886 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8887 GOTO_OPCODE(ip) @ jump to next instruction 8888 8889 8890/* continuation for OP_IPUT_SHORT */ 8891 8892 /* 8893 * Currently: 8894 * r0 holds resolved field 8895 * r9 holds object 8896 */ 8897.LOP_IPUT_SHORT_finish: 8898 @bl common_squeak4 8899 mov r1, rINST, lsr #8 @ r1<- A+ 8900 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8901 and r1, r1, #15 @ r1<- A 8902 cmp r9, #0 @ check object for null 8903 GET_VREG(r0, r1) @ r0<- fp[A] 8904 beq common_errNullObject @ object was null 8905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8906 GET_INST_OPCODE(ip) @ extract opcode from rINST 8907 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8908 GOTO_OPCODE(ip) @ jump to next instruction 8909 8910 8911/* continuation for OP_SGET */ 8912 8913 /* 8914 * Continuation if the field has not yet been resolved. 8915 * r1: BBBB field ref 8916 */ 8917.LOP_SGET_resolve: 8918 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8919 EXPORT_PC() @ resolve() could throw, so export now 8920 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8921 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8922 cmp r0, #0 @ success? 8923 bne .LOP_SGET_finish @ yes, finish 8924 b common_exceptionThrown @ no, handle exception 8925 8926 8927/* continuation for OP_SGET_WIDE */ 8928 8929 /* 8930 * Continuation if the field has not yet been resolved. 8931 * r1: BBBB field ref 8932 */ 8933.LOP_SGET_WIDE_resolve: 8934 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8935 EXPORT_PC() @ resolve() could throw, so export now 8936 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8937 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8938 cmp r0, #0 @ success? 8939 bne .LOP_SGET_WIDE_finish @ yes, finish 8940 b common_exceptionThrown @ no, handle exception 8941 8942 8943/* continuation for OP_SGET_OBJECT */ 8944 8945 /* 8946 * Continuation if the field has not yet been resolved. 8947 * r1: BBBB field ref 8948 */ 8949.LOP_SGET_OBJECT_resolve: 8950 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8951 EXPORT_PC() @ resolve() could throw, so export now 8952 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8953 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8954 cmp r0, #0 @ success? 8955 bne .LOP_SGET_OBJECT_finish @ yes, finish 8956 b common_exceptionThrown @ no, handle exception 8957 8958 8959/* continuation for OP_SGET_BOOLEAN */ 8960 8961 /* 8962 * Continuation if the field has not yet been resolved. 8963 * r1: BBBB field ref 8964 */ 8965.LOP_SGET_BOOLEAN_resolve: 8966 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8967 EXPORT_PC() @ resolve() could throw, so export now 8968 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8969 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8970 cmp r0, #0 @ success? 8971 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8972 b common_exceptionThrown @ no, handle exception 8973 8974 8975/* continuation for OP_SGET_BYTE */ 8976 8977 /* 8978 * Continuation if the field has not yet been resolved. 8979 * r1: BBBB field ref 8980 */ 8981.LOP_SGET_BYTE_resolve: 8982 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8983 EXPORT_PC() @ resolve() could throw, so export now 8984 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8985 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8986 cmp r0, #0 @ success? 8987 bne .LOP_SGET_BYTE_finish @ yes, finish 8988 b common_exceptionThrown @ no, handle exception 8989 8990 8991/* continuation for OP_SGET_CHAR */ 8992 8993 /* 8994 * Continuation if the field has not yet been resolved. 8995 * r1: BBBB field ref 8996 */ 8997.LOP_SGET_CHAR_resolve: 8998 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8999 EXPORT_PC() @ resolve() could throw, so export now 9000 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9001 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9002 cmp r0, #0 @ success? 9003 bne .LOP_SGET_CHAR_finish @ yes, finish 9004 b common_exceptionThrown @ no, handle exception 9005 9006 9007/* continuation for OP_SGET_SHORT */ 9008 9009 /* 9010 * Continuation if the field has not yet been resolved. 9011 * r1: BBBB field ref 9012 */ 9013.LOP_SGET_SHORT_resolve: 9014 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9015 EXPORT_PC() @ resolve() could throw, so export now 9016 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9017 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9018 cmp r0, #0 @ success? 9019 bne .LOP_SGET_SHORT_finish @ yes, finish 9020 b common_exceptionThrown @ no, handle exception 9021 9022 9023/* continuation for OP_SPUT */ 9024 9025 /* 9026 * Continuation if the field has not yet been resolved. 9027 * r1: BBBB field ref 9028 */ 9029.LOP_SPUT_resolve: 9030 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9031 EXPORT_PC() @ resolve() could throw, so export now 9032 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9033 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9034 cmp r0, #0 @ success? 9035 bne .LOP_SPUT_finish @ yes, finish 9036 b common_exceptionThrown @ no, handle exception 9037 9038 9039/* continuation for OP_SPUT_WIDE */ 9040 9041 /* 9042 * Continuation if the field has not yet been resolved. 9043 * r1: BBBB field ref 9044 * r9: &fp[AA] 9045 */ 9046.LOP_SPUT_WIDE_resolve: 9047 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9048 EXPORT_PC() @ resolve() could throw, so export now 9049 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9050 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9051 cmp r0, #0 @ success? 9052 bne .LOP_SPUT_WIDE_finish @ yes, finish 9053 b common_exceptionThrown @ no, handle exception 9054 9055 9056/* continuation for OP_SPUT_OBJECT */ 9057 9058 /* 9059 * Continuation if the field has not yet been resolved. 9060 * r1: BBBB field ref 9061 */ 9062.LOP_SPUT_OBJECT_resolve: 9063 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9064 EXPORT_PC() @ resolve() could throw, so export now 9065 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9066 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9067 cmp r0, #0 @ success? 9068 bne .LOP_SPUT_OBJECT_finish @ yes, finish 9069 b common_exceptionThrown @ no, handle exception 9070 9071 9072/* continuation for OP_SPUT_BOOLEAN */ 9073 9074 /* 9075 * Continuation if the field has not yet been resolved. 9076 * r1: BBBB field ref 9077 */ 9078.LOP_SPUT_BOOLEAN_resolve: 9079 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9080 EXPORT_PC() @ resolve() could throw, so export now 9081 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9082 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9083 cmp r0, #0 @ success? 9084 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 9085 b common_exceptionThrown @ no, handle exception 9086 9087 9088/* continuation for OP_SPUT_BYTE */ 9089 9090 /* 9091 * Continuation if the field has not yet been resolved. 9092 * r1: BBBB field ref 9093 */ 9094.LOP_SPUT_BYTE_resolve: 9095 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9096 EXPORT_PC() @ resolve() could throw, so export now 9097 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9098 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9099 cmp r0, #0 @ success? 9100 bne .LOP_SPUT_BYTE_finish @ yes, finish 9101 b common_exceptionThrown @ no, handle exception 9102 9103 9104/* continuation for OP_SPUT_CHAR */ 9105 9106 /* 9107 * Continuation if the field has not yet been resolved. 9108 * r1: BBBB field ref 9109 */ 9110.LOP_SPUT_CHAR_resolve: 9111 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9112 EXPORT_PC() @ resolve() could throw, so export now 9113 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9114 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9115 cmp r0, #0 @ success? 9116 bne .LOP_SPUT_CHAR_finish @ yes, finish 9117 b common_exceptionThrown @ no, handle exception 9118 9119 9120/* continuation for OP_SPUT_SHORT */ 9121 9122 /* 9123 * Continuation if the field has not yet been resolved. 9124 * r1: BBBB field ref 9125 */ 9126.LOP_SPUT_SHORT_resolve: 9127 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9128 EXPORT_PC() @ resolve() could throw, so export now 9129 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9130 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9131 cmp r0, #0 @ success? 9132 bne .LOP_SPUT_SHORT_finish @ yes, finish 9133 b common_exceptionThrown @ no, handle exception 9134 9135 9136/* continuation for OP_INVOKE_VIRTUAL */ 9137 9138 /* 9139 * At this point: 9140 * r0 = resolved base method 9141 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9142 */ 9143.LOP_INVOKE_VIRTUAL_continue: 9144 GET_VREG(r1, r10) @ r1<- "this" ptr 9145 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9146 cmp r1, #0 @ is "this" null? 9147 beq common_errNullObject @ null "this", throw exception 9148 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9149 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9150 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9151 bl common_invokeMethodNoRange @ continue on 9152 9153 9154/* continuation for OP_INVOKE_SUPER */ 9155 9156 /* 9157 * At this point: 9158 * r0 = resolved base method 9159 * r9 = method->clazz 9160 */ 9161.LOP_INVOKE_SUPER_continue: 9162 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9163 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9164 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9165 EXPORT_PC() @ must export for invoke 9166 cmp r2, r3 @ compare (methodIndex, vtableCount) 9167 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 9168 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9169 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9170 bl common_invokeMethodNoRange @ continue on 9171 9172.LOP_INVOKE_SUPER_resolve: 9173 mov r0, r9 @ r0<- method->clazz 9174 mov r2, #METHOD_VIRTUAL @ resolver method type 9175 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9176 cmp r0, #0 @ got null? 9177 bne .LOP_INVOKE_SUPER_continue @ no, continue 9178 b common_exceptionThrown @ yes, handle exception 9179 9180 /* 9181 * Throw a NoSuchMethodError with the method name as the message. 9182 * r0 = resolved base method 9183 */ 9184.LOP_INVOKE_SUPER_nsm: 9185 ldr r1, [r0, #offMethod_name] @ r1<- method name 9186 b common_errNoSuchMethod 9187 9188 9189/* continuation for OP_INVOKE_DIRECT */ 9190 9191 /* 9192 * On entry: 9193 * r1 = reference (BBBB or CCCC) 9194 * r10 = "this" register 9195 */ 9196.LOP_INVOKE_DIRECT_resolve: 9197 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9198 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9199 mov r2, #METHOD_DIRECT @ resolver method type 9200 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9201 cmp r0, #0 @ got null? 9202 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9203 bne .LOP_INVOKE_DIRECT_finish @ no, continue 9204 b common_exceptionThrown @ yes, handle exception 9205 9206 9207/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 9208 9209 /* 9210 * At this point: 9211 * r0 = resolved base method 9212 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9213 */ 9214.LOP_INVOKE_VIRTUAL_RANGE_continue: 9215 GET_VREG(r1, r10) @ r1<- "this" ptr 9216 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9217 cmp r1, #0 @ is "this" null? 9218 beq common_errNullObject @ null "this", throw exception 9219 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9220 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9221 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9222 bl common_invokeMethodRange @ continue on 9223 9224 9225/* continuation for OP_INVOKE_SUPER_RANGE */ 9226 9227 /* 9228 * At this point: 9229 * r0 = resolved base method 9230 * r9 = method->clazz 9231 */ 9232.LOP_INVOKE_SUPER_RANGE_continue: 9233 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9234 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9235 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9236 EXPORT_PC() @ must export for invoke 9237 cmp r2, r3 @ compare (methodIndex, vtableCount) 9238 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 9239 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9240 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9241 bl common_invokeMethodRange @ continue on 9242 9243.LOP_INVOKE_SUPER_RANGE_resolve: 9244 mov r0, r9 @ r0<- method->clazz 9245 mov r2, #METHOD_VIRTUAL @ resolver method type 9246 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9247 cmp r0, #0 @ got null? 9248 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 9249 b common_exceptionThrown @ yes, handle exception 9250 9251 /* 9252 * Throw a NoSuchMethodError with the method name as the message. 9253 * r0 = resolved base method 9254 */ 9255.LOP_INVOKE_SUPER_RANGE_nsm: 9256 ldr r1, [r0, #offMethod_name] @ r1<- method name 9257 b common_errNoSuchMethod 9258 9259 9260/* continuation for OP_INVOKE_DIRECT_RANGE */ 9261 9262 /* 9263 * On entry: 9264 * r1 = reference (BBBB or CCCC) 9265 * r10 = "this" register 9266 */ 9267.LOP_INVOKE_DIRECT_RANGE_resolve: 9268 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9269 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9270 mov r2, #METHOD_DIRECT @ resolver method type 9271 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9272 cmp r0, #0 @ got null? 9273 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9274 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 9275 b common_exceptionThrown @ yes, handle exception 9276 9277 9278/* continuation for OP_FLOAT_TO_LONG */ 9279/* 9280 * Convert the float in r0 to a long in r0/r1. 9281 * 9282 * We have to clip values to long min/max per the specification. The 9283 * expected common case is a "reasonable" value that converts directly 9284 * to modest integer. The EABI convert function isn't doing this for us. 9285 */ 9286f2l_doconv: 9287 stmfd sp!, {r4, lr} 9288 mov r1, #0x5f000000 @ (float)maxlong 9289 mov r4, r0 9290 bl __aeabi_fcmpge @ is arg >= maxlong? 9291 cmp r0, #0 @ nonzero == yes 9292 mvnne r0, #0 @ return maxlong (7fffffff) 9293 mvnne r1, #0x80000000 9294 ldmnefd sp!, {r4, pc} 9295 9296 mov r0, r4 @ recover arg 9297 mov r1, #0xdf000000 @ (float)minlong 9298 bl __aeabi_fcmple @ is arg <= minlong? 9299 cmp r0, #0 @ nonzero == yes 9300 movne r0, #0 @ return minlong (80000000) 9301 movne r1, #0x80000000 9302 ldmnefd sp!, {r4, pc} 9303 9304 mov r0, r4 @ recover arg 9305 mov r1, r4 9306 bl __aeabi_fcmpeq @ is arg == self? 9307 cmp r0, #0 @ zero == no 9308 moveq r1, #0 @ return zero for NaN 9309 ldmeqfd sp!, {r4, pc} 9310 9311 mov r0, r4 @ recover arg 9312 bl __aeabi_f2lz @ convert float to long 9313 ldmfd sp!, {r4, pc} 9314 9315 9316/* continuation for OP_DOUBLE_TO_LONG */ 9317/* 9318 * Convert the double in r0/r1 to a long in r0/r1. 9319 * 9320 * We have to clip values to long min/max per the specification. The 9321 * expected common case is a "reasonable" value that converts directly 9322 * to modest integer. The EABI convert function isn't doing this for us. 9323 */ 9324d2l_doconv: 9325 stmfd sp!, {r4, r5, lr} @ save regs 9326 mov r3, #0x43000000 @ maxlong, as a double (high word) 9327 add r3, #0x00e00000 @ 0x43e00000 9328 mov r2, #0 @ maxlong, as a double (low word) 9329 sub sp, sp, #4 @ align for EABI 9330 mov r4, r0 @ save a copy of r0 9331 mov r5, r1 @ and r1 9332 bl __aeabi_dcmpge @ is arg >= maxlong? 9333 cmp r0, #0 @ nonzero == yes 9334 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9335 mvnne r1, #0x80000000 9336 bne 1f 9337 9338 mov r0, r4 @ recover arg 9339 mov r1, r5 9340 mov r3, #0xc3000000 @ minlong, as a double (high word) 9341 add r3, #0x00e00000 @ 0xc3e00000 9342 mov r2, #0 @ minlong, as a double (low word) 9343 bl __aeabi_dcmple @ is arg <= minlong? 9344 cmp r0, #0 @ nonzero == yes 9345 movne r0, #0 @ return minlong (8000000000000000) 9346 movne r1, #0x80000000 9347 bne 1f 9348 9349 mov r0, r4 @ recover arg 9350 mov r1, r5 9351 mov r2, r4 @ compare against self 9352 mov r3, r5 9353 bl __aeabi_dcmpeq @ is arg == self? 9354 cmp r0, #0 @ zero == no 9355 moveq r1, #0 @ return zero for NaN 9356 beq 1f 9357 9358 mov r0, r4 @ recover arg 9359 mov r1, r5 9360 bl __aeabi_d2lz @ convert double to long 9361 93621: 9363 add sp, sp, #4 9364 ldmfd sp!, {r4, r5, pc} 9365 9366 9367/* continuation for OP_MUL_LONG */ 9368 9369.LOP_MUL_LONG_finish: 9370 GET_INST_OPCODE(ip) @ extract opcode from rINST 9371 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9372 GOTO_OPCODE(ip) @ jump to next instruction 9373 9374 9375/* continuation for OP_SHL_LONG */ 9376 9377.LOP_SHL_LONG_finish: 9378 mov r0, r0, asl r2 @ r0<- r0 << r2 9379 GET_INST_OPCODE(ip) @ extract opcode from rINST 9380 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9381 GOTO_OPCODE(ip) @ jump to next instruction 9382 9383 9384/* continuation for OP_SHR_LONG */ 9385 9386.LOP_SHR_LONG_finish: 9387 mov r1, r1, asr r2 @ r1<- r1 >> r2 9388 GET_INST_OPCODE(ip) @ extract opcode from rINST 9389 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9390 GOTO_OPCODE(ip) @ jump to next instruction 9391 9392 9393/* continuation for OP_USHR_LONG */ 9394 9395.LOP_USHR_LONG_finish: 9396 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9397 GET_INST_OPCODE(ip) @ extract opcode from rINST 9398 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9399 GOTO_OPCODE(ip) @ jump to next instruction 9400 9401 9402/* continuation for OP_SHL_LONG_2ADDR */ 9403 9404.LOP_SHL_LONG_2ADDR_finish: 9405 GET_INST_OPCODE(ip) @ extract opcode from rINST 9406 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9407 GOTO_OPCODE(ip) @ jump to next instruction 9408 9409 9410/* continuation for OP_SHR_LONG_2ADDR */ 9411 9412.LOP_SHR_LONG_2ADDR_finish: 9413 GET_INST_OPCODE(ip) @ extract opcode from rINST 9414 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9415 GOTO_OPCODE(ip) @ jump to next instruction 9416 9417 9418/* continuation for OP_USHR_LONG_2ADDR */ 9419 9420.LOP_USHR_LONG_2ADDR_finish: 9421 GET_INST_OPCODE(ip) @ extract opcode from rINST 9422 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9423 GOTO_OPCODE(ip) @ jump to next instruction 9424 9425 9426/* continuation for OP_EXECUTE_INLINE */ 9427 9428 /* 9429 * Extract args, call function. 9430 * r0 = #of args (0-4) 9431 * r10 = call index 9432 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9433 * 9434 * Other ideas: 9435 * - Use a jump table from the main piece to jump directly into the 9436 * AND/LDR pairs. Costs a data load, saves a branch. 9437 * - Have five separate pieces that do the loading, so we can work the 9438 * interleave a little better. Increases code size. 9439 */ 9440.LOP_EXECUTE_INLINE_continue: 9441 rsb r0, r0, #4 @ r0<- 4-r0 9442 FETCH(r9, 2) @ r9<- FEDC 9443 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9444 bl common_abort @ (skipped due to ARM prefetch) 94454: and ip, r9, #0xf000 @ isolate F 9446 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 94473: and ip, r9, #0x0f00 @ isolate E 9448 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 94492: and ip, r9, #0x00f0 @ isolate D 9450 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 94511: and ip, r9, #0x000f @ isolate C 9452 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 94530: 9454 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9455 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9456 @ (not reached) 9457 9458.LOP_EXECUTE_INLINE_table: 9459 .word gDvmInlineOpsTable 9460 9461 9462 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9463 .global dvmAsmSisterEnd 9464dvmAsmSisterEnd: 9465 9466/* File: armv5te/footer.S */ 9467 9468/* 9469 * =========================================================================== 9470 * Common subroutines and data 9471 * =========================================================================== 9472 */ 9473 9474 9475 9476 .text 9477 .align 2 9478 9479#if defined(WITH_JIT) 9480#if defined(WITH_SELF_VERIFICATION) 9481 .global dvmJitToInterpPunt 9482dvmJitToInterpPunt: 9483 mov r2,#kSVSPunt @ r2<- interpreter entry point 9484 b dvmJitSelfVerificationEnd @ doesn't return 9485 9486 .global dvmJitToInterpSingleStep 9487dvmJitToInterpSingleStep: 9488 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9489 b dvmJitSelfVerificationEnd @ doesn't return 9490 9491 .global dvmJitToTraceSelect 9492dvmJitToTraceSelect: 9493 ldr r0,[lr, #-1] @ pass our target PC 9494 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9495 b dvmJitSelfVerificationEnd @ doesn't return 9496 9497 .global dvmJitToBackwardBranch 9498dvmJitToBackwardBranch: 9499 ldr r0,[lr, #-1] @ pass our target PC 9500 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9501 b dvmJitSelfVerificationEnd @ doesn't return 9502 9503 .global dvmJitToInterpNormal 9504dvmJitToInterpNormal: 9505 ldr r0,[lr, #-1] @ pass our target PC 9506 mov r2,#kSVSNormal @ r2<- interpreter entry point 9507 b dvmJitSelfVerificationEnd @ doesn't return 9508 9509 .global dvmJitToInterpNoChain 9510dvmJitToInterpNoChain: 9511 mov r0,rPC @ pass our target PC 9512 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9513 b dvmJitSelfVerificationEnd @ doesn't return 9514#else 9515/* 9516 * Return from the translation cache to the interpreter when the compiler is 9517 * having issues translating/executing a Dalvik instruction. We have to skip 9518 * the code cache lookup otherwise it is possible to indefinitely bouce 9519 * between the interpreter and the code cache if the instruction that fails 9520 * to be compiled happens to be at a trace start. 9521 */ 9522 .global dvmJitToInterpPunt 9523dvmJitToInterpPunt: 9524 mov rPC, r0 9525#ifdef EXIT_STATS 9526 mov r0,lr 9527 bl dvmBumpPunt; 9528#endif 9529 EXPORT_PC() 9530 adrl rIBASE, dvmAsmInstructionStart 9531 FETCH_INST() 9532 GET_INST_OPCODE(ip) 9533 GOTO_OPCODE(ip) 9534 9535/* 9536 * Return to the interpreter to handle a single instruction. 9537 * On entry: 9538 * r0 <= PC 9539 * r1 <= PC of resume instruction 9540 * lr <= resume point in translation 9541 */ 9542 .global dvmJitToInterpSingleStep 9543dvmJitToInterpSingleStep: 9544 str lr,[rGLUE,#offGlue_jitResume] 9545 str r1,[rGLUE,#offGlue_jitResumePC] 9546 mov r1,#kInterpEntryInstr 9547 @ enum is 4 byte in aapcs-EABI 9548 str r1, [rGLUE, #offGlue_entryPoint] 9549 mov rPC,r0 9550 EXPORT_PC() 9551 adrl rIBASE, dvmAsmInstructionStart 9552 mov r2,#kJitSingleStep @ Ask for single step and then revert 9553 str r2,[rGLUE,#offGlue_jitState] 9554 mov r1,#1 @ set changeInterp to bail to debug interp 9555 b common_gotoBail 9556 9557 9558/* 9559 * Return from the translation cache and immediately request 9560 * a translation for the exit target. Commonly used following 9561 * invokes. 9562 */ 9563 .global dvmJitToTraceSelect 9564dvmJitToTraceSelect: 9565 ldr rPC,[lr, #-1] @ get our target PC 9566 add rINST,lr,#-5 @ save start of chain branch 9567 mov r0,rPC 9568 bl dvmJitGetCodeAddr @ Is there a translation? 9569 cmp r0,#0 9570 beq 2f 9571 mov r1,rINST 9572 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9573 mov r1, rPC @ arg1 of translation may need this 9574 mov lr, #0 @ in case target is HANDLER_INTERPRET 9575 cmp r0,#0 @ successful chain? 9576 bxne r0 @ continue native execution 9577 b toInterpreter @ didn't chain - resume with interpreter 9578 9579/* No translation, so request one if profiling isn't disabled*/ 95802: 9581 adrl rIBASE, dvmAsmInstructionStart 9582 GET_JIT_PROF_TABLE(r0) 9583 FETCH_INST() 9584 cmp r0, #0 9585 bne common_selectTrace 9586 GET_INST_OPCODE(ip) 9587 GOTO_OPCODE(ip) 9588 9589/* 9590 * Return from the translation cache to the interpreter. 9591 * The return was done with a BLX from thumb mode, and 9592 * the following 32-bit word contains the target rPC value. 9593 * Note that lr (r14) will have its low-order bit set to denote 9594 * its thumb-mode origin. 9595 * 9596 * We'll need to stash our lr origin away, recover the new 9597 * target and then check to see if there is a translation available 9598 * for our new target. If so, we do a translation chain and 9599 * go back to native execution. Otherwise, it's back to the 9600 * interpreter (after treating this entry as a potential 9601 * trace start). 9602 */ 9603 .global dvmJitToInterpNormal 9604dvmJitToInterpNormal: 9605 ldr rPC,[lr, #-1] @ get our target PC 9606 add rINST,lr,#-5 @ save start of chain branch 9607#ifdef EXIT_STATS 9608 bl dvmBumpNormal 9609#endif 9610 mov r0,rPC 9611 bl dvmJitGetCodeAddr @ Is there a translation? 9612 cmp r0,#0 9613 beq toInterpreter @ go if not, otherwise do chain 9614 mov r1,rINST 9615 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9616 mov r1, rPC @ arg1 of translation may need this 9617 mov lr, #0 @ in case target is HANDLER_INTERPRET 9618 cmp r0,#0 @ successful chain? 9619 bxne r0 @ continue native execution 9620 b toInterpreter @ didn't chain - resume with interpreter 9621 9622/* 9623 * Return from the translation cache to the interpreter to do method invocation. 9624 * Check if translation exists for the callee, but don't chain to it. 9625 */ 9626 .global dvmJitToInterpNoChain 9627dvmJitToInterpNoChain: 9628#ifdef EXIT_STATS 9629 bl dvmBumpNoChain 9630#endif 9631 mov r0,rPC 9632 bl dvmJitGetCodeAddr @ Is there a translation? 9633 mov r1, rPC @ arg1 of translation may need this 9634 mov lr, #0 @ in case target is HANDLER_INTERPRET 9635 cmp r0,#0 9636 bxne r0 @ continue native execution if so 9637#endif 9638 9639/* 9640 * No translation, restore interpreter regs and start interpreting. 9641 * rGLUE & rFP were preserved in the translated code, and rPC has 9642 * already been restored by the time we get here. We'll need to set 9643 * up rIBASE & rINST, and load the address of the JitTable into r0. 9644 */ 9645toInterpreter: 9646 EXPORT_PC() 9647 adrl rIBASE, dvmAsmInstructionStart 9648 FETCH_INST() 9649 GET_JIT_PROF_TABLE(r0) 9650 @ NOTE: intended fallthrough 9651/* 9652 * Common code to update potential trace start counter, and initiate 9653 * a trace-build if appropriate. On entry, rPC should point to the 9654 * next instruction to execute, and rINST should be already loaded with 9655 * the next opcode word, and r0 holds a pointer to the jit profile 9656 * table (pJitProfTable). 9657 */ 9658common_testUpdateProfile: 9659 cmp r0,#0 9660 GET_INST_OPCODE(ip) 9661 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9662 9663common_updateProfile: 9664 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9665 lsl r3,r3,#23 @ shift out excess 511 9666 ldrb r1,[r0,r3,lsr #23] @ get counter 9667 GET_INST_OPCODE(ip) 9668 subs r1,r1,#1 @ decrement counter 9669 strb r1,[r0,r3,lsr #23] @ and store it 9670 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9671 9672/* 9673 * Here, we switch to the debug interpreter to request 9674 * trace selection. First, though, check to see if there 9675 * is already a native translation in place (and, if so, 9676 * jump to it now). 9677 */ 9678 mov r1,#255 9679 strb r1,[r0,r3,lsr #23] @ reset counter 9680 EXPORT_PC() 9681 mov r0,rPC 9682 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9683 mov r1, rPC @ arg1 of translation may need this 9684 mov lr, #0 @ in case target is HANDLER_INTERPRET 9685 cmp r0,#0 9686#if !defined(WITH_SELF_VERIFICATION) 9687 bxne r0 @ jump to the translation 9688#else 9689 beq common_selectTrace 9690 /* 9691 * At this point, we have a target translation. However, if 9692 * that translation is actually the interpret-only pseudo-translation 9693 * we want to treat it the same as no translation. 9694 */ 9695 mov r10, r0 @ save target 9696 bl dvmCompilerGetInterpretTemplate 9697 cmp r0, r10 @ special case? 9698 bne dvmJitSelfVerificationStart @ set up self verification 9699 GET_INST_OPCODE(ip) 9700 GOTO_OPCODE(ip) 9701 /* no return */ 9702#endif 9703 9704common_selectTrace: 9705 mov r2,#kJitTSelectRequest @ ask for trace selection 9706 str r2,[rGLUE,#offGlue_jitState] 9707 mov r2,#kInterpEntryInstr @ normal entry reason 9708 str r2,[rGLUE,#offGlue_entryPoint] 9709 mov r1,#1 @ set changeInterp 9710 b common_gotoBail 9711 9712#if defined(WITH_SELF_VERIFICATION) 9713/* 9714 * Save PC and registers to shadow memory for self verification mode 9715 * before jumping to native translation. 9716 * On entry, r10 contains the address of the target translation. 9717 */ 9718dvmJitSelfVerificationStart: 9719 mov r0,rPC @ r0<- program counter 9720 mov r1,rFP @ r1<- frame pointer 9721 mov r2,rGLUE @ r2<- InterpState pointer 9722 mov r3,r10 @ r3<- target translation 9723 bl dvmSelfVerificationSaveState @ save registers to shadow space 9724 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9725 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9726 bx r10 @ jump to the translation 9727 9728/* 9729 * Restore PC, registers, and interpState to original values 9730 * before jumping back to the interpreter. 9731 */ 9732dvmJitSelfVerificationEnd: 9733 mov r1,rFP @ pass ending fp 9734 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9735 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9736 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9737 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9738 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9739 cmp r1,#0 @ check for punt condition 9740 beq 1f 9741 mov r2,#kJitSelfVerification @ ask for self verification 9742 str r2,[rGLUE,#offGlue_jitState] 9743 mov r2,#kInterpEntryInstr @ normal entry reason 9744 str r2,[rGLUE,#offGlue_entryPoint] 9745 mov r1,#1 @ set changeInterp 9746 b common_gotoBail 9747 97481: @ exit to interpreter without check 9749 EXPORT_PC() 9750 adrl rIBASE, dvmAsmInstructionStart 9751 FETCH_INST() 9752 GET_INST_OPCODE(ip) 9753 GOTO_OPCODE(ip) 9754#endif 9755 9756#endif 9757 9758/* 9759 * Common code when a backward branch is taken. 9760 * 9761 * On entry: 9762 * r9 is PC adjustment *in bytes* 9763 */ 9764common_backwardBranch: 9765 mov r0, #kInterpEntryInstr 9766 bl common_periodicChecks 9767#if defined(WITH_JIT) 9768 GET_JIT_PROF_TABLE(r0) 9769 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9770 cmp r0,#0 9771 bne common_updateProfile 9772 GET_INST_OPCODE(ip) 9773 GOTO_OPCODE(ip) 9774#else 9775 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9776 GET_INST_OPCODE(ip) @ extract opcode from rINST 9777 GOTO_OPCODE(ip) @ jump to next instruction 9778#endif 9779 9780 9781/* 9782 * Need to see if the thread needs to be suspended or debugger/profiler 9783 * activity has begun. 9784 * 9785 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9786 * have to do the second ldr. 9787 * 9788 * TODO: reduce this so we're just checking a single location. 9789 * 9790 * On entry: 9791 * r0 is reentry type, e.g. kInterpEntryInstr 9792 * r9 is trampoline PC adjustment *in bytes* 9793 */ 9794common_periodicChecks: 9795 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9796 9797 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending 9798 str r0, [rGLUE, #offGlue_entryPoint] 9799 9800#if defined(WITH_DEBUGGER) 9801 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9802#endif 9803#if defined(WITH_PROFILER) 9804 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9805#endif 9806 9807 ldr r3, [r3] @ r3<- suspendCount (int) 9808 9809#if defined(WITH_DEBUGGER) 9810 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9811#endif 9812#if defined (WITH_PROFILER) 9813 ldr r2, [r2] @ r2<- activeProfilers (int) 9814#endif 9815 9816 cmp r3, #0 @ suspend pending? 9817 bne 2f @ yes, do full suspension check 9818 9819#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9820# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9821 orrs r1, r1, r2 @ r1<- r1 | r2 9822 cmp r1, #0 @ debugger attached or profiler started? 9823# elif defined(WITH_DEBUGGER) 9824 cmp r1, #0 @ debugger attached? 9825# elif defined(WITH_PROFILER) 9826 cmp r2, #0 @ profiler started? 9827# endif 9828 bne 3f @ debugger/profiler, switch interp 9829#endif 9830 9831 bx lr @ nothing to do, return 9832 98332: @ check suspend 9834 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9835 EXPORT_PC() @ need for precise GC 9836 b dvmCheckSuspendPending @ suspend if necessary, then return 9837 98383: @ debugger/profiler enabled, bail out 9839 add rPC, rPC, r9 @ update rPC 9840 mov r1, #1 @ "want switch" = true 9841 b common_gotoBail 9842 9843 9844/* 9845 * The equivalent of "goto bail", this calls through the "bail handler". 9846 * 9847 * State registers will be saved to the "glue" area before bailing. 9848 * 9849 * On entry: 9850 * r1 is "bool changeInterp", indicating if we want to switch to the 9851 * other interpreter or just bail all the way out 9852 */ 9853common_gotoBail: 9854 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9855 mov r0, rGLUE @ r0<- glue ptr 9856 b dvmMterpStdBail @ call(glue, changeInterp) 9857 9858 @add r1, r1, #1 @ using (boolean+1) 9859 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9860 @bl _longjmp @ does not return 9861 @bl common_abort 9862 9863 9864/* 9865 * Common code for method invocation with range. 9866 * 9867 * On entry: 9868 * r0 is "Method* methodToCall", the method we're trying to call 9869 */ 9870common_invokeMethodRange: 9871.LinvokeNewRange: 9872 @ prepare to copy args to "outs" area of current frame 9873 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9874 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9875 beq .LinvokeArgsDone @ if no args, skip the rest 9876 FETCH(r1, 2) @ r1<- CCCC 9877 9878 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9879 @ (very few methods have > 10 args; could unroll for common cases) 9880 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9881 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9882 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98831: ldr r1, [r3], #4 @ val = *fp++ 9884 subs r2, r2, #1 @ count-- 9885 str r1, [r10], #4 @ *outs++ = val 9886 bne 1b @ ...while count != 0 9887 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9888 b .LinvokeArgsDone 9889 9890/* 9891 * Common code for method invocation without range. 9892 * 9893 * On entry: 9894 * r0 is "Method* methodToCall", the method we're trying to call 9895 */ 9896common_invokeMethodNoRange: 9897.LinvokeNewNoRange: 9898 @ prepare to copy args to "outs" area of current frame 9899 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9900 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9901 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9902 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9903 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9904 beq .LinvokeArgsDone 9905 9906 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9907.LinvokeNonRange: 9908 rsb r2, r2, #5 @ r2<- 5-r2 9909 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9910 bl common_abort @ (skipped due to ARM prefetch) 99115: and ip, rINST, #0x0f00 @ isolate A 9912 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9913 mov r0, r0 @ nop 9914 str r2, [r10, #-4]! @ *--outs = vA 99154: and ip, r1, #0xf000 @ isolate G 9916 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9917 mov r0, r0 @ nop 9918 str r2, [r10, #-4]! @ *--outs = vG 99193: and ip, r1, #0x0f00 @ isolate F 9920 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9921 mov r0, r0 @ nop 9922 str r2, [r10, #-4]! @ *--outs = vF 99232: and ip, r1, #0x00f0 @ isolate E 9924 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9925 mov r0, r0 @ nop 9926 str r2, [r10, #-4]! @ *--outs = vE 99271: and ip, r1, #0x000f @ isolate D 9928 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9929 mov r0, r0 @ nop 9930 str r2, [r10, #-4]! @ *--outs = vD 99310: @ fall through to .LinvokeArgsDone 9932 9933.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9934 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9935 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9936 @ find space for the new stack frame, check for overflow 9937 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9938 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9939 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9940@ bl common_dumpRegs 9941 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9942 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9943 cmp r3, r9 @ bottom < interpStackEnd? 9944 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9945 blt .LstackOverflow @ yes, this frame will overflow stack 9946 9947 @ set up newSaveArea 9948#ifdef EASY_GDB 9949 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9950 str ip, [r10, #offStackSaveArea_prevSave] 9951#endif 9952 str rFP, [r10, #offStackSaveArea_prevFrame] 9953 str rPC, [r10, #offStackSaveArea_savedPc] 9954#if defined(WITH_JIT) 9955 mov r9, #0 9956 str r9, [r10, #offStackSaveArea_returnAddr] 9957#endif 9958 str r0, [r10, #offStackSaveArea_method] 9959 tst r3, #ACC_NATIVE 9960 bne .LinvokeNative 9961 9962 /* 9963 stmfd sp!, {r0-r3} 9964 bl common_printNewline 9965 mov r0, rFP 9966 mov r1, #0 9967 bl dvmDumpFp 9968 ldmfd sp!, {r0-r3} 9969 stmfd sp!, {r0-r3} 9970 mov r0, r1 9971 mov r1, r10 9972 bl dvmDumpFp 9973 bl common_printNewline 9974 ldmfd sp!, {r0-r3} 9975 */ 9976 9977 ldrh r9, [r2] @ r9 <- load INST from new PC 9978 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9979 mov rPC, r2 @ publish new rPC 9980 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9981 9982 @ Update "glue" values for the new method 9983 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9984 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9985 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9986#if defined(WITH_JIT) 9987 GET_JIT_PROF_TABLE(r0) 9988 mov rFP, r1 @ fp = newFp 9989 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9990 mov rINST, r9 @ publish new rINST 9991 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9992 cmp r0,#0 9993 bne common_updateProfile 9994 GOTO_OPCODE(ip) @ jump to next instruction 9995#else 9996 mov rFP, r1 @ fp = newFp 9997 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9998 mov rINST, r9 @ publish new rINST 9999 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10000 GOTO_OPCODE(ip) @ jump to next instruction 10001#endif 10002 10003.LinvokeNative: 10004 @ Prep for the native call 10005 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10006 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10007 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10008 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10009 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10010 mov r9, r3 @ r9<- glue->self (preserve) 10011 10012 mov r2, r0 @ r2<- methodToCall 10013 mov r0, r1 @ r0<- newFp (points to args) 10014 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10015 10016#ifdef ASSIST_DEBUGGER 10017 /* insert fake function header to help gdb find the stack frame */ 10018 b .Lskip 10019 .type dalvik_mterp, %function 10020dalvik_mterp: 10021 .fnstart 10022 MTERP_ENTRY1 10023 MTERP_ENTRY2 10024.Lskip: 10025#endif 10026 10027 @mov lr, pc @ set return addr 10028 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10029 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10030 10031 @ native return; r9=self, r10=newSaveArea 10032 @ equivalent to dvmPopJniLocals 10033 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10034 ldr r1, [r9, #offThread_exception] @ check for exception 10035 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10036 cmp r1, #0 @ null? 10037 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10038 bne common_exceptionThrown @ no, handle exception 10039 10040 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10041 GET_INST_OPCODE(ip) @ extract opcode from rINST 10042 GOTO_OPCODE(ip) @ jump to next instruction 10043 10044.LstackOverflow: @ r0=methodToCall 10045 mov r1, r0 @ r1<- methodToCall 10046 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10047 bl dvmHandleStackOverflow 10048 b common_exceptionThrown 10049#ifdef ASSIST_DEBUGGER 10050 .fnend 10051#endif 10052 10053 10054 /* 10055 * Common code for method invocation, calling through "glue code". 10056 * 10057 * TODO: now that we have range and non-range invoke handlers, this 10058 * needs to be split into two. Maybe just create entry points 10059 * that set r9 and jump here? 10060 * 10061 * On entry: 10062 * r0 is "Method* methodToCall", the method we're trying to call 10063 * r9 is "bool methodCallRange", indicating if this is a /range variant 10064 */ 10065 .if 0 10066.LinvokeOld: 10067 sub sp, sp, #8 @ space for args + pad 10068 FETCH(ip, 2) @ ip<- FEDC or CCCC 10069 mov r2, r0 @ A2<- methodToCall 10070 mov r0, rGLUE @ A0<- glue 10071 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10072 mov r1, r9 @ A1<- methodCallRange 10073 mov r3, rINST, lsr #8 @ A3<- AA 10074 str ip, [sp, #0] @ A4<- ip 10075 bl dvmMterp_invokeMethod @ call the C invokeMethod 10076 add sp, sp, #8 @ remove arg area 10077 b common_resumeAfterGlueCall @ continue to next instruction 10078 .endif 10079 10080 10081 10082/* 10083 * Common code for handling a return instruction. 10084 * 10085 * This does not return. 10086 */ 10087common_returnFromMethod: 10088.LreturnNew: 10089 mov r0, #kInterpEntryReturn 10090 mov r9, #0 10091 bl common_periodicChecks 10092 10093 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10094 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10095 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10096 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10097 @ r2<- method we're returning to 10098 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10099 cmp r2, #0 @ is this a break frame? 10100 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10101 mov r1, #0 @ "want switch" = false 10102 beq common_gotoBail @ break frame, bail out completely 10103 10104 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10105 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10106 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10107 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10108#if defined(WITH_JIT) 10109 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr 10110 GET_JIT_PROF_TABLE(r0) 10111 mov rPC, r9 @ publish new rPC 10112 str r1, [rGLUE, #offGlue_methodClassDex] 10113 cmp r3, #0 @ caller is compiled code 10114 blxne r3 10115 GET_INST_OPCODE(ip) @ extract opcode from rINST 10116 cmp r0,#0 10117 bne common_updateProfile 10118 GOTO_OPCODE(ip) @ jump to next instruction 10119#else 10120 GET_INST_OPCODE(ip) @ extract opcode from rINST 10121 mov rPC, r9 @ publish new rPC 10122 str r1, [rGLUE, #offGlue_methodClassDex] 10123 GOTO_OPCODE(ip) @ jump to next instruction 10124#endif 10125 10126 /* 10127 * Return handling, calls through "glue code". 10128 */ 10129 .if 0 10130.LreturnOld: 10131 SAVE_PC_FP_TO_GLUE() @ export state 10132 mov r0, rGLUE @ arg to function 10133 bl dvmMterp_returnFromMethod 10134 b common_resumeAfterGlueCall 10135 .endif 10136 10137 10138/* 10139 * Somebody has thrown an exception. Handle it. 10140 * 10141 * If the exception processing code returns to us (instead of falling 10142 * out of the interpreter), continue with whatever the next instruction 10143 * now happens to be. 10144 * 10145 * This does not return. 10146 */ 10147 .global dvmMterpCommonExceptionThrown 10148dvmMterpCommonExceptionThrown: 10149common_exceptionThrown: 10150.LexceptionNew: 10151 mov r0, #kInterpEntryThrow 10152 mov r9, #0 10153 bl common_periodicChecks 10154 10155#if defined(WITH_JIT) 10156 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 10157 str r2,[rGLUE,#offGlue_jitState] 10158#endif 10159 10160 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10161 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10162 mov r1, r10 @ r1<- self 10163 mov r0, r9 @ r0<- exception 10164 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10165 mov r3, #0 @ r3<- NULL 10166 str r3, [r10, #offThread_exception] @ self->exception = NULL 10167 10168 /* set up args and a local for "&fp" */ 10169 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10170 str rFP, [sp, #-4]! @ *--sp = fp 10171 mov ip, sp @ ip<- &fp 10172 mov r3, #0 @ r3<- false 10173 str ip, [sp, #-4]! @ *--sp = &fp 10174 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10175 mov r0, r10 @ r0<- self 10176 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10177 mov r2, r9 @ r2<- exception 10178 sub r1, rPC, r1 @ r1<- pc - method->insns 10179 mov r1, r1, asr #1 @ r1<- offset in code units 10180 10181 /* call, r0 gets catchRelPc (a code-unit offset) */ 10182 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10183 10184 /* fix earlier stack overflow if necessary; may trash rFP */ 10185 ldrb r1, [r10, #offThread_stackOverflowed] 10186 cmp r1, #0 @ did we overflow earlier? 10187 beq 1f @ no, skip ahead 10188 mov rFP, r0 @ save relPc result in rFP 10189 mov r0, r10 @ r0<- self 10190 bl dvmCleanupStackOverflow @ call(self) 10191 mov r0, rFP @ restore result 101921: 10193 10194 /* update frame pointer and check result from dvmFindCatchBlock */ 10195 ldr rFP, [sp, #4] @ retrieve the updated rFP 10196 cmp r0, #0 @ is catchRelPc < 0? 10197 add sp, sp, #8 @ restore stack 10198 bmi .LnotCaughtLocally 10199 10200 /* adjust locals to match self->curFrame and updated PC */ 10201 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10202 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10203 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10204 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10205 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10206 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10207 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10208 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10209 10210 /* release the tracked alloc on the exception */ 10211 mov r0, r9 @ r0<- exception 10212 mov r1, r10 @ r1<- self 10213 bl dvmReleaseTrackedAlloc @ release the exception 10214 10215 /* restore the exception if the handler wants it */ 10216 FETCH_INST() @ load rINST from rPC 10217 GET_INST_OPCODE(ip) @ extract opcode from rINST 10218 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10219 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10220 GOTO_OPCODE(ip) @ jump to next instruction 10221 10222.LnotCaughtLocally: @ r9=exception, r10=self 10223 /* fix stack overflow if necessary */ 10224 ldrb r1, [r10, #offThread_stackOverflowed] 10225 cmp r1, #0 @ did we overflow earlier? 10226 movne r0, r10 @ if yes: r0<- self 10227 blne dvmCleanupStackOverflow @ if yes: call(self) 10228 10229 @ may want to show "not caught locally" debug messages here 10230#if DVM_SHOW_EXCEPTION >= 2 10231 /* call __android_log_print(prio, tag, format, ...) */ 10232 /* "Exception %s from %s:%d not caught locally" */ 10233 @ dvmLineNumFromPC(method, pc - method->insns) 10234 ldr r0, [rGLUE, #offGlue_method] 10235 ldr r1, [r0, #offMethod_insns] 10236 sub r1, rPC, r1 10237 asr r1, r1, #1 10238 bl dvmLineNumFromPC 10239 str r0, [sp, #-4]! 10240 @ dvmGetMethodSourceFile(method) 10241 ldr r0, [rGLUE, #offGlue_method] 10242 bl dvmGetMethodSourceFile 10243 str r0, [sp, #-4]! 10244 @ exception->clazz->descriptor 10245 ldr r3, [r9, #offObject_clazz] 10246 ldr r3, [r3, #offClassObject_descriptor] 10247 @ 10248 ldr r2, strExceptionNotCaughtLocally 10249 ldr r1, strLogTag 10250 mov r0, #3 @ LOG_DEBUG 10251 bl __android_log_print 10252#endif 10253 str r9, [r10, #offThread_exception] @ restore exception 10254 mov r0, r9 @ r0<- exception 10255 mov r1, r10 @ r1<- self 10256 bl dvmReleaseTrackedAlloc @ release the exception 10257 mov r1, #0 @ "want switch" = false 10258 b common_gotoBail @ bail out 10259 10260 10261 /* 10262 * Exception handling, calls through "glue code". 10263 */ 10264 .if 0 10265.LexceptionOld: 10266 SAVE_PC_FP_TO_GLUE() @ export state 10267 mov r0, rGLUE @ arg to function 10268 bl dvmMterp_exceptionThrown 10269 b common_resumeAfterGlueCall 10270 .endif 10271 10272 10273/* 10274 * After returning from a "glued" function, pull out the updated 10275 * values and start executing at the next instruction. 10276 */ 10277common_resumeAfterGlueCall: 10278 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10279 FETCH_INST() @ load rINST from rPC 10280 GET_INST_OPCODE(ip) @ extract opcode from rINST 10281 GOTO_OPCODE(ip) @ jump to next instruction 10282 10283/* 10284 * Invalid array index. 10285 */ 10286common_errArrayIndex: 10287 EXPORT_PC() 10288 ldr r0, strArrayIndexException 10289 mov r1, #0 10290 bl dvmThrowException 10291 b common_exceptionThrown 10292 10293/* 10294 * Invalid array value. 10295 */ 10296common_errArrayStore: 10297 EXPORT_PC() 10298 ldr r0, strArrayStoreException 10299 mov r1, #0 10300 bl dvmThrowException 10301 b common_exceptionThrown 10302 10303/* 10304 * Integer divide or mod by zero. 10305 */ 10306common_errDivideByZero: 10307 EXPORT_PC() 10308 ldr r0, strArithmeticException 10309 ldr r1, strDivideByZero 10310 bl dvmThrowException 10311 b common_exceptionThrown 10312 10313/* 10314 * Attempt to allocate an array with a negative size. 10315 */ 10316common_errNegativeArraySize: 10317 EXPORT_PC() 10318 ldr r0, strNegativeArraySizeException 10319 mov r1, #0 10320 bl dvmThrowException 10321 b common_exceptionThrown 10322 10323/* 10324 * Invocation of a non-existent method. 10325 */ 10326common_errNoSuchMethod: 10327 EXPORT_PC() 10328 ldr r0, strNoSuchMethodError 10329 mov r1, #0 10330 bl dvmThrowException 10331 b common_exceptionThrown 10332 10333/* 10334 * We encountered a null object when we weren't expecting one. We 10335 * export the PC, throw a NullPointerException, and goto the exception 10336 * processing code. 10337 */ 10338common_errNullObject: 10339 EXPORT_PC() 10340 ldr r0, strNullPointerException 10341 mov r1, #0 10342 bl dvmThrowException 10343 b common_exceptionThrown 10344 10345/* 10346 * For debugging, cause an immediate fault. The source address will 10347 * be in lr (use a bl instruction to jump here). 10348 */ 10349common_abort: 10350 ldr pc, .LdeadFood 10351.LdeadFood: 10352 .word 0xdeadf00d 10353 10354/* 10355 * Spit out a "we were here", preserving all registers. (The attempt 10356 * to save ip won't work, but we need to save an even number of 10357 * registers for EABI 64-bit stack alignment.) 10358 */ 10359 .macro SQUEAK num 10360common_squeak\num: 10361 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10362 ldr r0, strSqueak 10363 mov r1, #\num 10364 bl printf 10365 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10366 bx lr 10367 .endm 10368 10369 SQUEAK 0 10370 SQUEAK 1 10371 SQUEAK 2 10372 SQUEAK 3 10373 SQUEAK 4 10374 SQUEAK 5 10375 10376/* 10377 * Spit out the number in r0, preserving registers. 10378 */ 10379common_printNum: 10380 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10381 mov r1, r0 10382 ldr r0, strSqueak 10383 bl printf 10384 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10385 bx lr 10386 10387/* 10388 * Print a newline, preserving registers. 10389 */ 10390common_printNewline: 10391 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10392 ldr r0, strNewline 10393 bl printf 10394 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10395 bx lr 10396 10397 /* 10398 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10399 */ 10400common_printHex: 10401 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10402 mov r1, r0 10403 ldr r0, strPrintHex 10404 bl printf 10405 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10406 bx lr 10407 10408/* 10409 * Print the 64-bit quantity in r0-r1, preserving registers. 10410 */ 10411common_printLong: 10412 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10413 mov r3, r1 10414 mov r2, r0 10415 ldr r0, strPrintLong 10416 bl printf 10417 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10418 bx lr 10419 10420/* 10421 * Print full method info. Pass the Method* in r0. Preserves regs. 10422 */ 10423common_printMethod: 10424 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10425 bl dvmMterpPrintMethod 10426 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10427 bx lr 10428 10429/* 10430 * Call a C helper function that dumps regs and possibly some 10431 * additional info. Requires the C function to be compiled in. 10432 */ 10433 .if 0 10434common_dumpRegs: 10435 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10436 bl dvmMterpDumpArmRegs 10437 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10438 bx lr 10439 .endif 10440 10441#if 0 10442/* 10443 * Experiment on VFP mode. 10444 * 10445 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10446 * 10447 * Updates the bits specified by "mask", setting them to the values in "val". 10448 */ 10449setFPSCR: 10450 and r0, r0, r1 @ make sure no stray bits are set 10451 fmrx r2, fpscr @ get VFP reg 10452 mvn r1, r1 @ bit-invert mask 10453 and r2, r2, r1 @ clear masked bits 10454 orr r2, r2, r0 @ set specified bits 10455 fmxr fpscr, r2 @ set VFP reg 10456 mov r0, r2 @ return new value 10457 bx lr 10458 10459 .align 2 10460 .global dvmConfigureFP 10461 .type dvmConfigureFP, %function 10462dvmConfigureFP: 10463 stmfd sp!, {ip, lr} 10464 /* 0x03000000 sets DN/FZ */ 10465 /* 0x00009f00 clears the six exception enable flags */ 10466 bl common_squeak0 10467 mov r0, #0x03000000 @ r0<- 0x03000000 10468 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10469 bl setFPSCR 10470 ldmfd sp!, {ip, pc} 10471#endif 10472 10473 10474/* 10475 * String references, must be close to the code that uses them. 10476 */ 10477 .align 2 10478strArithmeticException: 10479 .word .LstrArithmeticException 10480strArrayIndexException: 10481 .word .LstrArrayIndexException 10482strArrayStoreException: 10483 .word .LstrArrayStoreException 10484strDivideByZero: 10485 .word .LstrDivideByZero 10486strNegativeArraySizeException: 10487 .word .LstrNegativeArraySizeException 10488strNoSuchMethodError: 10489 .word .LstrNoSuchMethodError 10490strNullPointerException: 10491 .word .LstrNullPointerException 10492 10493strLogTag: 10494 .word .LstrLogTag 10495strExceptionNotCaughtLocally: 10496 .word .LstrExceptionNotCaughtLocally 10497 10498strNewline: 10499 .word .LstrNewline 10500strSqueak: 10501 .word .LstrSqueak 10502strPrintHex: 10503 .word .LstrPrintHex 10504strPrintLong: 10505 .word .LstrPrintLong 10506 10507/* 10508 * Zero-terminated ASCII string data. 10509 * 10510 * On ARM we have two choices: do like gcc does, and LDR from a .word 10511 * with the address, or use an ADR pseudo-op to get the address 10512 * directly. ADR saves 4 bytes and an indirection, but it's using a 10513 * PC-relative addressing mode and hence has a limited range, which 10514 * makes it not work well with mergeable string sections. 10515 */ 10516 .section .rodata.str1.4,"aMS",%progbits,1 10517 10518.LstrBadEntryPoint: 10519 .asciz "Bad entry point %d\n" 10520.LstrArithmeticException: 10521 .asciz "Ljava/lang/ArithmeticException;" 10522.LstrArrayIndexException: 10523 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10524.LstrArrayStoreException: 10525 .asciz "Ljava/lang/ArrayStoreException;" 10526.LstrClassCastException: 10527 .asciz "Ljava/lang/ClassCastException;" 10528.LstrDivideByZero: 10529 .asciz "divide by zero" 10530.LstrFilledNewArrayNotImpl: 10531 .asciz "filled-new-array only implemented for objects and 'int'" 10532.LstrInternalError: 10533 .asciz "Ljava/lang/InternalError;" 10534.LstrInstantiationError: 10535 .asciz "Ljava/lang/InstantiationError;" 10536.LstrNegativeArraySizeException: 10537 .asciz "Ljava/lang/NegativeArraySizeException;" 10538.LstrNoSuchMethodError: 10539 .asciz "Ljava/lang/NoSuchMethodError;" 10540.LstrNullPointerException: 10541 .asciz "Ljava/lang/NullPointerException;" 10542 10543.LstrLogTag: 10544 .asciz "mterp" 10545.LstrExceptionNotCaughtLocally: 10546 .asciz "Exception %s from %s:%d not caught locally\n" 10547 10548.LstrNewline: 10549 .asciz "\n" 10550.LstrSqueak: 10551 .asciz "<%d>" 10552.LstrPrintHex: 10553 .asciz "<0x%x>" 10554.LstrPrintLong: 10555 .asciz "<%lld>" 10556 10557 10558