InterpAsm-armv5te.S revision 2717622484eb0f7ad537275f7260b2f93324eda2
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 ldr r2, .LOP_DOUBLE_TO_INT_maxlo @ (double)maxint, lo 4025 ldr r3, .LOP_DOUBLE_TO_INT_maxhi @ (double)maxint, hi 4026 sub sp, sp, #4 @ align for EABI 4027 mov r4, r0 @ save r0 4028 mov r5, r1 @ and r1 4029 bl __aeabi_dcmpge @ is arg >= maxint? 4030 cmp r0, #0 @ nonzero == yes 4031 mvnne r0, #0x80000000 @ return maxint (7fffffff) 4032 bne 1f 4033 4034 mov r0, r4 @ recover arg 4035 mov r1, r5 4036 ldr r3, .LOP_DOUBLE_TO_INT_min @ (double)minint, hi 4037 mov r2, #0 @ (double)minint, lo 4038 bl __aeabi_dcmple @ is arg <= minint? 4039 cmp r0, #0 @ nonzero == yes 4040 movne r0, #0x80000000 @ return minint (80000000) 4041 bne 1f 4042 4043 mov r0, r4 @ recover arg 4044 mov r1, r5 4045 mov r2, r4 @ compare against self 4046 mov r3, r5 4047 bl __aeabi_dcmpeq @ is arg == self? 4048 cmp r0, #0 @ zero == no 4049 beq 1f @ return zero for NaN 4050 4051 mov r0, r4 @ recover arg 4052 mov r1, r5 4053 bl __aeabi_d2iz @ convert double to int 4054 40551: 4056 add sp, sp, #4 4057 ldmfd sp!, {r4, r5, pc} 4058 4059.LOP_DOUBLE_TO_INT_maxlo: 4060 .word 0xffc00000 @ maxint, as a double (low word) 4061.LOP_DOUBLE_TO_INT_maxhi: 4062 .word 0x41dfffff @ maxint, as a double (high word) 4063.LOP_DOUBLE_TO_INT_min: 4064 .word 0xc1e00000 @ minint, as a double (high word) 4065#endif 4066 4067 4068/* ------------------------------ */ 4069 .balign 64 4070.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 4071/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 4072@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 4073/* File: armv5te/unopWide.S */ 4074 /* 4075 * Generic 64-bit unary operation. Provide an "instr" line that 4076 * specifies an instruction that performs "result = op r0/r1". 4077 * This could be an ARM instruction or a function call. 4078 * 4079 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 4080 */ 4081 /* unop vA, vB */ 4082 mov r9, rINST, lsr #8 @ r9<- A+ 4083 mov r3, rINST, lsr #12 @ r3<- B 4084 and r9, r9, #15 4085 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4086 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 4087 ldmia r3, {r0-r1} @ r0/r1<- vAA 4088 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4089 @ optional op; may set condition codes 4090 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 4091 GET_INST_OPCODE(ip) @ extract opcode from rINST 4092 stmia r9, {r0-r1} @ vAA<- r0/r1 4093 GOTO_OPCODE(ip) @ jump to next instruction 4094 /* 12-13 instructions */ 4095 4096 4097 4098 4099/* ------------------------------ */ 4100 .balign 64 4101.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 4102/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */ 4103/* File: armv5te/unopNarrower.S */ 4104 /* 4105 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 4106 * that specifies an instruction that performs "result = op r0/r1", where 4107 * "result" is a 32-bit quantity in r0. 4108 * 4109 * For: long-to-float, double-to-int, double-to-float 4110 * 4111 * (This would work for long-to-int, but that instruction is actually 4112 * an exact match for OP_MOVE.) 4113 */ 4114 /* unop vA, vB */ 4115 mov r3, rINST, lsr #12 @ r3<- B 4116 mov r9, rINST, lsr #8 @ r9<- A+ 4117 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 4118 and r9, r9, #15 4119 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 4120 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4121 @ optional op; may set condition codes 4122 bl __aeabi_d2f @ r0<- op, r0-r3 changed 4123 GET_INST_OPCODE(ip) @ extract opcode from rINST 4124 SET_VREG(r0, r9) @ vA<- r0 4125 GOTO_OPCODE(ip) @ jump to next instruction 4126 /* 10-11 instructions */ 4127 4128 4129/* ------------------------------ */ 4130 .balign 64 4131.L_OP_INT_TO_BYTE: /* 0x8d */ 4132/* File: armv5te/OP_INT_TO_BYTE.S */ 4133/* File: armv5te/unop.S */ 4134 /* 4135 * Generic 32-bit unary operation. Provide an "instr" line that 4136 * specifies an instruction that performs "result = op r0". 4137 * This could be an ARM instruction or a function call. 4138 * 4139 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4140 * int-to-byte, int-to-char, int-to-short 4141 */ 4142 /* unop vA, vB */ 4143 mov r3, rINST, lsr #12 @ r3<- B 4144 mov r9, rINST, lsr #8 @ r9<- A+ 4145 GET_VREG(r0, r3) @ r0<- vB 4146 and r9, r9, #15 4147 mov r0, r0, asl #24 @ optional op; may set condition codes 4148 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4149 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4150 GET_INST_OPCODE(ip) @ extract opcode from rINST 4151 SET_VREG(r0, r9) @ vAA<- r0 4152 GOTO_OPCODE(ip) @ jump to next instruction 4153 /* 9-10 instructions */ 4154 4155 4156/* ------------------------------ */ 4157 .balign 64 4158.L_OP_INT_TO_CHAR: /* 0x8e */ 4159/* File: armv5te/OP_INT_TO_CHAR.S */ 4160/* File: armv5te/unop.S */ 4161 /* 4162 * Generic 32-bit unary operation. Provide an "instr" line that 4163 * specifies an instruction that performs "result = op r0". 4164 * This could be an ARM instruction or a function call. 4165 * 4166 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4167 * int-to-byte, int-to-char, int-to-short 4168 */ 4169 /* unop vA, vB */ 4170 mov r3, rINST, lsr #12 @ r3<- B 4171 mov r9, rINST, lsr #8 @ r9<- A+ 4172 GET_VREG(r0, r3) @ r0<- vB 4173 and r9, r9, #15 4174 mov r0, r0, asl #16 @ optional op; may set condition codes 4175 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4176 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4177 GET_INST_OPCODE(ip) @ extract opcode from rINST 4178 SET_VREG(r0, r9) @ vAA<- r0 4179 GOTO_OPCODE(ip) @ jump to next instruction 4180 /* 9-10 instructions */ 4181 4182 4183/* ------------------------------ */ 4184 .balign 64 4185.L_OP_INT_TO_SHORT: /* 0x8f */ 4186/* File: armv5te/OP_INT_TO_SHORT.S */ 4187/* File: armv5te/unop.S */ 4188 /* 4189 * Generic 32-bit unary operation. Provide an "instr" line that 4190 * specifies an instruction that performs "result = op r0". 4191 * This could be an ARM instruction or a function call. 4192 * 4193 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4194 * int-to-byte, int-to-char, int-to-short 4195 */ 4196 /* unop vA, vB */ 4197 mov r3, rINST, lsr #12 @ r3<- B 4198 mov r9, rINST, lsr #8 @ r9<- A+ 4199 GET_VREG(r0, r3) @ r0<- vB 4200 and r9, r9, #15 4201 mov r0, r0, asl #16 @ optional op; may set condition codes 4202 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4203 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4204 GET_INST_OPCODE(ip) @ extract opcode from rINST 4205 SET_VREG(r0, r9) @ vAA<- r0 4206 GOTO_OPCODE(ip) @ jump to next instruction 4207 /* 9-10 instructions */ 4208 4209 4210/* ------------------------------ */ 4211 .balign 64 4212.L_OP_ADD_INT: /* 0x90 */ 4213/* File: armv5te/OP_ADD_INT.S */ 4214/* File: armv5te/binop.S */ 4215 /* 4216 * Generic 32-bit binary operation. Provide an "instr" line that 4217 * specifies an instruction that performs "result = r0 op r1". 4218 * This could be an ARM instruction or a function call. (If the result 4219 * comes back in a register other than r0, you can override "result".) 4220 * 4221 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4222 * vCC (r1). Useful for integer division and modulus. Note that we 4223 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4224 * handles it correctly. 4225 * 4226 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4227 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4228 * mul-float, div-float, rem-float 4229 */ 4230 /* binop vAA, vBB, vCC */ 4231 FETCH(r0, 1) @ r0<- CCBB 4232 mov r9, rINST, lsr #8 @ r9<- AA 4233 mov r3, r0, lsr #8 @ r3<- CC 4234 and r2, r0, #255 @ r2<- BB 4235 GET_VREG(r1, r3) @ r1<- vCC 4236 GET_VREG(r0, r2) @ r0<- vBB 4237 .if 0 4238 cmp r1, #0 @ is second operand zero? 4239 beq common_errDivideByZero 4240 .endif 4241 4242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4243 @ optional op; may set condition codes 4244 add r0, r0, r1 @ r0<- op, r0-r3 changed 4245 GET_INST_OPCODE(ip) @ extract opcode from rINST 4246 SET_VREG(r0, r9) @ vAA<- r0 4247 GOTO_OPCODE(ip) @ jump to next instruction 4248 /* 11-14 instructions */ 4249 4250 4251 4252/* ------------------------------ */ 4253 .balign 64 4254.L_OP_SUB_INT: /* 0x91 */ 4255/* File: armv5te/OP_SUB_INT.S */ 4256/* File: armv5te/binop.S */ 4257 /* 4258 * Generic 32-bit binary operation. Provide an "instr" line that 4259 * specifies an instruction that performs "result = r0 op r1". 4260 * This could be an ARM instruction or a function call. (If the result 4261 * comes back in a register other than r0, you can override "result".) 4262 * 4263 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4264 * vCC (r1). Useful for integer division and modulus. Note that we 4265 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4266 * handles it correctly. 4267 * 4268 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4269 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4270 * mul-float, div-float, rem-float 4271 */ 4272 /* binop vAA, vBB, vCC */ 4273 FETCH(r0, 1) @ r0<- CCBB 4274 mov r9, rINST, lsr #8 @ r9<- AA 4275 mov r3, r0, lsr #8 @ r3<- CC 4276 and r2, r0, #255 @ r2<- BB 4277 GET_VREG(r1, r3) @ r1<- vCC 4278 GET_VREG(r0, r2) @ r0<- vBB 4279 .if 0 4280 cmp r1, #0 @ is second operand zero? 4281 beq common_errDivideByZero 4282 .endif 4283 4284 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4285 @ optional op; may set condition codes 4286 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4287 GET_INST_OPCODE(ip) @ extract opcode from rINST 4288 SET_VREG(r0, r9) @ vAA<- r0 4289 GOTO_OPCODE(ip) @ jump to next instruction 4290 /* 11-14 instructions */ 4291 4292 4293 4294/* ------------------------------ */ 4295 .balign 64 4296.L_OP_MUL_INT: /* 0x92 */ 4297/* File: armv5te/OP_MUL_INT.S */ 4298/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4299/* File: armv5te/binop.S */ 4300 /* 4301 * Generic 32-bit binary operation. Provide an "instr" line that 4302 * specifies an instruction that performs "result = r0 op r1". 4303 * This could be an ARM instruction or a function call. (If the result 4304 * comes back in a register other than r0, you can override "result".) 4305 * 4306 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4307 * vCC (r1). Useful for integer division and modulus. Note that we 4308 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4309 * handles it correctly. 4310 * 4311 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4312 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4313 * mul-float, div-float, rem-float 4314 */ 4315 /* binop vAA, vBB, vCC */ 4316 FETCH(r0, 1) @ r0<- CCBB 4317 mov r9, rINST, lsr #8 @ r9<- AA 4318 mov r3, r0, lsr #8 @ r3<- CC 4319 and r2, r0, #255 @ r2<- BB 4320 GET_VREG(r1, r3) @ r1<- vCC 4321 GET_VREG(r0, r2) @ r0<- vBB 4322 .if 0 4323 cmp r1, #0 @ is second operand zero? 4324 beq common_errDivideByZero 4325 .endif 4326 4327 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4328 @ optional op; may set condition codes 4329 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4330 GET_INST_OPCODE(ip) @ extract opcode from rINST 4331 SET_VREG(r0, r9) @ vAA<- r0 4332 GOTO_OPCODE(ip) @ jump to next instruction 4333 /* 11-14 instructions */ 4334 4335 4336 4337/* ------------------------------ */ 4338 .balign 64 4339.L_OP_DIV_INT: /* 0x93 */ 4340/* File: armv5te/OP_DIV_INT.S */ 4341/* File: armv5te/binop.S */ 4342 /* 4343 * Generic 32-bit binary operation. Provide an "instr" line that 4344 * specifies an instruction that performs "result = r0 op r1". 4345 * This could be an ARM instruction or a function call. (If the result 4346 * comes back in a register other than r0, you can override "result".) 4347 * 4348 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4349 * vCC (r1). Useful for integer division and modulus. Note that we 4350 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4351 * handles it correctly. 4352 * 4353 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4354 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4355 * mul-float, div-float, rem-float 4356 */ 4357 /* binop vAA, vBB, vCC */ 4358 FETCH(r0, 1) @ r0<- CCBB 4359 mov r9, rINST, lsr #8 @ r9<- AA 4360 mov r3, r0, lsr #8 @ r3<- CC 4361 and r2, r0, #255 @ r2<- BB 4362 GET_VREG(r1, r3) @ r1<- vCC 4363 GET_VREG(r0, r2) @ r0<- vBB 4364 .if 1 4365 cmp r1, #0 @ is second operand zero? 4366 beq common_errDivideByZero 4367 .endif 4368 4369 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4370 @ optional op; may set condition codes 4371 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4372 GET_INST_OPCODE(ip) @ extract opcode from rINST 4373 SET_VREG(r0, r9) @ vAA<- r0 4374 GOTO_OPCODE(ip) @ jump to next instruction 4375 /* 11-14 instructions */ 4376 4377 4378 4379/* ------------------------------ */ 4380 .balign 64 4381.L_OP_REM_INT: /* 0x94 */ 4382/* File: armv5te/OP_REM_INT.S */ 4383/* idivmod returns quotient in r0 and remainder in r1 */ 4384/* File: armv5te/binop.S */ 4385 /* 4386 * Generic 32-bit binary operation. Provide an "instr" line that 4387 * specifies an instruction that performs "result = r0 op r1". 4388 * This could be an ARM instruction or a function call. (If the result 4389 * comes back in a register other than r0, you can override "result".) 4390 * 4391 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4392 * vCC (r1). Useful for integer division and modulus. Note that we 4393 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4394 * handles it correctly. 4395 * 4396 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4397 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4398 * mul-float, div-float, rem-float 4399 */ 4400 /* binop vAA, vBB, vCC */ 4401 FETCH(r0, 1) @ r0<- CCBB 4402 mov r9, rINST, lsr #8 @ r9<- AA 4403 mov r3, r0, lsr #8 @ r3<- CC 4404 and r2, r0, #255 @ r2<- BB 4405 GET_VREG(r1, r3) @ r1<- vCC 4406 GET_VREG(r0, r2) @ r0<- vBB 4407 .if 1 4408 cmp r1, #0 @ is second operand zero? 4409 beq common_errDivideByZero 4410 .endif 4411 4412 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4413 @ optional op; may set condition codes 4414 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4415 GET_INST_OPCODE(ip) @ extract opcode from rINST 4416 SET_VREG(r1, r9) @ vAA<- r1 4417 GOTO_OPCODE(ip) @ jump to next instruction 4418 /* 11-14 instructions */ 4419 4420 4421 4422/* ------------------------------ */ 4423 .balign 64 4424.L_OP_AND_INT: /* 0x95 */ 4425/* File: armv5te/OP_AND_INT.S */ 4426/* File: armv5te/binop.S */ 4427 /* 4428 * Generic 32-bit binary operation. Provide an "instr" line that 4429 * specifies an instruction that performs "result = r0 op r1". 4430 * This could be an ARM instruction or a function call. (If the result 4431 * comes back in a register other than r0, you can override "result".) 4432 * 4433 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4434 * vCC (r1). Useful for integer division and modulus. Note that we 4435 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4436 * handles it correctly. 4437 * 4438 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4439 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4440 * mul-float, div-float, rem-float 4441 */ 4442 /* binop vAA, vBB, vCC */ 4443 FETCH(r0, 1) @ r0<- CCBB 4444 mov r9, rINST, lsr #8 @ r9<- AA 4445 mov r3, r0, lsr #8 @ r3<- CC 4446 and r2, r0, #255 @ r2<- BB 4447 GET_VREG(r1, r3) @ r1<- vCC 4448 GET_VREG(r0, r2) @ r0<- vBB 4449 .if 0 4450 cmp r1, #0 @ is second operand zero? 4451 beq common_errDivideByZero 4452 .endif 4453 4454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4455 @ optional op; may set condition codes 4456 and r0, r0, r1 @ r0<- op, r0-r3 changed 4457 GET_INST_OPCODE(ip) @ extract opcode from rINST 4458 SET_VREG(r0, r9) @ vAA<- r0 4459 GOTO_OPCODE(ip) @ jump to next instruction 4460 /* 11-14 instructions */ 4461 4462 4463 4464/* ------------------------------ */ 4465 .balign 64 4466.L_OP_OR_INT: /* 0x96 */ 4467/* File: armv5te/OP_OR_INT.S */ 4468/* File: armv5te/binop.S */ 4469 /* 4470 * Generic 32-bit binary operation. Provide an "instr" line that 4471 * specifies an instruction that performs "result = r0 op r1". 4472 * This could be an ARM instruction or a function call. (If the result 4473 * comes back in a register other than r0, you can override "result".) 4474 * 4475 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4476 * vCC (r1). Useful for integer division and modulus. Note that we 4477 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4478 * handles it correctly. 4479 * 4480 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4481 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4482 * mul-float, div-float, rem-float 4483 */ 4484 /* binop vAA, vBB, vCC */ 4485 FETCH(r0, 1) @ r0<- CCBB 4486 mov r9, rINST, lsr #8 @ r9<- AA 4487 mov r3, r0, lsr #8 @ r3<- CC 4488 and r2, r0, #255 @ r2<- BB 4489 GET_VREG(r1, r3) @ r1<- vCC 4490 GET_VREG(r0, r2) @ r0<- vBB 4491 .if 0 4492 cmp r1, #0 @ is second operand zero? 4493 beq common_errDivideByZero 4494 .endif 4495 4496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4497 @ optional op; may set condition codes 4498 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4499 GET_INST_OPCODE(ip) @ extract opcode from rINST 4500 SET_VREG(r0, r9) @ vAA<- r0 4501 GOTO_OPCODE(ip) @ jump to next instruction 4502 /* 11-14 instructions */ 4503 4504 4505 4506/* ------------------------------ */ 4507 .balign 64 4508.L_OP_XOR_INT: /* 0x97 */ 4509/* File: armv5te/OP_XOR_INT.S */ 4510/* File: armv5te/binop.S */ 4511 /* 4512 * Generic 32-bit binary operation. Provide an "instr" line that 4513 * specifies an instruction that performs "result = r0 op r1". 4514 * This could be an ARM instruction or a function call. (If the result 4515 * comes back in a register other than r0, you can override "result".) 4516 * 4517 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4518 * vCC (r1). Useful for integer division and modulus. Note that we 4519 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4520 * handles it correctly. 4521 * 4522 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4523 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4524 * mul-float, div-float, rem-float 4525 */ 4526 /* binop vAA, vBB, vCC */ 4527 FETCH(r0, 1) @ r0<- CCBB 4528 mov r9, rINST, lsr #8 @ r9<- AA 4529 mov r3, r0, lsr #8 @ r3<- CC 4530 and r2, r0, #255 @ r2<- BB 4531 GET_VREG(r1, r3) @ r1<- vCC 4532 GET_VREG(r0, r2) @ r0<- vBB 4533 .if 0 4534 cmp r1, #0 @ is second operand zero? 4535 beq common_errDivideByZero 4536 .endif 4537 4538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4539 @ optional op; may set condition codes 4540 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4541 GET_INST_OPCODE(ip) @ extract opcode from rINST 4542 SET_VREG(r0, r9) @ vAA<- r0 4543 GOTO_OPCODE(ip) @ jump to next instruction 4544 /* 11-14 instructions */ 4545 4546 4547 4548/* ------------------------------ */ 4549 .balign 64 4550.L_OP_SHL_INT: /* 0x98 */ 4551/* File: armv5te/OP_SHL_INT.S */ 4552/* File: armv5te/binop.S */ 4553 /* 4554 * Generic 32-bit binary operation. Provide an "instr" line that 4555 * specifies an instruction that performs "result = r0 op r1". 4556 * This could be an ARM instruction or a function call. (If the result 4557 * comes back in a register other than r0, you can override "result".) 4558 * 4559 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4560 * vCC (r1). Useful for integer division and modulus. Note that we 4561 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4562 * handles it correctly. 4563 * 4564 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4565 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4566 * mul-float, div-float, rem-float 4567 */ 4568 /* binop vAA, vBB, vCC */ 4569 FETCH(r0, 1) @ r0<- CCBB 4570 mov r9, rINST, lsr #8 @ r9<- AA 4571 mov r3, r0, lsr #8 @ r3<- CC 4572 and r2, r0, #255 @ r2<- BB 4573 GET_VREG(r1, r3) @ r1<- vCC 4574 GET_VREG(r0, r2) @ r0<- vBB 4575 .if 0 4576 cmp r1, #0 @ is second operand zero? 4577 beq common_errDivideByZero 4578 .endif 4579 4580 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4581 and r1, r1, #31 @ optional op; may set condition codes 4582 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4583 GET_INST_OPCODE(ip) @ extract opcode from rINST 4584 SET_VREG(r0, r9) @ vAA<- r0 4585 GOTO_OPCODE(ip) @ jump to next instruction 4586 /* 11-14 instructions */ 4587 4588 4589 4590/* ------------------------------ */ 4591 .balign 64 4592.L_OP_SHR_INT: /* 0x99 */ 4593/* File: armv5te/OP_SHR_INT.S */ 4594/* File: armv5te/binop.S */ 4595 /* 4596 * Generic 32-bit binary operation. Provide an "instr" line that 4597 * specifies an instruction that performs "result = r0 op r1". 4598 * This could be an ARM instruction or a function call. (If the result 4599 * comes back in a register other than r0, you can override "result".) 4600 * 4601 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4602 * vCC (r1). Useful for integer division and modulus. Note that we 4603 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4604 * handles it correctly. 4605 * 4606 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4607 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4608 * mul-float, div-float, rem-float 4609 */ 4610 /* binop vAA, vBB, vCC */ 4611 FETCH(r0, 1) @ r0<- CCBB 4612 mov r9, rINST, lsr #8 @ r9<- AA 4613 mov r3, r0, lsr #8 @ r3<- CC 4614 and r2, r0, #255 @ r2<- BB 4615 GET_VREG(r1, r3) @ r1<- vCC 4616 GET_VREG(r0, r2) @ r0<- vBB 4617 .if 0 4618 cmp r1, #0 @ is second operand zero? 4619 beq common_errDivideByZero 4620 .endif 4621 4622 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4623 and r1, r1, #31 @ optional op; may set condition codes 4624 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4625 GET_INST_OPCODE(ip) @ extract opcode from rINST 4626 SET_VREG(r0, r9) @ vAA<- r0 4627 GOTO_OPCODE(ip) @ jump to next instruction 4628 /* 11-14 instructions */ 4629 4630 4631 4632/* ------------------------------ */ 4633 .balign 64 4634.L_OP_USHR_INT: /* 0x9a */ 4635/* File: armv5te/OP_USHR_INT.S */ 4636/* File: armv5te/binop.S */ 4637 /* 4638 * Generic 32-bit binary operation. Provide an "instr" line that 4639 * specifies an instruction that performs "result = r0 op r1". 4640 * This could be an ARM instruction or a function call. (If the result 4641 * comes back in a register other than r0, you can override "result".) 4642 * 4643 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4644 * vCC (r1). Useful for integer division and modulus. Note that we 4645 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4646 * handles it correctly. 4647 * 4648 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4649 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4650 * mul-float, div-float, rem-float 4651 */ 4652 /* binop vAA, vBB, vCC */ 4653 FETCH(r0, 1) @ r0<- CCBB 4654 mov r9, rINST, lsr #8 @ r9<- AA 4655 mov r3, r0, lsr #8 @ r3<- CC 4656 and r2, r0, #255 @ r2<- BB 4657 GET_VREG(r1, r3) @ r1<- vCC 4658 GET_VREG(r0, r2) @ r0<- vBB 4659 .if 0 4660 cmp r1, #0 @ is second operand zero? 4661 beq common_errDivideByZero 4662 .endif 4663 4664 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4665 and r1, r1, #31 @ optional op; may set condition codes 4666 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4667 GET_INST_OPCODE(ip) @ extract opcode from rINST 4668 SET_VREG(r0, r9) @ vAA<- r0 4669 GOTO_OPCODE(ip) @ jump to next instruction 4670 /* 11-14 instructions */ 4671 4672 4673 4674/* ------------------------------ */ 4675 .balign 64 4676.L_OP_ADD_LONG: /* 0x9b */ 4677/* File: armv5te/OP_ADD_LONG.S */ 4678/* File: armv5te/binopWide.S */ 4679 /* 4680 * Generic 64-bit binary operation. Provide an "instr" line that 4681 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4682 * This could be an ARM instruction or a function call. (If the result 4683 * comes back in a register other than r0, you can override "result".) 4684 * 4685 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4686 * vCC (r1). Useful for integer division and modulus. 4687 * 4688 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4689 * xor-long, add-double, sub-double, mul-double, div-double, 4690 * rem-double 4691 * 4692 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4693 */ 4694 /* binop vAA, vBB, vCC */ 4695 FETCH(r0, 1) @ r0<- CCBB 4696 mov r9, rINST, lsr #8 @ r9<- AA 4697 and r2, r0, #255 @ r2<- BB 4698 mov r3, r0, lsr #8 @ r3<- CC 4699 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4700 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4701 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4702 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4703 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4704 .if 0 4705 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4706 beq common_errDivideByZero 4707 .endif 4708 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4709 4710 adds r0, r0, r2 @ optional op; may set condition codes 4711 adc r1, r1, r3 @ result<- op, r0-r3 changed 4712 GET_INST_OPCODE(ip) @ extract opcode from rINST 4713 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4714 GOTO_OPCODE(ip) @ jump to next instruction 4715 /* 14-17 instructions */ 4716 4717 4718 4719/* ------------------------------ */ 4720 .balign 64 4721.L_OP_SUB_LONG: /* 0x9c */ 4722/* File: armv5te/OP_SUB_LONG.S */ 4723/* File: armv5te/binopWide.S */ 4724 /* 4725 * Generic 64-bit binary operation. Provide an "instr" line that 4726 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4727 * This could be an ARM instruction or a function call. (If the result 4728 * comes back in a register other than r0, you can override "result".) 4729 * 4730 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4731 * vCC (r1). Useful for integer division and modulus. 4732 * 4733 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4734 * xor-long, add-double, sub-double, mul-double, div-double, 4735 * rem-double 4736 * 4737 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4738 */ 4739 /* binop vAA, vBB, vCC */ 4740 FETCH(r0, 1) @ r0<- CCBB 4741 mov r9, rINST, lsr #8 @ r9<- AA 4742 and r2, r0, #255 @ r2<- BB 4743 mov r3, r0, lsr #8 @ r3<- CC 4744 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4745 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4746 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4747 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4748 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4749 .if 0 4750 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4751 beq common_errDivideByZero 4752 .endif 4753 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4754 4755 subs r0, r0, r2 @ optional op; may set condition codes 4756 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4757 GET_INST_OPCODE(ip) @ extract opcode from rINST 4758 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4759 GOTO_OPCODE(ip) @ jump to next instruction 4760 /* 14-17 instructions */ 4761 4762 4763 4764/* ------------------------------ */ 4765 .balign 64 4766.L_OP_MUL_LONG: /* 0x9d */ 4767/* File: armv5te/OP_MUL_LONG.S */ 4768 /* 4769 * Signed 64-bit integer multiply. 4770 * 4771 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4772 * WX 4773 * x YZ 4774 * -------- 4775 * ZW ZX 4776 * YW YX 4777 * 4778 * The low word of the result holds ZX, the high word holds 4779 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4780 * it doesn't fit in the low 64 bits. 4781 * 4782 * Unlike most ARM math operations, multiply instructions have 4783 * restrictions on using the same register more than once (Rd and Rm 4784 * cannot be the same). 4785 */ 4786 /* mul-long vAA, vBB, vCC */ 4787 FETCH(r0, 1) @ r0<- CCBB 4788 and r2, r0, #255 @ r2<- BB 4789 mov r3, r0, lsr #8 @ r3<- CC 4790 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4791 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4792 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4793 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4794 mul ip, r2, r1 @ ip<- ZxW 4795 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4796 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4797 mov r0, rINST, lsr #8 @ r0<- AA 4798 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4799 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4801 b .LOP_MUL_LONG_finish 4802 4803/* ------------------------------ */ 4804 .balign 64 4805.L_OP_DIV_LONG: /* 0x9e */ 4806/* File: armv5te/OP_DIV_LONG.S */ 4807/* File: armv5te/binopWide.S */ 4808 /* 4809 * Generic 64-bit binary operation. Provide an "instr" line that 4810 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4811 * This could be an ARM instruction or a function call. (If the result 4812 * comes back in a register other than r0, you can override "result".) 4813 * 4814 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4815 * vCC (r1). Useful for integer division and modulus. 4816 * 4817 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4818 * xor-long, add-double, sub-double, mul-double, div-double, 4819 * rem-double 4820 * 4821 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4822 */ 4823 /* binop vAA, vBB, vCC */ 4824 FETCH(r0, 1) @ r0<- CCBB 4825 mov r9, rINST, lsr #8 @ r9<- AA 4826 and r2, r0, #255 @ r2<- BB 4827 mov r3, r0, lsr #8 @ r3<- CC 4828 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4829 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4830 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4831 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4832 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4833 .if 1 4834 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4835 beq common_errDivideByZero 4836 .endif 4837 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4838 4839 @ optional op; may set condition codes 4840 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4841 GET_INST_OPCODE(ip) @ extract opcode from rINST 4842 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4843 GOTO_OPCODE(ip) @ jump to next instruction 4844 /* 14-17 instructions */ 4845 4846 4847 4848/* ------------------------------ */ 4849 .balign 64 4850.L_OP_REM_LONG: /* 0x9f */ 4851/* File: armv5te/OP_REM_LONG.S */ 4852/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4853/* File: armv5te/binopWide.S */ 4854 /* 4855 * Generic 64-bit binary operation. Provide an "instr" line that 4856 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4857 * This could be an ARM instruction or a function call. (If the result 4858 * comes back in a register other than r0, you can override "result".) 4859 * 4860 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4861 * vCC (r1). Useful for integer division and modulus. 4862 * 4863 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4864 * xor-long, add-double, sub-double, mul-double, div-double, 4865 * rem-double 4866 * 4867 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4868 */ 4869 /* binop vAA, vBB, vCC */ 4870 FETCH(r0, 1) @ r0<- CCBB 4871 mov r9, rINST, lsr #8 @ r9<- AA 4872 and r2, r0, #255 @ r2<- BB 4873 mov r3, r0, lsr #8 @ r3<- CC 4874 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4875 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4876 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4877 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4878 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4879 .if 1 4880 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4881 beq common_errDivideByZero 4882 .endif 4883 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4884 4885 @ optional op; may set condition codes 4886 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4887 GET_INST_OPCODE(ip) @ extract opcode from rINST 4888 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4889 GOTO_OPCODE(ip) @ jump to next instruction 4890 /* 14-17 instructions */ 4891 4892 4893 4894/* ------------------------------ */ 4895 .balign 64 4896.L_OP_AND_LONG: /* 0xa0 */ 4897/* File: armv5te/OP_AND_LONG.S */ 4898/* File: armv5te/binopWide.S */ 4899 /* 4900 * Generic 64-bit binary operation. Provide an "instr" line that 4901 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4902 * This could be an ARM instruction or a function call. (If the result 4903 * comes back in a register other than r0, you can override "result".) 4904 * 4905 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4906 * vCC (r1). Useful for integer division and modulus. 4907 * 4908 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4909 * xor-long, add-double, sub-double, mul-double, div-double, 4910 * rem-double 4911 * 4912 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4913 */ 4914 /* binop vAA, vBB, vCC */ 4915 FETCH(r0, 1) @ r0<- CCBB 4916 mov r9, rINST, lsr #8 @ r9<- AA 4917 and r2, r0, #255 @ r2<- BB 4918 mov r3, r0, lsr #8 @ r3<- CC 4919 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4920 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4921 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4922 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4923 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4924 .if 0 4925 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4926 beq common_errDivideByZero 4927 .endif 4928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4929 4930 and r0, r0, r2 @ optional op; may set condition codes 4931 and r1, r1, r3 @ result<- op, r0-r3 changed 4932 GET_INST_OPCODE(ip) @ extract opcode from rINST 4933 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4934 GOTO_OPCODE(ip) @ jump to next instruction 4935 /* 14-17 instructions */ 4936 4937 4938 4939/* ------------------------------ */ 4940 .balign 64 4941.L_OP_OR_LONG: /* 0xa1 */ 4942/* File: armv5te/OP_OR_LONG.S */ 4943/* File: armv5te/binopWide.S */ 4944 /* 4945 * Generic 64-bit binary operation. Provide an "instr" line that 4946 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4947 * This could be an ARM instruction or a function call. (If the result 4948 * comes back in a register other than r0, you can override "result".) 4949 * 4950 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4951 * vCC (r1). Useful for integer division and modulus. 4952 * 4953 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4954 * xor-long, add-double, sub-double, mul-double, div-double, 4955 * rem-double 4956 * 4957 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4958 */ 4959 /* binop vAA, vBB, vCC */ 4960 FETCH(r0, 1) @ r0<- CCBB 4961 mov r9, rINST, lsr #8 @ r9<- AA 4962 and r2, r0, #255 @ r2<- BB 4963 mov r3, r0, lsr #8 @ r3<- CC 4964 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4965 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4966 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4967 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4968 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4969 .if 0 4970 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4971 beq common_errDivideByZero 4972 .endif 4973 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4974 4975 orr r0, r0, r2 @ optional op; may set condition codes 4976 orr r1, r1, r3 @ result<- op, r0-r3 changed 4977 GET_INST_OPCODE(ip) @ extract opcode from rINST 4978 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4979 GOTO_OPCODE(ip) @ jump to next instruction 4980 /* 14-17 instructions */ 4981 4982 4983 4984/* ------------------------------ */ 4985 .balign 64 4986.L_OP_XOR_LONG: /* 0xa2 */ 4987/* File: armv5te/OP_XOR_LONG.S */ 4988/* File: armv5te/binopWide.S */ 4989 /* 4990 * Generic 64-bit binary operation. Provide an "instr" line that 4991 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4992 * This could be an ARM instruction or a function call. (If the result 4993 * comes back in a register other than r0, you can override "result".) 4994 * 4995 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4996 * vCC (r1). Useful for integer division and modulus. 4997 * 4998 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4999 * xor-long, add-double, sub-double, mul-double, div-double, 5000 * rem-double 5001 * 5002 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5003 */ 5004 /* binop vAA, vBB, vCC */ 5005 FETCH(r0, 1) @ r0<- CCBB 5006 mov r9, rINST, lsr #8 @ r9<- AA 5007 and r2, r0, #255 @ r2<- BB 5008 mov r3, r0, lsr #8 @ r3<- CC 5009 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5010 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5011 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5012 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5013 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5014 .if 0 5015 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5016 beq common_errDivideByZero 5017 .endif 5018 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5019 5020 eor r0, r0, r2 @ optional op; may set condition codes 5021 eor r1, r1, r3 @ result<- op, r0-r3 changed 5022 GET_INST_OPCODE(ip) @ extract opcode from rINST 5023 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5024 GOTO_OPCODE(ip) @ jump to next instruction 5025 /* 14-17 instructions */ 5026 5027 5028 5029/* ------------------------------ */ 5030 .balign 64 5031.L_OP_SHL_LONG: /* 0xa3 */ 5032/* File: armv5te/OP_SHL_LONG.S */ 5033 /* 5034 * Long integer shift. This is different from the generic 32/64-bit 5035 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5036 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5037 * 6 bits of the shift distance. 5038 */ 5039 /* shl-long vAA, vBB, vCC */ 5040 FETCH(r0, 1) @ r0<- CCBB 5041 mov r9, rINST, lsr #8 @ r9<- AA 5042 and r3, r0, #255 @ r3<- BB 5043 mov r0, r0, lsr #8 @ r0<- CC 5044 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5045 GET_VREG(r2, r0) @ r2<- vCC 5046 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5047 and r2, r2, #63 @ r2<- r2 & 0x3f 5048 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5049 5050 mov r1, r1, asl r2 @ r1<- r1 << r2 5051 rsb r3, r2, #32 @ r3<- 32 - r2 5052 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5053 subs ip, r2, #32 @ ip<- r2 - 32 5054 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5056 b .LOP_SHL_LONG_finish 5057 5058/* ------------------------------ */ 5059 .balign 64 5060.L_OP_SHR_LONG: /* 0xa4 */ 5061/* File: armv5te/OP_SHR_LONG.S */ 5062 /* 5063 * Long integer shift. This is different from the generic 32/64-bit 5064 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5065 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5066 * 6 bits of the shift distance. 5067 */ 5068 /* shr-long vAA, vBB, vCC */ 5069 FETCH(r0, 1) @ r0<- CCBB 5070 mov r9, rINST, lsr #8 @ r9<- AA 5071 and r3, r0, #255 @ r3<- BB 5072 mov r0, r0, lsr #8 @ r0<- CC 5073 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5074 GET_VREG(r2, r0) @ r2<- vCC 5075 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5076 and r2, r2, #63 @ r0<- r0 & 0x3f 5077 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5078 5079 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5080 rsb r3, r2, #32 @ r3<- 32 - r2 5081 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5082 subs ip, r2, #32 @ ip<- r2 - 32 5083 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 5084 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5085 b .LOP_SHR_LONG_finish 5086 5087/* ------------------------------ */ 5088 .balign 64 5089.L_OP_USHR_LONG: /* 0xa5 */ 5090/* File: armv5te/OP_USHR_LONG.S */ 5091 /* 5092 * Long integer shift. This is different from the generic 32/64-bit 5093 * binary operations because vAA/vBB are 64-bit but vCC (the shift 5094 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 5095 * 6 bits of the shift distance. 5096 */ 5097 /* ushr-long vAA, vBB, vCC */ 5098 FETCH(r0, 1) @ r0<- CCBB 5099 mov r9, rINST, lsr #8 @ r9<- AA 5100 and r3, r0, #255 @ r3<- BB 5101 mov r0, r0, lsr #8 @ r0<- CC 5102 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 5103 GET_VREG(r2, r0) @ r2<- vCC 5104 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 5105 and r2, r2, #63 @ r0<- r0 & 0x3f 5106 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5107 5108 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5109 rsb r3, r2, #32 @ r3<- 32 - r2 5110 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5111 subs ip, r2, #32 @ ip<- r2 - 32 5112 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 5113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5114 b .LOP_USHR_LONG_finish 5115 5116/* ------------------------------ */ 5117 .balign 64 5118.L_OP_ADD_FLOAT: /* 0xa6 */ 5119/* File: armv5te/OP_ADD_FLOAT.S */ 5120/* File: armv5te/binop.S */ 5121 /* 5122 * Generic 32-bit binary operation. Provide an "instr" line that 5123 * specifies an instruction that performs "result = r0 op r1". 5124 * This could be an ARM instruction or a function call. (If the result 5125 * comes back in a register other than r0, you can override "result".) 5126 * 5127 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5128 * vCC (r1). Useful for integer division and modulus. Note that we 5129 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5130 * handles it correctly. 5131 * 5132 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5133 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5134 * mul-float, div-float, rem-float 5135 */ 5136 /* binop vAA, vBB, vCC */ 5137 FETCH(r0, 1) @ r0<- CCBB 5138 mov r9, rINST, lsr #8 @ r9<- AA 5139 mov r3, r0, lsr #8 @ r3<- CC 5140 and r2, r0, #255 @ r2<- BB 5141 GET_VREG(r1, r3) @ r1<- vCC 5142 GET_VREG(r0, r2) @ r0<- vBB 5143 .if 0 5144 cmp r1, #0 @ is second operand zero? 5145 beq common_errDivideByZero 5146 .endif 5147 5148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5149 @ optional op; may set condition codes 5150 bl __aeabi_fadd @ r0<- op, r0-r3 changed 5151 GET_INST_OPCODE(ip) @ extract opcode from rINST 5152 SET_VREG(r0, r9) @ vAA<- r0 5153 GOTO_OPCODE(ip) @ jump to next instruction 5154 /* 11-14 instructions */ 5155 5156 5157 5158/* ------------------------------ */ 5159 .balign 64 5160.L_OP_SUB_FLOAT: /* 0xa7 */ 5161/* File: armv5te/OP_SUB_FLOAT.S */ 5162/* File: armv5te/binop.S */ 5163 /* 5164 * Generic 32-bit binary operation. Provide an "instr" line that 5165 * specifies an instruction that performs "result = r0 op r1". 5166 * This could be an ARM instruction or a function call. (If the result 5167 * comes back in a register other than r0, you can override "result".) 5168 * 5169 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5170 * vCC (r1). Useful for integer division and modulus. Note that we 5171 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5172 * handles it correctly. 5173 * 5174 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5175 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5176 * mul-float, div-float, rem-float 5177 */ 5178 /* binop vAA, vBB, vCC */ 5179 FETCH(r0, 1) @ r0<- CCBB 5180 mov r9, rINST, lsr #8 @ r9<- AA 5181 mov r3, r0, lsr #8 @ r3<- CC 5182 and r2, r0, #255 @ r2<- BB 5183 GET_VREG(r1, r3) @ r1<- vCC 5184 GET_VREG(r0, r2) @ r0<- vBB 5185 .if 0 5186 cmp r1, #0 @ is second operand zero? 5187 beq common_errDivideByZero 5188 .endif 5189 5190 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5191 @ optional op; may set condition codes 5192 bl __aeabi_fsub @ r0<- op, r0-r3 changed 5193 GET_INST_OPCODE(ip) @ extract opcode from rINST 5194 SET_VREG(r0, r9) @ vAA<- r0 5195 GOTO_OPCODE(ip) @ jump to next instruction 5196 /* 11-14 instructions */ 5197 5198 5199 5200/* ------------------------------ */ 5201 .balign 64 5202.L_OP_MUL_FLOAT: /* 0xa8 */ 5203/* File: armv5te/OP_MUL_FLOAT.S */ 5204/* File: armv5te/binop.S */ 5205 /* 5206 * Generic 32-bit binary operation. Provide an "instr" line that 5207 * specifies an instruction that performs "result = r0 op r1". 5208 * This could be an ARM instruction or a function call. (If the result 5209 * comes back in a register other than r0, you can override "result".) 5210 * 5211 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5212 * vCC (r1). Useful for integer division and modulus. Note that we 5213 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5214 * handles it correctly. 5215 * 5216 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5217 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5218 * mul-float, div-float, rem-float 5219 */ 5220 /* binop vAA, vBB, vCC */ 5221 FETCH(r0, 1) @ r0<- CCBB 5222 mov r9, rINST, lsr #8 @ r9<- AA 5223 mov r3, r0, lsr #8 @ r3<- CC 5224 and r2, r0, #255 @ r2<- BB 5225 GET_VREG(r1, r3) @ r1<- vCC 5226 GET_VREG(r0, r2) @ r0<- vBB 5227 .if 0 5228 cmp r1, #0 @ is second operand zero? 5229 beq common_errDivideByZero 5230 .endif 5231 5232 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5233 @ optional op; may set condition codes 5234 bl __aeabi_fmul @ r0<- op, r0-r3 changed 5235 GET_INST_OPCODE(ip) @ extract opcode from rINST 5236 SET_VREG(r0, r9) @ vAA<- r0 5237 GOTO_OPCODE(ip) @ jump to next instruction 5238 /* 11-14 instructions */ 5239 5240 5241 5242/* ------------------------------ */ 5243 .balign 64 5244.L_OP_DIV_FLOAT: /* 0xa9 */ 5245/* File: armv5te/OP_DIV_FLOAT.S */ 5246/* File: armv5te/binop.S */ 5247 /* 5248 * Generic 32-bit binary operation. Provide an "instr" line that 5249 * specifies an instruction that performs "result = r0 op r1". 5250 * This could be an ARM instruction or a function call. (If the result 5251 * comes back in a register other than r0, you can override "result".) 5252 * 5253 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5254 * vCC (r1). Useful for integer division and modulus. Note that we 5255 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5256 * handles it correctly. 5257 * 5258 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5259 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5260 * mul-float, div-float, rem-float 5261 */ 5262 /* binop vAA, vBB, vCC */ 5263 FETCH(r0, 1) @ r0<- CCBB 5264 mov r9, rINST, lsr #8 @ r9<- AA 5265 mov r3, r0, lsr #8 @ r3<- CC 5266 and r2, r0, #255 @ r2<- BB 5267 GET_VREG(r1, r3) @ r1<- vCC 5268 GET_VREG(r0, r2) @ r0<- vBB 5269 .if 0 5270 cmp r1, #0 @ is second operand zero? 5271 beq common_errDivideByZero 5272 .endif 5273 5274 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5275 @ optional op; may set condition codes 5276 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 5277 GET_INST_OPCODE(ip) @ extract opcode from rINST 5278 SET_VREG(r0, r9) @ vAA<- r0 5279 GOTO_OPCODE(ip) @ jump to next instruction 5280 /* 11-14 instructions */ 5281 5282 5283 5284/* ------------------------------ */ 5285 .balign 64 5286.L_OP_REM_FLOAT: /* 0xaa */ 5287/* File: armv5te/OP_REM_FLOAT.S */ 5288/* EABI doesn't define a float remainder function, but libm does */ 5289/* File: armv5te/binop.S */ 5290 /* 5291 * Generic 32-bit binary operation. Provide an "instr" line that 5292 * specifies an instruction that performs "result = r0 op r1". 5293 * This could be an ARM instruction or a function call. (If the result 5294 * comes back in a register other than r0, you can override "result".) 5295 * 5296 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5297 * vCC (r1). Useful for integer division and modulus. Note that we 5298 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5299 * handles it correctly. 5300 * 5301 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5302 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5303 * mul-float, div-float, rem-float 5304 */ 5305 /* binop vAA, vBB, vCC */ 5306 FETCH(r0, 1) @ r0<- CCBB 5307 mov r9, rINST, lsr #8 @ r9<- AA 5308 mov r3, r0, lsr #8 @ r3<- CC 5309 and r2, r0, #255 @ r2<- BB 5310 GET_VREG(r1, r3) @ r1<- vCC 5311 GET_VREG(r0, r2) @ r0<- vBB 5312 .if 0 5313 cmp r1, #0 @ is second operand zero? 5314 beq common_errDivideByZero 5315 .endif 5316 5317 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5318 @ optional op; may set condition codes 5319 bl fmodf @ r0<- op, r0-r3 changed 5320 GET_INST_OPCODE(ip) @ extract opcode from rINST 5321 SET_VREG(r0, r9) @ vAA<- r0 5322 GOTO_OPCODE(ip) @ jump to next instruction 5323 /* 11-14 instructions */ 5324 5325 5326 5327/* ------------------------------ */ 5328 .balign 64 5329.L_OP_ADD_DOUBLE: /* 0xab */ 5330/* File: armv5te/OP_ADD_DOUBLE.S */ 5331/* File: armv5te/binopWide.S */ 5332 /* 5333 * Generic 64-bit binary operation. Provide an "instr" line that 5334 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5335 * This could be an ARM instruction or a function call. (If the result 5336 * comes back in a register other than r0, you can override "result".) 5337 * 5338 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5339 * vCC (r1). Useful for integer division and modulus. 5340 * 5341 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5342 * xor-long, add-double, sub-double, mul-double, div-double, 5343 * rem-double 5344 * 5345 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5346 */ 5347 /* binop vAA, vBB, vCC */ 5348 FETCH(r0, 1) @ r0<- CCBB 5349 mov r9, rINST, lsr #8 @ r9<- AA 5350 and r2, r0, #255 @ r2<- BB 5351 mov r3, r0, lsr #8 @ r3<- CC 5352 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5353 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5354 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5355 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5356 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5357 .if 0 5358 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5359 beq common_errDivideByZero 5360 .endif 5361 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5362 5363 @ optional op; may set condition codes 5364 bl __aeabi_dadd @ result<- op, r0-r3 changed 5365 GET_INST_OPCODE(ip) @ extract opcode from rINST 5366 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5367 GOTO_OPCODE(ip) @ jump to next instruction 5368 /* 14-17 instructions */ 5369 5370 5371 5372/* ------------------------------ */ 5373 .balign 64 5374.L_OP_SUB_DOUBLE: /* 0xac */ 5375/* File: armv5te/OP_SUB_DOUBLE.S */ 5376/* File: armv5te/binopWide.S */ 5377 /* 5378 * Generic 64-bit binary operation. Provide an "instr" line that 5379 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5380 * This could be an ARM instruction or a function call. (If the result 5381 * comes back in a register other than r0, you can override "result".) 5382 * 5383 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5384 * vCC (r1). Useful for integer division and modulus. 5385 * 5386 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5387 * xor-long, add-double, sub-double, mul-double, div-double, 5388 * rem-double 5389 * 5390 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5391 */ 5392 /* binop vAA, vBB, vCC */ 5393 FETCH(r0, 1) @ r0<- CCBB 5394 mov r9, rINST, lsr #8 @ r9<- AA 5395 and r2, r0, #255 @ r2<- BB 5396 mov r3, r0, lsr #8 @ r3<- CC 5397 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5398 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5399 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5400 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5401 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5402 .if 0 5403 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5404 beq common_errDivideByZero 5405 .endif 5406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5407 5408 @ optional op; may set condition codes 5409 bl __aeabi_dsub @ result<- op, r0-r3 changed 5410 GET_INST_OPCODE(ip) @ extract opcode from rINST 5411 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5412 GOTO_OPCODE(ip) @ jump to next instruction 5413 /* 14-17 instructions */ 5414 5415 5416 5417/* ------------------------------ */ 5418 .balign 64 5419.L_OP_MUL_DOUBLE: /* 0xad */ 5420/* File: armv5te/OP_MUL_DOUBLE.S */ 5421/* File: armv5te/binopWide.S */ 5422 /* 5423 * Generic 64-bit binary operation. Provide an "instr" line that 5424 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5425 * This could be an ARM instruction or a function call. (If the result 5426 * comes back in a register other than r0, you can override "result".) 5427 * 5428 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5429 * vCC (r1). Useful for integer division and modulus. 5430 * 5431 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5432 * xor-long, add-double, sub-double, mul-double, div-double, 5433 * rem-double 5434 * 5435 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5436 */ 5437 /* binop vAA, vBB, vCC */ 5438 FETCH(r0, 1) @ r0<- CCBB 5439 mov r9, rINST, lsr #8 @ r9<- AA 5440 and r2, r0, #255 @ r2<- BB 5441 mov r3, r0, lsr #8 @ r3<- CC 5442 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5443 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5444 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5445 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5446 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5447 .if 0 5448 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5449 beq common_errDivideByZero 5450 .endif 5451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5452 5453 @ optional op; may set condition codes 5454 bl __aeabi_dmul @ result<- op, r0-r3 changed 5455 GET_INST_OPCODE(ip) @ extract opcode from rINST 5456 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5457 GOTO_OPCODE(ip) @ jump to next instruction 5458 /* 14-17 instructions */ 5459 5460 5461 5462/* ------------------------------ */ 5463 .balign 64 5464.L_OP_DIV_DOUBLE: /* 0xae */ 5465/* File: armv5te/OP_DIV_DOUBLE.S */ 5466/* File: armv5te/binopWide.S */ 5467 /* 5468 * Generic 64-bit binary operation. Provide an "instr" line that 5469 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5470 * This could be an ARM instruction or a function call. (If the result 5471 * comes back in a register other than r0, you can override "result".) 5472 * 5473 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5474 * vCC (r1). Useful for integer division and modulus. 5475 * 5476 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5477 * xor-long, add-double, sub-double, mul-double, div-double, 5478 * rem-double 5479 * 5480 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5481 */ 5482 /* binop vAA, vBB, vCC */ 5483 FETCH(r0, 1) @ r0<- CCBB 5484 mov r9, rINST, lsr #8 @ r9<- AA 5485 and r2, r0, #255 @ r2<- BB 5486 mov r3, r0, lsr #8 @ r3<- CC 5487 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5488 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5489 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5490 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5491 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5492 .if 0 5493 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5494 beq common_errDivideByZero 5495 .endif 5496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5497 5498 @ optional op; may set condition codes 5499 bl __aeabi_ddiv @ result<- op, r0-r3 changed 5500 GET_INST_OPCODE(ip) @ extract opcode from rINST 5501 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5502 GOTO_OPCODE(ip) @ jump to next instruction 5503 /* 14-17 instructions */ 5504 5505 5506 5507/* ------------------------------ */ 5508 .balign 64 5509.L_OP_REM_DOUBLE: /* 0xaf */ 5510/* File: armv5te/OP_REM_DOUBLE.S */ 5511/* EABI doesn't define a double remainder function, but libm does */ 5512/* File: armv5te/binopWide.S */ 5513 /* 5514 * Generic 64-bit binary operation. Provide an "instr" line that 5515 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5516 * This could be an ARM instruction or a function call. (If the result 5517 * comes back in a register other than r0, you can override "result".) 5518 * 5519 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5520 * vCC (r1). Useful for integer division and modulus. 5521 * 5522 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5523 * xor-long, add-double, sub-double, mul-double, div-double, 5524 * rem-double 5525 * 5526 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5527 */ 5528 /* binop vAA, vBB, vCC */ 5529 FETCH(r0, 1) @ r0<- CCBB 5530 mov r9, rINST, lsr #8 @ r9<- AA 5531 and r2, r0, #255 @ r2<- BB 5532 mov r3, r0, lsr #8 @ r3<- CC 5533 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5534 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5535 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5536 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5537 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5538 .if 0 5539 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5540 beq common_errDivideByZero 5541 .endif 5542 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5543 5544 @ optional op; may set condition codes 5545 bl fmod @ result<- op, r0-r3 changed 5546 GET_INST_OPCODE(ip) @ extract opcode from rINST 5547 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5548 GOTO_OPCODE(ip) @ jump to next instruction 5549 /* 14-17 instructions */ 5550 5551 5552 5553/* ------------------------------ */ 5554 .balign 64 5555.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5556/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5557/* File: armv5te/binop2addr.S */ 5558 /* 5559 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5560 * that specifies an instruction that performs "result = r0 op r1". 5561 * This could be an ARM instruction or a function call. (If the result 5562 * comes back in a register other than r0, you can override "result".) 5563 * 5564 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5565 * vCC (r1). Useful for integer division and modulus. 5566 * 5567 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5568 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5569 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5570 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5571 */ 5572 /* binop/2addr vA, vB */ 5573 mov r9, rINST, lsr #8 @ r9<- A+ 5574 mov r3, rINST, lsr #12 @ r3<- B 5575 and r9, r9, #15 5576 GET_VREG(r0, r9) @ r0<- vA 5577 GET_VREG(r1, r3) @ r1<- vB 5578 .if 0 5579 cmp r1, #0 @ is second operand zero? 5580 beq common_errDivideByZero 5581 .endif 5582 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5583 5584 @ optional op; may set condition codes 5585 add r0, r0, r1 @ r0<- op, r0-r3 changed 5586 GET_INST_OPCODE(ip) @ extract opcode from rINST 5587 SET_VREG(r0, r9) @ vAA<- r0 5588 GOTO_OPCODE(ip) @ jump to next instruction 5589 /* 10-13 instructions */ 5590 5591 5592 5593/* ------------------------------ */ 5594 .balign 64 5595.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5596/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5597/* File: armv5te/binop2addr.S */ 5598 /* 5599 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5600 * that specifies an instruction that performs "result = r0 op r1". 5601 * This could be an ARM instruction or a function call. (If the result 5602 * comes back in a register other than r0, you can override "result".) 5603 * 5604 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5605 * vCC (r1). Useful for integer division and modulus. 5606 * 5607 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5608 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5609 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5610 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5611 */ 5612 /* binop/2addr vA, vB */ 5613 mov r9, rINST, lsr #8 @ r9<- A+ 5614 mov r3, rINST, lsr #12 @ r3<- B 5615 and r9, r9, #15 5616 GET_VREG(r0, r9) @ r0<- vA 5617 GET_VREG(r1, r3) @ r1<- vB 5618 .if 0 5619 cmp r1, #0 @ is second operand zero? 5620 beq common_errDivideByZero 5621 .endif 5622 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5623 5624 @ optional op; may set condition codes 5625 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5626 GET_INST_OPCODE(ip) @ extract opcode from rINST 5627 SET_VREG(r0, r9) @ vAA<- r0 5628 GOTO_OPCODE(ip) @ jump to next instruction 5629 /* 10-13 instructions */ 5630 5631 5632 5633/* ------------------------------ */ 5634 .balign 64 5635.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5636/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5637/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5638/* File: armv5te/binop2addr.S */ 5639 /* 5640 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5641 * that specifies an instruction that performs "result = r0 op r1". 5642 * This could be an ARM instruction or a function call. (If the result 5643 * comes back in a register other than r0, you can override "result".) 5644 * 5645 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5646 * vCC (r1). Useful for integer division and modulus. 5647 * 5648 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5649 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5650 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5651 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5652 */ 5653 /* binop/2addr vA, vB */ 5654 mov r9, rINST, lsr #8 @ r9<- A+ 5655 mov r3, rINST, lsr #12 @ r3<- B 5656 and r9, r9, #15 5657 GET_VREG(r0, r9) @ r0<- vA 5658 GET_VREG(r1, r3) @ r1<- vB 5659 .if 0 5660 cmp r1, #0 @ is second operand zero? 5661 beq common_errDivideByZero 5662 .endif 5663 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5664 5665 @ optional op; may set condition codes 5666 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5667 GET_INST_OPCODE(ip) @ extract opcode from rINST 5668 SET_VREG(r0, r9) @ vAA<- r0 5669 GOTO_OPCODE(ip) @ jump to next instruction 5670 /* 10-13 instructions */ 5671 5672 5673 5674/* ------------------------------ */ 5675 .balign 64 5676.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5677/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5678/* File: armv5te/binop2addr.S */ 5679 /* 5680 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5681 * that specifies an instruction that performs "result = r0 op r1". 5682 * This could be an ARM instruction or a function call. (If the result 5683 * comes back in a register other than r0, you can override "result".) 5684 * 5685 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5686 * vCC (r1). Useful for integer division and modulus. 5687 * 5688 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5689 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5690 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5691 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5692 */ 5693 /* binop/2addr vA, vB */ 5694 mov r9, rINST, lsr #8 @ r9<- A+ 5695 mov r3, rINST, lsr #12 @ r3<- B 5696 and r9, r9, #15 5697 GET_VREG(r0, r9) @ r0<- vA 5698 GET_VREG(r1, r3) @ r1<- vB 5699 .if 1 5700 cmp r1, #0 @ is second operand zero? 5701 beq common_errDivideByZero 5702 .endif 5703 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5704 5705 @ optional op; may set condition codes 5706 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5707 GET_INST_OPCODE(ip) @ extract opcode from rINST 5708 SET_VREG(r0, r9) @ vAA<- r0 5709 GOTO_OPCODE(ip) @ jump to next instruction 5710 /* 10-13 instructions */ 5711 5712 5713 5714/* ------------------------------ */ 5715 .balign 64 5716.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5717/* File: armv5te/OP_REM_INT_2ADDR.S */ 5718/* idivmod returns quotient in r0 and remainder in r1 */ 5719/* File: armv5te/binop2addr.S */ 5720 /* 5721 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5722 * that specifies an instruction that performs "result = r0 op r1". 5723 * This could be an ARM instruction or a function call. (If the result 5724 * comes back in a register other than r0, you can override "result".) 5725 * 5726 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5727 * vCC (r1). Useful for integer division and modulus. 5728 * 5729 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5730 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5731 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5732 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5733 */ 5734 /* binop/2addr vA, vB */ 5735 mov r9, rINST, lsr #8 @ r9<- A+ 5736 mov r3, rINST, lsr #12 @ r3<- B 5737 and r9, r9, #15 5738 GET_VREG(r0, r9) @ r0<- vA 5739 GET_VREG(r1, r3) @ r1<- vB 5740 .if 1 5741 cmp r1, #0 @ is second operand zero? 5742 beq common_errDivideByZero 5743 .endif 5744 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5745 5746 @ optional op; may set condition codes 5747 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5748 GET_INST_OPCODE(ip) @ extract opcode from rINST 5749 SET_VREG(r1, r9) @ vAA<- r1 5750 GOTO_OPCODE(ip) @ jump to next instruction 5751 /* 10-13 instructions */ 5752 5753 5754 5755/* ------------------------------ */ 5756 .balign 64 5757.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5758/* File: armv5te/OP_AND_INT_2ADDR.S */ 5759/* File: armv5te/binop2addr.S */ 5760 /* 5761 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5762 * that specifies an instruction that performs "result = r0 op r1". 5763 * This could be an ARM instruction or a function call. (If the result 5764 * comes back in a register other than r0, you can override "result".) 5765 * 5766 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5767 * vCC (r1). Useful for integer division and modulus. 5768 * 5769 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5770 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5771 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5772 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5773 */ 5774 /* binop/2addr vA, vB */ 5775 mov r9, rINST, lsr #8 @ r9<- A+ 5776 mov r3, rINST, lsr #12 @ r3<- B 5777 and r9, r9, #15 5778 GET_VREG(r0, r9) @ r0<- vA 5779 GET_VREG(r1, r3) @ r1<- vB 5780 .if 0 5781 cmp r1, #0 @ is second operand zero? 5782 beq common_errDivideByZero 5783 .endif 5784 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5785 5786 @ optional op; may set condition codes 5787 and r0, r0, r1 @ r0<- op, r0-r3 changed 5788 GET_INST_OPCODE(ip) @ extract opcode from rINST 5789 SET_VREG(r0, r9) @ vAA<- r0 5790 GOTO_OPCODE(ip) @ jump to next instruction 5791 /* 10-13 instructions */ 5792 5793 5794 5795/* ------------------------------ */ 5796 .balign 64 5797.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5798/* File: armv5te/OP_OR_INT_2ADDR.S */ 5799/* File: armv5te/binop2addr.S */ 5800 /* 5801 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5802 * that specifies an instruction that performs "result = r0 op r1". 5803 * This could be an ARM instruction or a function call. (If the result 5804 * comes back in a register other than r0, you can override "result".) 5805 * 5806 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5807 * vCC (r1). Useful for integer division and modulus. 5808 * 5809 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5810 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5811 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5812 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5813 */ 5814 /* binop/2addr vA, vB */ 5815 mov r9, rINST, lsr #8 @ r9<- A+ 5816 mov r3, rINST, lsr #12 @ r3<- B 5817 and r9, r9, #15 5818 GET_VREG(r0, r9) @ r0<- vA 5819 GET_VREG(r1, r3) @ r1<- vB 5820 .if 0 5821 cmp r1, #0 @ is second operand zero? 5822 beq common_errDivideByZero 5823 .endif 5824 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5825 5826 @ optional op; may set condition codes 5827 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5828 GET_INST_OPCODE(ip) @ extract opcode from rINST 5829 SET_VREG(r0, r9) @ vAA<- r0 5830 GOTO_OPCODE(ip) @ jump to next instruction 5831 /* 10-13 instructions */ 5832 5833 5834 5835/* ------------------------------ */ 5836 .balign 64 5837.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5838/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5839/* File: armv5te/binop2addr.S */ 5840 /* 5841 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5842 * that specifies an instruction that performs "result = r0 op r1". 5843 * This could be an ARM instruction or a function call. (If the result 5844 * comes back in a register other than r0, you can override "result".) 5845 * 5846 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5847 * vCC (r1). Useful for integer division and modulus. 5848 * 5849 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5850 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5851 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5852 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5853 */ 5854 /* binop/2addr vA, vB */ 5855 mov r9, rINST, lsr #8 @ r9<- A+ 5856 mov r3, rINST, lsr #12 @ r3<- B 5857 and r9, r9, #15 5858 GET_VREG(r0, r9) @ r0<- vA 5859 GET_VREG(r1, r3) @ r1<- vB 5860 .if 0 5861 cmp r1, #0 @ is second operand zero? 5862 beq common_errDivideByZero 5863 .endif 5864 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5865 5866 @ optional op; may set condition codes 5867 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5868 GET_INST_OPCODE(ip) @ extract opcode from rINST 5869 SET_VREG(r0, r9) @ vAA<- r0 5870 GOTO_OPCODE(ip) @ jump to next instruction 5871 /* 10-13 instructions */ 5872 5873 5874 5875/* ------------------------------ */ 5876 .balign 64 5877.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5878/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5879/* File: armv5te/binop2addr.S */ 5880 /* 5881 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5882 * that specifies an instruction that performs "result = r0 op r1". 5883 * This could be an ARM instruction or a function call. (If the result 5884 * comes back in a register other than r0, you can override "result".) 5885 * 5886 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5887 * vCC (r1). Useful for integer division and modulus. 5888 * 5889 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5890 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5891 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5892 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5893 */ 5894 /* binop/2addr vA, vB */ 5895 mov r9, rINST, lsr #8 @ r9<- A+ 5896 mov r3, rINST, lsr #12 @ r3<- B 5897 and r9, r9, #15 5898 GET_VREG(r0, r9) @ r0<- vA 5899 GET_VREG(r1, r3) @ r1<- vB 5900 .if 0 5901 cmp r1, #0 @ is second operand zero? 5902 beq common_errDivideByZero 5903 .endif 5904 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5905 5906 and r1, r1, #31 @ optional op; may set condition codes 5907 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5908 GET_INST_OPCODE(ip) @ extract opcode from rINST 5909 SET_VREG(r0, r9) @ vAA<- r0 5910 GOTO_OPCODE(ip) @ jump to next instruction 5911 /* 10-13 instructions */ 5912 5913 5914 5915/* ------------------------------ */ 5916 .balign 64 5917.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5918/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5919/* File: armv5te/binop2addr.S */ 5920 /* 5921 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5922 * that specifies an instruction that performs "result = r0 op r1". 5923 * This could be an ARM instruction or a function call. (If the result 5924 * comes back in a register other than r0, you can override "result".) 5925 * 5926 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5927 * vCC (r1). Useful for integer division and modulus. 5928 * 5929 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5930 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5931 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5932 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5933 */ 5934 /* binop/2addr vA, vB */ 5935 mov r9, rINST, lsr #8 @ r9<- A+ 5936 mov r3, rINST, lsr #12 @ r3<- B 5937 and r9, r9, #15 5938 GET_VREG(r0, r9) @ r0<- vA 5939 GET_VREG(r1, r3) @ r1<- vB 5940 .if 0 5941 cmp r1, #0 @ is second operand zero? 5942 beq common_errDivideByZero 5943 .endif 5944 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5945 5946 and r1, r1, #31 @ optional op; may set condition codes 5947 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5948 GET_INST_OPCODE(ip) @ extract opcode from rINST 5949 SET_VREG(r0, r9) @ vAA<- r0 5950 GOTO_OPCODE(ip) @ jump to next instruction 5951 /* 10-13 instructions */ 5952 5953 5954 5955/* ------------------------------ */ 5956 .balign 64 5957.L_OP_USHR_INT_2ADDR: /* 0xba */ 5958/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5959/* File: armv5te/binop2addr.S */ 5960 /* 5961 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5962 * that specifies an instruction that performs "result = r0 op r1". 5963 * This could be an ARM instruction or a function call. (If the result 5964 * comes back in a register other than r0, you can override "result".) 5965 * 5966 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5967 * vCC (r1). Useful for integer division and modulus. 5968 * 5969 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5970 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5971 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5972 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5973 */ 5974 /* binop/2addr vA, vB */ 5975 mov r9, rINST, lsr #8 @ r9<- A+ 5976 mov r3, rINST, lsr #12 @ r3<- B 5977 and r9, r9, #15 5978 GET_VREG(r0, r9) @ r0<- vA 5979 GET_VREG(r1, r3) @ r1<- vB 5980 .if 0 5981 cmp r1, #0 @ is second operand zero? 5982 beq common_errDivideByZero 5983 .endif 5984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5985 5986 and r1, r1, #31 @ optional op; may set condition codes 5987 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5988 GET_INST_OPCODE(ip) @ extract opcode from rINST 5989 SET_VREG(r0, r9) @ vAA<- r0 5990 GOTO_OPCODE(ip) @ jump to next instruction 5991 /* 10-13 instructions */ 5992 5993 5994 5995/* ------------------------------ */ 5996 .balign 64 5997.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5998/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5999/* File: armv5te/binopWide2addr.S */ 6000 /* 6001 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6002 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6003 * This could be an ARM instruction or a function call. (If the result 6004 * comes back in a register other than r0, you can override "result".) 6005 * 6006 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6007 * vCC (r1). Useful for integer division and modulus. 6008 * 6009 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6010 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6011 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6012 * rem-double/2addr 6013 */ 6014 /* binop/2addr vA, vB */ 6015 mov r9, rINST, lsr #8 @ r9<- A+ 6016 mov r1, rINST, lsr #12 @ r1<- B 6017 and r9, r9, #15 6018 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6019 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6020 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6021 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6022 .if 0 6023 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6024 beq common_errDivideByZero 6025 .endif 6026 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6027 6028 adds r0, r0, r2 @ optional op; may set condition codes 6029 adc r1, r1, r3 @ result<- op, r0-r3 changed 6030 GET_INST_OPCODE(ip) @ extract opcode from rINST 6031 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6032 GOTO_OPCODE(ip) @ jump to next instruction 6033 /* 12-15 instructions */ 6034 6035 6036 6037/* ------------------------------ */ 6038 .balign 64 6039.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 6040/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 6041/* File: armv5te/binopWide2addr.S */ 6042 /* 6043 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6044 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6045 * This could be an ARM instruction or a function call. (If the result 6046 * comes back in a register other than r0, you can override "result".) 6047 * 6048 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6049 * vCC (r1). Useful for integer division and modulus. 6050 * 6051 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6052 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6053 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6054 * rem-double/2addr 6055 */ 6056 /* binop/2addr vA, vB */ 6057 mov r9, rINST, lsr #8 @ r9<- A+ 6058 mov r1, rINST, lsr #12 @ r1<- B 6059 and r9, r9, #15 6060 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6061 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6062 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6063 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6064 .if 0 6065 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6066 beq common_errDivideByZero 6067 .endif 6068 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6069 6070 subs r0, r0, r2 @ optional op; may set condition codes 6071 sbc r1, r1, r3 @ result<- op, r0-r3 changed 6072 GET_INST_OPCODE(ip) @ extract opcode from rINST 6073 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6074 GOTO_OPCODE(ip) @ jump to next instruction 6075 /* 12-15 instructions */ 6076 6077 6078 6079/* ------------------------------ */ 6080 .balign 64 6081.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 6082/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 6083 /* 6084 * Signed 64-bit integer multiply, "/2addr" version. 6085 * 6086 * See OP_MUL_LONG for an explanation. 6087 * 6088 * We get a little tight on registers, so to avoid looking up &fp[A] 6089 * again we stuff it into rINST. 6090 */ 6091 /* mul-long/2addr vA, vB */ 6092 mov r9, rINST, lsr #8 @ r9<- A+ 6093 mov r1, rINST, lsr #12 @ r1<- B 6094 and r9, r9, #15 6095 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6096 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 6097 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6098 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 6099 mul ip, r2, r1 @ ip<- ZxW 6100 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 6101 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 6102 mov r0, rINST @ r0<- &fp[A] (free up rINST) 6103 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6104 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 6105 GET_INST_OPCODE(ip) @ extract opcode from rINST 6106 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 6107 GOTO_OPCODE(ip) @ jump to next instruction 6108 6109 6110/* ------------------------------ */ 6111 .balign 64 6112.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 6113/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 6114/* File: armv5te/binopWide2addr.S */ 6115 /* 6116 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6117 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6118 * This could be an ARM instruction or a function call. (If the result 6119 * comes back in a register other than r0, you can override "result".) 6120 * 6121 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6122 * vCC (r1). Useful for integer division and modulus. 6123 * 6124 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6125 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6126 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6127 * rem-double/2addr 6128 */ 6129 /* binop/2addr vA, vB */ 6130 mov r9, rINST, lsr #8 @ r9<- A+ 6131 mov r1, rINST, lsr #12 @ r1<- B 6132 and r9, r9, #15 6133 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6134 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6135 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6136 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6137 .if 1 6138 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6139 beq common_errDivideByZero 6140 .endif 6141 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6142 6143 @ optional op; may set condition codes 6144 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6145 GET_INST_OPCODE(ip) @ extract opcode from rINST 6146 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6147 GOTO_OPCODE(ip) @ jump to next instruction 6148 /* 12-15 instructions */ 6149 6150 6151 6152/* ------------------------------ */ 6153 .balign 64 6154.L_OP_REM_LONG_2ADDR: /* 0xbf */ 6155/* File: armv5te/OP_REM_LONG_2ADDR.S */ 6156/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 6157/* File: armv5te/binopWide2addr.S */ 6158 /* 6159 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6160 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6161 * This could be an ARM instruction or a function call. (If the result 6162 * comes back in a register other than r0, you can override "result".) 6163 * 6164 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6165 * vCC (r1). Useful for integer division and modulus. 6166 * 6167 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6168 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6169 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6170 * rem-double/2addr 6171 */ 6172 /* binop/2addr vA, vB */ 6173 mov r9, rINST, lsr #8 @ r9<- A+ 6174 mov r1, rINST, lsr #12 @ r1<- B 6175 and r9, r9, #15 6176 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6177 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6178 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6179 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6180 .if 1 6181 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6182 beq common_errDivideByZero 6183 .endif 6184 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6185 6186 @ optional op; may set condition codes 6187 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6188 GET_INST_OPCODE(ip) @ extract opcode from rINST 6189 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 6190 GOTO_OPCODE(ip) @ jump to next instruction 6191 /* 12-15 instructions */ 6192 6193 6194 6195/* ------------------------------ */ 6196 .balign 64 6197.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 6198/* File: armv5te/OP_AND_LONG_2ADDR.S */ 6199/* File: armv5te/binopWide2addr.S */ 6200 /* 6201 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6202 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6203 * This could be an ARM instruction or a function call. (If the result 6204 * comes back in a register other than r0, you can override "result".) 6205 * 6206 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6207 * vCC (r1). Useful for integer division and modulus. 6208 * 6209 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6210 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6211 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6212 * rem-double/2addr 6213 */ 6214 /* binop/2addr vA, vB */ 6215 mov r9, rINST, lsr #8 @ r9<- A+ 6216 mov r1, rINST, lsr #12 @ r1<- B 6217 and r9, r9, #15 6218 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6219 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6220 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6221 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6222 .if 0 6223 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6224 beq common_errDivideByZero 6225 .endif 6226 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6227 6228 and r0, r0, r2 @ optional op; may set condition codes 6229 and r1, r1, r3 @ result<- op, r0-r3 changed 6230 GET_INST_OPCODE(ip) @ extract opcode from rINST 6231 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6232 GOTO_OPCODE(ip) @ jump to next instruction 6233 /* 12-15 instructions */ 6234 6235 6236 6237/* ------------------------------ */ 6238 .balign 64 6239.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6240/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6241/* File: armv5te/binopWide2addr.S */ 6242 /* 6243 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6244 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6245 * This could be an ARM instruction or a function call. (If the result 6246 * comes back in a register other than r0, you can override "result".) 6247 * 6248 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6249 * vCC (r1). Useful for integer division and modulus. 6250 * 6251 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6252 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6253 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6254 * rem-double/2addr 6255 */ 6256 /* binop/2addr vA, vB */ 6257 mov r9, rINST, lsr #8 @ r9<- A+ 6258 mov r1, rINST, lsr #12 @ r1<- B 6259 and r9, r9, #15 6260 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6261 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6262 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6263 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6264 .if 0 6265 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6266 beq common_errDivideByZero 6267 .endif 6268 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6269 6270 orr r0, r0, r2 @ optional op; may set condition codes 6271 orr r1, r1, r3 @ result<- op, r0-r3 changed 6272 GET_INST_OPCODE(ip) @ extract opcode from rINST 6273 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6274 GOTO_OPCODE(ip) @ jump to next instruction 6275 /* 12-15 instructions */ 6276 6277 6278 6279/* ------------------------------ */ 6280 .balign 64 6281.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6282/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6283/* File: armv5te/binopWide2addr.S */ 6284 /* 6285 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6286 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6287 * This could be an ARM instruction or a function call. (If the result 6288 * comes back in a register other than r0, you can override "result".) 6289 * 6290 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6291 * vCC (r1). Useful for integer division and modulus. 6292 * 6293 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6294 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6295 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6296 * rem-double/2addr 6297 */ 6298 /* binop/2addr vA, vB */ 6299 mov r9, rINST, lsr #8 @ r9<- A+ 6300 mov r1, rINST, lsr #12 @ r1<- B 6301 and r9, r9, #15 6302 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6303 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6304 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6305 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6306 .if 0 6307 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6308 beq common_errDivideByZero 6309 .endif 6310 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6311 6312 eor r0, r0, r2 @ optional op; may set condition codes 6313 eor r1, r1, r3 @ result<- op, r0-r3 changed 6314 GET_INST_OPCODE(ip) @ extract opcode from rINST 6315 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6316 GOTO_OPCODE(ip) @ jump to next instruction 6317 /* 12-15 instructions */ 6318 6319 6320 6321/* ------------------------------ */ 6322 .balign 64 6323.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6324/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6325 /* 6326 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6327 * 32-bit shift distance. 6328 */ 6329 /* shl-long/2addr vA, vB */ 6330 mov r9, rINST, lsr #8 @ r9<- A+ 6331 mov r3, rINST, lsr #12 @ r3<- B 6332 and r9, r9, #15 6333 GET_VREG(r2, r3) @ r2<- vB 6334 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6335 and r2, r2, #63 @ r2<- r2 & 0x3f 6336 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6337 6338 mov r1, r1, asl r2 @ r1<- r1 << r2 6339 rsb r3, r2, #32 @ r3<- 32 - r2 6340 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6341 subs ip, r2, #32 @ ip<- r2 - 32 6342 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6343 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6344 mov r0, r0, asl r2 @ r0<- r0 << r2 6345 b .LOP_SHL_LONG_2ADDR_finish 6346 6347/* ------------------------------ */ 6348 .balign 64 6349.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6350/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6351 /* 6352 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6353 * 32-bit shift distance. 6354 */ 6355 /* shr-long/2addr vA, vB */ 6356 mov r9, rINST, lsr #8 @ r9<- A+ 6357 mov r3, rINST, lsr #12 @ r3<- B 6358 and r9, r9, #15 6359 GET_VREG(r2, r3) @ r2<- vB 6360 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6361 and r2, r2, #63 @ r2<- r2 & 0x3f 6362 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6363 6364 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6365 rsb r3, r2, #32 @ r3<- 32 - r2 6366 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6367 subs ip, r2, #32 @ ip<- r2 - 32 6368 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6369 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6370 mov r1, r1, asr r2 @ r1<- r1 >> r2 6371 b .LOP_SHR_LONG_2ADDR_finish 6372 6373/* ------------------------------ */ 6374 .balign 64 6375.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6376/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6377 /* 6378 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6379 * 32-bit shift distance. 6380 */ 6381 /* ushr-long/2addr vA, vB */ 6382 mov r9, rINST, lsr #8 @ r9<- A+ 6383 mov r3, rINST, lsr #12 @ r3<- B 6384 and r9, r9, #15 6385 GET_VREG(r2, r3) @ r2<- vB 6386 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6387 and r2, r2, #63 @ r2<- r2 & 0x3f 6388 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6389 6390 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6391 rsb r3, r2, #32 @ r3<- 32 - r2 6392 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6393 subs ip, r2, #32 @ ip<- r2 - 32 6394 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6395 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6396 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6397 b .LOP_USHR_LONG_2ADDR_finish 6398 6399/* ------------------------------ */ 6400 .balign 64 6401.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6402/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */ 6403/* File: armv5te/binop2addr.S */ 6404 /* 6405 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6406 * that specifies an instruction that performs "result = r0 op r1". 6407 * This could be an ARM instruction or a function call. (If the result 6408 * comes back in a register other than r0, you can override "result".) 6409 * 6410 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6411 * vCC (r1). Useful for integer division and modulus. 6412 * 6413 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6414 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6415 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6416 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6417 */ 6418 /* binop/2addr vA, vB */ 6419 mov r9, rINST, lsr #8 @ r9<- A+ 6420 mov r3, rINST, lsr #12 @ r3<- B 6421 and r9, r9, #15 6422 GET_VREG(r0, r9) @ r0<- vA 6423 GET_VREG(r1, r3) @ r1<- vB 6424 .if 0 6425 cmp r1, #0 @ is second operand zero? 6426 beq common_errDivideByZero 6427 .endif 6428 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6429 6430 @ optional op; may set condition codes 6431 bl __aeabi_fadd @ r0<- op, r0-r3 changed 6432 GET_INST_OPCODE(ip) @ extract opcode from rINST 6433 SET_VREG(r0, r9) @ vAA<- r0 6434 GOTO_OPCODE(ip) @ jump to next instruction 6435 /* 10-13 instructions */ 6436 6437 6438 6439/* ------------------------------ */ 6440 .balign 64 6441.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6442/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */ 6443/* File: armv5te/binop2addr.S */ 6444 /* 6445 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6446 * that specifies an instruction that performs "result = r0 op r1". 6447 * This could be an ARM instruction or a function call. (If the result 6448 * comes back in a register other than r0, you can override "result".) 6449 * 6450 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6451 * vCC (r1). Useful for integer division and modulus. 6452 * 6453 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6454 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6455 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6456 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6457 */ 6458 /* binop/2addr vA, vB */ 6459 mov r9, rINST, lsr #8 @ r9<- A+ 6460 mov r3, rINST, lsr #12 @ r3<- B 6461 and r9, r9, #15 6462 GET_VREG(r0, r9) @ r0<- vA 6463 GET_VREG(r1, r3) @ r1<- vB 6464 .if 0 6465 cmp r1, #0 @ is second operand zero? 6466 beq common_errDivideByZero 6467 .endif 6468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6469 6470 @ optional op; may set condition codes 6471 bl __aeabi_fsub @ r0<- op, r0-r3 changed 6472 GET_INST_OPCODE(ip) @ extract opcode from rINST 6473 SET_VREG(r0, r9) @ vAA<- r0 6474 GOTO_OPCODE(ip) @ jump to next instruction 6475 /* 10-13 instructions */ 6476 6477 6478 6479/* ------------------------------ */ 6480 .balign 64 6481.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6482/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */ 6483/* File: armv5te/binop2addr.S */ 6484 /* 6485 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6486 * that specifies an instruction that performs "result = r0 op r1". 6487 * This could be an ARM instruction or a function call. (If the result 6488 * comes back in a register other than r0, you can override "result".) 6489 * 6490 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6491 * vCC (r1). Useful for integer division and modulus. 6492 * 6493 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6494 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6495 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6496 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6497 */ 6498 /* binop/2addr vA, vB */ 6499 mov r9, rINST, lsr #8 @ r9<- A+ 6500 mov r3, rINST, lsr #12 @ r3<- B 6501 and r9, r9, #15 6502 GET_VREG(r0, r9) @ r0<- vA 6503 GET_VREG(r1, r3) @ r1<- vB 6504 .if 0 6505 cmp r1, #0 @ is second operand zero? 6506 beq common_errDivideByZero 6507 .endif 6508 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6509 6510 @ optional op; may set condition codes 6511 bl __aeabi_fmul @ r0<- op, r0-r3 changed 6512 GET_INST_OPCODE(ip) @ extract opcode from rINST 6513 SET_VREG(r0, r9) @ vAA<- r0 6514 GOTO_OPCODE(ip) @ jump to next instruction 6515 /* 10-13 instructions */ 6516 6517 6518 6519/* ------------------------------ */ 6520 .balign 64 6521.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6522/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */ 6523/* File: armv5te/binop2addr.S */ 6524 /* 6525 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6526 * that specifies an instruction that performs "result = r0 op r1". 6527 * This could be an ARM instruction or a function call. (If the result 6528 * comes back in a register other than r0, you can override "result".) 6529 * 6530 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6531 * vCC (r1). Useful for integer division and modulus. 6532 * 6533 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6534 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6535 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6536 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6537 */ 6538 /* binop/2addr vA, vB */ 6539 mov r9, rINST, lsr #8 @ r9<- A+ 6540 mov r3, rINST, lsr #12 @ r3<- B 6541 and r9, r9, #15 6542 GET_VREG(r0, r9) @ r0<- vA 6543 GET_VREG(r1, r3) @ r1<- vB 6544 .if 0 6545 cmp r1, #0 @ is second operand zero? 6546 beq common_errDivideByZero 6547 .endif 6548 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6549 6550 @ optional op; may set condition codes 6551 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 6552 GET_INST_OPCODE(ip) @ extract opcode from rINST 6553 SET_VREG(r0, r9) @ vAA<- r0 6554 GOTO_OPCODE(ip) @ jump to next instruction 6555 /* 10-13 instructions */ 6556 6557 6558 6559/* ------------------------------ */ 6560 .balign 64 6561.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6562/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6563/* EABI doesn't define a float remainder function, but libm does */ 6564/* File: armv5te/binop2addr.S */ 6565 /* 6566 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6567 * that specifies an instruction that performs "result = r0 op r1". 6568 * This could be an ARM instruction or a function call. (If the result 6569 * comes back in a register other than r0, you can override "result".) 6570 * 6571 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6572 * vCC (r1). Useful for integer division and modulus. 6573 * 6574 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6575 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6576 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6577 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6578 */ 6579 /* binop/2addr vA, vB */ 6580 mov r9, rINST, lsr #8 @ r9<- A+ 6581 mov r3, rINST, lsr #12 @ r3<- B 6582 and r9, r9, #15 6583 GET_VREG(r0, r9) @ r0<- vA 6584 GET_VREG(r1, r3) @ r1<- vB 6585 .if 0 6586 cmp r1, #0 @ is second operand zero? 6587 beq common_errDivideByZero 6588 .endif 6589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6590 6591 @ optional op; may set condition codes 6592 bl fmodf @ r0<- op, r0-r3 changed 6593 GET_INST_OPCODE(ip) @ extract opcode from rINST 6594 SET_VREG(r0, r9) @ vAA<- r0 6595 GOTO_OPCODE(ip) @ jump to next instruction 6596 /* 10-13 instructions */ 6597 6598 6599 6600/* ------------------------------ */ 6601 .balign 64 6602.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6603/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */ 6604/* File: armv5te/binopWide2addr.S */ 6605 /* 6606 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6607 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6608 * This could be an ARM instruction or a function call. (If the result 6609 * comes back in a register other than r0, you can override "result".) 6610 * 6611 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6612 * vCC (r1). Useful for integer division and modulus. 6613 * 6614 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6615 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6616 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6617 * rem-double/2addr 6618 */ 6619 /* binop/2addr vA, vB */ 6620 mov r9, rINST, lsr #8 @ r9<- A+ 6621 mov r1, rINST, lsr #12 @ r1<- B 6622 and r9, r9, #15 6623 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6624 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6625 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6626 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6627 .if 0 6628 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6629 beq common_errDivideByZero 6630 .endif 6631 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6632 6633 @ optional op; may set condition codes 6634 bl __aeabi_dadd @ result<- op, r0-r3 changed 6635 GET_INST_OPCODE(ip) @ extract opcode from rINST 6636 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6637 GOTO_OPCODE(ip) @ jump to next instruction 6638 /* 12-15 instructions */ 6639 6640 6641 6642/* ------------------------------ */ 6643 .balign 64 6644.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6645/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */ 6646/* File: armv5te/binopWide2addr.S */ 6647 /* 6648 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6649 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6650 * This could be an ARM instruction or a function call. (If the result 6651 * comes back in a register other than r0, you can override "result".) 6652 * 6653 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6654 * vCC (r1). Useful for integer division and modulus. 6655 * 6656 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6657 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6658 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6659 * rem-double/2addr 6660 */ 6661 /* binop/2addr vA, vB */ 6662 mov r9, rINST, lsr #8 @ r9<- A+ 6663 mov r1, rINST, lsr #12 @ r1<- B 6664 and r9, r9, #15 6665 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6666 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6667 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6668 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6669 .if 0 6670 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6671 beq common_errDivideByZero 6672 .endif 6673 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6674 6675 @ optional op; may set condition codes 6676 bl __aeabi_dsub @ result<- op, r0-r3 changed 6677 GET_INST_OPCODE(ip) @ extract opcode from rINST 6678 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6679 GOTO_OPCODE(ip) @ jump to next instruction 6680 /* 12-15 instructions */ 6681 6682 6683 6684/* ------------------------------ */ 6685 .balign 64 6686.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6687/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */ 6688/* File: armv5te/binopWide2addr.S */ 6689 /* 6690 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6691 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6692 * This could be an ARM instruction or a function call. (If the result 6693 * comes back in a register other than r0, you can override "result".) 6694 * 6695 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6696 * vCC (r1). Useful for integer division and modulus. 6697 * 6698 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6699 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6700 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6701 * rem-double/2addr 6702 */ 6703 /* binop/2addr vA, vB */ 6704 mov r9, rINST, lsr #8 @ r9<- A+ 6705 mov r1, rINST, lsr #12 @ r1<- B 6706 and r9, r9, #15 6707 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6708 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6709 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6710 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6711 .if 0 6712 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6713 beq common_errDivideByZero 6714 .endif 6715 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6716 6717 @ optional op; may set condition codes 6718 bl __aeabi_dmul @ result<- op, r0-r3 changed 6719 GET_INST_OPCODE(ip) @ extract opcode from rINST 6720 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6721 GOTO_OPCODE(ip) @ jump to next instruction 6722 /* 12-15 instructions */ 6723 6724 6725 6726/* ------------------------------ */ 6727 .balign 64 6728.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6729/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */ 6730/* File: armv5te/binopWide2addr.S */ 6731 /* 6732 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6733 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6734 * This could be an ARM instruction or a function call. (If the result 6735 * comes back in a register other than r0, you can override "result".) 6736 * 6737 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6738 * vCC (r1). Useful for integer division and modulus. 6739 * 6740 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6741 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6742 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6743 * rem-double/2addr 6744 */ 6745 /* binop/2addr vA, vB */ 6746 mov r9, rINST, lsr #8 @ r9<- A+ 6747 mov r1, rINST, lsr #12 @ r1<- B 6748 and r9, r9, #15 6749 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6750 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6751 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6752 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6753 .if 0 6754 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6755 beq common_errDivideByZero 6756 .endif 6757 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6758 6759 @ optional op; may set condition codes 6760 bl __aeabi_ddiv @ result<- op, r0-r3 changed 6761 GET_INST_OPCODE(ip) @ extract opcode from rINST 6762 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6763 GOTO_OPCODE(ip) @ jump to next instruction 6764 /* 12-15 instructions */ 6765 6766 6767 6768/* ------------------------------ */ 6769 .balign 64 6770.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6771/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6772/* EABI doesn't define a double remainder function, but libm does */ 6773/* File: armv5te/binopWide2addr.S */ 6774 /* 6775 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6776 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6777 * This could be an ARM instruction or a function call. (If the result 6778 * comes back in a register other than r0, you can override "result".) 6779 * 6780 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6781 * vCC (r1). Useful for integer division and modulus. 6782 * 6783 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6784 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6785 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6786 * rem-double/2addr 6787 */ 6788 /* binop/2addr vA, vB */ 6789 mov r9, rINST, lsr #8 @ r9<- A+ 6790 mov r1, rINST, lsr #12 @ r1<- B 6791 and r9, r9, #15 6792 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6793 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6794 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6795 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6796 .if 0 6797 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6798 beq common_errDivideByZero 6799 .endif 6800 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6801 6802 @ optional op; may set condition codes 6803 bl fmod @ result<- op, r0-r3 changed 6804 GET_INST_OPCODE(ip) @ extract opcode from rINST 6805 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6806 GOTO_OPCODE(ip) @ jump to next instruction 6807 /* 12-15 instructions */ 6808 6809 6810 6811/* ------------------------------ */ 6812 .balign 64 6813.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6814/* File: armv5te/OP_ADD_INT_LIT16.S */ 6815/* File: armv5te/binopLit16.S */ 6816 /* 6817 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6818 * that specifies an instruction that performs "result = r0 op r1". 6819 * This could be an ARM instruction or a function call. (If the result 6820 * comes back in a register other than r0, you can override "result".) 6821 * 6822 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6823 * vCC (r1). Useful for integer division and modulus. 6824 * 6825 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6826 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6827 */ 6828 /* binop/lit16 vA, vB, #+CCCC */ 6829 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6830 mov r2, rINST, lsr #12 @ r2<- B 6831 mov r9, rINST, lsr #8 @ r9<- A+ 6832 GET_VREG(r0, r2) @ r0<- vB 6833 and r9, r9, #15 6834 .if 0 6835 cmp r1, #0 @ is second operand zero? 6836 beq common_errDivideByZero 6837 .endif 6838 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6839 6840 add r0, r0, r1 @ r0<- op, r0-r3 changed 6841 GET_INST_OPCODE(ip) @ extract opcode from rINST 6842 SET_VREG(r0, r9) @ vAA<- r0 6843 GOTO_OPCODE(ip) @ jump to next instruction 6844 /* 10-13 instructions */ 6845 6846 6847 6848/* ------------------------------ */ 6849 .balign 64 6850.L_OP_RSUB_INT: /* 0xd1 */ 6851/* File: armv5te/OP_RSUB_INT.S */ 6852/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6853/* File: armv5te/binopLit16.S */ 6854 /* 6855 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6856 * that specifies an instruction that performs "result = r0 op r1". 6857 * This could be an ARM instruction or a function call. (If the result 6858 * comes back in a register other than r0, you can override "result".) 6859 * 6860 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6861 * vCC (r1). Useful for integer division and modulus. 6862 * 6863 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6864 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6865 */ 6866 /* binop/lit16 vA, vB, #+CCCC */ 6867 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6868 mov r2, rINST, lsr #12 @ r2<- B 6869 mov r9, rINST, lsr #8 @ r9<- A+ 6870 GET_VREG(r0, r2) @ r0<- vB 6871 and r9, r9, #15 6872 .if 0 6873 cmp r1, #0 @ is second operand zero? 6874 beq common_errDivideByZero 6875 .endif 6876 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6877 6878 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6879 GET_INST_OPCODE(ip) @ extract opcode from rINST 6880 SET_VREG(r0, r9) @ vAA<- r0 6881 GOTO_OPCODE(ip) @ jump to next instruction 6882 /* 10-13 instructions */ 6883 6884 6885 6886/* ------------------------------ */ 6887 .balign 64 6888.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6889/* File: armv5te/OP_MUL_INT_LIT16.S */ 6890/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6891/* File: armv5te/binopLit16.S */ 6892 /* 6893 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6894 * that specifies an instruction that performs "result = r0 op r1". 6895 * This could be an ARM instruction or a function call. (If the result 6896 * comes back in a register other than r0, you can override "result".) 6897 * 6898 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6899 * vCC (r1). Useful for integer division and modulus. 6900 * 6901 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6902 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6903 */ 6904 /* binop/lit16 vA, vB, #+CCCC */ 6905 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6906 mov r2, rINST, lsr #12 @ r2<- B 6907 mov r9, rINST, lsr #8 @ r9<- A+ 6908 GET_VREG(r0, r2) @ r0<- vB 6909 and r9, r9, #15 6910 .if 0 6911 cmp r1, #0 @ is second operand zero? 6912 beq common_errDivideByZero 6913 .endif 6914 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6915 6916 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6917 GET_INST_OPCODE(ip) @ extract opcode from rINST 6918 SET_VREG(r0, r9) @ vAA<- r0 6919 GOTO_OPCODE(ip) @ jump to next instruction 6920 /* 10-13 instructions */ 6921 6922 6923 6924/* ------------------------------ */ 6925 .balign 64 6926.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6927/* File: armv5te/OP_DIV_INT_LIT16.S */ 6928/* File: armv5te/binopLit16.S */ 6929 /* 6930 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6931 * that specifies an instruction that performs "result = r0 op r1". 6932 * This could be an ARM instruction or a function call. (If the result 6933 * comes back in a register other than r0, you can override "result".) 6934 * 6935 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6936 * vCC (r1). Useful for integer division and modulus. 6937 * 6938 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6939 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6940 */ 6941 /* binop/lit16 vA, vB, #+CCCC */ 6942 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6943 mov r2, rINST, lsr #12 @ r2<- B 6944 mov r9, rINST, lsr #8 @ r9<- A+ 6945 GET_VREG(r0, r2) @ r0<- vB 6946 and r9, r9, #15 6947 .if 1 6948 cmp r1, #0 @ is second operand zero? 6949 beq common_errDivideByZero 6950 .endif 6951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6952 6953 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6954 GET_INST_OPCODE(ip) @ extract opcode from rINST 6955 SET_VREG(r0, r9) @ vAA<- r0 6956 GOTO_OPCODE(ip) @ jump to next instruction 6957 /* 10-13 instructions */ 6958 6959 6960 6961/* ------------------------------ */ 6962 .balign 64 6963.L_OP_REM_INT_LIT16: /* 0xd4 */ 6964/* File: armv5te/OP_REM_INT_LIT16.S */ 6965/* idivmod returns quotient in r0 and remainder in r1 */ 6966/* File: armv5te/binopLit16.S */ 6967 /* 6968 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6969 * that specifies an instruction that performs "result = r0 op r1". 6970 * This could be an ARM instruction or a function call. (If the result 6971 * comes back in a register other than r0, you can override "result".) 6972 * 6973 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6974 * vCC (r1). Useful for integer division and modulus. 6975 * 6976 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6977 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6978 */ 6979 /* binop/lit16 vA, vB, #+CCCC */ 6980 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6981 mov r2, rINST, lsr #12 @ r2<- B 6982 mov r9, rINST, lsr #8 @ r9<- A+ 6983 GET_VREG(r0, r2) @ r0<- vB 6984 and r9, r9, #15 6985 .if 1 6986 cmp r1, #0 @ is second operand zero? 6987 beq common_errDivideByZero 6988 .endif 6989 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6990 6991 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6992 GET_INST_OPCODE(ip) @ extract opcode from rINST 6993 SET_VREG(r1, r9) @ vAA<- r1 6994 GOTO_OPCODE(ip) @ jump to next instruction 6995 /* 10-13 instructions */ 6996 6997 6998 6999/* ------------------------------ */ 7000 .balign 64 7001.L_OP_AND_INT_LIT16: /* 0xd5 */ 7002/* File: armv5te/OP_AND_INT_LIT16.S */ 7003/* File: armv5te/binopLit16.S */ 7004 /* 7005 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7006 * that specifies an instruction that performs "result = r0 op r1". 7007 * This could be an ARM instruction or a function call. (If the result 7008 * comes back in a register other than r0, you can override "result".) 7009 * 7010 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7011 * vCC (r1). Useful for integer division and modulus. 7012 * 7013 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7014 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7015 */ 7016 /* binop/lit16 vA, vB, #+CCCC */ 7017 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7018 mov r2, rINST, lsr #12 @ r2<- B 7019 mov r9, rINST, lsr #8 @ r9<- A+ 7020 GET_VREG(r0, r2) @ r0<- vB 7021 and r9, r9, #15 7022 .if 0 7023 cmp r1, #0 @ is second operand zero? 7024 beq common_errDivideByZero 7025 .endif 7026 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7027 7028 and r0, r0, r1 @ r0<- op, r0-r3 changed 7029 GET_INST_OPCODE(ip) @ extract opcode from rINST 7030 SET_VREG(r0, r9) @ vAA<- r0 7031 GOTO_OPCODE(ip) @ jump to next instruction 7032 /* 10-13 instructions */ 7033 7034 7035 7036/* ------------------------------ */ 7037 .balign 64 7038.L_OP_OR_INT_LIT16: /* 0xd6 */ 7039/* File: armv5te/OP_OR_INT_LIT16.S */ 7040/* File: armv5te/binopLit16.S */ 7041 /* 7042 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7043 * that specifies an instruction that performs "result = r0 op r1". 7044 * This could be an ARM instruction or a function call. (If the result 7045 * comes back in a register other than r0, you can override "result".) 7046 * 7047 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7048 * vCC (r1). Useful for integer division and modulus. 7049 * 7050 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7051 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7052 */ 7053 /* binop/lit16 vA, vB, #+CCCC */ 7054 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7055 mov r2, rINST, lsr #12 @ r2<- B 7056 mov r9, rINST, lsr #8 @ r9<- A+ 7057 GET_VREG(r0, r2) @ r0<- vB 7058 and r9, r9, #15 7059 .if 0 7060 cmp r1, #0 @ is second operand zero? 7061 beq common_errDivideByZero 7062 .endif 7063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7064 7065 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7066 GET_INST_OPCODE(ip) @ extract opcode from rINST 7067 SET_VREG(r0, r9) @ vAA<- r0 7068 GOTO_OPCODE(ip) @ jump to next instruction 7069 /* 10-13 instructions */ 7070 7071 7072 7073/* ------------------------------ */ 7074 .balign 64 7075.L_OP_XOR_INT_LIT16: /* 0xd7 */ 7076/* File: armv5te/OP_XOR_INT_LIT16.S */ 7077/* File: armv5te/binopLit16.S */ 7078 /* 7079 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 7080 * that specifies an instruction that performs "result = r0 op r1". 7081 * This could be an ARM instruction or a function call. (If the result 7082 * comes back in a register other than r0, you can override "result".) 7083 * 7084 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7085 * vCC (r1). Useful for integer division and modulus. 7086 * 7087 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 7088 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 7089 */ 7090 /* binop/lit16 vA, vB, #+CCCC */ 7091 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 7092 mov r2, rINST, lsr #12 @ r2<- B 7093 mov r9, rINST, lsr #8 @ r9<- A+ 7094 GET_VREG(r0, r2) @ r0<- vB 7095 and r9, r9, #15 7096 .if 0 7097 cmp r1, #0 @ is second operand zero? 7098 beq common_errDivideByZero 7099 .endif 7100 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7101 7102 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7103 GET_INST_OPCODE(ip) @ extract opcode from rINST 7104 SET_VREG(r0, r9) @ vAA<- r0 7105 GOTO_OPCODE(ip) @ jump to next instruction 7106 /* 10-13 instructions */ 7107 7108 7109 7110/* ------------------------------ */ 7111 .balign 64 7112.L_OP_ADD_INT_LIT8: /* 0xd8 */ 7113/* File: armv5te/OP_ADD_INT_LIT8.S */ 7114/* File: armv5te/binopLit8.S */ 7115 /* 7116 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7117 * that specifies an instruction that performs "result = r0 op r1". 7118 * This could be an ARM instruction or a function call. (If the result 7119 * comes back in a register other than r0, you can override "result".) 7120 * 7121 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7122 * vCC (r1). Useful for integer division and modulus. 7123 * 7124 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7125 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7126 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7127 */ 7128 /* binop/lit8 vAA, vBB, #+CC */ 7129 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7130 mov r9, rINST, lsr #8 @ r9<- AA 7131 and r2, r3, #255 @ r2<- BB 7132 GET_VREG(r0, r2) @ r0<- vBB 7133 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7134 .if 0 7135 @cmp r1, #0 @ is second operand zero? 7136 beq common_errDivideByZero 7137 .endif 7138 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7139 7140 @ optional op; may set condition codes 7141 add r0, r0, r1 @ r0<- op, r0-r3 changed 7142 GET_INST_OPCODE(ip) @ extract opcode from rINST 7143 SET_VREG(r0, r9) @ vAA<- r0 7144 GOTO_OPCODE(ip) @ jump to next instruction 7145 /* 10-12 instructions */ 7146 7147 7148 7149/* ------------------------------ */ 7150 .balign 64 7151.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 7152/* File: armv5te/OP_RSUB_INT_LIT8.S */ 7153/* File: armv5te/binopLit8.S */ 7154 /* 7155 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7156 * that specifies an instruction that performs "result = r0 op r1". 7157 * This could be an ARM instruction or a function call. (If the result 7158 * comes back in a register other than r0, you can override "result".) 7159 * 7160 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7161 * vCC (r1). Useful for integer division and modulus. 7162 * 7163 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7164 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7165 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7166 */ 7167 /* binop/lit8 vAA, vBB, #+CC */ 7168 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7169 mov r9, rINST, lsr #8 @ r9<- AA 7170 and r2, r3, #255 @ r2<- BB 7171 GET_VREG(r0, r2) @ r0<- vBB 7172 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7173 .if 0 7174 @cmp r1, #0 @ is second operand zero? 7175 beq common_errDivideByZero 7176 .endif 7177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7178 7179 @ optional op; may set condition codes 7180 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 7181 GET_INST_OPCODE(ip) @ extract opcode from rINST 7182 SET_VREG(r0, r9) @ vAA<- r0 7183 GOTO_OPCODE(ip) @ jump to next instruction 7184 /* 10-12 instructions */ 7185 7186 7187 7188/* ------------------------------ */ 7189 .balign 64 7190.L_OP_MUL_INT_LIT8: /* 0xda */ 7191/* File: armv5te/OP_MUL_INT_LIT8.S */ 7192/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 7193/* File: armv5te/binopLit8.S */ 7194 /* 7195 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7196 * that specifies an instruction that performs "result = r0 op r1". 7197 * This could be an ARM instruction or a function call. (If the result 7198 * comes back in a register other than r0, you can override "result".) 7199 * 7200 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7201 * vCC (r1). Useful for integer division and modulus. 7202 * 7203 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7204 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7205 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7206 */ 7207 /* binop/lit8 vAA, vBB, #+CC */ 7208 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7209 mov r9, rINST, lsr #8 @ r9<- AA 7210 and r2, r3, #255 @ r2<- BB 7211 GET_VREG(r0, r2) @ r0<- vBB 7212 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7213 .if 0 7214 @cmp r1, #0 @ is second operand zero? 7215 beq common_errDivideByZero 7216 .endif 7217 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7218 7219 @ optional op; may set condition codes 7220 mul r0, r1, r0 @ r0<- op, r0-r3 changed 7221 GET_INST_OPCODE(ip) @ extract opcode from rINST 7222 SET_VREG(r0, r9) @ vAA<- r0 7223 GOTO_OPCODE(ip) @ jump to next instruction 7224 /* 10-12 instructions */ 7225 7226 7227 7228/* ------------------------------ */ 7229 .balign 64 7230.L_OP_DIV_INT_LIT8: /* 0xdb */ 7231/* File: armv5te/OP_DIV_INT_LIT8.S */ 7232/* File: armv5te/binopLit8.S */ 7233 /* 7234 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7235 * that specifies an instruction that performs "result = r0 op r1". 7236 * This could be an ARM instruction or a function call. (If the result 7237 * comes back in a register other than r0, you can override "result".) 7238 * 7239 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7240 * vCC (r1). Useful for integer division and modulus. 7241 * 7242 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7243 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7244 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7245 */ 7246 /* binop/lit8 vAA, vBB, #+CC */ 7247 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7248 mov r9, rINST, lsr #8 @ r9<- AA 7249 and r2, r3, #255 @ r2<- BB 7250 GET_VREG(r0, r2) @ r0<- vBB 7251 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7252 .if 1 7253 @cmp r1, #0 @ is second operand zero? 7254 beq common_errDivideByZero 7255 .endif 7256 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7257 7258 @ optional op; may set condition codes 7259 bl __aeabi_idiv @ r0<- op, r0-r3 changed 7260 GET_INST_OPCODE(ip) @ extract opcode from rINST 7261 SET_VREG(r0, r9) @ vAA<- r0 7262 GOTO_OPCODE(ip) @ jump to next instruction 7263 /* 10-12 instructions */ 7264 7265 7266 7267/* ------------------------------ */ 7268 .balign 64 7269.L_OP_REM_INT_LIT8: /* 0xdc */ 7270/* File: armv5te/OP_REM_INT_LIT8.S */ 7271/* idivmod returns quotient in r0 and remainder in r1 */ 7272/* File: armv5te/binopLit8.S */ 7273 /* 7274 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7275 * that specifies an instruction that performs "result = r0 op r1". 7276 * This could be an ARM instruction or a function call. (If the result 7277 * comes back in a register other than r0, you can override "result".) 7278 * 7279 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7280 * vCC (r1). Useful for integer division and modulus. 7281 * 7282 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7283 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7284 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7285 */ 7286 /* binop/lit8 vAA, vBB, #+CC */ 7287 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7288 mov r9, rINST, lsr #8 @ r9<- AA 7289 and r2, r3, #255 @ r2<- BB 7290 GET_VREG(r0, r2) @ r0<- vBB 7291 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7292 .if 1 7293 @cmp r1, #0 @ is second operand zero? 7294 beq common_errDivideByZero 7295 .endif 7296 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7297 7298 @ optional op; may set condition codes 7299 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 7300 GET_INST_OPCODE(ip) @ extract opcode from rINST 7301 SET_VREG(r1, r9) @ vAA<- r1 7302 GOTO_OPCODE(ip) @ jump to next instruction 7303 /* 10-12 instructions */ 7304 7305 7306 7307/* ------------------------------ */ 7308 .balign 64 7309.L_OP_AND_INT_LIT8: /* 0xdd */ 7310/* File: armv5te/OP_AND_INT_LIT8.S */ 7311/* File: armv5te/binopLit8.S */ 7312 /* 7313 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7314 * that specifies an instruction that performs "result = r0 op r1". 7315 * This could be an ARM instruction or a function call. (If the result 7316 * comes back in a register other than r0, you can override "result".) 7317 * 7318 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7319 * vCC (r1). Useful for integer division and modulus. 7320 * 7321 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7322 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7323 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7324 */ 7325 /* binop/lit8 vAA, vBB, #+CC */ 7326 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7327 mov r9, rINST, lsr #8 @ r9<- AA 7328 and r2, r3, #255 @ r2<- BB 7329 GET_VREG(r0, r2) @ r0<- vBB 7330 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7331 .if 0 7332 @cmp r1, #0 @ is second operand zero? 7333 beq common_errDivideByZero 7334 .endif 7335 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7336 7337 @ optional op; may set condition codes 7338 and r0, r0, r1 @ r0<- op, r0-r3 changed 7339 GET_INST_OPCODE(ip) @ extract opcode from rINST 7340 SET_VREG(r0, r9) @ vAA<- r0 7341 GOTO_OPCODE(ip) @ jump to next instruction 7342 /* 10-12 instructions */ 7343 7344 7345 7346/* ------------------------------ */ 7347 .balign 64 7348.L_OP_OR_INT_LIT8: /* 0xde */ 7349/* File: armv5te/OP_OR_INT_LIT8.S */ 7350/* File: armv5te/binopLit8.S */ 7351 /* 7352 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7353 * that specifies an instruction that performs "result = r0 op r1". 7354 * This could be an ARM instruction or a function call. (If the result 7355 * comes back in a register other than r0, you can override "result".) 7356 * 7357 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7358 * vCC (r1). Useful for integer division and modulus. 7359 * 7360 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7361 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7362 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7363 */ 7364 /* binop/lit8 vAA, vBB, #+CC */ 7365 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7366 mov r9, rINST, lsr #8 @ r9<- AA 7367 and r2, r3, #255 @ r2<- BB 7368 GET_VREG(r0, r2) @ r0<- vBB 7369 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7370 .if 0 7371 @cmp r1, #0 @ is second operand zero? 7372 beq common_errDivideByZero 7373 .endif 7374 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7375 7376 @ optional op; may set condition codes 7377 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7378 GET_INST_OPCODE(ip) @ extract opcode from rINST 7379 SET_VREG(r0, r9) @ vAA<- r0 7380 GOTO_OPCODE(ip) @ jump to next instruction 7381 /* 10-12 instructions */ 7382 7383 7384 7385/* ------------------------------ */ 7386 .balign 64 7387.L_OP_XOR_INT_LIT8: /* 0xdf */ 7388/* File: armv5te/OP_XOR_INT_LIT8.S */ 7389/* File: armv5te/binopLit8.S */ 7390 /* 7391 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7392 * that specifies an instruction that performs "result = r0 op r1". 7393 * This could be an ARM instruction or a function call. (If the result 7394 * comes back in a register other than r0, you can override "result".) 7395 * 7396 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7397 * vCC (r1). Useful for integer division and modulus. 7398 * 7399 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7400 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7401 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7402 */ 7403 /* binop/lit8 vAA, vBB, #+CC */ 7404 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7405 mov r9, rINST, lsr #8 @ r9<- AA 7406 and r2, r3, #255 @ r2<- BB 7407 GET_VREG(r0, r2) @ r0<- vBB 7408 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7409 .if 0 7410 @cmp r1, #0 @ is second operand zero? 7411 beq common_errDivideByZero 7412 .endif 7413 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7414 7415 @ optional op; may set condition codes 7416 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7417 GET_INST_OPCODE(ip) @ extract opcode from rINST 7418 SET_VREG(r0, r9) @ vAA<- r0 7419 GOTO_OPCODE(ip) @ jump to next instruction 7420 /* 10-12 instructions */ 7421 7422 7423 7424/* ------------------------------ */ 7425 .balign 64 7426.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7427/* File: armv5te/OP_SHL_INT_LIT8.S */ 7428/* File: armv5te/binopLit8.S */ 7429 /* 7430 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7431 * that specifies an instruction that performs "result = r0 op r1". 7432 * This could be an ARM instruction or a function call. (If the result 7433 * comes back in a register other than r0, you can override "result".) 7434 * 7435 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7436 * vCC (r1). Useful for integer division and modulus. 7437 * 7438 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7439 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7440 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7441 */ 7442 /* binop/lit8 vAA, vBB, #+CC */ 7443 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7444 mov r9, rINST, lsr #8 @ r9<- AA 7445 and r2, r3, #255 @ r2<- BB 7446 GET_VREG(r0, r2) @ r0<- vBB 7447 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7448 .if 0 7449 @cmp r1, #0 @ is second operand zero? 7450 beq common_errDivideByZero 7451 .endif 7452 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7453 7454 and r1, r1, #31 @ optional op; may set condition codes 7455 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7456 GET_INST_OPCODE(ip) @ extract opcode from rINST 7457 SET_VREG(r0, r9) @ vAA<- r0 7458 GOTO_OPCODE(ip) @ jump to next instruction 7459 /* 10-12 instructions */ 7460 7461 7462 7463/* ------------------------------ */ 7464 .balign 64 7465.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7466/* File: armv5te/OP_SHR_INT_LIT8.S */ 7467/* File: armv5te/binopLit8.S */ 7468 /* 7469 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7470 * that specifies an instruction that performs "result = r0 op r1". 7471 * This could be an ARM instruction or a function call. (If the result 7472 * comes back in a register other than r0, you can override "result".) 7473 * 7474 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7475 * vCC (r1). Useful for integer division and modulus. 7476 * 7477 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7478 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7479 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7480 */ 7481 /* binop/lit8 vAA, vBB, #+CC */ 7482 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7483 mov r9, rINST, lsr #8 @ r9<- AA 7484 and r2, r3, #255 @ r2<- BB 7485 GET_VREG(r0, r2) @ r0<- vBB 7486 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7487 .if 0 7488 @cmp r1, #0 @ is second operand zero? 7489 beq common_errDivideByZero 7490 .endif 7491 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7492 7493 and r1, r1, #31 @ optional op; may set condition codes 7494 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7495 GET_INST_OPCODE(ip) @ extract opcode from rINST 7496 SET_VREG(r0, r9) @ vAA<- r0 7497 GOTO_OPCODE(ip) @ jump to next instruction 7498 /* 10-12 instructions */ 7499 7500 7501 7502/* ------------------------------ */ 7503 .balign 64 7504.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7505/* File: armv5te/OP_USHR_INT_LIT8.S */ 7506/* File: armv5te/binopLit8.S */ 7507 /* 7508 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7509 * that specifies an instruction that performs "result = r0 op r1". 7510 * This could be an ARM instruction or a function call. (If the result 7511 * comes back in a register other than r0, you can override "result".) 7512 * 7513 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7514 * vCC (r1). Useful for integer division and modulus. 7515 * 7516 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7517 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7518 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7519 */ 7520 /* binop/lit8 vAA, vBB, #+CC */ 7521 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7522 mov r9, rINST, lsr #8 @ r9<- AA 7523 and r2, r3, #255 @ r2<- BB 7524 GET_VREG(r0, r2) @ r0<- vBB 7525 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7526 .if 0 7527 @cmp r1, #0 @ is second operand zero? 7528 beq common_errDivideByZero 7529 .endif 7530 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7531 7532 and r1, r1, #31 @ optional op; may set condition codes 7533 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7534 GET_INST_OPCODE(ip) @ extract opcode from rINST 7535 SET_VREG(r0, r9) @ vAA<- r0 7536 GOTO_OPCODE(ip) @ jump to next instruction 7537 /* 10-12 instructions */ 7538 7539 7540 7541/* ------------------------------ */ 7542 .balign 64 7543.L_OP_UNUSED_E3: /* 0xe3 */ 7544/* File: armv5te/OP_UNUSED_E3.S */ 7545/* File: armv5te/unused.S */ 7546 bl common_abort 7547 7548 7549 7550/* ------------------------------ */ 7551 .balign 64 7552.L_OP_UNUSED_E4: /* 0xe4 */ 7553/* File: armv5te/OP_UNUSED_E4.S */ 7554/* File: armv5te/unused.S */ 7555 bl common_abort 7556 7557 7558 7559/* ------------------------------ */ 7560 .balign 64 7561.L_OP_UNUSED_E5: /* 0xe5 */ 7562/* File: armv5te/OP_UNUSED_E5.S */ 7563/* File: armv5te/unused.S */ 7564 bl common_abort 7565 7566 7567 7568/* ------------------------------ */ 7569 .balign 64 7570.L_OP_UNUSED_E6: /* 0xe6 */ 7571/* File: armv5te/OP_UNUSED_E6.S */ 7572/* File: armv5te/unused.S */ 7573 bl common_abort 7574 7575 7576 7577/* ------------------------------ */ 7578 .balign 64 7579.L_OP_UNUSED_E7: /* 0xe7 */ 7580/* File: armv5te/OP_UNUSED_E7.S */ 7581/* File: armv5te/unused.S */ 7582 bl common_abort 7583 7584 7585 7586/* ------------------------------ */ 7587 .balign 64 7588.L_OP_UNUSED_E8: /* 0xe8 */ 7589/* File: armv5te/OP_UNUSED_E8.S */ 7590/* File: armv5te/unused.S */ 7591 bl common_abort 7592 7593 7594 7595/* ------------------------------ */ 7596 .balign 64 7597.L_OP_UNUSED_E9: /* 0xe9 */ 7598/* File: armv5te/OP_UNUSED_E9.S */ 7599/* File: armv5te/unused.S */ 7600 bl common_abort 7601 7602 7603 7604/* ------------------------------ */ 7605 .balign 64 7606.L_OP_UNUSED_EA: /* 0xea */ 7607/* File: armv5te/OP_UNUSED_EA.S */ 7608/* File: armv5te/unused.S */ 7609 bl common_abort 7610 7611 7612 7613/* ------------------------------ */ 7614 .balign 64 7615.L_OP_UNUSED_EB: /* 0xeb */ 7616/* File: armv5te/OP_UNUSED_EB.S */ 7617/* File: armv5te/unused.S */ 7618 bl common_abort 7619 7620 7621 7622/* ------------------------------ */ 7623 .balign 64 7624.L_OP_UNUSED_EC: /* 0xec */ 7625/* File: armv5te/OP_UNUSED_EC.S */ 7626/* File: armv5te/unused.S */ 7627 bl common_abort 7628 7629 7630 7631/* ------------------------------ */ 7632 .balign 64 7633.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7634/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7635 /* 7636 * Handle a throw-verification-error instruction. This throws an 7637 * exception for an error discovered during verification. The 7638 * exception is indicated by AA, with some detail provided by BBBB. 7639 */ 7640 /* op AA, ref@BBBB */ 7641 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7642 FETCH(r2, 1) @ r2<- BBBB 7643 EXPORT_PC() @ export the PC 7644 mov r1, rINST, lsr #8 @ r1<- AA 7645 bl dvmThrowVerificationError @ always throws 7646 b common_exceptionThrown @ handle exception 7647 7648 7649/* ------------------------------ */ 7650 .balign 64 7651.L_OP_EXECUTE_INLINE: /* 0xee */ 7652/* File: armv5te/OP_EXECUTE_INLINE.S */ 7653 /* 7654 * Execute a "native inline" instruction. 7655 * 7656 * We need to call: 7657 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7658 * 7659 * The first four args are in r0-r3, but the last two must be pushed 7660 * onto the stack. 7661 */ 7662 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7663 FETCH(r10, 1) @ r10<- BBBB 7664 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7665 EXPORT_PC() @ can throw 7666 sub sp, sp, #8 @ make room for arg(s) 7667 mov r0, rINST, lsr #12 @ r0<- B 7668 str r1, [sp] @ push &glue->retval 7669 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7670 add sp, sp, #8 @ pop stack 7671 cmp r0, #0 @ test boolean result of inline 7672 beq common_exceptionThrown @ returned false, handle exception 7673 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7674 GET_INST_OPCODE(ip) @ extract opcode from rINST 7675 GOTO_OPCODE(ip) @ jump to next instruction 7676 7677/* ------------------------------ */ 7678 .balign 64 7679.L_OP_UNUSED_EF: /* 0xef */ 7680/* File: armv5te/OP_UNUSED_EF.S */ 7681/* File: armv5te/unused.S */ 7682 bl common_abort 7683 7684 7685 7686/* ------------------------------ */ 7687 .balign 64 7688.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7689/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7690 /* 7691 * invoke-direct-empty is a no-op in a "standard" interpreter. 7692 */ 7693 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7694 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7695 GOTO_OPCODE(ip) @ execute it 7696 7697/* ------------------------------ */ 7698 .balign 64 7699.L_OP_UNUSED_F1: /* 0xf1 */ 7700/* File: armv5te/OP_UNUSED_F1.S */ 7701/* File: armv5te/unused.S */ 7702 bl common_abort 7703 7704 7705 7706/* ------------------------------ */ 7707 .balign 64 7708.L_OP_IGET_QUICK: /* 0xf2 */ 7709/* File: armv5te/OP_IGET_QUICK.S */ 7710 /* For: iget-quick, iget-object-quick */ 7711 /* op vA, vB, offset@CCCC */ 7712 mov r2, rINST, lsr #12 @ r2<- B 7713 GET_VREG(r3, r2) @ r3<- object we're operating on 7714 FETCH(r1, 1) @ r1<- field byte offset 7715 cmp r3, #0 @ check object for null 7716 mov r2, rINST, lsr #8 @ r2<- A(+) 7717 beq common_errNullObject @ object was null 7718 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7720 and r2, r2, #15 7721 GET_INST_OPCODE(ip) @ extract opcode from rINST 7722 SET_VREG(r0, r2) @ fp[A]<- r0 7723 GOTO_OPCODE(ip) @ jump to next instruction 7724 7725 7726/* ------------------------------ */ 7727 .balign 64 7728.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7729/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7730 /* iget-wide-quick vA, vB, offset@CCCC */ 7731 mov r2, rINST, lsr #12 @ r2<- B 7732 GET_VREG(r3, r2) @ r3<- object we're operating on 7733 FETCH(r1, 1) @ r1<- field byte offset 7734 cmp r3, #0 @ check object for null 7735 mov r2, rINST, lsr #8 @ r2<- A(+) 7736 beq common_errNullObject @ object was null 7737 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7738 and r2, r2, #15 7739 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7740 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7741 GET_INST_OPCODE(ip) @ extract opcode from rINST 7742 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7743 GOTO_OPCODE(ip) @ jump to next instruction 7744 7745 7746/* ------------------------------ */ 7747 .balign 64 7748.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7749/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7750/* File: armv5te/OP_IGET_QUICK.S */ 7751 /* For: iget-quick, iget-object-quick */ 7752 /* op vA, vB, offset@CCCC */ 7753 mov r2, rINST, lsr #12 @ r2<- B 7754 GET_VREG(r3, r2) @ r3<- object we're operating on 7755 FETCH(r1, 1) @ r1<- field byte offset 7756 cmp r3, #0 @ check object for null 7757 mov r2, rINST, lsr #8 @ r2<- A(+) 7758 beq common_errNullObject @ object was null 7759 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7761 and r2, r2, #15 7762 GET_INST_OPCODE(ip) @ extract opcode from rINST 7763 SET_VREG(r0, r2) @ fp[A]<- r0 7764 GOTO_OPCODE(ip) @ jump to next instruction 7765 7766 7767 7768/* ------------------------------ */ 7769 .balign 64 7770.L_OP_IPUT_QUICK: /* 0xf5 */ 7771/* File: armv5te/OP_IPUT_QUICK.S */ 7772 /* For: iput-quick, iput-object-quick */ 7773 /* op vA, vB, offset@CCCC */ 7774 mov r2, rINST, lsr #12 @ r2<- B 7775 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7776 FETCH(r1, 1) @ r1<- field byte offset 7777 cmp r3, #0 @ check object for null 7778 mov r2, rINST, lsr #8 @ r2<- A(+) 7779 beq common_errNullObject @ object was null 7780 and r2, r2, #15 7781 GET_VREG(r0, r2) @ r0<- fp[A] 7782 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7783 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7784 GET_INST_OPCODE(ip) @ extract opcode from rINST 7785 GOTO_OPCODE(ip) @ jump to next instruction 7786 7787 7788/* ------------------------------ */ 7789 .balign 64 7790.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7791/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7792 /* iput-wide-quick vA, vB, offset@CCCC */ 7793 mov r0, rINST, lsr #8 @ r0<- A(+) 7794 mov r1, rINST, lsr #12 @ r1<- B 7795 and r0, r0, #15 7796 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7797 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7798 cmp r2, #0 @ check object for null 7799 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7800 beq common_errNullObject @ object was null 7801 FETCH(r3, 1) @ r3<- field byte offset 7802 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7803 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7804 GET_INST_OPCODE(ip) @ extract opcode from rINST 7805 GOTO_OPCODE(ip) @ jump to next instruction 7806 7807 7808/* ------------------------------ */ 7809 .balign 64 7810.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7811/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7812/* File: armv5te/OP_IPUT_QUICK.S */ 7813 /* For: iput-quick, iput-object-quick */ 7814 /* op vA, vB, offset@CCCC */ 7815 mov r2, rINST, lsr #12 @ r2<- B 7816 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7817 FETCH(r1, 1) @ r1<- field byte offset 7818 cmp r3, #0 @ check object for null 7819 mov r2, rINST, lsr #8 @ r2<- A(+) 7820 beq common_errNullObject @ object was null 7821 and r2, r2, #15 7822 GET_VREG(r0, r2) @ r0<- fp[A] 7823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7824 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7825 GET_INST_OPCODE(ip) @ extract opcode from rINST 7826 GOTO_OPCODE(ip) @ jump to next instruction 7827 7828 7829 7830/* ------------------------------ */ 7831 .balign 64 7832.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7833/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7834 /* 7835 * Handle an optimized virtual method call. 7836 * 7837 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7838 */ 7839 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7840 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7841 FETCH(r3, 2) @ r3<- FEDC or CCCC 7842 FETCH(r1, 1) @ r1<- BBBB 7843 .if (!0) 7844 and r3, r3, #15 @ r3<- C (or stays CCCC) 7845 .endif 7846 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7847 cmp r2, #0 @ is "this" null? 7848 beq common_errNullObject @ null "this", throw exception 7849 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7850 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7851 EXPORT_PC() @ invoke must export 7852 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7853 bl common_invokeMethodNoRange @ continue on 7854 7855/* ------------------------------ */ 7856 .balign 64 7857.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7858/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7859/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7860 /* 7861 * Handle an optimized virtual method call. 7862 * 7863 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7864 */ 7865 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7866 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7867 FETCH(r3, 2) @ r3<- FEDC or CCCC 7868 FETCH(r1, 1) @ r1<- BBBB 7869 .if (!1) 7870 and r3, r3, #15 @ r3<- C (or stays CCCC) 7871 .endif 7872 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7873 cmp r2, #0 @ is "this" null? 7874 beq common_errNullObject @ null "this", throw exception 7875 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7876 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7877 EXPORT_PC() @ invoke must export 7878 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7879 bl common_invokeMethodRange @ continue on 7880 7881 7882/* ------------------------------ */ 7883 .balign 64 7884.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7885/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7886 /* 7887 * Handle an optimized "super" method call. 7888 * 7889 * for: [opt] invoke-super-quick, invoke-super-quick/range 7890 */ 7891 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7892 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7893 FETCH(r10, 2) @ r10<- GFED or CCCC 7894 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7895 .if (!0) 7896 and r10, r10, #15 @ r10<- D (or stays CCCC) 7897 .endif 7898 FETCH(r1, 1) @ r1<- BBBB 7899 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7900 EXPORT_PC() @ must export for invoke 7901 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7902 GET_VREG(r3, r10) @ r3<- "this" 7903 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7904 cmp r3, #0 @ null "this" ref? 7905 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7906 beq common_errNullObject @ "this" is null, throw exception 7907 bl common_invokeMethodNoRange @ continue on 7908 7909 7910/* ------------------------------ */ 7911 .balign 64 7912.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7913/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7914/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7915 /* 7916 * Handle an optimized "super" method call. 7917 * 7918 * for: [opt] invoke-super-quick, invoke-super-quick/range 7919 */ 7920 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7921 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7922 FETCH(r10, 2) @ r10<- GFED or CCCC 7923 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7924 .if (!1) 7925 and r10, r10, #15 @ r10<- D (or stays CCCC) 7926 .endif 7927 FETCH(r1, 1) @ r1<- BBBB 7928 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7929 EXPORT_PC() @ must export for invoke 7930 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7931 GET_VREG(r3, r10) @ r3<- "this" 7932 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7933 cmp r3, #0 @ null "this" ref? 7934 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7935 beq common_errNullObject @ "this" is null, throw exception 7936 bl common_invokeMethodRange @ continue on 7937 7938 7939 7940/* ------------------------------ */ 7941 .balign 64 7942.L_OP_UNUSED_FC: /* 0xfc */ 7943/* File: armv5te/OP_UNUSED_FC.S */ 7944/* File: armv5te/unused.S */ 7945 bl common_abort 7946 7947 7948 7949/* ------------------------------ */ 7950 .balign 64 7951.L_OP_UNUSED_FD: /* 0xfd */ 7952/* File: armv5te/OP_UNUSED_FD.S */ 7953/* File: armv5te/unused.S */ 7954 bl common_abort 7955 7956 7957 7958/* ------------------------------ */ 7959 .balign 64 7960.L_OP_UNUSED_FE: /* 0xfe */ 7961/* File: armv5te/OP_UNUSED_FE.S */ 7962/* File: armv5te/unused.S */ 7963 bl common_abort 7964 7965 7966 7967/* ------------------------------ */ 7968 .balign 64 7969.L_OP_UNUSED_FF: /* 0xff */ 7970/* File: armv5te/OP_UNUSED_FF.S */ 7971/* File: armv5te/unused.S */ 7972 bl common_abort 7973 7974 7975 7976 7977 .balign 64 7978 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7979 .global dvmAsmInstructionEnd 7980dvmAsmInstructionEnd: 7981 7982/* 7983 * =========================================================================== 7984 * Sister implementations 7985 * =========================================================================== 7986 */ 7987 .global dvmAsmSisterStart 7988 .type dvmAsmSisterStart, %function 7989 .text 7990 .balign 4 7991dvmAsmSisterStart: 7992 7993/* continuation for OP_CONST_STRING */ 7994 7995 /* 7996 * Continuation if the String has not yet been resolved. 7997 * r1: BBBB (String ref) 7998 * r9: target register 7999 */ 8000.LOP_CONST_STRING_resolve: 8001 EXPORT_PC() 8002 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8003 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8004 bl dvmResolveString @ r0<- String reference 8005 cmp r0, #0 @ failed? 8006 beq common_exceptionThrown @ yup, handle the exception 8007 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8008 GET_INST_OPCODE(ip) @ extract opcode from rINST 8009 SET_VREG(r0, r9) @ vAA<- r0 8010 GOTO_OPCODE(ip) @ jump to next instruction 8011 8012 8013/* continuation for OP_CONST_STRING_JUMBO */ 8014 8015 /* 8016 * Continuation if the String has not yet been resolved. 8017 * r1: BBBBBBBB (String ref) 8018 * r9: target register 8019 */ 8020.LOP_CONST_STRING_JUMBO_resolve: 8021 EXPORT_PC() 8022 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8023 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8024 bl dvmResolveString @ r0<- String reference 8025 cmp r0, #0 @ failed? 8026 beq common_exceptionThrown @ yup, handle the exception 8027 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 8028 GET_INST_OPCODE(ip) @ extract opcode from rINST 8029 SET_VREG(r0, r9) @ vAA<- r0 8030 GOTO_OPCODE(ip) @ jump to next instruction 8031 8032 8033/* continuation for OP_CONST_CLASS */ 8034 8035 /* 8036 * Continuation if the Class has not yet been resolved. 8037 * r1: BBBB (Class ref) 8038 * r9: target register 8039 */ 8040.LOP_CONST_CLASS_resolve: 8041 EXPORT_PC() 8042 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8043 mov r2, #1 @ r2<- true 8044 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8045 bl dvmResolveClass @ r0<- Class reference 8046 cmp r0, #0 @ failed? 8047 beq common_exceptionThrown @ yup, handle the exception 8048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8049 GET_INST_OPCODE(ip) @ extract opcode from rINST 8050 SET_VREG(r0, r9) @ vAA<- r0 8051 GOTO_OPCODE(ip) @ jump to next instruction 8052 8053 8054/* continuation for OP_CHECK_CAST */ 8055 8056 /* 8057 * Trivial test failed, need to perform full check. This is common. 8058 * r0 holds obj->clazz 8059 * r1 holds class resolved from BBBB 8060 * r9 holds object 8061 */ 8062.LOP_CHECK_CAST_fullcheck: 8063 bl dvmInstanceofNonTrivial @ r0<- boolean result 8064 cmp r0, #0 @ failed? 8065 bne .LOP_CHECK_CAST_okay @ no, success 8066 8067 @ A cast has failed. We need to throw a ClassCastException with the 8068 @ class of the object that failed to be cast. 8069 EXPORT_PC() @ about to throw 8070 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 8071 ldr r0, .LstrClassCastExceptionPtr 8072 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 8073 bl dvmThrowExceptionWithClassMessage 8074 b common_exceptionThrown 8075 8076 /* 8077 * Resolution required. This is the least-likely path. 8078 * 8079 * r2 holds BBBB 8080 * r9 holds object 8081 */ 8082.LOP_CHECK_CAST_resolve: 8083 EXPORT_PC() @ resolve() could throw 8084 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8085 mov r1, r2 @ r1<- BBBB 8086 mov r2, #0 @ r2<- false 8087 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8088 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8089 cmp r0, #0 @ got null? 8090 beq common_exceptionThrown @ yes, handle exception 8091 mov r1, r0 @ r1<- class resolved from BBB 8092 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8093 b .LOP_CHECK_CAST_resolved @ pick up where we left off 8094 8095.LstrClassCastExceptionPtr: 8096 .word .LstrClassCastException 8097 8098 8099/* continuation for OP_INSTANCE_OF */ 8100 8101 /* 8102 * Trivial test failed, need to perform full check. This is common. 8103 * r0 holds obj->clazz 8104 * r1 holds class resolved from BBBB 8105 * r9 holds A 8106 */ 8107.LOP_INSTANCE_OF_fullcheck: 8108 bl dvmInstanceofNonTrivial @ r0<- boolean result 8109 @ fall through to OP_INSTANCE_OF_store 8110 8111 /* 8112 * r0 holds boolean result 8113 * r9 holds A 8114 */ 8115.LOP_INSTANCE_OF_store: 8116 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8117 SET_VREG(r0, r9) @ vA<- r0 8118 GET_INST_OPCODE(ip) @ extract opcode from rINST 8119 GOTO_OPCODE(ip) @ jump to next instruction 8120 8121 /* 8122 * Trivial test succeeded, save and bail. 8123 * r9 holds A 8124 */ 8125.LOP_INSTANCE_OF_trivial: 8126 mov r0, #1 @ indicate success 8127 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 8128 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8129 SET_VREG(r0, r9) @ vA<- r0 8130 GET_INST_OPCODE(ip) @ extract opcode from rINST 8131 GOTO_OPCODE(ip) @ jump to next instruction 8132 8133 /* 8134 * Resolution required. This is the least-likely path. 8135 * 8136 * r3 holds BBBB 8137 * r9 holds A 8138 */ 8139.LOP_INSTANCE_OF_resolve: 8140 EXPORT_PC() @ resolve() could throw 8141 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 8142 mov r1, r3 @ r1<- BBBB 8143 mov r2, #1 @ r2<- true 8144 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 8145 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8146 cmp r0, #0 @ got null? 8147 beq common_exceptionThrown @ yes, handle exception 8148 mov r1, r0 @ r1<- class resolved from BBB 8149 mov r3, rINST, lsr #12 @ r3<- B 8150 GET_VREG(r0, r3) @ r0<- vB (object) 8151 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 8152 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 8153 8154 8155/* continuation for OP_NEW_INSTANCE */ 8156 8157 .balign 32 @ minimize cache lines 8158.LOP_NEW_INSTANCE_finish: @ r0=new object 8159 mov r3, rINST, lsr #8 @ r3<- AA 8160 cmp r0, #0 @ failed? 8161 beq common_exceptionThrown @ yes, handle the exception 8162 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8163 GET_INST_OPCODE(ip) @ extract opcode from rINST 8164 SET_VREG(r0, r3) @ vAA<- r0 8165 GOTO_OPCODE(ip) @ jump to next instruction 8166 8167 /* 8168 * Class initialization required. 8169 * 8170 * r0 holds class object 8171 */ 8172.LOP_NEW_INSTANCE_needinit: 8173 mov r9, r0 @ save r0 8174 bl dvmInitClass @ initialize class 8175 cmp r0, #0 @ check boolean result 8176 mov r0, r9 @ restore r0 8177 bne .LOP_NEW_INSTANCE_initialized @ success, continue 8178 b common_exceptionThrown @ failed, deal with init exception 8179 8180 /* 8181 * Resolution required. This is the least-likely path. 8182 * 8183 * r1 holds BBBB 8184 */ 8185.LOP_NEW_INSTANCE_resolve: 8186 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8187 mov r2, #0 @ r2<- false 8188 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8189 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8190 cmp r0, #0 @ got null? 8191 bne .LOP_NEW_INSTANCE_resolved @ no, continue 8192 b common_exceptionThrown @ yes, handle exception 8193 8194.LstrInstantiationErrorPtr: 8195 .word .LstrInstantiationError 8196 8197 8198/* continuation for OP_NEW_ARRAY */ 8199 8200 8201 /* 8202 * Resolve class. (This is an uncommon case.) 8203 * 8204 * r1 holds array length 8205 * r2 holds class ref CCCC 8206 */ 8207.LOP_NEW_ARRAY_resolve: 8208 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8209 mov r9, r1 @ r9<- length (save) 8210 mov r1, r2 @ r1<- CCCC 8211 mov r2, #0 @ r2<- false 8212 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8213 bl dvmResolveClass @ r0<- call(clazz, ref) 8214 cmp r0, #0 @ got null? 8215 mov r1, r9 @ r1<- length (restore) 8216 beq common_exceptionThrown @ yes, handle exception 8217 @ fall through to OP_NEW_ARRAY_finish 8218 8219 /* 8220 * Finish allocation. 8221 * 8222 * r0 holds class 8223 * r1 holds array length 8224 */ 8225.LOP_NEW_ARRAY_finish: 8226 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8227 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8228 cmp r0, #0 @ failed? 8229 mov r2, rINST, lsr #8 @ r2<- A+ 8230 beq common_exceptionThrown @ yes, handle the exception 8231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8232 and r2, r2, #15 @ r2<- A 8233 GET_INST_OPCODE(ip) @ extract opcode from rINST 8234 SET_VREG(r0, r2) @ vA<- r0 8235 GOTO_OPCODE(ip) @ jump to next instruction 8236 8237 8238/* continuation for OP_FILLED_NEW_ARRAY */ 8239 8240 /* 8241 * On entry: 8242 * r0 holds array class 8243 * r10 holds AA or BA 8244 */ 8245.LOP_FILLED_NEW_ARRAY_continue: 8246 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8247 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8248 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8249 .if 0 8250 mov r1, r10 @ r1<- AA (length) 8251 .else 8252 mov r1, r10, lsr #4 @ r1<- B (length) 8253 .endif 8254 cmp r3, #'I' @ array of ints? 8255 cmpne r3, #'L' @ array of objects? 8256 cmpne r3, #'[' @ array of arrays? 8257 mov r9, r1 @ save length in r9 8258 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8259 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8260 cmp r0, #0 @ null return? 8261 beq common_exceptionThrown @ alloc failed, handle exception 8262 8263 FETCH(r1, 2) @ r1<- FEDC or CCCC 8264 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8265 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8266 subs r9, r9, #1 @ length--, check for neg 8267 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8268 bmi 2f @ was zero, bail 8269 8270 @ copy values from registers into the array 8271 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8272 .if 0 8273 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 82741: ldr r3, [r2], #4 @ r3<- *r2++ 8275 subs r9, r9, #1 @ count-- 8276 str r3, [r0], #4 @ *contents++ = vX 8277 bpl 1b 8278 @ continue at 2 8279 .else 8280 cmp r9, #4 @ length was initially 5? 8281 and r2, r10, #15 @ r2<- A 8282 bne 1f @ <= 4 args, branch 8283 GET_VREG(r3, r2) @ r3<- vA 8284 sub r9, r9, #1 @ count-- 8285 str r3, [r0, #16] @ contents[4] = vA 82861: and r2, r1, #15 @ r2<- F/E/D/C 8287 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8288 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8289 subs r9, r9, #1 @ count-- 8290 str r3, [r0], #4 @ *contents++ = vX 8291 bpl 1b 8292 @ continue at 2 8293 .endif 8294 82952: 8296 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8297 GOTO_OPCODE(ip) @ execute it 8298 8299 /* 8300 * Throw an exception indicating that we have not implemented this 8301 * mode of filled-new-array. 8302 */ 8303.LOP_FILLED_NEW_ARRAY_notimpl: 8304 ldr r0, .L_strInternalError 8305 ldr r1, .L_strFilledNewArrayNotImpl 8306 bl dvmThrowException 8307 b common_exceptionThrown 8308 8309 .if (!0) @ define in one or the other, not both 8310.L_strFilledNewArrayNotImpl: 8311 .word .LstrFilledNewArrayNotImpl 8312.L_strInternalError: 8313 .word .LstrInternalError 8314 .endif 8315 8316 8317/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8318 8319 /* 8320 * On entry: 8321 * r0 holds array class 8322 * r10 holds AA or BA 8323 */ 8324.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8325 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8326 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8327 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8328 .if 1 8329 mov r1, r10 @ r1<- AA (length) 8330 .else 8331 mov r1, r10, lsr #4 @ r1<- B (length) 8332 .endif 8333 cmp r3, #'I' @ array of ints? 8334 cmpne r3, #'L' @ array of objects? 8335 cmpne r3, #'[' @ array of arrays? 8336 mov r9, r1 @ save length in r9 8337 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8338 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8339 cmp r0, #0 @ null return? 8340 beq common_exceptionThrown @ alloc failed, handle exception 8341 8342 FETCH(r1, 2) @ r1<- FEDC or CCCC 8343 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8344 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8345 subs r9, r9, #1 @ length--, check for neg 8346 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8347 bmi 2f @ was zero, bail 8348 8349 @ copy values from registers into the array 8350 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8351 .if 1 8352 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 83531: ldr r3, [r2], #4 @ r3<- *r2++ 8354 subs r9, r9, #1 @ count-- 8355 str r3, [r0], #4 @ *contents++ = vX 8356 bpl 1b 8357 @ continue at 2 8358 .else 8359 cmp r9, #4 @ length was initially 5? 8360 and r2, r10, #15 @ r2<- A 8361 bne 1f @ <= 4 args, branch 8362 GET_VREG(r3, r2) @ r3<- vA 8363 sub r9, r9, #1 @ count-- 8364 str r3, [r0, #16] @ contents[4] = vA 83651: and r2, r1, #15 @ r2<- F/E/D/C 8366 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8367 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8368 subs r9, r9, #1 @ count-- 8369 str r3, [r0], #4 @ *contents++ = vX 8370 bpl 1b 8371 @ continue at 2 8372 .endif 8373 83742: 8375 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8376 GOTO_OPCODE(ip) @ execute it 8377 8378 /* 8379 * Throw an exception indicating that we have not implemented this 8380 * mode of filled-new-array. 8381 */ 8382.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8383 ldr r0, .L_strInternalError 8384 ldr r1, .L_strFilledNewArrayNotImpl 8385 bl dvmThrowException 8386 b common_exceptionThrown 8387 8388 .if (!1) @ define in one or the other, not both 8389.L_strFilledNewArrayNotImpl: 8390 .word .LstrFilledNewArrayNotImpl 8391.L_strInternalError: 8392 .word .LstrInternalError 8393 .endif 8394 8395 8396/* continuation for OP_CMPL_FLOAT */ 8397 8398 @ Test for NaN with a second comparison. EABI forbids testing bit 8399 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8400 @ make the library call. 8401.LOP_CMPL_FLOAT_gt_or_nan: 8402 mov r1, r9 @ reverse order 8403 mov r0, r10 8404 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8405 @bleq common_abort 8406 movcc r1, #1 @ (greater than) r1<- 1 8407 bcc .LOP_CMPL_FLOAT_finish 8408 mvn r1, #0 @ r1<- 1 or -1 for NaN 8409 b .LOP_CMPL_FLOAT_finish 8410 8411 8412#if 0 /* "clasic" form */ 8413 FETCH(r0, 1) @ r0<- CCBB 8414 and r2, r0, #255 @ r2<- BB 8415 mov r3, r0, lsr #8 @ r3<- CC 8416 GET_VREG(r9, r2) @ r9<- vBB 8417 GET_VREG(r10, r3) @ r10<- vCC 8418 mov r0, r9 @ r0<- vBB 8419 mov r1, r10 @ r1<- vCC 8420 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8421 cmp r0, #0 @ equal? 8422 movne r1, #0 @ yes, result is 0 8423 bne OP_CMPL_FLOAT_finish 8424 mov r0, r9 @ r0<- vBB 8425 mov r1, r10 @ r1<- vCC 8426 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8427 cmp r0, #0 @ less than? 8428 b OP_CMPL_FLOAT_continue 8429@%break 8430 8431OP_CMPL_FLOAT_continue: 8432 mvnne r1, #0 @ yes, result is -1 8433 bne OP_CMPL_FLOAT_finish 8434 mov r0, r9 @ r0<- vBB 8435 mov r1, r10 @ r1<- vCC 8436 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8437 cmp r0, #0 @ greater than? 8438 beq OP_CMPL_FLOAT_nan @ no, must be NaN 8439 mov r1, #1 @ yes, result is 1 8440 @ fall through to _finish 8441 8442OP_CMPL_FLOAT_finish: 8443 mov r3, rINST, lsr #8 @ r3<- AA 8444 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8445 SET_VREG(r1, r3) @ vAA<- r1 8446 GET_INST_OPCODE(ip) @ extract opcode from rINST 8447 GOTO_OPCODE(ip) @ jump to next instruction 8448 8449 /* 8450 * This is expected to be uncommon, so we double-branch (once to here, 8451 * again back to _finish). 8452 */ 8453OP_CMPL_FLOAT_nan: 8454 mvn r1, #0 @ r1<- 1 or -1 for NaN 8455 b OP_CMPL_FLOAT_finish 8456 8457#endif 8458 8459 8460/* continuation for OP_CMPG_FLOAT */ 8461 8462 @ Test for NaN with a second comparison. EABI forbids testing bit 8463 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8464 @ make the library call. 8465.LOP_CMPG_FLOAT_gt_or_nan: 8466 mov r1, r9 @ reverse order 8467 mov r0, r10 8468 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8469 @bleq common_abort 8470 movcc r1, #1 @ (greater than) r1<- 1 8471 bcc .LOP_CMPG_FLOAT_finish 8472 mov r1, #1 @ r1<- 1 or -1 for NaN 8473 b .LOP_CMPG_FLOAT_finish 8474 8475 8476#if 0 /* "clasic" form */ 8477 FETCH(r0, 1) @ r0<- CCBB 8478 and r2, r0, #255 @ r2<- BB 8479 mov r3, r0, lsr #8 @ r3<- CC 8480 GET_VREG(r9, r2) @ r9<- vBB 8481 GET_VREG(r10, r3) @ r10<- vCC 8482 mov r0, r9 @ r0<- vBB 8483 mov r1, r10 @ r1<- vCC 8484 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8485 cmp r0, #0 @ equal? 8486 movne r1, #0 @ yes, result is 0 8487 bne OP_CMPG_FLOAT_finish 8488 mov r0, r9 @ r0<- vBB 8489 mov r1, r10 @ r1<- vCC 8490 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8491 cmp r0, #0 @ less than? 8492 b OP_CMPG_FLOAT_continue 8493@%break 8494 8495OP_CMPG_FLOAT_continue: 8496 mvnne r1, #0 @ yes, result is -1 8497 bne OP_CMPG_FLOAT_finish 8498 mov r0, r9 @ r0<- vBB 8499 mov r1, r10 @ r1<- vCC 8500 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8501 cmp r0, #0 @ greater than? 8502 beq OP_CMPG_FLOAT_nan @ no, must be NaN 8503 mov r1, #1 @ yes, result is 1 8504 @ fall through to _finish 8505 8506OP_CMPG_FLOAT_finish: 8507 mov r3, rINST, lsr #8 @ r3<- AA 8508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8509 SET_VREG(r1, r3) @ vAA<- r1 8510 GET_INST_OPCODE(ip) @ extract opcode from rINST 8511 GOTO_OPCODE(ip) @ jump to next instruction 8512 8513 /* 8514 * This is expected to be uncommon, so we double-branch (once to here, 8515 * again back to _finish). 8516 */ 8517OP_CMPG_FLOAT_nan: 8518 mov r1, #1 @ r1<- 1 or -1 for NaN 8519 b OP_CMPG_FLOAT_finish 8520 8521#endif 8522 8523 8524/* continuation for OP_CMPL_DOUBLE */ 8525 8526 @ Test for NaN with a second comparison. EABI forbids testing bit 8527 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8528 @ make the library call. 8529.LOP_CMPL_DOUBLE_gt_or_nan: 8530 ldmia r10, {r0-r1} @ reverse order 8531 ldmia r9, {r2-r3} 8532 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8533 @bleq common_abort 8534 movcc r1, #1 @ (greater than) r1<- 1 8535 bcc .LOP_CMPL_DOUBLE_finish 8536 mvn r1, #0 @ r1<- 1 or -1 for NaN 8537 b .LOP_CMPL_DOUBLE_finish 8538 8539 8540/* continuation for OP_CMPG_DOUBLE */ 8541 8542 @ Test for NaN with a second comparison. EABI forbids testing bit 8543 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8544 @ make the library call. 8545.LOP_CMPG_DOUBLE_gt_or_nan: 8546 ldmia r10, {r0-r1} @ reverse order 8547 ldmia r9, {r2-r3} 8548 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8549 @bleq common_abort 8550 movcc r1, #1 @ (greater than) r1<- 1 8551 bcc .LOP_CMPG_DOUBLE_finish 8552 mov r1, #1 @ r1<- 1 or -1 for NaN 8553 b .LOP_CMPG_DOUBLE_finish 8554 8555 8556/* continuation for OP_CMP_LONG */ 8557 8558.LOP_CMP_LONG_less: 8559 mvn r1, #0 @ r1<- -1 8560 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8561 @ instead, we just replicate the tail end. 8562 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8563 SET_VREG(r1, r9) @ vAA<- r1 8564 GET_INST_OPCODE(ip) @ extract opcode from rINST 8565 GOTO_OPCODE(ip) @ jump to next instruction 8566 8567.LOP_CMP_LONG_greater: 8568 mov r1, #1 @ r1<- 1 8569 @ fall through to _finish 8570 8571.LOP_CMP_LONG_finish: 8572 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8573 SET_VREG(r1, r9) @ vAA<- r1 8574 GET_INST_OPCODE(ip) @ extract opcode from rINST 8575 GOTO_OPCODE(ip) @ jump to next instruction 8576 8577 8578/* continuation for OP_AGET_WIDE */ 8579 8580.LOP_AGET_WIDE_finish: 8581 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8582 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8583 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8584 GET_INST_OPCODE(ip) @ extract opcode from rINST 8585 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8586 GOTO_OPCODE(ip) @ jump to next instruction 8587 8588 8589/* continuation for OP_APUT_WIDE */ 8590 8591.LOP_APUT_WIDE_finish: 8592 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8593 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8594 GET_INST_OPCODE(ip) @ extract opcode from rINST 8595 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8596 GOTO_OPCODE(ip) @ jump to next instruction 8597 8598 8599/* continuation for OP_APUT_OBJECT */ 8600 /* 8601 * On entry: 8602 * r1 = vBB (arrayObj) 8603 * r9 = vAA (obj) 8604 * r10 = offset into array (vBB + vCC * width) 8605 */ 8606.LOP_APUT_OBJECT_finish: 8607 cmp r9, #0 @ storing null reference? 8608 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8609 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8610 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8611 bl dvmCanPutArrayElement @ test object type vs. array type 8612 cmp r0, #0 @ okay? 8613 beq common_errArrayStore @ no 8614.LOP_APUT_OBJECT_skip_check: 8615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8616 GET_INST_OPCODE(ip) @ extract opcode from rINST 8617 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8618 GOTO_OPCODE(ip) @ jump to next instruction 8619 8620 8621/* continuation for OP_IGET */ 8622 8623 /* 8624 * Currently: 8625 * r0 holds resolved field 8626 * r9 holds object 8627 */ 8628.LOP_IGET_finish: 8629 @bl common_squeak0 8630 cmp r9, #0 @ check object for null 8631 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8632 beq common_errNullObject @ object was null 8633 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8634 mov r2, rINST, lsr #8 @ r2<- A+ 8635 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8636 and r2, r2, #15 @ r2<- A 8637 GET_INST_OPCODE(ip) @ extract opcode from rINST 8638 SET_VREG(r0, r2) @ fp[A]<- r0 8639 GOTO_OPCODE(ip) @ jump to next instruction 8640 8641 8642/* continuation for OP_IGET_WIDE */ 8643 8644 /* 8645 * Currently: 8646 * r0 holds resolved field 8647 * r9 holds object 8648 */ 8649.LOP_IGET_WIDE_finish: 8650 cmp r9, #0 @ check object for null 8651 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8652 beq common_errNullObject @ object was null 8653 mov r2, rINST, lsr #8 @ r2<- A+ 8654 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8655 and r2, r2, #15 @ r2<- A 8656 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8657 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8658 GET_INST_OPCODE(ip) @ extract opcode from rINST 8659 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8660 GOTO_OPCODE(ip) @ jump to next instruction 8661 8662 8663/* continuation for OP_IGET_OBJECT */ 8664 8665 /* 8666 * Currently: 8667 * r0 holds resolved field 8668 * r9 holds object 8669 */ 8670.LOP_IGET_OBJECT_finish: 8671 @bl common_squeak0 8672 cmp r9, #0 @ check object for null 8673 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8674 beq common_errNullObject @ object was null 8675 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8676 mov r2, rINST, lsr #8 @ r2<- A+ 8677 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8678 and r2, r2, #15 @ r2<- A 8679 GET_INST_OPCODE(ip) @ extract opcode from rINST 8680 SET_VREG(r0, r2) @ fp[A]<- r0 8681 GOTO_OPCODE(ip) @ jump to next instruction 8682 8683 8684/* continuation for OP_IGET_BOOLEAN */ 8685 8686 /* 8687 * Currently: 8688 * r0 holds resolved field 8689 * r9 holds object 8690 */ 8691.LOP_IGET_BOOLEAN_finish: 8692 @bl common_squeak1 8693 cmp r9, #0 @ check object for null 8694 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8695 beq common_errNullObject @ object was null 8696 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8697 mov r2, rINST, lsr #8 @ r2<- A+ 8698 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8699 and r2, r2, #15 @ r2<- A 8700 GET_INST_OPCODE(ip) @ extract opcode from rINST 8701 SET_VREG(r0, r2) @ fp[A]<- r0 8702 GOTO_OPCODE(ip) @ jump to next instruction 8703 8704 8705/* continuation for OP_IGET_BYTE */ 8706 8707 /* 8708 * Currently: 8709 * r0 holds resolved field 8710 * r9 holds object 8711 */ 8712.LOP_IGET_BYTE_finish: 8713 @bl common_squeak2 8714 cmp r9, #0 @ check object for null 8715 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8716 beq common_errNullObject @ object was null 8717 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8718 mov r2, rINST, lsr #8 @ r2<- A+ 8719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8720 and r2, r2, #15 @ r2<- A 8721 GET_INST_OPCODE(ip) @ extract opcode from rINST 8722 SET_VREG(r0, r2) @ fp[A]<- r0 8723 GOTO_OPCODE(ip) @ jump to next instruction 8724 8725 8726/* continuation for OP_IGET_CHAR */ 8727 8728 /* 8729 * Currently: 8730 * r0 holds resolved field 8731 * r9 holds object 8732 */ 8733.LOP_IGET_CHAR_finish: 8734 @bl common_squeak3 8735 cmp r9, #0 @ check object for null 8736 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8737 beq common_errNullObject @ object was null 8738 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8739 mov r2, rINST, lsr #8 @ r2<- A+ 8740 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8741 and r2, r2, #15 @ r2<- A 8742 GET_INST_OPCODE(ip) @ extract opcode from rINST 8743 SET_VREG(r0, r2) @ fp[A]<- r0 8744 GOTO_OPCODE(ip) @ jump to next instruction 8745 8746 8747/* continuation for OP_IGET_SHORT */ 8748 8749 /* 8750 * Currently: 8751 * r0 holds resolved field 8752 * r9 holds object 8753 */ 8754.LOP_IGET_SHORT_finish: 8755 @bl common_squeak4 8756 cmp r9, #0 @ check object for null 8757 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8758 beq common_errNullObject @ object was null 8759 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8760 mov r2, rINST, lsr #8 @ r2<- A+ 8761 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8762 and r2, r2, #15 @ r2<- A 8763 GET_INST_OPCODE(ip) @ extract opcode from rINST 8764 SET_VREG(r0, r2) @ fp[A]<- r0 8765 GOTO_OPCODE(ip) @ jump to next instruction 8766 8767 8768/* continuation for OP_IPUT */ 8769 8770 /* 8771 * Currently: 8772 * r0 holds resolved field 8773 * r9 holds object 8774 */ 8775.LOP_IPUT_finish: 8776 @bl common_squeak0 8777 mov r1, rINST, lsr #8 @ r1<- A+ 8778 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8779 and r1, r1, #15 @ r1<- A 8780 cmp r9, #0 @ check object for null 8781 GET_VREG(r0, r1) @ r0<- fp[A] 8782 beq common_errNullObject @ object was null 8783 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8784 GET_INST_OPCODE(ip) @ extract opcode from rINST 8785 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8786 GOTO_OPCODE(ip) @ jump to next instruction 8787 8788 8789/* continuation for OP_IPUT_WIDE */ 8790 8791 /* 8792 * Currently: 8793 * r0 holds resolved field 8794 * r9 holds object 8795 */ 8796.LOP_IPUT_WIDE_finish: 8797 mov r2, rINST, lsr #8 @ r2<- A+ 8798 cmp r9, #0 @ check object for null 8799 and r2, r2, #15 @ r2<- A 8800 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8801 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8802 beq common_errNullObject @ object was null 8803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8804 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8805 GET_INST_OPCODE(ip) @ extract opcode from rINST 8806 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8807 GOTO_OPCODE(ip) @ jump to next instruction 8808 8809 8810/* continuation for OP_IPUT_OBJECT */ 8811 8812 /* 8813 * Currently: 8814 * r0 holds resolved field 8815 * r9 holds object 8816 */ 8817.LOP_IPUT_OBJECT_finish: 8818 @bl common_squeak0 8819 mov r1, rINST, lsr #8 @ r1<- A+ 8820 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8821 and r1, r1, #15 @ r1<- A 8822 cmp r9, #0 @ check object for null 8823 GET_VREG(r0, r1) @ r0<- fp[A] 8824 beq common_errNullObject @ object was null 8825 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8826 GET_INST_OPCODE(ip) @ extract opcode from rINST 8827 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8828 GOTO_OPCODE(ip) @ jump to next instruction 8829 8830 8831/* continuation for OP_IPUT_BOOLEAN */ 8832 8833 /* 8834 * Currently: 8835 * r0 holds resolved field 8836 * r9 holds object 8837 */ 8838.LOP_IPUT_BOOLEAN_finish: 8839 @bl common_squeak1 8840 mov r1, rINST, lsr #8 @ r1<- A+ 8841 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8842 and r1, r1, #15 @ r1<- A 8843 cmp r9, #0 @ check object for null 8844 GET_VREG(r0, r1) @ r0<- fp[A] 8845 beq common_errNullObject @ object was null 8846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8847 GET_INST_OPCODE(ip) @ extract opcode from rINST 8848 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8849 GOTO_OPCODE(ip) @ jump to next instruction 8850 8851 8852/* continuation for OP_IPUT_BYTE */ 8853 8854 /* 8855 * Currently: 8856 * r0 holds resolved field 8857 * r9 holds object 8858 */ 8859.LOP_IPUT_BYTE_finish: 8860 @bl common_squeak2 8861 mov r1, rINST, lsr #8 @ r1<- A+ 8862 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8863 and r1, r1, #15 @ r1<- A 8864 cmp r9, #0 @ check object for null 8865 GET_VREG(r0, r1) @ r0<- fp[A] 8866 beq common_errNullObject @ object was null 8867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8868 GET_INST_OPCODE(ip) @ extract opcode from rINST 8869 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8870 GOTO_OPCODE(ip) @ jump to next instruction 8871 8872 8873/* continuation for OP_IPUT_CHAR */ 8874 8875 /* 8876 * Currently: 8877 * r0 holds resolved field 8878 * r9 holds object 8879 */ 8880.LOP_IPUT_CHAR_finish: 8881 @bl common_squeak3 8882 mov r1, rINST, lsr #8 @ r1<- A+ 8883 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8884 and r1, r1, #15 @ r1<- A 8885 cmp r9, #0 @ check object for null 8886 GET_VREG(r0, r1) @ r0<- fp[A] 8887 beq common_errNullObject @ object was null 8888 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8889 GET_INST_OPCODE(ip) @ extract opcode from rINST 8890 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8891 GOTO_OPCODE(ip) @ jump to next instruction 8892 8893 8894/* continuation for OP_IPUT_SHORT */ 8895 8896 /* 8897 * Currently: 8898 * r0 holds resolved field 8899 * r9 holds object 8900 */ 8901.LOP_IPUT_SHORT_finish: 8902 @bl common_squeak4 8903 mov r1, rINST, lsr #8 @ r1<- A+ 8904 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8905 and r1, r1, #15 @ r1<- A 8906 cmp r9, #0 @ check object for null 8907 GET_VREG(r0, r1) @ r0<- fp[A] 8908 beq common_errNullObject @ object was null 8909 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8910 GET_INST_OPCODE(ip) @ extract opcode from rINST 8911 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8912 GOTO_OPCODE(ip) @ jump to next instruction 8913 8914 8915/* continuation for OP_SGET */ 8916 8917 /* 8918 * Continuation if the field has not yet been resolved. 8919 * r1: BBBB field ref 8920 */ 8921.LOP_SGET_resolve: 8922 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8923 EXPORT_PC() @ resolve() could throw, so export now 8924 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8925 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8926 cmp r0, #0 @ success? 8927 bne .LOP_SGET_finish @ yes, finish 8928 b common_exceptionThrown @ no, handle exception 8929 8930 8931/* continuation for OP_SGET_WIDE */ 8932 8933 /* 8934 * Continuation if the field has not yet been resolved. 8935 * r1: BBBB field ref 8936 */ 8937.LOP_SGET_WIDE_resolve: 8938 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8939 EXPORT_PC() @ resolve() could throw, so export now 8940 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8941 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8942 cmp r0, #0 @ success? 8943 bne .LOP_SGET_WIDE_finish @ yes, finish 8944 b common_exceptionThrown @ no, handle exception 8945 8946 8947/* continuation for OP_SGET_OBJECT */ 8948 8949 /* 8950 * Continuation if the field has not yet been resolved. 8951 * r1: BBBB field ref 8952 */ 8953.LOP_SGET_OBJECT_resolve: 8954 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8955 EXPORT_PC() @ resolve() could throw, so export now 8956 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8957 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8958 cmp r0, #0 @ success? 8959 bne .LOP_SGET_OBJECT_finish @ yes, finish 8960 b common_exceptionThrown @ no, handle exception 8961 8962 8963/* continuation for OP_SGET_BOOLEAN */ 8964 8965 /* 8966 * Continuation if the field has not yet been resolved. 8967 * r1: BBBB field ref 8968 */ 8969.LOP_SGET_BOOLEAN_resolve: 8970 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8971 EXPORT_PC() @ resolve() could throw, so export now 8972 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8973 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8974 cmp r0, #0 @ success? 8975 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8976 b common_exceptionThrown @ no, handle exception 8977 8978 8979/* continuation for OP_SGET_BYTE */ 8980 8981 /* 8982 * Continuation if the field has not yet been resolved. 8983 * r1: BBBB field ref 8984 */ 8985.LOP_SGET_BYTE_resolve: 8986 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8987 EXPORT_PC() @ resolve() could throw, so export now 8988 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8989 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8990 cmp r0, #0 @ success? 8991 bne .LOP_SGET_BYTE_finish @ yes, finish 8992 b common_exceptionThrown @ no, handle exception 8993 8994 8995/* continuation for OP_SGET_CHAR */ 8996 8997 /* 8998 * Continuation if the field has not yet been resolved. 8999 * r1: BBBB field ref 9000 */ 9001.LOP_SGET_CHAR_resolve: 9002 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9003 EXPORT_PC() @ resolve() could throw, so export now 9004 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9005 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9006 cmp r0, #0 @ success? 9007 bne .LOP_SGET_CHAR_finish @ yes, finish 9008 b common_exceptionThrown @ no, handle exception 9009 9010 9011/* continuation for OP_SGET_SHORT */ 9012 9013 /* 9014 * Continuation if the field has not yet been resolved. 9015 * r1: BBBB field ref 9016 */ 9017.LOP_SGET_SHORT_resolve: 9018 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9019 EXPORT_PC() @ resolve() could throw, so export now 9020 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9021 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9022 cmp r0, #0 @ success? 9023 bne .LOP_SGET_SHORT_finish @ yes, finish 9024 b common_exceptionThrown @ no, handle exception 9025 9026 9027/* continuation for OP_SPUT */ 9028 9029 /* 9030 * Continuation if the field has not yet been resolved. 9031 * r1: BBBB field ref 9032 */ 9033.LOP_SPUT_resolve: 9034 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9035 EXPORT_PC() @ resolve() could throw, so export now 9036 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9037 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9038 cmp r0, #0 @ success? 9039 bne .LOP_SPUT_finish @ yes, finish 9040 b common_exceptionThrown @ no, handle exception 9041 9042 9043/* continuation for OP_SPUT_WIDE */ 9044 9045 /* 9046 * Continuation if the field has not yet been resolved. 9047 * r1: BBBB field ref 9048 * r9: &fp[AA] 9049 */ 9050.LOP_SPUT_WIDE_resolve: 9051 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9052 EXPORT_PC() @ resolve() could throw, so export now 9053 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9054 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9055 cmp r0, #0 @ success? 9056 bne .LOP_SPUT_WIDE_finish @ yes, finish 9057 b common_exceptionThrown @ no, handle exception 9058 9059 9060/* continuation for OP_SPUT_OBJECT */ 9061 9062 /* 9063 * Continuation if the field has not yet been resolved. 9064 * r1: BBBB field ref 9065 */ 9066.LOP_SPUT_OBJECT_resolve: 9067 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9068 EXPORT_PC() @ resolve() could throw, so export now 9069 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9070 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9071 cmp r0, #0 @ success? 9072 bne .LOP_SPUT_OBJECT_finish @ yes, finish 9073 b common_exceptionThrown @ no, handle exception 9074 9075 9076/* continuation for OP_SPUT_BOOLEAN */ 9077 9078 /* 9079 * Continuation if the field has not yet been resolved. 9080 * r1: BBBB field ref 9081 */ 9082.LOP_SPUT_BOOLEAN_resolve: 9083 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9084 EXPORT_PC() @ resolve() could throw, so export now 9085 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9086 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9087 cmp r0, #0 @ success? 9088 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 9089 b common_exceptionThrown @ no, handle exception 9090 9091 9092/* continuation for OP_SPUT_BYTE */ 9093 9094 /* 9095 * Continuation if the field has not yet been resolved. 9096 * r1: BBBB field ref 9097 */ 9098.LOP_SPUT_BYTE_resolve: 9099 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9100 EXPORT_PC() @ resolve() could throw, so export now 9101 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9102 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9103 cmp r0, #0 @ success? 9104 bne .LOP_SPUT_BYTE_finish @ yes, finish 9105 b common_exceptionThrown @ no, handle exception 9106 9107 9108/* continuation for OP_SPUT_CHAR */ 9109 9110 /* 9111 * Continuation if the field has not yet been resolved. 9112 * r1: BBBB field ref 9113 */ 9114.LOP_SPUT_CHAR_resolve: 9115 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9116 EXPORT_PC() @ resolve() could throw, so export now 9117 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9118 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9119 cmp r0, #0 @ success? 9120 bne .LOP_SPUT_CHAR_finish @ yes, finish 9121 b common_exceptionThrown @ no, handle exception 9122 9123 9124/* continuation for OP_SPUT_SHORT */ 9125 9126 /* 9127 * Continuation if the field has not yet been resolved. 9128 * r1: BBBB field ref 9129 */ 9130.LOP_SPUT_SHORT_resolve: 9131 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9132 EXPORT_PC() @ resolve() could throw, so export now 9133 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9134 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9135 cmp r0, #0 @ success? 9136 bne .LOP_SPUT_SHORT_finish @ yes, finish 9137 b common_exceptionThrown @ no, handle exception 9138 9139 9140/* continuation for OP_INVOKE_VIRTUAL */ 9141 9142 /* 9143 * At this point: 9144 * r0 = resolved base method 9145 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9146 */ 9147.LOP_INVOKE_VIRTUAL_continue: 9148 GET_VREG(r1, r10) @ r1<- "this" ptr 9149 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9150 cmp r1, #0 @ is "this" null? 9151 beq common_errNullObject @ null "this", throw exception 9152 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9153 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9154 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9155 bl common_invokeMethodNoRange @ continue on 9156 9157 9158/* continuation for OP_INVOKE_SUPER */ 9159 9160 /* 9161 * At this point: 9162 * r0 = resolved base method 9163 * r9 = method->clazz 9164 */ 9165.LOP_INVOKE_SUPER_continue: 9166 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9167 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9168 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9169 EXPORT_PC() @ must export for invoke 9170 cmp r2, r3 @ compare (methodIndex, vtableCount) 9171 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 9172 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9173 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9174 bl common_invokeMethodNoRange @ continue on 9175 9176.LOP_INVOKE_SUPER_resolve: 9177 mov r0, r9 @ r0<- method->clazz 9178 mov r2, #METHOD_VIRTUAL @ resolver method type 9179 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9180 cmp r0, #0 @ got null? 9181 bne .LOP_INVOKE_SUPER_continue @ no, continue 9182 b common_exceptionThrown @ yes, handle exception 9183 9184 /* 9185 * Throw a NoSuchMethodError with the method name as the message. 9186 * r0 = resolved base method 9187 */ 9188.LOP_INVOKE_SUPER_nsm: 9189 ldr r1, [r0, #offMethod_name] @ r1<- method name 9190 b common_errNoSuchMethod 9191 9192 9193/* continuation for OP_INVOKE_DIRECT */ 9194 9195 /* 9196 * On entry: 9197 * r1 = reference (BBBB or CCCC) 9198 * r10 = "this" register 9199 */ 9200.LOP_INVOKE_DIRECT_resolve: 9201 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9202 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9203 mov r2, #METHOD_DIRECT @ resolver method type 9204 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9205 cmp r0, #0 @ got null? 9206 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9207 bne .LOP_INVOKE_DIRECT_finish @ no, continue 9208 b common_exceptionThrown @ yes, handle exception 9209 9210 9211/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 9212 9213 /* 9214 * At this point: 9215 * r0 = resolved base method 9216 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9217 */ 9218.LOP_INVOKE_VIRTUAL_RANGE_continue: 9219 GET_VREG(r1, r10) @ r1<- "this" ptr 9220 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9221 cmp r1, #0 @ is "this" null? 9222 beq common_errNullObject @ null "this", throw exception 9223 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9224 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9225 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9226 bl common_invokeMethodRange @ continue on 9227 9228 9229/* continuation for OP_INVOKE_SUPER_RANGE */ 9230 9231 /* 9232 * At this point: 9233 * r0 = resolved base method 9234 * r9 = method->clazz 9235 */ 9236.LOP_INVOKE_SUPER_RANGE_continue: 9237 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9238 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9239 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9240 EXPORT_PC() @ must export for invoke 9241 cmp r2, r3 @ compare (methodIndex, vtableCount) 9242 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 9243 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9244 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9245 bl common_invokeMethodRange @ continue on 9246 9247.LOP_INVOKE_SUPER_RANGE_resolve: 9248 mov r0, r9 @ r0<- method->clazz 9249 mov r2, #METHOD_VIRTUAL @ resolver method type 9250 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9251 cmp r0, #0 @ got null? 9252 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 9253 b common_exceptionThrown @ yes, handle exception 9254 9255 /* 9256 * Throw a NoSuchMethodError with the method name as the message. 9257 * r0 = resolved base method 9258 */ 9259.LOP_INVOKE_SUPER_RANGE_nsm: 9260 ldr r1, [r0, #offMethod_name] @ r1<- method name 9261 b common_errNoSuchMethod 9262 9263 9264/* continuation for OP_INVOKE_DIRECT_RANGE */ 9265 9266 /* 9267 * On entry: 9268 * r1 = reference (BBBB or CCCC) 9269 * r10 = "this" register 9270 */ 9271.LOP_INVOKE_DIRECT_RANGE_resolve: 9272 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9273 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9274 mov r2, #METHOD_DIRECT @ resolver method type 9275 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9276 cmp r0, #0 @ got null? 9277 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9278 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 9279 b common_exceptionThrown @ yes, handle exception 9280 9281 9282/* continuation for OP_FLOAT_TO_LONG */ 9283/* 9284 * Convert the float in r0 to a long in r0/r1. 9285 * 9286 * We have to clip values to long min/max per the specification. The 9287 * expected common case is a "reasonable" value that converts directly 9288 * to modest integer. The EABI convert function isn't doing this for us. 9289 */ 9290f2l_doconv: 9291 stmfd sp!, {r4, lr} 9292 mov r1, #0x5f000000 @ (float)maxlong 9293 mov r4, r0 9294 bl __aeabi_fcmpge @ is arg >= maxlong? 9295 cmp r0, #0 @ nonzero == yes 9296 mvnne r0, #0 @ return maxlong (7fffffff) 9297 mvnne r1, #0x80000000 9298 ldmnefd sp!, {r4, pc} 9299 9300 mov r0, r4 @ recover arg 9301 mov r1, #0xdf000000 @ (float)minlong 9302 bl __aeabi_fcmple @ is arg <= minlong? 9303 cmp r0, #0 @ nonzero == yes 9304 movne r0, #0 @ return minlong (80000000) 9305 movne r1, #0x80000000 9306 ldmnefd sp!, {r4, pc} 9307 9308 mov r0, r4 @ recover arg 9309 mov r1, r4 9310 bl __aeabi_fcmpeq @ is arg == self? 9311 cmp r0, #0 @ zero == no 9312 moveq r1, #0 @ return zero for NaN 9313 ldmeqfd sp!, {r4, pc} 9314 9315 mov r0, r4 @ recover arg 9316 bl __aeabi_f2lz @ convert float to long 9317 ldmfd sp!, {r4, pc} 9318 9319 9320/* continuation for OP_DOUBLE_TO_LONG */ 9321/* 9322 * Convert the double in r0/r1 to a long in r0/r1. 9323 * 9324 * We have to clip values to long min/max per the specification. The 9325 * expected common case is a "reasonable" value that converts directly 9326 * to modest integer. The EABI convert function isn't doing this for us. 9327 */ 9328d2l_doconv: 9329 stmfd sp!, {r4, r5, lr} @ save regs 9330 ldr r3, .LOP_DOUBLE_TO_LONG_max @ (double)maxlong, hi 9331 sub sp, sp, #4 @ align for EABI 9332 mov r2, #0 @ (double)maxlong, lo 9333 mov r4, r0 @ save r0 9334 mov r5, r1 @ and r1 9335 bl __aeabi_dcmpge @ is arg >= maxlong? 9336 cmp r0, #0 @ nonzero == yes 9337 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9338 mvnne r1, #0x80000000 9339 bne 1f 9340 9341 mov r0, r4 @ recover arg 9342 mov r1, r5 9343 ldr r3, .LOP_DOUBLE_TO_LONG_min @ (double)minlong, hi 9344 mov r2, #0 @ (double)minlong, lo 9345 bl __aeabi_dcmple @ is arg <= minlong? 9346 cmp r0, #0 @ nonzero == yes 9347 movne r0, #0 @ return minlong (8000000000000000) 9348 movne r1, #0x80000000 9349 bne 1f 9350 9351 mov r0, r4 @ recover arg 9352 mov r1, r5 9353 mov r2, r4 @ compare against self 9354 mov r3, r5 9355 bl __aeabi_dcmpeq @ is arg == self? 9356 cmp r0, #0 @ zero == no 9357 moveq r1, #0 @ return zero for NaN 9358 beq 1f 9359 9360 mov r0, r4 @ recover arg 9361 mov r1, r5 9362 bl __aeabi_d2lz @ convert double to long 9363 93641: 9365 add sp, sp, #4 9366 ldmfd sp!, {r4, r5, pc} 9367 9368.LOP_DOUBLE_TO_LONG_max: 9369 .word 0x43e00000 @ maxlong, as a double (high word) 9370.LOP_DOUBLE_TO_LONG_min: 9371 .word 0xc3e00000 @ minlong, as a double (high word) 9372 9373 9374/* continuation for OP_MUL_LONG */ 9375 9376.LOP_MUL_LONG_finish: 9377 GET_INST_OPCODE(ip) @ extract opcode from rINST 9378 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9379 GOTO_OPCODE(ip) @ jump to next instruction 9380 9381 9382/* continuation for OP_SHL_LONG */ 9383 9384.LOP_SHL_LONG_finish: 9385 mov r0, r0, asl r2 @ r0<- r0 << r2 9386 GET_INST_OPCODE(ip) @ extract opcode from rINST 9387 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9388 GOTO_OPCODE(ip) @ jump to next instruction 9389 9390 9391/* continuation for OP_SHR_LONG */ 9392 9393.LOP_SHR_LONG_finish: 9394 mov r1, r1, asr r2 @ r1<- r1 >> r2 9395 GET_INST_OPCODE(ip) @ extract opcode from rINST 9396 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9397 GOTO_OPCODE(ip) @ jump to next instruction 9398 9399 9400/* continuation for OP_USHR_LONG */ 9401 9402.LOP_USHR_LONG_finish: 9403 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9404 GET_INST_OPCODE(ip) @ extract opcode from rINST 9405 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9406 GOTO_OPCODE(ip) @ jump to next instruction 9407 9408 9409/* continuation for OP_SHL_LONG_2ADDR */ 9410 9411.LOP_SHL_LONG_2ADDR_finish: 9412 GET_INST_OPCODE(ip) @ extract opcode from rINST 9413 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9414 GOTO_OPCODE(ip) @ jump to next instruction 9415 9416 9417/* continuation for OP_SHR_LONG_2ADDR */ 9418 9419.LOP_SHR_LONG_2ADDR_finish: 9420 GET_INST_OPCODE(ip) @ extract opcode from rINST 9421 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9422 GOTO_OPCODE(ip) @ jump to next instruction 9423 9424 9425/* continuation for OP_USHR_LONG_2ADDR */ 9426 9427.LOP_USHR_LONG_2ADDR_finish: 9428 GET_INST_OPCODE(ip) @ extract opcode from rINST 9429 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9430 GOTO_OPCODE(ip) @ jump to next instruction 9431 9432 9433/* continuation for OP_EXECUTE_INLINE */ 9434 9435 /* 9436 * Extract args, call function. 9437 * r0 = #of args (0-4) 9438 * r10 = call index 9439 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9440 * 9441 * Other ideas: 9442 * - Use a jump table from the main piece to jump directly into the 9443 * AND/LDR pairs. Costs a data load, saves a branch. 9444 * - Have five separate pieces that do the loading, so we can work the 9445 * interleave a little better. Increases code size. 9446 */ 9447.LOP_EXECUTE_INLINE_continue: 9448 rsb r0, r0, #4 @ r0<- 4-r0 9449 FETCH(r9, 2) @ r9<- FEDC 9450 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9451 bl common_abort @ (skipped due to ARM prefetch) 94524: and ip, r9, #0xf000 @ isolate F 9453 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 94543: and ip, r9, #0x0f00 @ isolate E 9455 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 94562: and ip, r9, #0x00f0 @ isolate D 9457 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 94581: and ip, r9, #0x000f @ isolate C 9459 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 94600: 9461 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9462 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9463 @ (not reached) 9464 9465.LOP_EXECUTE_INLINE_table: 9466 .word gDvmInlineOpsTable 9467 9468 9469 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9470 .global dvmAsmSisterEnd 9471dvmAsmSisterEnd: 9472 9473/* File: armv5te/footer.S */ 9474 9475/* 9476 * =========================================================================== 9477 * Common subroutines and data 9478 * =========================================================================== 9479 */ 9480 9481 9482 9483 .text 9484 .align 2 9485 9486#if defined(WITH_JIT) 9487/* 9488 * Return from the translation cache to the interpreter when the compiler is 9489 * having issues translating/executing a Dalvik instruction. We have to skip 9490 * the code cache lookup otherwise it is possible to indefinitely bouce 9491 * between the interpreter and the code cache if the instruction that fails 9492 * to be compiled happens to be at a trace start. 9493 */ 9494 .global dvmJitToInterpPunt 9495dvmJitToInterpPunt: 9496 mov rPC, r0 9497#ifdef EXIT_STATS 9498 mov r0,lr 9499 bl dvmBumpPunt; 9500#endif 9501 EXPORT_PC() 9502 adrl rIBASE, dvmAsmInstructionStart 9503 FETCH_INST() 9504 GET_INST_OPCODE(ip) 9505 GOTO_OPCODE(ip) 9506 9507/* 9508 * Return to the interpreter to handle a single instruction. 9509 * On entry: 9510 * r0 <= PC 9511 * r1 <= PC of resume instruction 9512 * lr <= resume point in translation 9513 */ 9514 .global dvmJitToInterpSingleStep 9515dvmJitToInterpSingleStep: 9516 str lr,[rGLUE,#offGlue_jitResume] 9517 str r1,[rGLUE,#offGlue_jitResumePC] 9518 mov r1,#kInterpEntryInstr 9519 @ enum is 4 byte in aapcs-EABI 9520 str r1, [rGLUE, #offGlue_entryPoint] 9521 mov rPC,r0 9522 EXPORT_PC() 9523 adrl rIBASE, dvmAsmInstructionStart 9524 mov r2,#kJitSingleStep @ Ask for single step and then revert 9525 str r2,[rGLUE,#offGlue_jitState] 9526 mov r1,#1 @ set changeInterp to bail to debug interp 9527 b common_gotoBail 9528 9529 9530/* 9531 * Return from the translation cache and immediately request 9532 * a translation for the exit target. Commonly used following 9533 * invokes. 9534 */ 9535 .global dvmJitToTraceSelect 9536dvmJitToTraceSelect: 9537 ldr rPC,[r14, #-1] @ get our target PC 9538 add rINST,r14,#-5 @ save start of chain branch 9539 mov r0,rPC 9540 bl dvmJitGetCodeAddr @ Is there a translation? 9541 cmp r0,#0 9542 beq 2f 9543 mov r1,rINST 9544 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9545 cmp r0,#0 @ successful chain? 9546 bxne r0 @ continue native execution 9547 b toInterpreter @ didn't chain - resume with interpreter 9548 9549/* No translation, so request one if profiling isn't disabled*/ 95502: 9551 adrl rIBASE, dvmAsmInstructionStart 9552 GET_JIT_PROF_TABLE(r0) 9553 FETCH_INST() 9554 cmp r0, #0 9555 bne common_selectTrace 9556 GET_INST_OPCODE(ip) 9557 GOTO_OPCODE(ip) 9558 9559/* 9560 * Return from the translation cache to the interpreter. 9561 * The return was done with a BLX from thumb mode, and 9562 * the following 32-bit word contains the target rPC value. 9563 * Note that lr (r14) will have its low-order bit set to denote 9564 * its thumb-mode origin. 9565 * 9566 * We'll need to stash our lr origin away, recover the new 9567 * target and then check to see if there is a translation available 9568 * for our new target. If so, we do a translation chain and 9569 * go back to native execution. Otherwise, it's back to the 9570 * interpreter (after treating this entry as a potential 9571 * trace start). 9572 */ 9573 .global dvmJitToInterpNormal 9574dvmJitToInterpNormal: 9575 ldr rPC,[r14, #-1] @ get our target PC 9576 add rINST,r14,#-5 @ save start of chain branch 9577#ifdef EXIT_STATS 9578 bl dvmBumpNormal 9579#endif 9580 mov r0,rPC 9581 bl dvmJitGetCodeAddr @ Is there a translation? 9582 cmp r0,#0 9583 beq toInterpreter @ go if not, otherwise do chain 9584 mov r1,rINST 9585 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9586 cmp r0,#0 @ successful chain? 9587 bxne r0 @ continue native execution 9588 b toInterpreter @ didn't chain - resume with interpreter 9589 9590/* 9591 * Return from the translation cache to the interpreter to do method invocation. 9592 * Check if translation exists for the callee, but don't chain to it. 9593 */ 9594 .global dvmJitToInterpNoChain 9595dvmJitToInterpNoChain: 9596#ifdef EXIT_STATS 9597 bl dvmBumpNoChain 9598#endif 9599 mov r0,rPC 9600 bl dvmJitGetCodeAddr @ Is there a translation? 9601 cmp r0,#0 9602 bxne r0 @ continue native execution if so 9603 9604/* 9605 * No translation, restore interpreter regs and start interpreting. 9606 * rGLUE & rFP were preserved in the translated code, and rPC has 9607 * already been restored by the time we get here. We'll need to set 9608 * up rIBASE & rINST, and load the address of the JitTable into r0. 9609 */ 9610toInterpreter: 9611 EXPORT_PC() 9612 adrl rIBASE, dvmAsmInstructionStart 9613 FETCH_INST() 9614 GET_JIT_PROF_TABLE(r0) 9615 @ NOTE: intended fallthrough 9616/* 9617 * Common code to update potential trace start counter, and initiate 9618 * a trace-build if appropriate. On entry, rPC should point to the 9619 * next instruction to execute, and rINST should be already loaded with 9620 * the next opcode word, and r0 holds a pointer to the jit profile 9621 * table (pJitProfTable). 9622 */ 9623common_testUpdateProfile: 9624 cmp r0,#0 9625 GET_INST_OPCODE(ip) 9626 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9627 9628common_updateProfile: 9629 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9630 lsl r3,r3,#23 @ shift out excess 511 9631 ldrb r1,[r0,r3,lsr #23] @ get counter 9632 GET_INST_OPCODE(ip) 9633 subs r1,r1,#1 @ decrement counter 9634 strb r1,[r0,r3,lsr #23] @ and store it 9635 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9636 9637/* 9638 * Here, we switch to the debug interpreter to request 9639 * trace selection. First, though, check to see if there 9640 * is already a native translation in place (and, if so, 9641 * jump to it now). 9642 */ 9643 mov r1,#255 9644 strb r1,[r0,r3,lsr #23] @ reset counter 9645 EXPORT_PC() 9646 mov r0,rPC 9647 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9648 cmp r0,#0 9649 beq common_selectTrace 9650 bxne r0 @ jump to the translation 9651common_selectTrace: 9652 mov r2,#kJitTSelectRequest @ ask for trace selection 9653 str r2,[rGLUE,#offGlue_jitState] 9654 mov r1,#1 @ set changeInterp 9655 b common_gotoBail 9656 9657#endif 9658 9659/* 9660 * Common code when a backward branch is taken. 9661 * 9662 * On entry: 9663 * r9 is PC adjustment *in bytes* 9664 */ 9665common_backwardBranch: 9666 mov r0, #kInterpEntryInstr 9667 bl common_periodicChecks 9668#if defined(WITH_JIT) 9669 GET_JIT_PROF_TABLE(r0) 9670 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9671 cmp r0,#0 9672 bne common_updateProfile 9673 GET_INST_OPCODE(ip) 9674 GOTO_OPCODE(ip) 9675#else 9676 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9677 GET_INST_OPCODE(ip) @ extract opcode from rINST 9678 GOTO_OPCODE(ip) @ jump to next instruction 9679#endif 9680 9681 9682/* 9683 * Need to see if the thread needs to be suspended or debugger/profiler 9684 * activity has begun. 9685 * 9686 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9687 * have to do the second ldr. 9688 * 9689 * TODO: reduce this so we're just checking a single location. 9690 * 9691 * On entry: 9692 * r0 is reentry type, e.g. kInterpEntryInstr 9693 * r9 is trampoline PC adjustment *in bytes* 9694 */ 9695common_periodicChecks: 9696 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9697 9698#if defined(WITH_DEBUGGER) 9699 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9700#endif 9701#if defined(WITH_PROFILER) 9702 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9703#endif 9704 9705 ldr r3, [r3] @ r3<- suspendCount (int) 9706 9707#if defined(WITH_DEBUGGER) 9708 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9709#endif 9710#if defined (WITH_PROFILER) 9711 ldr r2, [r2] @ r2<- activeProfilers (int) 9712#endif 9713 9714 cmp r3, #0 @ suspend pending? 9715 bne 2f @ yes, do full suspension check 9716 9717#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9718# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9719 orrs r1, r1, r2 @ r1<- r1 | r2 9720 cmp r1, #0 @ debugger attached or profiler started? 9721# elif defined(WITH_DEBUGGER) 9722 cmp r1, #0 @ debugger attached? 9723# elif defined(WITH_PROFILER) 9724 cmp r2, #0 @ profiler started? 9725# endif 9726 bne 3f @ debugger/profiler, switch interp 9727#endif 9728 9729 bx lr @ nothing to do, return 9730 97312: @ check suspend 9732 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9733 EXPORT_PC() @ need for precise GC 9734 b dvmCheckSuspendPending @ suspend if necessary, then return 9735 97363: @ debugger/profiler enabled, bail out 9737 add rPC, rPC, r9 @ update rPC 9738 str r0, [rGLUE, #offGlue_entryPoint] 9739 mov r1, #1 @ "want switch" = true 9740 b common_gotoBail 9741 9742 9743/* 9744 * The equivalent of "goto bail", this calls through the "bail handler". 9745 * 9746 * State registers will be saved to the "glue" area before bailing. 9747 * 9748 * On entry: 9749 * r1 is "bool changeInterp", indicating if we want to switch to the 9750 * other interpreter or just bail all the way out 9751 */ 9752common_gotoBail: 9753 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9754 mov r0, rGLUE @ r0<- glue ptr 9755 b dvmMterpStdBail @ call(glue, changeInterp) 9756 9757 @add r1, r1, #1 @ using (boolean+1) 9758 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9759 @bl _longjmp @ does not return 9760 @bl common_abort 9761 9762 9763/* 9764 * Common code for method invocation with range. 9765 * 9766 * On entry: 9767 * r0 is "Method* methodToCall", the method we're trying to call 9768 */ 9769common_invokeMethodRange: 9770.LinvokeNewRange: 9771 @ prepare to copy args to "outs" area of current frame 9772 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9773 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9774 beq .LinvokeArgsDone @ if no args, skip the rest 9775 FETCH(r1, 2) @ r1<- CCCC 9776 9777 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9778 @ (very few methods have > 10 args; could unroll for common cases) 9779 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9780 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9781 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 97821: ldr r1, [r3], #4 @ val = *fp++ 9783 subs r2, r2, #1 @ count-- 9784 str r1, [r10], #4 @ *outs++ = val 9785 bne 1b @ ...while count != 0 9786 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9787 b .LinvokeArgsDone 9788 9789/* 9790 * Common code for method invocation without range. 9791 * 9792 * On entry: 9793 * r0 is "Method* methodToCall", the method we're trying to call 9794 */ 9795common_invokeMethodNoRange: 9796.LinvokeNewNoRange: 9797 @ prepare to copy args to "outs" area of current frame 9798 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9799 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9800 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9801 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9802 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9803 beq .LinvokeArgsDone 9804 9805 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9806.LinvokeNonRange: 9807 rsb r2, r2, #5 @ r2<- 5-r2 9808 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9809 bl common_abort @ (skipped due to ARM prefetch) 98105: and ip, rINST, #0x0f00 @ isolate A 9811 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9812 mov r0, r0 @ nop 9813 str r2, [r10, #-4]! @ *--outs = vA 98144: and ip, r1, #0xf000 @ isolate G 9815 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9816 mov r0, r0 @ nop 9817 str r2, [r10, #-4]! @ *--outs = vG 98183: and ip, r1, #0x0f00 @ isolate F 9819 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9820 mov r0, r0 @ nop 9821 str r2, [r10, #-4]! @ *--outs = vF 98222: and ip, r1, #0x00f0 @ isolate E 9823 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9824 mov r0, r0 @ nop 9825 str r2, [r10, #-4]! @ *--outs = vE 98261: and ip, r1, #0x000f @ isolate D 9827 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9828 mov r0, r0 @ nop 9829 str r2, [r10, #-4]! @ *--outs = vD 98300: @ fall through to .LinvokeArgsDone 9831 9832.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9833 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9834 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9835 @ find space for the new stack frame, check for overflow 9836 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9837 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9838 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9839@ bl common_dumpRegs 9840 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9841 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9842 cmp r3, r9 @ bottom < interpStackEnd? 9843 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9844 blt .LstackOverflow @ yes, this frame will overflow stack 9845 9846 @ set up newSaveArea 9847#ifdef EASY_GDB 9848 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9849 str ip, [r10, #offStackSaveArea_prevSave] 9850#endif 9851 str rFP, [r10, #offStackSaveArea_prevFrame] 9852 str rPC, [r10, #offStackSaveArea_savedPc] 9853#if defined(WITH_JIT) 9854 mov r9, #0 9855 str r9, [r10, #offStackSaveArea_returnAddr] 9856#endif 9857 str r0, [r10, #offStackSaveArea_method] 9858 tst r3, #ACC_NATIVE 9859 bne .LinvokeNative 9860 9861 /* 9862 stmfd sp!, {r0-r3} 9863 bl common_printNewline 9864 mov r0, rFP 9865 mov r1, #0 9866 bl dvmDumpFp 9867 ldmfd sp!, {r0-r3} 9868 stmfd sp!, {r0-r3} 9869 mov r0, r1 9870 mov r1, r10 9871 bl dvmDumpFp 9872 bl common_printNewline 9873 ldmfd sp!, {r0-r3} 9874 */ 9875 9876 ldrh r9, [r2] @ r9 <- load INST from new PC 9877 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9878 mov rPC, r2 @ publish new rPC 9879 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9880 9881 @ Update "glue" values for the new method 9882 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9883 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9884 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9885#if defined(WITH_JIT) 9886 GET_JIT_PROF_TABLE(r0) 9887 mov rFP, r1 @ fp = newFp 9888 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9889 mov rINST, r9 @ publish new rINST 9890 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9891 cmp r0,#0 9892 bne common_updateProfile 9893 GOTO_OPCODE(ip) @ jump to next instruction 9894#else 9895 mov rFP, r1 @ fp = newFp 9896 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9897 mov rINST, r9 @ publish new rINST 9898 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9899 GOTO_OPCODE(ip) @ jump to next instruction 9900#endif 9901 9902.LinvokeNative: 9903 @ Prep for the native call 9904 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9905 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9906 ldr r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext 9907 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9908 str r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext 9909 mov r9, r3 @ r9<- glue->self (preserve) 9910 9911 mov r2, r0 @ r2<- methodToCall 9912 mov r0, r1 @ r0<- newFp (points to args) 9913 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9914 9915#ifdef ASSIST_DEBUGGER 9916 /* insert fake function header to help gdb find the stack frame */ 9917 b .Lskip 9918 .type dalvik_mterp, %function 9919dalvik_mterp: 9920 .fnstart 9921 MTERP_ENTRY1 9922 MTERP_ENTRY2 9923.Lskip: 9924#endif 9925 9926 @mov lr, pc @ set return addr 9927 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9928 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9929 9930 @ native return; r9=self, r10=newSaveArea 9931 @ equivalent to dvmPopJniLocals 9932 ldr r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop 9933 ldr r1, [r9, #offThread_exception] @ check for exception 9934 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9935 cmp r1, #0 @ null? 9936 str r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0 9937 bne common_exceptionThrown @ no, handle exception 9938 9939 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9940 GET_INST_OPCODE(ip) @ extract opcode from rINST 9941 GOTO_OPCODE(ip) @ jump to next instruction 9942 9943.LstackOverflow: 9944 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9945 bl dvmHandleStackOverflow 9946 b common_exceptionThrown 9947#ifdef ASSIST_DEBUGGER 9948 .fnend 9949#endif 9950 9951 9952 /* 9953 * Common code for method invocation, calling through "glue code". 9954 * 9955 * TODO: now that we have range and non-range invoke handlers, this 9956 * needs to be split into two. Maybe just create entry points 9957 * that set r9 and jump here? 9958 * 9959 * On entry: 9960 * r0 is "Method* methodToCall", the method we're trying to call 9961 * r9 is "bool methodCallRange", indicating if this is a /range variant 9962 */ 9963 .if 0 9964.LinvokeOld: 9965 sub sp, sp, #8 @ space for args + pad 9966 FETCH(ip, 2) @ ip<- FEDC or CCCC 9967 mov r2, r0 @ A2<- methodToCall 9968 mov r0, rGLUE @ A0<- glue 9969 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9970 mov r1, r9 @ A1<- methodCallRange 9971 mov r3, rINST, lsr #8 @ A3<- AA 9972 str ip, [sp, #0] @ A4<- ip 9973 bl dvmMterp_invokeMethod @ call the C invokeMethod 9974 add sp, sp, #8 @ remove arg area 9975 b common_resumeAfterGlueCall @ continue to next instruction 9976 .endif 9977 9978 9979 9980/* 9981 * Common code for handling a return instruction. 9982 * 9983 * This does not return. 9984 */ 9985common_returnFromMethod: 9986.LreturnNew: 9987 mov r0, #kInterpEntryReturn 9988 mov r9, #0 9989 bl common_periodicChecks 9990 9991 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9992 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9993 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9994 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9995 @ r2<- method we're returning to 9996 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9997 cmp r2, #0 @ is this a break frame? 9998 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9999 mov r1, #0 @ "want switch" = false 10000 beq common_gotoBail @ break frame, bail out completely 10001 10002 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10003 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10004 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10005 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10006#if defined(WITH_JIT) 10007 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr 10008 GET_JIT_PROF_TABLE(r0) 10009 mov rPC, r9 @ publish new rPC 10010 str r1, [rGLUE, #offGlue_methodClassDex] 10011 cmp r3, #0 @ caller is compiled code 10012 blxne r3 10013 GET_INST_OPCODE(ip) @ extract opcode from rINST 10014 cmp r0,#0 10015 bne common_updateProfile 10016 GOTO_OPCODE(ip) @ jump to next instruction 10017#else 10018 GET_INST_OPCODE(ip) @ extract opcode from rINST 10019 mov rPC, r9 @ publish new rPC 10020 str r1, [rGLUE, #offGlue_methodClassDex] 10021 GOTO_OPCODE(ip) @ jump to next instruction 10022#endif 10023 10024 /* 10025 * Return handling, calls through "glue code". 10026 */ 10027 .if 0 10028.LreturnOld: 10029 SAVE_PC_FP_TO_GLUE() @ export state 10030 mov r0, rGLUE @ arg to function 10031 bl dvmMterp_returnFromMethod 10032 b common_resumeAfterGlueCall 10033 .endif 10034 10035 10036/* 10037 * Somebody has thrown an exception. Handle it. 10038 * 10039 * If the exception processing code returns to us (instead of falling 10040 * out of the interpreter), continue with whatever the next instruction 10041 * now happens to be. 10042 * 10043 * This does not return. 10044 */ 10045 .global dvmMterpCommonExceptionThrown 10046dvmMterpCommonExceptionThrown: 10047common_exceptionThrown: 10048.LexceptionNew: 10049 mov r0, #kInterpEntryThrow 10050 mov r9, #0 10051 bl common_periodicChecks 10052 10053#if defined(WITH_JIT) 10054 mov r2,#kJitTSelectAbort @ abandon trace selection in progress 10055 str r2,[rGLUE,#offGlue_jitState] 10056#endif 10057 10058 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10059 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10060 mov r1, r10 @ r1<- self 10061 mov r0, r9 @ r0<- exception 10062 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10063 mov r3, #0 @ r3<- NULL 10064 str r3, [r10, #offThread_exception] @ self->exception = NULL 10065 10066 /* set up args and a local for "&fp" */ 10067 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10068 str rFP, [sp, #-4]! @ *--sp = fp 10069 mov ip, sp @ ip<- &fp 10070 mov r3, #0 @ r3<- false 10071 str ip, [sp, #-4]! @ *--sp = &fp 10072 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10073 mov r0, r10 @ r0<- self 10074 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10075 mov r2, r9 @ r2<- exception 10076 sub r1, rPC, r1 @ r1<- pc - method->insns 10077 mov r1, r1, asr #1 @ r1<- offset in code units 10078 10079 /* call, r0 gets catchRelPc (a code-unit offset) */ 10080 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10081 10082 /* fix earlier stack overflow if necessary; may trash rFP */ 10083 ldrb r1, [r10, #offThread_stackOverflowed] 10084 cmp r1, #0 @ did we overflow earlier? 10085 beq 1f @ no, skip ahead 10086 mov rFP, r0 @ save relPc result in rFP 10087 mov r0, r10 @ r0<- self 10088 bl dvmCleanupStackOverflow @ call(self) 10089 mov r0, rFP @ restore result 100901: 10091 10092 /* update frame pointer and check result from dvmFindCatchBlock */ 10093 ldr rFP, [sp, #4] @ retrieve the updated rFP 10094 cmp r0, #0 @ is catchRelPc < 0? 10095 add sp, sp, #8 @ restore stack 10096 bmi .LnotCaughtLocally 10097 10098 /* adjust locals to match self->curFrame and updated PC */ 10099 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10100 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10101 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10102 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10103 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10104 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10105 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10106 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10107 10108 /* release the tracked alloc on the exception */ 10109 mov r0, r9 @ r0<- exception 10110 mov r1, r10 @ r1<- self 10111 bl dvmReleaseTrackedAlloc @ release the exception 10112 10113 /* restore the exception if the handler wants it */ 10114 FETCH_INST() @ load rINST from rPC 10115 GET_INST_OPCODE(ip) @ extract opcode from rINST 10116 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10117 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10118 GOTO_OPCODE(ip) @ jump to next instruction 10119 10120.LnotCaughtLocally: @ r9=exception, r10=self 10121 /* fix stack overflow if necessary */ 10122 ldrb r1, [r10, #offThread_stackOverflowed] 10123 cmp r1, #0 @ did we overflow earlier? 10124 movne r0, r10 @ if yes: r0<- self 10125 blne dvmCleanupStackOverflow @ if yes: call(self) 10126 10127 @ may want to show "not caught locally" debug messages here 10128#if DVM_SHOW_EXCEPTION >= 2 10129 /* call __android_log_print(prio, tag, format, ...) */ 10130 /* "Exception %s from %s:%d not caught locally" */ 10131 @ dvmLineNumFromPC(method, pc - method->insns) 10132 ldr r0, [rGLUE, #offGlue_method] 10133 ldr r1, [r0, #offMethod_insns] 10134 sub r1, rPC, r1 10135 asr r1, r1, #1 10136 bl dvmLineNumFromPC 10137 str r0, [sp, #-4]! 10138 @ dvmGetMethodSourceFile(method) 10139 ldr r0, [rGLUE, #offGlue_method] 10140 bl dvmGetMethodSourceFile 10141 str r0, [sp, #-4]! 10142 @ exception->clazz->descriptor 10143 ldr r3, [r9, #offObject_clazz] 10144 ldr r3, [r3, #offClassObject_descriptor] 10145 @ 10146 ldr r2, strExceptionNotCaughtLocally 10147 ldr r1, strLogTag 10148 mov r0, #3 @ LOG_DEBUG 10149 bl __android_log_print 10150#endif 10151 str r9, [r10, #offThread_exception] @ restore exception 10152 mov r0, r9 @ r0<- exception 10153 mov r1, r10 @ r1<- self 10154 bl dvmReleaseTrackedAlloc @ release the exception 10155 mov r1, #0 @ "want switch" = false 10156 b common_gotoBail @ bail out 10157 10158 10159 /* 10160 * Exception handling, calls through "glue code". 10161 */ 10162 .if 0 10163.LexceptionOld: 10164 SAVE_PC_FP_TO_GLUE() @ export state 10165 mov r0, rGLUE @ arg to function 10166 bl dvmMterp_exceptionThrown 10167 b common_resumeAfterGlueCall 10168 .endif 10169 10170 10171/* 10172 * After returning from a "glued" function, pull out the updated 10173 * values and start executing at the next instruction. 10174 */ 10175common_resumeAfterGlueCall: 10176 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10177 FETCH_INST() @ load rINST from rPC 10178 GET_INST_OPCODE(ip) @ extract opcode from rINST 10179 GOTO_OPCODE(ip) @ jump to next instruction 10180 10181/* 10182 * Invalid array index. 10183 */ 10184common_errArrayIndex: 10185 EXPORT_PC() 10186 ldr r0, strArrayIndexException 10187 mov r1, #0 10188 bl dvmThrowException 10189 b common_exceptionThrown 10190 10191/* 10192 * Invalid array value. 10193 */ 10194common_errArrayStore: 10195 EXPORT_PC() 10196 ldr r0, strArrayStoreException 10197 mov r1, #0 10198 bl dvmThrowException 10199 b common_exceptionThrown 10200 10201/* 10202 * Integer divide or mod by zero. 10203 */ 10204common_errDivideByZero: 10205 EXPORT_PC() 10206 ldr r0, strArithmeticException 10207 ldr r1, strDivideByZero 10208 bl dvmThrowException 10209 b common_exceptionThrown 10210 10211/* 10212 * Attempt to allocate an array with a negative size. 10213 */ 10214common_errNegativeArraySize: 10215 EXPORT_PC() 10216 ldr r0, strNegativeArraySizeException 10217 mov r1, #0 10218 bl dvmThrowException 10219 b common_exceptionThrown 10220 10221/* 10222 * Invocation of a non-existent method. 10223 */ 10224common_errNoSuchMethod: 10225 EXPORT_PC() 10226 ldr r0, strNoSuchMethodError 10227 mov r1, #0 10228 bl dvmThrowException 10229 b common_exceptionThrown 10230 10231/* 10232 * We encountered a null object when we weren't expecting one. We 10233 * export the PC, throw a NullPointerException, and goto the exception 10234 * processing code. 10235 */ 10236common_errNullObject: 10237 EXPORT_PC() 10238 ldr r0, strNullPointerException 10239 mov r1, #0 10240 bl dvmThrowException 10241 b common_exceptionThrown 10242 10243/* 10244 * For debugging, cause an immediate fault. The source address will 10245 * be in lr (use a bl instruction to jump here). 10246 */ 10247common_abort: 10248 ldr pc, .LdeadFood 10249.LdeadFood: 10250 .word 0xdeadf00d 10251 10252/* 10253 * Spit out a "we were here", preserving all registers. (The attempt 10254 * to save ip won't work, but we need to save an even number of 10255 * registers for EABI 64-bit stack alignment.) 10256 */ 10257 .macro SQUEAK num 10258common_squeak\num: 10259 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10260 ldr r0, strSqueak 10261 mov r1, #\num 10262 bl printf 10263 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10264 bx lr 10265 .endm 10266 10267 SQUEAK 0 10268 SQUEAK 1 10269 SQUEAK 2 10270 SQUEAK 3 10271 SQUEAK 4 10272 SQUEAK 5 10273 10274/* 10275 * Spit out the number in r0, preserving registers. 10276 */ 10277common_printNum: 10278 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10279 mov r1, r0 10280 ldr r0, strSqueak 10281 bl printf 10282 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10283 bx lr 10284 10285/* 10286 * Print a newline, preserving registers. 10287 */ 10288common_printNewline: 10289 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10290 ldr r0, strNewline 10291 bl printf 10292 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10293 bx lr 10294 10295 /* 10296 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10297 */ 10298common_printHex: 10299 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10300 mov r1, r0 10301 ldr r0, strPrintHex 10302 bl printf 10303 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10304 bx lr 10305 10306/* 10307 * Print the 64-bit quantity in r0-r1, preserving registers. 10308 */ 10309common_printLong: 10310 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10311 mov r3, r1 10312 mov r2, r0 10313 ldr r0, strPrintLong 10314 bl printf 10315 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10316 bx lr 10317 10318/* 10319 * Print full method info. Pass the Method* in r0. Preserves regs. 10320 */ 10321common_printMethod: 10322 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10323 bl dvmMterpPrintMethod 10324 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10325 bx lr 10326 10327/* 10328 * Call a C helper function that dumps regs and possibly some 10329 * additional info. Requires the C function to be compiled in. 10330 */ 10331 .if 0 10332common_dumpRegs: 10333 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10334 bl dvmMterpDumpArmRegs 10335 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10336 bx lr 10337 .endif 10338 10339 10340/* 10341 * String references, must be close to the code that uses them. 10342 */ 10343 .align 2 10344strArithmeticException: 10345 .word .LstrArithmeticException 10346strArrayIndexException: 10347 .word .LstrArrayIndexException 10348strArrayStoreException: 10349 .word .LstrArrayStoreException 10350strDivideByZero: 10351 .word .LstrDivideByZero 10352strNegativeArraySizeException: 10353 .word .LstrNegativeArraySizeException 10354strNoSuchMethodError: 10355 .word .LstrNoSuchMethodError 10356strNullPointerException: 10357 .word .LstrNullPointerException 10358 10359strLogTag: 10360 .word .LstrLogTag 10361strExceptionNotCaughtLocally: 10362 .word .LstrExceptionNotCaughtLocally 10363 10364strNewline: 10365 .word .LstrNewline 10366strSqueak: 10367 .word .LstrSqueak 10368strPrintHex: 10369 .word .LstrPrintHex 10370strPrintLong: 10371 .word .LstrPrintLong 10372 10373/* 10374 * Zero-terminated ASCII string data. 10375 * 10376 * On ARM we have two choices: do like gcc does, and LDR from a .word 10377 * with the address, or use an ADR pseudo-op to get the address 10378 * directly. ADR saves 4 bytes and an indirection, but it's using a 10379 * PC-relative addressing mode and hence has a limited range, which 10380 * makes it not work well with mergeable string sections. 10381 */ 10382 .section .rodata.str1.4,"aMS",%progbits,1 10383 10384.LstrBadEntryPoint: 10385 .asciz "Bad entry point %d\n" 10386.LstrArithmeticException: 10387 .asciz "Ljava/lang/ArithmeticException;" 10388.LstrArrayIndexException: 10389 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10390.LstrArrayStoreException: 10391 .asciz "Ljava/lang/ArrayStoreException;" 10392.LstrClassCastException: 10393 .asciz "Ljava/lang/ClassCastException;" 10394.LstrDivideByZero: 10395 .asciz "divide by zero" 10396.LstrFilledNewArrayNotImpl: 10397 .asciz "filled-new-array only implemented for objects and 'int'" 10398.LstrInternalError: 10399 .asciz "Ljava/lang/InternalError;" 10400.LstrInstantiationError: 10401 .asciz "Ljava/lang/InstantiationError;" 10402.LstrNegativeArraySizeException: 10403 .asciz "Ljava/lang/NegativeArraySizeException;" 10404.LstrNoSuchMethodError: 10405 .asciz "Ljava/lang/NoSuchMethodError;" 10406.LstrNullPointerException: 10407 .asciz "Ljava/lang/NullPointerException;" 10408 10409.LstrLogTag: 10410 .asciz "mterp" 10411.LstrExceptionNotCaughtLocally: 10412 .asciz "Exception %s from %s:%d not caught locally\n" 10413 10414.LstrNewline: 10415 .asciz "\n" 10416.LstrSqueak: 10417 .asciz "<%d>" 10418.LstrPrintHex: 10419 .asciz "<0x%x>" 10420.LstrPrintLong: 10421 .asciz "<%lld>" 10422 10423 10424