InterpAsm-armv4t.S revision 3a1aedbc9777eab6275a360b93b81b079464238e
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv4t'. 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. 44 45Stack is "full descending". Only the arguments that don't fit in the first 4 46registers are placed on the stack. "sp" points at the first stacked argument 47(i.e. the 5th arg). 48 49VFP: single-precision results in s0, double-precision results in d0. 50 51In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5264-bit quantities (long long, double) must be 64-bit aligned. 53*/ 54 55/* 56Mterp and ARM notes: 57 58The following registers have fixed assignments: 59 60 reg nick purpose 61 r4 rPC interpreted program counter, used for fetching instructions 62 r5 rFP interpreted frame pointer, used for accessing locals and args 63 r6 rGLUE MterpGlue pointer 64 r7 rIBASE interpreted instruction base pointer, used for computed goto 65 r8 rINST first 16-bit code unit of current instruction 66 67Macros are provided for common operations. Each macro MUST emit only 68one instruction to make instruction-counting easier. They MUST NOT alter 69unspecified registers or condition codes. 70*/ 71 72/* single-purpose registers, given names for clarity */ 73#define rPC r4 74#define rFP r5 75#define rGLUE r6 76#define rIBASE r7 77#define rINST r8 78 79/* save/restore the PC and/or FP from the glue struct */ 80#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 81#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 82#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 83#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 84#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 85#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 86 87/* 88 * "export" the PC to the stack frame, f/b/o future exception objects. Must 89 * be done *before* something calls dvmThrowException. 90 * 91 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 92 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 93 * 94 * It's okay to do this more than once. 95 */ 96#define EXPORT_PC() \ 97 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 98 99/* 100 * Given a frame pointer, find the stack save area. 101 * 102 * In C this is "((StackSaveArea*)(_fp) -1)". 103 */ 104#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 105 sub _reg, _fpreg, #sizeofStackSaveArea 106 107/* 108 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 109 */ 110#define FETCH_INST() ldrh rINST, [rPC] 111 112/* 113 * Fetch the next instruction from the specified offset. Advances rPC 114 * to point to the next instruction. "_count" is in 16-bit code units. 115 * 116 * Because of the limited size of immediate constants on ARM, this is only 117 * suitable for small forward movements (i.e. don't try to implement "goto" 118 * with this). 119 * 120 * This must come AFTER anything that can throw an exception, or the 121 * exception catch may miss. (This also implies that it must come after 122 * EXPORT_PC().) 123 */ 124#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 125 126/* 127 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 128 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 129 */ 130#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 131 ldrh _dreg, [_sreg, #(_count*2)]! 132 133/* 134 * Fetch the next instruction from an offset specified by _reg. Updates 135 * rPC to point to the next instruction. "_reg" must specify the distance 136 * in bytes, *not* 16-bit code units, and may be a signed value. 137 * 138 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 139 * bits that hold the shift distance are used for the half/byte/sign flags. 140 * In some cases we can pre-double _reg for free, so we require a byte offset 141 * here. 142 */ 143#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 144 145/* 146 * Fetch a half-word code unit from an offset past the current PC. The 147 * "_count" value is in 16-bit code units. Does not advance rPC. 148 * 149 * The "_S" variant works the same but treats the value as signed. 150 */ 151#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 152#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 153 154/* 155 * Fetch one byte from an offset past the current PC. Pass in the same 156 * "_count" as you would for FETCH, and an additional 0/1 indicating which 157 * byte of the halfword you want (lo/hi). 158 */ 159#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 160 161/* 162 * Put the instruction's opcode field into the specified register. 163 */ 164#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 165 166/* 167 * Put the prefetched instruction's opcode field into the specified register. 168 */ 169#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 170 171/* 172 * Begin executing the opcode in _reg. Because this only jumps within the 173 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 174 */ 175#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 176 177/* 178 * Get/set the 32-bit value from a Dalvik register. 179 */ 180#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 181#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 182 183/* 184 * This is a #include, not a %include, because we want the C pre-processor 185 * to expand the macros into assembler assignment statements. 186 */ 187#include "../common/asm-constants.h" 188 189 190/* File: armv5te/platform.S */ 191/* 192 * =========================================================================== 193 * CPU-version-specific defines 194 * =========================================================================== 195 */ 196 197/* 198 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 199 * one-way branch. 200 * 201 * May modify IP. Does not modify LR. 202 */ 203.macro LDR_PC source 204 ldr pc, \source 205.endm 206 207/* 208 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 209 * Jump to subroutine. 210 * 211 * May modify IP and LR. 212 */ 213.macro LDR_PC_LR source 214 mov lr, pc 215 ldr pc, \source 216.endm 217 218/* 219 * Macro for "LDMFD SP!, {...regs...,PC}". 220 * 221 * May modify IP and LR. 222 */ 223.macro LDMFD_PC regs 224 ldmfd sp!, {\regs,pc} 225.endm 226 227 228/* File: armv5te/entry.S */ 229/* 230 * Copyright (C) 2008 The Android Open Source Project 231 * 232 * Licensed under the Apache License, Version 2.0 (the "License"); 233 * you may not use this file except in compliance with the License. 234 * You may obtain a copy of the License at 235 * 236 * http://www.apache.org/licenses/LICENSE-2.0 237 * 238 * Unless required by applicable law or agreed to in writing, software 239 * distributed under the License is distributed on an "AS IS" BASIS, 240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 241 * See the License for the specific language governing permissions and 242 * limitations under the License. 243 */ 244/* 245 * Interpreter entry point. 246 */ 247 248/* 249 * We don't have formal stack frames, so gdb scans upward in the code 250 * to find the start of the function (a label with the %function type), 251 * and then looks at the next few instructions to figure out what 252 * got pushed onto the stack. From this it figures out how to restore 253 * the registers, including PC, for the previous stack frame. If gdb 254 * sees a non-function label, it stops scanning, so either we need to 255 * have nothing but assembler-local labels between the entry point and 256 * the break, or we need to fake it out. 257 * 258 * When this is defined, we add some stuff to make gdb less confused. 259 */ 260#define ASSIST_DEBUGGER 1 261 262 .text 263 .align 2 264 .global dvmMterpStdRun 265 .type dvmMterpStdRun, %function 266 267/* 268 * On entry: 269 * r0 MterpGlue* glue 270 * 271 * This function returns a boolean "changeInterp" value. The return comes 272 * via a call to dvmMterpStdBail(). 273 */ 274dvmMterpStdRun: 275#define MTERP_ENTRY1 \ 276 .save {r4-r10,fp,lr}; \ 277 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 278#define MTERP_ENTRY2 \ 279 .pad #4; \ 280 sub sp, sp, #4 @ align 64 281 282 .fnstart 283 MTERP_ENTRY1 284 MTERP_ENTRY2 285 286 /* save stack pointer, add magic word for debuggerd */ 287 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 288 289 /* set up "named" registers, figure out entry point */ 290 mov rGLUE, r0 @ set rGLUE 291 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 292 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 293 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 294 cmp r1, #kInterpEntryInstr @ usual case? 295 bne .Lnot_instr @ no, handle it 296 297 /* start executing the instruction at rPC */ 298 FETCH_INST() @ load rINST from rPC 299 GET_INST_OPCODE(ip) @ extract opcode from rINST 300 GOTO_OPCODE(ip) @ jump to next instruction 301 302.Lnot_instr: 303 cmp r1, #kInterpEntryReturn @ were we returning from a method? 304 beq common_returnFromMethod 305 306.Lnot_return: 307 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 308 beq common_exceptionThrown 309 310.Lbad_arg: 311 ldr r0, strBadEntryPoint 312 @ r1 holds value of entryPoint 313 bl printf 314 bl dvmAbort 315 .fnend 316 317 318 .global dvmMterpStdBail 319 .type dvmMterpStdBail, %function 320 321/* 322 * Restore the stack pointer and PC from the save point established on entry. 323 * This is essentially the same as a longjmp, but should be cheaper. The 324 * last instruction causes us to return to whoever called dvmMterpStdRun. 325 * 326 * We pushed some registers on the stack in dvmMterpStdRun, then saved 327 * SP and LR. Here we restore SP, restore the registers, and then restore 328 * LR to PC. 329 * 330 * On entry: 331 * r0 MterpGlue* glue 332 * r1 bool changeInterp 333 */ 334dvmMterpStdBail: 335 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 336 mov r0, r1 @ return the changeInterp value 337 add sp, sp, #4 @ un-align 64 338 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 339 340 341/* 342 * String references. 343 */ 344strBadEntryPoint: 345 .word .LstrBadEntryPoint 346 347 348 349 .global dvmAsmInstructionStart 350 .type dvmAsmInstructionStart, %function 351dvmAsmInstructionStart = .L_OP_NOP 352 .text 353 354/* ------------------------------ */ 355 .balign 64 356.L_OP_NOP: /* 0x00 */ 357/* File: armv5te/OP_NOP.S */ 358 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 359 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 360 GOTO_OPCODE(ip) @ execute it 361 362#ifdef ASSIST_DEBUGGER 363 /* insert fake function header to help gdb find the stack frame */ 364 .type dalvik_inst, %function 365dalvik_inst: 366 .fnstart 367 MTERP_ENTRY1 368 MTERP_ENTRY2 369 .fnend 370#endif 371 372 373/* ------------------------------ */ 374 .balign 64 375.L_OP_MOVE: /* 0x01 */ 376/* File: armv5te/OP_MOVE.S */ 377 /* for move, move-object, long-to-int */ 378 /* op vA, vB */ 379 mov r1, rINST, lsr #12 @ r1<- B from 15:12 380 mov r0, rINST, lsr #8 @ r0<- A from 11:8 381 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 382 GET_VREG(r2, r1) @ r2<- fp[B] 383 and r0, r0, #15 384 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 385 SET_VREG(r2, r0) @ fp[A]<- r2 386 GOTO_OPCODE(ip) @ execute next instruction 387 388 389/* ------------------------------ */ 390 .balign 64 391.L_OP_MOVE_FROM16: /* 0x02 */ 392/* File: armv5te/OP_MOVE_FROM16.S */ 393 /* for: move/from16, move-object/from16 */ 394 /* op vAA, vBBBB */ 395 FETCH(r1, 1) @ r1<- BBBB 396 mov r0, rINST, lsr #8 @ r0<- AA 397 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 398 GET_VREG(r2, r1) @ r2<- fp[BBBB] 399 GET_INST_OPCODE(ip) @ extract opcode from rINST 400 SET_VREG(r2, r0) @ fp[AA]<- r2 401 GOTO_OPCODE(ip) @ jump to next instruction 402 403 404/* ------------------------------ */ 405 .balign 64 406.L_OP_MOVE_16: /* 0x03 */ 407/* File: armv5te/OP_MOVE_16.S */ 408 /* for: move/16, move-object/16 */ 409 /* op vAAAA, vBBBB */ 410 FETCH(r1, 2) @ r1<- BBBB 411 FETCH(r0, 1) @ r0<- AAAA 412 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 413 GET_VREG(r2, r1) @ r2<- fp[BBBB] 414 GET_INST_OPCODE(ip) @ extract opcode from rINST 415 SET_VREG(r2, r0) @ fp[AAAA]<- r2 416 GOTO_OPCODE(ip) @ jump to next instruction 417 418 419/* ------------------------------ */ 420 .balign 64 421.L_OP_MOVE_WIDE: /* 0x04 */ 422/* File: armv5te/OP_MOVE_WIDE.S */ 423 /* move-wide vA, vB */ 424 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 425 mov r2, rINST, lsr #8 @ r2<- A(+) 426 mov r3, rINST, lsr #12 @ r3<- B 427 and r2, r2, #15 428 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 429 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 430 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 431 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 432 GET_INST_OPCODE(ip) @ extract opcode from rINST 433 stmia r2, {r0-r1} @ fp[A]<- r0/r1 434 GOTO_OPCODE(ip) @ jump to next instruction 435 436 437/* ------------------------------ */ 438 .balign 64 439.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 440/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 441 /* move-wide/from16 vAA, vBBBB */ 442 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 443 FETCH(r3, 1) @ r3<- BBBB 444 mov r2, rINST, lsr #8 @ r2<- AA 445 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 446 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 447 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 449 GET_INST_OPCODE(ip) @ extract opcode from rINST 450 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 451 GOTO_OPCODE(ip) @ jump to next instruction 452 453 454/* ------------------------------ */ 455 .balign 64 456.L_OP_MOVE_WIDE_16: /* 0x06 */ 457/* File: armv5te/OP_MOVE_WIDE_16.S */ 458 /* move-wide/16 vAAAA, vBBBB */ 459 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 460 FETCH(r3, 2) @ r3<- BBBB 461 FETCH(r2, 1) @ r2<- AAAA 462 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 463 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 464 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 466 GET_INST_OPCODE(ip) @ extract opcode from rINST 467 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 468 GOTO_OPCODE(ip) @ jump to next instruction 469 470 471/* ------------------------------ */ 472 .balign 64 473.L_OP_MOVE_OBJECT: /* 0x07 */ 474/* File: armv5te/OP_MOVE_OBJECT.S */ 475/* File: armv5te/OP_MOVE.S */ 476 /* for move, move-object, long-to-int */ 477 /* op vA, vB */ 478 mov r1, rINST, lsr #12 @ r1<- B from 15:12 479 mov r0, rINST, lsr #8 @ r0<- A from 11:8 480 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 481 GET_VREG(r2, r1) @ r2<- fp[B] 482 and r0, r0, #15 483 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 484 SET_VREG(r2, r0) @ fp[A]<- r2 485 GOTO_OPCODE(ip) @ execute next instruction 486 487 488 489/* ------------------------------ */ 490 .balign 64 491.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 492/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 493/* File: armv5te/OP_MOVE_FROM16.S */ 494 /* for: move/from16, move-object/from16 */ 495 /* op vAA, vBBBB */ 496 FETCH(r1, 1) @ r1<- BBBB 497 mov r0, rINST, lsr #8 @ r0<- AA 498 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 499 GET_VREG(r2, r1) @ r2<- fp[BBBB] 500 GET_INST_OPCODE(ip) @ extract opcode from rINST 501 SET_VREG(r2, r0) @ fp[AA]<- r2 502 GOTO_OPCODE(ip) @ jump to next instruction 503 504 505 506/* ------------------------------ */ 507 .balign 64 508.L_OP_MOVE_OBJECT_16: /* 0x09 */ 509/* File: armv5te/OP_MOVE_OBJECT_16.S */ 510/* File: armv5te/OP_MOVE_16.S */ 511 /* for: move/16, move-object/16 */ 512 /* op vAAAA, vBBBB */ 513 FETCH(r1, 2) @ r1<- BBBB 514 FETCH(r0, 1) @ r0<- AAAA 515 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 516 GET_VREG(r2, r1) @ r2<- fp[BBBB] 517 GET_INST_OPCODE(ip) @ extract opcode from rINST 518 SET_VREG(r2, r0) @ fp[AAAA]<- r2 519 GOTO_OPCODE(ip) @ jump to next instruction 520 521 522 523/* ------------------------------ */ 524 .balign 64 525.L_OP_MOVE_RESULT: /* 0x0a */ 526/* File: armv5te/OP_MOVE_RESULT.S */ 527 /* for: move-result, move-result-object */ 528 /* op vAA */ 529 mov r2, rINST, lsr #8 @ r2<- AA 530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 531 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 532 GET_INST_OPCODE(ip) @ extract opcode from rINST 533 SET_VREG(r0, r2) @ fp[AA]<- r0 534 GOTO_OPCODE(ip) @ jump to next instruction 535 536 537/* ------------------------------ */ 538 .balign 64 539.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 540/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 541 /* move-result-wide vAA */ 542 mov r2, rINST, lsr #8 @ r2<- AA 543 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 544 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 545 ldmia r3, {r0-r1} @ r0/r1<- retval.j 546 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 547 GET_INST_OPCODE(ip) @ extract opcode from rINST 548 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 549 GOTO_OPCODE(ip) @ jump to next instruction 550 551 552/* ------------------------------ */ 553 .balign 64 554.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 555/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 556/* File: armv5te/OP_MOVE_RESULT.S */ 557 /* for: move-result, move-result-object */ 558 /* op vAA */ 559 mov r2, rINST, lsr #8 @ r2<- AA 560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 561 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 562 GET_INST_OPCODE(ip) @ extract opcode from rINST 563 SET_VREG(r0, r2) @ fp[AA]<- r0 564 GOTO_OPCODE(ip) @ jump to next instruction 565 566 567 568/* ------------------------------ */ 569 .balign 64 570.L_OP_MOVE_EXCEPTION: /* 0x0d */ 571/* File: armv5te/OP_MOVE_EXCEPTION.S */ 572 /* move-exception vAA */ 573 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 574 mov r2, rINST, lsr #8 @ r2<- AA 575 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 576 mov r1, #0 @ r1<- 0 577 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 578 SET_VREG(r3, r2) @ fp[AA]<- exception obj 579 GET_INST_OPCODE(ip) @ extract opcode from rINST 580 str r1, [r0, #offThread_exception] @ dvmClearException bypass 581 GOTO_OPCODE(ip) @ jump to next instruction 582 583 584/* ------------------------------ */ 585 .balign 64 586.L_OP_RETURN_VOID: /* 0x0e */ 587/* File: armv5te/OP_RETURN_VOID.S */ 588 b common_returnFromMethod 589 590 591/* ------------------------------ */ 592 .balign 64 593.L_OP_RETURN: /* 0x0f */ 594/* File: armv5te/OP_RETURN.S */ 595 /* 596 * Return a 32-bit value. Copies the return value into the "glue" 597 * structure, then jumps to the return handler. 598 * 599 * for: return, return-object 600 */ 601 /* op vAA */ 602 mov r2, rINST, lsr #8 @ r2<- AA 603 GET_VREG(r0, r2) @ r0<- vAA 604 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 605 b common_returnFromMethod 606 607 608/* ------------------------------ */ 609 .balign 64 610.L_OP_RETURN_WIDE: /* 0x10 */ 611/* File: armv5te/OP_RETURN_WIDE.S */ 612 /* 613 * Return a 64-bit value. Copies the return value into the "glue" 614 * structure, then jumps to the return handler. 615 */ 616 /* return-wide vAA */ 617 mov r2, rINST, lsr #8 @ r2<- AA 618 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 619 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 620 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 621 stmia r3, {r0-r1} @ retval<- r0/r1 622 b common_returnFromMethod 623 624 625/* ------------------------------ */ 626 .balign 64 627.L_OP_RETURN_OBJECT: /* 0x11 */ 628/* File: armv5te/OP_RETURN_OBJECT.S */ 629/* File: armv5te/OP_RETURN.S */ 630 /* 631 * Return a 32-bit value. Copies the return value into the "glue" 632 * structure, then jumps to the return handler. 633 * 634 * for: return, return-object 635 */ 636 /* op vAA */ 637 mov r2, rINST, lsr #8 @ r2<- AA 638 GET_VREG(r0, r2) @ r0<- vAA 639 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 640 b common_returnFromMethod 641 642 643 644/* ------------------------------ */ 645 .balign 64 646.L_OP_CONST_4: /* 0x12 */ 647/* File: armv5te/OP_CONST_4.S */ 648 /* const/4 vA, #+B */ 649 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 650 mov r0, rINST, lsr #8 @ r0<- A+ 651 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 652 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 653 and r0, r0, #15 654 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 655 SET_VREG(r1, r0) @ fp[A]<- r1 656 GOTO_OPCODE(ip) @ execute next instruction 657 658 659/* ------------------------------ */ 660 .balign 64 661.L_OP_CONST_16: /* 0x13 */ 662/* File: armv5te/OP_CONST_16.S */ 663 /* const/16 vAA, #+BBBB */ 664 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 665 mov r3, rINST, lsr #8 @ r3<- AA 666 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 667 SET_VREG(r0, r3) @ vAA<- r0 668 GET_INST_OPCODE(ip) @ extract opcode from rINST 669 GOTO_OPCODE(ip) @ jump to next instruction 670 671 672/* ------------------------------ */ 673 .balign 64 674.L_OP_CONST: /* 0x14 */ 675/* File: armv5te/OP_CONST.S */ 676 /* const vAA, #+BBBBbbbb */ 677 mov r3, rINST, lsr #8 @ r3<- AA 678 FETCH(r0, 1) @ r0<- bbbb (low) 679 FETCH(r1, 2) @ r1<- BBBB (high) 680 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 681 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 682 GET_INST_OPCODE(ip) @ extract opcode from rINST 683 SET_VREG(r0, r3) @ vAA<- r0 684 GOTO_OPCODE(ip) @ jump to next instruction 685 686 687/* ------------------------------ */ 688 .balign 64 689.L_OP_CONST_HIGH16: /* 0x15 */ 690/* File: armv5te/OP_CONST_HIGH16.S */ 691 /* const/high16 vAA, #+BBBB0000 */ 692 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 693 mov r3, rINST, lsr #8 @ r3<- AA 694 mov r0, r0, lsl #16 @ r0<- BBBB0000 695 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 696 SET_VREG(r0, r3) @ vAA<- r0 697 GET_INST_OPCODE(ip) @ extract opcode from rINST 698 GOTO_OPCODE(ip) @ jump to next instruction 699 700 701/* ------------------------------ */ 702 .balign 64 703.L_OP_CONST_WIDE_16: /* 0x16 */ 704/* File: armv5te/OP_CONST_WIDE_16.S */ 705 /* const-wide/16 vAA, #+BBBB */ 706 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 707 mov r3, rINST, lsr #8 @ r3<- AA 708 mov r1, r0, asr #31 @ r1<- ssssssss 709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 710 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 711 GET_INST_OPCODE(ip) @ extract opcode from rINST 712 stmia r3, {r0-r1} @ vAA<- r0/r1 713 GOTO_OPCODE(ip) @ jump to next instruction 714 715 716/* ------------------------------ */ 717 .balign 64 718.L_OP_CONST_WIDE_32: /* 0x17 */ 719/* File: armv5te/OP_CONST_WIDE_32.S */ 720 /* const-wide/32 vAA, #+BBBBbbbb */ 721 FETCH(r0, 1) @ r0<- 0000bbbb (low) 722 mov r3, rINST, lsr #8 @ r3<- AA 723 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 724 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 725 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 726 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 727 mov r1, r0, asr #31 @ r1<- ssssssss 728 GET_INST_OPCODE(ip) @ extract opcode from rINST 729 stmia r3, {r0-r1} @ vAA<- r0/r1 730 GOTO_OPCODE(ip) @ jump to next instruction 731 732 733/* ------------------------------ */ 734 .balign 64 735.L_OP_CONST_WIDE: /* 0x18 */ 736/* File: armv5te/OP_CONST_WIDE.S */ 737 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 738 FETCH(r0, 1) @ r0<- bbbb (low) 739 FETCH(r1, 2) @ r1<- BBBB (low middle) 740 FETCH(r2, 3) @ r2<- hhhh (high middle) 741 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 742 FETCH(r3, 4) @ r3<- HHHH (high) 743 mov r9, rINST, lsr #8 @ r9<- AA 744 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 745 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 746 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 747 GET_INST_OPCODE(ip) @ extract opcode from rINST 748 stmia r9, {r0-r1} @ vAA<- r0/r1 749 GOTO_OPCODE(ip) @ jump to next instruction 750 751 752/* ------------------------------ */ 753 .balign 64 754.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 755/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 756 /* const-wide/high16 vAA, #+BBBB000000000000 */ 757 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 758 mov r3, rINST, lsr #8 @ r3<- AA 759 mov r0, #0 @ r0<- 00000000 760 mov r1, r1, lsl #16 @ r1<- BBBB0000 761 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 762 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 763 GET_INST_OPCODE(ip) @ extract opcode from rINST 764 stmia r3, {r0-r1} @ vAA<- r0/r1 765 GOTO_OPCODE(ip) @ jump to next instruction 766 767 768/* ------------------------------ */ 769 .balign 64 770.L_OP_CONST_STRING: /* 0x1a */ 771/* File: armv5te/OP_CONST_STRING.S */ 772 /* const/string vAA, String@BBBB */ 773 FETCH(r1, 1) @ r1<- BBBB 774 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 775 mov r9, rINST, lsr #8 @ r9<- AA 776 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 777 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 778 cmp r0, #0 @ not yet resolved? 779 beq .LOP_CONST_STRING_resolve 780 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 781 GET_INST_OPCODE(ip) @ extract opcode from rINST 782 SET_VREG(r0, r9) @ vAA<- r0 783 GOTO_OPCODE(ip) @ jump to next instruction 784 785/* ------------------------------ */ 786 .balign 64 787.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 788/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 789 /* const/string vAA, String@BBBBBBBB */ 790 FETCH(r0, 1) @ r0<- bbbb (low) 791 FETCH(r1, 2) @ r1<- BBBB (high) 792 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 793 mov r9, rINST, lsr #8 @ r9<- AA 794 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 795 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 796 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 797 cmp r0, #0 798 beq .LOP_CONST_STRING_JUMBO_resolve 799 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 800 GET_INST_OPCODE(ip) @ extract opcode from rINST 801 SET_VREG(r0, r9) @ vAA<- r0 802 GOTO_OPCODE(ip) @ jump to next instruction 803 804/* ------------------------------ */ 805 .balign 64 806.L_OP_CONST_CLASS: /* 0x1c */ 807/* File: armv5te/OP_CONST_CLASS.S */ 808 /* const/class vAA, Class@BBBB */ 809 FETCH(r1, 1) @ r1<- BBBB 810 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 811 mov r9, rINST, lsr #8 @ r9<- AA 812 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 813 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 814 cmp r0, #0 @ not yet resolved? 815 beq .LOP_CONST_CLASS_resolve 816 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 817 GET_INST_OPCODE(ip) @ extract opcode from rINST 818 SET_VREG(r0, r9) @ vAA<- r0 819 GOTO_OPCODE(ip) @ jump to next instruction 820 821/* ------------------------------ */ 822 .balign 64 823.L_OP_MONITOR_ENTER: /* 0x1d */ 824/* File: armv5te/OP_MONITOR_ENTER.S */ 825 /* 826 * Synchronize on an object. 827 */ 828 /* monitor-enter vAA */ 829 mov r2, rINST, lsr #8 @ r2<- AA 830 GET_VREG(r1, r2) @ r1<- vAA (object) 831 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 832 cmp r1, #0 @ null object? 833 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 834 beq common_errNullObject @ null object, throw an exception 835 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 836 bl dvmLockObject @ call(self, obj) 837#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 838 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 839 ldr r1, [r0, #offThread_exception] @ check for exception 840 cmp r1, #0 841 bne common_exceptionThrown @ exception raised, bail out 842#endif 843 GET_INST_OPCODE(ip) @ extract opcode from rINST 844 GOTO_OPCODE(ip) @ jump to next instruction 845 846 847/* ------------------------------ */ 848 .balign 64 849.L_OP_MONITOR_EXIT: /* 0x1e */ 850/* File: armv5te/OP_MONITOR_EXIT.S */ 851 /* 852 * Unlock an object. 853 * 854 * Exceptions that occur when unlocking a monitor need to appear as 855 * if they happened at the following instruction. See the Dalvik 856 * instruction spec. 857 */ 858 /* monitor-exit vAA */ 859 mov r2, rINST, lsr #8 @ r2<- AA 860 EXPORT_PC() @ before fetch: export the PC 861 GET_VREG(r1, r2) @ r1<- vAA (object) 862 cmp r1, #0 @ null object? 863 beq common_errNullObject @ yes 864 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 865 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 866 cmp r0, #0 @ failed? 867 beq common_exceptionThrown @ yes, exception is pending 868 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 869 GET_INST_OPCODE(ip) @ extract opcode from rINST 870 GOTO_OPCODE(ip) @ jump to next instruction 871 872 873/* ------------------------------ */ 874 .balign 64 875.L_OP_CHECK_CAST: /* 0x1f */ 876/* File: armv5te/OP_CHECK_CAST.S */ 877 /* 878 * Check to see if a cast from one class to another is allowed. 879 */ 880 /* check-cast vAA, class@BBBB */ 881 mov r3, rINST, lsr #8 @ r3<- AA 882 FETCH(r2, 1) @ r2<- BBBB 883 GET_VREG(r9, r3) @ r9<- object 884 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 885 cmp r9, #0 @ is object null? 886 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 887 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 888 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 889 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 890 cmp r1, #0 @ have we resolved this before? 891 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 892.LOP_CHECK_CAST_resolved: 893 cmp r0, r1 @ same class (trivial success)? 894 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 895.LOP_CHECK_CAST_okay: 896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 897 GET_INST_OPCODE(ip) @ extract opcode from rINST 898 GOTO_OPCODE(ip) @ jump to next instruction 899 900/* ------------------------------ */ 901 .balign 64 902.L_OP_INSTANCE_OF: /* 0x20 */ 903/* File: armv5te/OP_INSTANCE_OF.S */ 904 /* 905 * Check to see if an object reference is an instance of a class. 906 * 907 * Most common situation is a non-null object, being compared against 908 * an already-resolved class. 909 */ 910 /* instance-of vA, vB, class@CCCC */ 911 mov r3, rINST, lsr #12 @ r3<- B 912 mov r9, rINST, lsr #8 @ r9<- A+ 913 GET_VREG(r0, r3) @ r0<- vB (object) 914 and r9, r9, #15 @ r9<- A 915 cmp r0, #0 @ is object null? 916 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 917 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 918 FETCH(r3, 1) @ r3<- CCCC 919 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 920 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 921 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 922 cmp r1, #0 @ have we resolved this before? 923 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 924.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 925 cmp r0, r1 @ same class (trivial success)? 926 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 927 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 928 929/* ------------------------------ */ 930 .balign 64 931.L_OP_ARRAY_LENGTH: /* 0x21 */ 932/* File: armv5te/OP_ARRAY_LENGTH.S */ 933 /* 934 * Return the length of an array. 935 */ 936 mov r1, rINST, lsr #12 @ r1<- B 937 mov r2, rINST, lsr #8 @ r2<- A+ 938 GET_VREG(r0, r1) @ r0<- vB (object ref) 939 and r2, r2, #15 @ r2<- A 940 cmp r0, #0 @ is object null? 941 beq common_errNullObject @ yup, fail 942 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 943 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 944 GET_INST_OPCODE(ip) @ extract opcode from rINST 945 SET_VREG(r3, r2) @ vB<- length 946 GOTO_OPCODE(ip) @ jump to next instruction 947 948 949/* ------------------------------ */ 950 .balign 64 951.L_OP_NEW_INSTANCE: /* 0x22 */ 952/* File: armv5te/OP_NEW_INSTANCE.S */ 953 /* 954 * Create a new instance of a class. 955 */ 956 /* new-instance vAA, class@BBBB */ 957 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 958 FETCH(r1, 1) @ r1<- BBBB 959 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 960 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 961 EXPORT_PC() @ req'd for init, resolve, alloc 962 cmp r0, #0 @ already resolved? 963 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 964.LOP_NEW_INSTANCE_resolved: @ r0=class 965 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 966 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 967 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 968.LOP_NEW_INSTANCE_initialized: @ r0=class 969 ldr r3, [r0, #offClassObject_accessFlags] @ r3<- clazz->accessFlags 970 tst r3, #(ACC_INTERFACE|ACC_ABSTRACT) @ abstract or interface? 971 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 972 beq .LOP_NEW_INSTANCE_finish @ concrete class, continue 973 b .LOP_NEW_INSTANCE_abstract @ fail 974 975/* ------------------------------ */ 976 .balign 64 977.L_OP_NEW_ARRAY: /* 0x23 */ 978/* File: armv5te/OP_NEW_ARRAY.S */ 979 /* 980 * Allocate an array of objects, specified with the array class 981 * and a count. 982 * 983 * The verifier guarantees that this is an array class, so we don't 984 * check for it here. 985 */ 986 /* new-array vA, vB, class@CCCC */ 987 mov r0, rINST, lsr #12 @ r0<- B 988 FETCH(r2, 1) @ r2<- CCCC 989 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 990 GET_VREG(r1, r0) @ r1<- vB (array length) 991 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 992 cmp r1, #0 @ check length 993 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 994 bmi common_errNegativeArraySize @ negative length, bail 995 cmp r0, #0 @ already resolved? 996 EXPORT_PC() @ req'd for resolve, alloc 997 bne .LOP_NEW_ARRAY_finish @ resolved, continue 998 b .LOP_NEW_ARRAY_resolve @ do resolve now 999 1000/* ------------------------------ */ 1001 .balign 64 1002.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1003/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1004 /* 1005 * Create a new array with elements filled from registers. 1006 * 1007 * for: filled-new-array, filled-new-array/range 1008 */ 1009 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1010 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1011 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1012 FETCH(r1, 1) @ r1<- BBBB 1013 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1014 EXPORT_PC() @ need for resolve and alloc 1015 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1016 mov r10, rINST, lsr #8 @ r10<- AA or BA 1017 cmp r0, #0 @ already resolved? 1018 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10198: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1020 mov r2, #0 @ r2<- false 1021 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1022 bl dvmResolveClass @ r0<- call(clazz, ref) 1023 cmp r0, #0 @ got null? 1024 beq common_exceptionThrown @ yes, handle exception 1025 b .LOP_FILLED_NEW_ARRAY_continue 1026 1027/* ------------------------------ */ 1028 .balign 64 1029.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1030/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1031/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1032 /* 1033 * Create a new array with elements filled from registers. 1034 * 1035 * for: filled-new-array, filled-new-array/range 1036 */ 1037 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1038 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1039 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1040 FETCH(r1, 1) @ r1<- BBBB 1041 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1042 EXPORT_PC() @ need for resolve and alloc 1043 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1044 mov r10, rINST, lsr #8 @ r10<- AA or BA 1045 cmp r0, #0 @ already resolved? 1046 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10478: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1048 mov r2, #0 @ r2<- false 1049 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1050 bl dvmResolveClass @ r0<- call(clazz, ref) 1051 cmp r0, #0 @ got null? 1052 beq common_exceptionThrown @ yes, handle exception 1053 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1054 1055 1056/* ------------------------------ */ 1057 .balign 64 1058.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1059/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1060 /* fill-array-data vAA, +BBBBBBBB */ 1061 FETCH(r0, 1) @ r0<- bbbb (lo) 1062 FETCH(r1, 2) @ r1<- BBBB (hi) 1063 mov r3, rINST, lsr #8 @ r3<- AA 1064 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1065 GET_VREG(r0, r3) @ r0<- vAA (array object) 1066 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1067 EXPORT_PC(); 1068 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1069 cmp r0, #0 @ 0 means an exception is thrown 1070 beq common_exceptionThrown @ has exception 1071 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1072 GET_INST_OPCODE(ip) @ extract opcode from rINST 1073 GOTO_OPCODE(ip) @ jump to next instruction 1074 1075/* ------------------------------ */ 1076 .balign 64 1077.L_OP_THROW: /* 0x27 */ 1078/* File: armv5te/OP_THROW.S */ 1079 /* 1080 * Throw an exception object in the current thread. 1081 */ 1082 /* throw vAA */ 1083 mov r2, rINST, lsr #8 @ r2<- AA 1084 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1085 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1086 cmp r1, #0 @ null object? 1087 beq common_errNullObject @ yes, throw an NPE instead 1088 @ bypass dvmSetException, just store it 1089 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1090 b common_exceptionThrown 1091 1092 1093/* ------------------------------ */ 1094 .balign 64 1095.L_OP_GOTO: /* 0x28 */ 1096/* File: armv5te/OP_GOTO.S */ 1097 /* 1098 * Unconditional branch, 8-bit offset. 1099 * 1100 * The branch distance is a signed code-unit offset, which we need to 1101 * double to get a byte offset. 1102 */ 1103 /* goto +AA */ 1104 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1105 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1106 mov r9, r9, lsl #1 @ r9<- byte offset 1107 bmi common_backwardBranch @ backward branch, do periodic checks 1108 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1109 GET_INST_OPCODE(ip) @ extract opcode from rINST 1110 GOTO_OPCODE(ip) @ jump to next instruction 1111 1112 1113/* ------------------------------ */ 1114 .balign 64 1115.L_OP_GOTO_16: /* 0x29 */ 1116/* File: armv5te/OP_GOTO_16.S */ 1117 /* 1118 * Unconditional branch, 16-bit offset. 1119 * 1120 * The branch distance is a signed code-unit offset, which we need to 1121 * double to get a byte offset. 1122 */ 1123 /* goto/16 +AAAA */ 1124 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1125 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1126 bmi common_backwardBranch @ backward branch, do periodic checks 1127 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1128 GET_INST_OPCODE(ip) @ extract opcode from rINST 1129 GOTO_OPCODE(ip) @ jump to next instruction 1130 1131 1132/* ------------------------------ */ 1133 .balign 64 1134.L_OP_GOTO_32: /* 0x2a */ 1135/* File: armv5te/OP_GOTO_32.S */ 1136 /* 1137 * Unconditional branch, 32-bit offset. 1138 * 1139 * The branch distance is a signed code-unit offset, which we need to 1140 * double to get a byte offset. 1141 * 1142 * Unlike most opcodes, this one is allowed to branch to itself, so 1143 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1144 * instruction doesn't affect the V flag, so we need to clear it 1145 * explicitly. 1146 */ 1147 /* goto/32 +AAAAAAAA */ 1148 FETCH(r0, 1) @ r0<- aaaa (lo) 1149 FETCH(r1, 2) @ r1<- AAAA (hi) 1150 cmp ip, ip @ (clear V flag during stall) 1151 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1152 mov r9, r0, asl #1 @ r9<- byte offset 1153 ble common_backwardBranch @ backward branch, do periodic checks 1154 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1155 GET_INST_OPCODE(ip) @ extract opcode from rINST 1156 GOTO_OPCODE(ip) @ jump to next instruction 1157 1158 1159/* ------------------------------ */ 1160 .balign 64 1161.L_OP_PACKED_SWITCH: /* 0x2b */ 1162/* File: armv5te/OP_PACKED_SWITCH.S */ 1163 /* 1164 * Handle a packed-switch or sparse-switch instruction. In both cases 1165 * we decode it and hand it off to a helper function. 1166 * 1167 * We don't really expect backward branches in a switch statement, but 1168 * they're perfectly legal, so we check for them here. 1169 * 1170 * for: packed-switch, sparse-switch 1171 */ 1172 /* op vAA, +BBBB */ 1173 FETCH(r0, 1) @ r0<- bbbb (lo) 1174 FETCH(r1, 2) @ r1<- BBBB (hi) 1175 mov r3, rINST, lsr #8 @ r3<- AA 1176 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1177 GET_VREG(r1, r3) @ r1<- vAA 1178 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1179 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1180 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1181 bmi common_backwardBranch @ backward branch, do periodic checks 1182 beq common_backwardBranch @ (want to use BLE but V is unknown) 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 1187 1188/* ------------------------------ */ 1189 .balign 64 1190.L_OP_SPARSE_SWITCH: /* 0x2c */ 1191/* File: armv5te/OP_SPARSE_SWITCH.S */ 1192/* File: armv5te/OP_PACKED_SWITCH.S */ 1193 /* 1194 * Handle a packed-switch or sparse-switch instruction. In both cases 1195 * we decode it and hand it off to a helper function. 1196 * 1197 * We don't really expect backward branches in a switch statement, but 1198 * they're perfectly legal, so we check for them here. 1199 * 1200 * for: packed-switch, sparse-switch 1201 */ 1202 /* op vAA, +BBBB */ 1203 FETCH(r0, 1) @ r0<- bbbb (lo) 1204 FETCH(r1, 2) @ r1<- BBBB (hi) 1205 mov r3, rINST, lsr #8 @ r3<- AA 1206 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1207 GET_VREG(r1, r3) @ r1<- vAA 1208 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1209 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1210 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1211 bmi common_backwardBranch @ backward branch, do periodic checks 1212 beq common_backwardBranch @ (want to use BLE but V is unknown) 1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1214 GET_INST_OPCODE(ip) @ extract opcode from rINST 1215 GOTO_OPCODE(ip) @ jump to next instruction 1216 1217 1218 1219/* ------------------------------ */ 1220 .balign 64 1221.L_OP_CMPL_FLOAT: /* 0x2d */ 1222/* File: armv5te/OP_CMPL_FLOAT.S */ 1223 /* 1224 * Compare two floating-point values. Puts 0, 1, or -1 into the 1225 * destination register based on the results of the comparison. 1226 * 1227 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1228 * on what value we'd like to return when one of the operands is NaN. 1229 * 1230 * The operation we're implementing is: 1231 * if (x == y) 1232 * return 0; 1233 * else if (x < y) 1234 * return -1; 1235 * else if (x > y) 1236 * return 1; 1237 * else 1238 * return {-1,1}; // one or both operands was NaN 1239 * 1240 * The straightforward implementation requires 3 calls to functions 1241 * that return a result in r0. We can do it with two calls if our 1242 * EABI library supports __aeabi_cfcmple (only one if we want to check 1243 * for NaN directly): 1244 * check x <= y 1245 * if <, return -1 1246 * if ==, return 0 1247 * check y <= x 1248 * if <, return 1 1249 * return {-1,1} 1250 * 1251 * for: cmpl-float, cmpg-float 1252 */ 1253 /* op vAA, vBB, vCC */ 1254 FETCH(r0, 1) @ r0<- CCBB 1255 and r2, r0, #255 @ r2<- BB 1256 mov r3, r0, lsr #8 @ r3<- CC 1257 GET_VREG(r9, r2) @ r9<- vBB 1258 GET_VREG(r10, r3) @ r10<- vCC 1259 mov r0, r9 @ copy to arg registers 1260 mov r1, r10 1261 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1262 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1263 mvncc r1, #0 @ (less than) r1<- -1 1264 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1265.LOP_CMPL_FLOAT_finish: 1266 mov r3, rINST, lsr #8 @ r3<- AA 1267 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1268 SET_VREG(r1, r3) @ vAA<- r1 1269 GET_INST_OPCODE(ip) @ extract opcode from rINST 1270 GOTO_OPCODE(ip) @ jump to next instruction 1271 1272/* ------------------------------ */ 1273 .balign 64 1274.L_OP_CMPG_FLOAT: /* 0x2e */ 1275/* File: armv5te/OP_CMPG_FLOAT.S */ 1276/* File: armv5te/OP_CMPL_FLOAT.S */ 1277 /* 1278 * Compare two floating-point values. Puts 0, 1, or -1 into the 1279 * destination register based on the results of the comparison. 1280 * 1281 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1282 * on what value we'd like to return when one of the operands is NaN. 1283 * 1284 * The operation we're implementing is: 1285 * if (x == y) 1286 * return 0; 1287 * else if (x < y) 1288 * return -1; 1289 * else if (x > y) 1290 * return 1; 1291 * else 1292 * return {-1,1}; // one or both operands was NaN 1293 * 1294 * The straightforward implementation requires 3 calls to functions 1295 * that return a result in r0. We can do it with two calls if our 1296 * EABI library supports __aeabi_cfcmple (only one if we want to check 1297 * for NaN directly): 1298 * check x <= y 1299 * if <, return -1 1300 * if ==, return 0 1301 * check y <= x 1302 * if <, return 1 1303 * return {-1,1} 1304 * 1305 * for: cmpl-float, cmpg-float 1306 */ 1307 /* op vAA, vBB, vCC */ 1308 FETCH(r0, 1) @ r0<- CCBB 1309 and r2, r0, #255 @ r2<- BB 1310 mov r3, r0, lsr #8 @ r3<- CC 1311 GET_VREG(r9, r2) @ r9<- vBB 1312 GET_VREG(r10, r3) @ r10<- vCC 1313 mov r0, r9 @ copy to arg registers 1314 mov r1, r10 1315 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1316 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1317 mvncc r1, #0 @ (less than) r1<- -1 1318 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1319.LOP_CMPG_FLOAT_finish: 1320 mov r3, rINST, lsr #8 @ r3<- AA 1321 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1322 SET_VREG(r1, r3) @ vAA<- r1 1323 GET_INST_OPCODE(ip) @ extract opcode from rINST 1324 GOTO_OPCODE(ip) @ jump to next instruction 1325 1326 1327/* ------------------------------ */ 1328 .balign 64 1329.L_OP_CMPL_DOUBLE: /* 0x2f */ 1330/* File: armv5te/OP_CMPL_DOUBLE.S */ 1331 /* 1332 * Compare two floating-point values. Puts 0, 1, or -1 into the 1333 * destination register based on the results of the comparison. 1334 * 1335 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1336 * on what value we'd like to return when one of the operands is NaN. 1337 * 1338 * See OP_CMPL_FLOAT for an explanation. 1339 * 1340 * For: cmpl-double, cmpg-double 1341 */ 1342 /* op vAA, vBB, vCC */ 1343 FETCH(r0, 1) @ r0<- CCBB 1344 and r9, r0, #255 @ r9<- BB 1345 mov r10, r0, lsr #8 @ r10<- CC 1346 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1347 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1348 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1349 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1350 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1351 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1352 mvncc r1, #0 @ (less than) r1<- -1 1353 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1354.LOP_CMPL_DOUBLE_finish: 1355 mov r3, rINST, lsr #8 @ r3<- AA 1356 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1357 SET_VREG(r1, r3) @ vAA<- r1 1358 GET_INST_OPCODE(ip) @ extract opcode from rINST 1359 GOTO_OPCODE(ip) @ jump to next instruction 1360 1361/* ------------------------------ */ 1362 .balign 64 1363.L_OP_CMPG_DOUBLE: /* 0x30 */ 1364/* File: armv5te/OP_CMPG_DOUBLE.S */ 1365/* File: armv5te/OP_CMPL_DOUBLE.S */ 1366 /* 1367 * Compare two floating-point values. Puts 0, 1, or -1 into the 1368 * destination register based on the results of the comparison. 1369 * 1370 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1371 * on what value we'd like to return when one of the operands is NaN. 1372 * 1373 * See OP_CMPL_FLOAT for an explanation. 1374 * 1375 * For: cmpl-double, cmpg-double 1376 */ 1377 /* op vAA, vBB, vCC */ 1378 FETCH(r0, 1) @ r0<- CCBB 1379 and r9, r0, #255 @ r9<- BB 1380 mov r10, r0, lsr #8 @ r10<- CC 1381 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1382 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1383 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1384 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1385 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1386 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1387 mvncc r1, #0 @ (less than) r1<- -1 1388 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1389.LOP_CMPG_DOUBLE_finish: 1390 mov r3, rINST, lsr #8 @ r3<- AA 1391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1392 SET_VREG(r1, r3) @ vAA<- r1 1393 GET_INST_OPCODE(ip) @ extract opcode from rINST 1394 GOTO_OPCODE(ip) @ jump to next instruction 1395 1396 1397/* ------------------------------ */ 1398 .balign 64 1399.L_OP_CMP_LONG: /* 0x31 */ 1400/* File: armv5te/OP_CMP_LONG.S */ 1401 /* 1402 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1403 * register based on the results of the comparison. 1404 * 1405 * We load the full values with LDM, but in practice many values could 1406 * be resolved by only looking at the high word. This could be made 1407 * faster or slower by splitting the LDM into a pair of LDRs. 1408 * 1409 * If we just wanted to set condition flags, we could do this: 1410 * subs ip, r0, r2 1411 * sbcs ip, r1, r3 1412 * subeqs ip, r0, r2 1413 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1414 * integer value, which we can do with 2 conditional mov/mvn instructions 1415 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1416 * us a constant 5-cycle path plus a branch at the end to the 1417 * instruction epilogue code. The multi-compare approach below needs 1418 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1419 * in the worst case (the 64-bit values are equal). 1420 */ 1421 /* cmp-long vAA, vBB, vCC */ 1422 FETCH(r0, 1) @ r0<- CCBB 1423 mov r9, rINST, lsr #8 @ r9<- AA 1424 and r2, r0, #255 @ r2<- BB 1425 mov r3, r0, lsr #8 @ r3<- CC 1426 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1427 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1428 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1429 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1430 cmp r1, r3 @ compare (vBB+1, vCC+1) 1431 blt .LOP_CMP_LONG_less @ signed compare on high part 1432 bgt .LOP_CMP_LONG_greater 1433 subs r1, r0, r2 @ r1<- r0 - r2 1434 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1435 bne .LOP_CMP_LONG_less 1436 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1437 1438/* ------------------------------ */ 1439 .balign 64 1440.L_OP_IF_EQ: /* 0x32 */ 1441/* File: armv5te/OP_IF_EQ.S */ 1442/* File: armv5te/bincmp.S */ 1443 /* 1444 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1445 * fragment that specifies the *reverse* comparison to perform, e.g. 1446 * for "if-le" you would use "gt". 1447 * 1448 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1449 */ 1450 /* if-cmp vA, vB, +CCCC */ 1451 mov r0, rINST, lsr #8 @ r0<- A+ 1452 mov r1, rINST, lsr #12 @ r1<- B 1453 and r0, r0, #15 1454 GET_VREG(r3, r1) @ r3<- vB 1455 GET_VREG(r2, r0) @ r2<- vA 1456 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1457 cmp r2, r3 @ compare (vA, vB) 1458 bne 1f @ branch to 1 if comparison failed 1459 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1460 movs r9, r9, asl #1 @ convert to bytes, check sign 1461 bmi common_backwardBranch @ yes, do periodic checks 14621: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1463 GET_INST_OPCODE(ip) @ extract opcode from rINST 1464 GOTO_OPCODE(ip) @ jump to next instruction 1465 1466 1467 1468/* ------------------------------ */ 1469 .balign 64 1470.L_OP_IF_NE: /* 0x33 */ 1471/* File: armv5te/OP_IF_NE.S */ 1472/* File: armv5te/bincmp.S */ 1473 /* 1474 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1475 * fragment that specifies the *reverse* comparison to perform, e.g. 1476 * for "if-le" you would use "gt". 1477 * 1478 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1479 */ 1480 /* if-cmp vA, vB, +CCCC */ 1481 mov r0, rINST, lsr #8 @ r0<- A+ 1482 mov r1, rINST, lsr #12 @ r1<- B 1483 and r0, r0, #15 1484 GET_VREG(r3, r1) @ r3<- vB 1485 GET_VREG(r2, r0) @ r2<- vA 1486 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1487 cmp r2, r3 @ compare (vA, vB) 1488 beq 1f @ branch to 1 if comparison failed 1489 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1490 movs r9, r9, asl #1 @ convert to bytes, check sign 1491 bmi common_backwardBranch @ yes, do periodic checks 14921: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1493 GET_INST_OPCODE(ip) @ extract opcode from rINST 1494 GOTO_OPCODE(ip) @ jump to next instruction 1495 1496 1497 1498/* ------------------------------ */ 1499 .balign 64 1500.L_OP_IF_LT: /* 0x34 */ 1501/* File: armv5te/OP_IF_LT.S */ 1502/* File: armv5te/bincmp.S */ 1503 /* 1504 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1505 * fragment that specifies the *reverse* comparison to perform, e.g. 1506 * for "if-le" you would use "gt". 1507 * 1508 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1509 */ 1510 /* if-cmp vA, vB, +CCCC */ 1511 mov r0, rINST, lsr #8 @ r0<- A+ 1512 mov r1, rINST, lsr #12 @ r1<- B 1513 and r0, r0, #15 1514 GET_VREG(r3, r1) @ r3<- vB 1515 GET_VREG(r2, r0) @ r2<- vA 1516 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1517 cmp r2, r3 @ compare (vA, vB) 1518 bge 1f @ branch to 1 if comparison failed 1519 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1520 movs r9, r9, asl #1 @ convert to bytes, check sign 1521 bmi common_backwardBranch @ yes, do periodic checks 15221: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1523 GET_INST_OPCODE(ip) @ extract opcode from rINST 1524 GOTO_OPCODE(ip) @ jump to next instruction 1525 1526 1527 1528/* ------------------------------ */ 1529 .balign 64 1530.L_OP_IF_GE: /* 0x35 */ 1531/* File: armv5te/OP_IF_GE.S */ 1532/* File: armv5te/bincmp.S */ 1533 /* 1534 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1535 * fragment that specifies the *reverse* comparison to perform, e.g. 1536 * for "if-le" you would use "gt". 1537 * 1538 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1539 */ 1540 /* if-cmp vA, vB, +CCCC */ 1541 mov r0, rINST, lsr #8 @ r0<- A+ 1542 mov r1, rINST, lsr #12 @ r1<- B 1543 and r0, r0, #15 1544 GET_VREG(r3, r1) @ r3<- vB 1545 GET_VREG(r2, r0) @ r2<- vA 1546 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1547 cmp r2, r3 @ compare (vA, vB) 1548 blt 1f @ branch to 1 if comparison failed 1549 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1550 movs r9, r9, asl #1 @ convert to bytes, check sign 1551 bmi common_backwardBranch @ yes, do periodic checks 15521: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1553 GET_INST_OPCODE(ip) @ extract opcode from rINST 1554 GOTO_OPCODE(ip) @ jump to next instruction 1555 1556 1557 1558/* ------------------------------ */ 1559 .balign 64 1560.L_OP_IF_GT: /* 0x36 */ 1561/* File: armv5te/OP_IF_GT.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 ble 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: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1583 GET_INST_OPCODE(ip) @ extract opcode from rINST 1584 GOTO_OPCODE(ip) @ jump to next instruction 1585 1586 1587 1588/* ------------------------------ */ 1589 .balign 64 1590.L_OP_IF_LE: /* 0x37 */ 1591/* File: armv5te/OP_IF_LE.S */ 1592/* File: armv5te/bincmp.S */ 1593 /* 1594 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1595 * fragment that specifies the *reverse* comparison to perform, e.g. 1596 * for "if-le" you would use "gt". 1597 * 1598 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1599 */ 1600 /* if-cmp vA, vB, +CCCC */ 1601 mov r0, rINST, lsr #8 @ r0<- A+ 1602 mov r1, rINST, lsr #12 @ r1<- B 1603 and r0, r0, #15 1604 GET_VREG(r3, r1) @ r3<- vB 1605 GET_VREG(r2, r0) @ r2<- vA 1606 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1607 cmp r2, r3 @ compare (vA, vB) 1608 bgt 1f @ branch to 1 if comparison failed 1609 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1610 movs r9, r9, asl #1 @ convert to bytes, check sign 1611 bmi common_backwardBranch @ yes, do periodic checks 16121: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1613 GET_INST_OPCODE(ip) @ extract opcode from rINST 1614 GOTO_OPCODE(ip) @ jump to next instruction 1615 1616 1617 1618/* ------------------------------ */ 1619 .balign 64 1620.L_OP_IF_EQZ: /* 0x38 */ 1621/* File: armv5te/OP_IF_EQZ.S */ 1622/* File: armv5te/zcmp.S */ 1623 /* 1624 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1625 * fragment that specifies the *reverse* comparison to perform, e.g. 1626 * for "if-le" you would use "gt". 1627 * 1628 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1629 */ 1630 /* if-cmp vAA, +BBBB */ 1631 mov r0, rINST, lsr #8 @ r0<- AA 1632 GET_VREG(r2, r0) @ r2<- vAA 1633 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1634 cmp r2, #0 @ compare (vA, 0) 1635 bne 1f @ branch to 1 if comparison failed 1636 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1637 movs r9, r9, asl #1 @ convert to bytes, check sign 1638 bmi common_backwardBranch @ backward branch, do periodic checks 16391: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1640 GET_INST_OPCODE(ip) @ extract opcode from rINST 1641 GOTO_OPCODE(ip) @ jump to next instruction 1642 1643 1644 1645/* ------------------------------ */ 1646 .balign 64 1647.L_OP_IF_NEZ: /* 0x39 */ 1648/* File: armv5te/OP_IF_NEZ.S */ 1649/* File: armv5te/zcmp.S */ 1650 /* 1651 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1652 * fragment that specifies the *reverse* comparison to perform, e.g. 1653 * for "if-le" you would use "gt". 1654 * 1655 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1656 */ 1657 /* if-cmp vAA, +BBBB */ 1658 mov r0, rINST, lsr #8 @ r0<- AA 1659 GET_VREG(r2, r0) @ r2<- vAA 1660 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1661 cmp r2, #0 @ compare (vA, 0) 1662 beq 1f @ branch to 1 if comparison failed 1663 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1664 movs r9, r9, asl #1 @ convert to bytes, check sign 1665 bmi common_backwardBranch @ backward branch, do periodic checks 16661: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1667 GET_INST_OPCODE(ip) @ extract opcode from rINST 1668 GOTO_OPCODE(ip) @ jump to next instruction 1669 1670 1671 1672/* ------------------------------ */ 1673 .balign 64 1674.L_OP_IF_LTZ: /* 0x3a */ 1675/* File: armv5te/OP_IF_LTZ.S */ 1676/* File: armv5te/zcmp.S */ 1677 /* 1678 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1679 * fragment that specifies the *reverse* comparison to perform, e.g. 1680 * for "if-le" you would use "gt". 1681 * 1682 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1683 */ 1684 /* if-cmp vAA, +BBBB */ 1685 mov r0, rINST, lsr #8 @ r0<- AA 1686 GET_VREG(r2, r0) @ r2<- vAA 1687 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1688 cmp r2, #0 @ compare (vA, 0) 1689 bge 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 @ backward branch, do periodic checks 16931: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1694 GET_INST_OPCODE(ip) @ extract opcode from rINST 1695 GOTO_OPCODE(ip) @ jump to next instruction 1696 1697 1698 1699/* ------------------------------ */ 1700 .balign 64 1701.L_OP_IF_GEZ: /* 0x3b */ 1702/* File: armv5te/OP_IF_GEZ.S */ 1703/* File: armv5te/zcmp.S */ 1704 /* 1705 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1706 * fragment that specifies the *reverse* comparison to perform, e.g. 1707 * for "if-le" you would use "gt". 1708 * 1709 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1710 */ 1711 /* if-cmp vAA, +BBBB */ 1712 mov r0, rINST, lsr #8 @ r0<- AA 1713 GET_VREG(r2, r0) @ r2<- vAA 1714 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1715 cmp r2, #0 @ compare (vA, 0) 1716 blt 1f @ branch to 1 if comparison failed 1717 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1718 movs r9, r9, asl #1 @ convert to bytes, check sign 1719 bmi common_backwardBranch @ backward branch, do periodic checks 17201: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1721 GET_INST_OPCODE(ip) @ extract opcode from rINST 1722 GOTO_OPCODE(ip) @ jump to next instruction 1723 1724 1725 1726/* ------------------------------ */ 1727 .balign 64 1728.L_OP_IF_GTZ: /* 0x3c */ 1729/* File: armv5te/OP_IF_GTZ.S */ 1730/* File: armv5te/zcmp.S */ 1731 /* 1732 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1733 * fragment that specifies the *reverse* comparison to perform, e.g. 1734 * for "if-le" you would use "gt". 1735 * 1736 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1737 */ 1738 /* if-cmp vAA, +BBBB */ 1739 mov r0, rINST, lsr #8 @ r0<- AA 1740 GET_VREG(r2, r0) @ r2<- vAA 1741 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1742 cmp r2, #0 @ compare (vA, 0) 1743 ble 1f @ branch to 1 if comparison failed 1744 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1745 movs r9, r9, asl #1 @ convert to bytes, check sign 1746 bmi common_backwardBranch @ backward branch, do periodic checks 17471: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1748 GET_INST_OPCODE(ip) @ extract opcode from rINST 1749 GOTO_OPCODE(ip) @ jump to next instruction 1750 1751 1752 1753/* ------------------------------ */ 1754 .balign 64 1755.L_OP_IF_LEZ: /* 0x3d */ 1756/* File: armv5te/OP_IF_LEZ.S */ 1757/* File: armv5te/zcmp.S */ 1758 /* 1759 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1760 * fragment that specifies the *reverse* comparison to perform, e.g. 1761 * for "if-le" you would use "gt". 1762 * 1763 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1764 */ 1765 /* if-cmp vAA, +BBBB */ 1766 mov r0, rINST, lsr #8 @ r0<- AA 1767 GET_VREG(r2, r0) @ r2<- vAA 1768 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1769 cmp r2, #0 @ compare (vA, 0) 1770 bgt 1f @ branch to 1 if comparison failed 1771 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1772 movs r9, r9, asl #1 @ convert to bytes, check sign 1773 bmi common_backwardBranch @ backward branch, do periodic checks 17741: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1775 GET_INST_OPCODE(ip) @ extract opcode from rINST 1776 GOTO_OPCODE(ip) @ jump to next instruction 1777 1778 1779 1780/* ------------------------------ */ 1781 .balign 64 1782.L_OP_UNUSED_3E: /* 0x3e */ 1783/* File: armv5te/OP_UNUSED_3E.S */ 1784/* File: armv5te/unused.S */ 1785 bl common_abort 1786 1787 1788 1789/* ------------------------------ */ 1790 .balign 64 1791.L_OP_UNUSED_3F: /* 0x3f */ 1792/* File: armv5te/OP_UNUSED_3F.S */ 1793/* File: armv5te/unused.S */ 1794 bl common_abort 1795 1796 1797 1798/* ------------------------------ */ 1799 .balign 64 1800.L_OP_UNUSED_40: /* 0x40 */ 1801/* File: armv5te/OP_UNUSED_40.S */ 1802/* File: armv5te/unused.S */ 1803 bl common_abort 1804 1805 1806 1807/* ------------------------------ */ 1808 .balign 64 1809.L_OP_UNUSED_41: /* 0x41 */ 1810/* File: armv5te/OP_UNUSED_41.S */ 1811/* File: armv5te/unused.S */ 1812 bl common_abort 1813 1814 1815 1816/* ------------------------------ */ 1817 .balign 64 1818.L_OP_UNUSED_42: /* 0x42 */ 1819/* File: armv5te/OP_UNUSED_42.S */ 1820/* File: armv5te/unused.S */ 1821 bl common_abort 1822 1823 1824 1825/* ------------------------------ */ 1826 .balign 64 1827.L_OP_UNUSED_43: /* 0x43 */ 1828/* File: armv5te/OP_UNUSED_43.S */ 1829/* File: armv5te/unused.S */ 1830 bl common_abort 1831 1832 1833 1834/* ------------------------------ */ 1835 .balign 64 1836.L_OP_AGET: /* 0x44 */ 1837/* File: armv5te/OP_AGET.S */ 1838 /* 1839 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1840 * 1841 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1842 * instructions. We use a pair of FETCH_Bs instead. 1843 * 1844 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1845 */ 1846 /* op vAA, vBB, vCC */ 1847 FETCH_B(r2, 1, 0) @ r2<- BB 1848 mov r9, rINST, lsr #8 @ r9<- AA 1849 FETCH_B(r3, 1, 1) @ r3<- CC 1850 GET_VREG(r0, r2) @ r0<- vBB (array object) 1851 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1852 cmp r0, #0 @ null array object? 1853 beq common_errNullObject @ yes, bail 1854 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1855 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1856 cmp r1, r3 @ compare unsigned index, length 1857 bcs common_errArrayIndex @ index >= length, bail 1858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1859 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1860 GET_INST_OPCODE(ip) @ extract opcode from rINST 1861 SET_VREG(r2, r9) @ vAA<- r2 1862 GOTO_OPCODE(ip) @ jump to next instruction 1863 1864 1865/* ------------------------------ */ 1866 .balign 64 1867.L_OP_AGET_WIDE: /* 0x45 */ 1868/* File: armv4t/OP_AGET_WIDE.S */ 1869 /* 1870 * Array get, 64 bits. vAA <- vBB[vCC]. 1871 * 1872 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1873 */ 1874 /* aget-wide vAA, vBB, vCC */ 1875 FETCH(r0, 1) @ r0<- CCBB 1876 mov r9, rINST, lsr #8 @ r9<- AA 1877 and r2, r0, #255 @ r2<- BB 1878 mov r3, r0, lsr #8 @ r3<- CC 1879 GET_VREG(r0, r2) @ r0<- vBB (array object) 1880 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1881 cmp r0, #0 @ null array object? 1882 beq common_errNullObject @ yes, bail 1883 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1884 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 1885 cmp r1, r3 @ compare unsigned index, length 1886 bcc .LOP_AGET_WIDE_finish @ okay, continue below 1887 b common_errArrayIndex @ index >= length, bail 1888 @ May want to swap the order of these two branches depending on how the 1889 @ branch prediction (if any) handles conditional forward branches vs. 1890 @ unconditional forward branches. 1891 1892/* ------------------------------ */ 1893 .balign 64 1894.L_OP_AGET_OBJECT: /* 0x46 */ 1895/* File: armv5te/OP_AGET_OBJECT.S */ 1896/* File: armv5te/OP_AGET.S */ 1897 /* 1898 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1899 * 1900 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1901 * instructions. We use a pair of FETCH_Bs instead. 1902 * 1903 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1904 */ 1905 /* op vAA, vBB, vCC */ 1906 FETCH_B(r2, 1, 0) @ r2<- BB 1907 mov r9, rINST, lsr #8 @ r9<- AA 1908 FETCH_B(r3, 1, 1) @ r3<- CC 1909 GET_VREG(r0, r2) @ r0<- vBB (array object) 1910 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1911 cmp r0, #0 @ null array object? 1912 beq common_errNullObject @ yes, bail 1913 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1914 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1915 cmp r1, r3 @ compare unsigned index, length 1916 bcs common_errArrayIndex @ index >= length, bail 1917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1918 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1919 GET_INST_OPCODE(ip) @ extract opcode from rINST 1920 SET_VREG(r2, r9) @ vAA<- r2 1921 GOTO_OPCODE(ip) @ jump to next instruction 1922 1923 1924 1925/* ------------------------------ */ 1926 .balign 64 1927.L_OP_AGET_BOOLEAN: /* 0x47 */ 1928/* File: armv5te/OP_AGET_BOOLEAN.S */ 1929/* File: armv5te/OP_AGET.S */ 1930 /* 1931 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1932 * 1933 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1934 * instructions. We use a pair of FETCH_Bs instead. 1935 * 1936 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1937 */ 1938 /* op vAA, vBB, vCC */ 1939 FETCH_B(r2, 1, 0) @ r2<- BB 1940 mov r9, rINST, lsr #8 @ r9<- AA 1941 FETCH_B(r3, 1, 1) @ r3<- CC 1942 GET_VREG(r0, r2) @ r0<- vBB (array object) 1943 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1944 cmp r0, #0 @ null array object? 1945 beq common_errNullObject @ yes, bail 1946 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1947 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1948 cmp r1, r3 @ compare unsigned index, length 1949 bcs common_errArrayIndex @ index >= length, bail 1950 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1951 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1952 GET_INST_OPCODE(ip) @ extract opcode from rINST 1953 SET_VREG(r2, r9) @ vAA<- r2 1954 GOTO_OPCODE(ip) @ jump to next instruction 1955 1956 1957 1958/* ------------------------------ */ 1959 .balign 64 1960.L_OP_AGET_BYTE: /* 0x48 */ 1961/* File: armv5te/OP_AGET_BYTE.S */ 1962/* File: armv5te/OP_AGET.S */ 1963 /* 1964 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1965 * 1966 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1967 * instructions. We use a pair of FETCH_Bs instead. 1968 * 1969 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1970 */ 1971 /* op vAA, vBB, vCC */ 1972 FETCH_B(r2, 1, 0) @ r2<- BB 1973 mov r9, rINST, lsr #8 @ r9<- AA 1974 FETCH_B(r3, 1, 1) @ r3<- CC 1975 GET_VREG(r0, r2) @ r0<- vBB (array object) 1976 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1977 cmp r0, #0 @ null array object? 1978 beq common_errNullObject @ yes, bail 1979 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1980 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1981 cmp r1, r3 @ compare unsigned index, length 1982 bcs common_errArrayIndex @ index >= length, bail 1983 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1984 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1985 GET_INST_OPCODE(ip) @ extract opcode from rINST 1986 SET_VREG(r2, r9) @ vAA<- r2 1987 GOTO_OPCODE(ip) @ jump to next instruction 1988 1989 1990 1991/* ------------------------------ */ 1992 .balign 64 1993.L_OP_AGET_CHAR: /* 0x49 */ 1994/* File: armv5te/OP_AGET_CHAR.S */ 1995/* File: armv5te/OP_AGET.S */ 1996 /* 1997 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1998 * 1999 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2000 * instructions. We use a pair of FETCH_Bs instead. 2001 * 2002 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2003 */ 2004 /* op vAA, vBB, vCC */ 2005 FETCH_B(r2, 1, 0) @ r2<- BB 2006 mov r9, rINST, lsr #8 @ r9<- AA 2007 FETCH_B(r3, 1, 1) @ r3<- CC 2008 GET_VREG(r0, r2) @ r0<- vBB (array object) 2009 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2010 cmp r0, #0 @ null array object? 2011 beq common_errNullObject @ yes, bail 2012 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2013 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2014 cmp r1, r3 @ compare unsigned index, length 2015 bcs common_errArrayIndex @ index >= length, bail 2016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2017 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2018 GET_INST_OPCODE(ip) @ extract opcode from rINST 2019 SET_VREG(r2, r9) @ vAA<- r2 2020 GOTO_OPCODE(ip) @ jump to next instruction 2021 2022 2023 2024/* ------------------------------ */ 2025 .balign 64 2026.L_OP_AGET_SHORT: /* 0x4a */ 2027/* File: armv5te/OP_AGET_SHORT.S */ 2028/* File: armv5te/OP_AGET.S */ 2029 /* 2030 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2031 * 2032 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2033 * instructions. We use a pair of FETCH_Bs instead. 2034 * 2035 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2036 */ 2037 /* op vAA, vBB, vCC */ 2038 FETCH_B(r2, 1, 0) @ r2<- BB 2039 mov r9, rINST, lsr #8 @ r9<- AA 2040 FETCH_B(r3, 1, 1) @ r3<- CC 2041 GET_VREG(r0, r2) @ r0<- vBB (array object) 2042 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2043 cmp r0, #0 @ null array object? 2044 beq common_errNullObject @ yes, bail 2045 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2046 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2047 cmp r1, r3 @ compare unsigned index, length 2048 bcs common_errArrayIndex @ index >= length, bail 2049 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2050 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2051 GET_INST_OPCODE(ip) @ extract opcode from rINST 2052 SET_VREG(r2, r9) @ vAA<- r2 2053 GOTO_OPCODE(ip) @ jump to next instruction 2054 2055 2056 2057/* ------------------------------ */ 2058 .balign 64 2059.L_OP_APUT: /* 0x4b */ 2060/* File: armv5te/OP_APUT.S */ 2061 /* 2062 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2063 * 2064 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2065 * instructions. We use a pair of FETCH_Bs instead. 2066 * 2067 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2068 */ 2069 /* op vAA, vBB, vCC */ 2070 FETCH_B(r2, 1, 0) @ r2<- BB 2071 mov r9, rINST, lsr #8 @ r9<- AA 2072 FETCH_B(r3, 1, 1) @ r3<- CC 2073 GET_VREG(r0, r2) @ r0<- vBB (array object) 2074 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2075 cmp r0, #0 @ null array object? 2076 beq common_errNullObject @ yes, bail 2077 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2078 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2079 cmp r1, r3 @ compare unsigned index, length 2080 bcs common_errArrayIndex @ index >= length, bail 2081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2082 GET_VREG(r2, r9) @ r2<- vAA 2083 GET_INST_OPCODE(ip) @ extract opcode from rINST 2084 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2085 GOTO_OPCODE(ip) @ jump to next instruction 2086 2087 2088/* ------------------------------ */ 2089 .balign 64 2090.L_OP_APUT_WIDE: /* 0x4c */ 2091/* File: armv4t/OP_APUT_WIDE.S */ 2092 /* 2093 * Array put, 64 bits. vBB[vCC] <- vAA. 2094 */ 2095 /* aput-wide vAA, vBB, vCC */ 2096 FETCH(r0, 1) @ r0<- CCBB 2097 mov r9, rINST, lsr #8 @ r9<- AA 2098 and r2, r0, #255 @ r2<- BB 2099 mov r3, r0, lsr #8 @ r3<- CC 2100 GET_VREG(r0, r2) @ r0<- vBB (array object) 2101 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2102 cmp r0, #0 @ null array object? 2103 beq common_errNullObject @ yes, bail 2104 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2105 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2106 cmp r1, r3 @ compare unsigned index, length 2107 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2108 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2109 b common_errArrayIndex @ index >= length, bail 2110 @ May want to swap the order of these two branches depending on how the 2111 @ branch prediction (if any) handles conditional forward branches vs. 2112 @ unconditional forward branches. 2113 2114/* ------------------------------ */ 2115 .balign 64 2116.L_OP_APUT_OBJECT: /* 0x4d */ 2117/* File: armv5te/OP_APUT_OBJECT.S */ 2118 /* 2119 * Store an object into an array. vBB[vCC] <- vAA. 2120 * 2121 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2122 * instructions. We use a pair of FETCH_Bs instead. 2123 */ 2124 /* op vAA, vBB, vCC */ 2125 FETCH(r0, 1) @ r0<- CCBB 2126 mov r9, rINST, lsr #8 @ r9<- AA 2127 and r2, r0, #255 @ r2<- BB 2128 mov r3, r0, lsr #8 @ r3<- CC 2129 GET_VREG(r1, r2) @ r1<- vBB (array object) 2130 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2131 cmp r1, #0 @ null array object? 2132 GET_VREG(r9, r9) @ r9<- vAA 2133 beq common_errNullObject @ yes, bail 2134 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2135 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2136 cmp r0, r3 @ compare unsigned index, length 2137 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2138 b common_errArrayIndex @ index >= length, bail 2139 2140 2141/* ------------------------------ */ 2142 .balign 64 2143.L_OP_APUT_BOOLEAN: /* 0x4e */ 2144/* File: armv5te/OP_APUT_BOOLEAN.S */ 2145/* File: armv5te/OP_APUT.S */ 2146 /* 2147 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2148 * 2149 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2150 * instructions. We use a pair of FETCH_Bs instead. 2151 * 2152 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2153 */ 2154 /* op vAA, vBB, vCC */ 2155 FETCH_B(r2, 1, 0) @ r2<- BB 2156 mov r9, rINST, lsr #8 @ r9<- AA 2157 FETCH_B(r3, 1, 1) @ r3<- CC 2158 GET_VREG(r0, r2) @ r0<- vBB (array object) 2159 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2160 cmp r0, #0 @ null array object? 2161 beq common_errNullObject @ yes, bail 2162 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2163 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2164 cmp r1, r3 @ compare unsigned index, length 2165 bcs common_errArrayIndex @ index >= length, bail 2166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2167 GET_VREG(r2, r9) @ r2<- vAA 2168 GET_INST_OPCODE(ip) @ extract opcode from rINST 2169 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2170 GOTO_OPCODE(ip) @ jump to next instruction 2171 2172 2173 2174/* ------------------------------ */ 2175 .balign 64 2176.L_OP_APUT_BYTE: /* 0x4f */ 2177/* File: armv5te/OP_APUT_BYTE.S */ 2178/* File: armv5te/OP_APUT.S */ 2179 /* 2180 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2181 * 2182 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2183 * instructions. We use a pair of FETCH_Bs instead. 2184 * 2185 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2186 */ 2187 /* op vAA, vBB, vCC */ 2188 FETCH_B(r2, 1, 0) @ r2<- BB 2189 mov r9, rINST, lsr #8 @ r9<- AA 2190 FETCH_B(r3, 1, 1) @ r3<- CC 2191 GET_VREG(r0, r2) @ r0<- vBB (array object) 2192 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2193 cmp r0, #0 @ null array object? 2194 beq common_errNullObject @ yes, bail 2195 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2196 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2197 cmp r1, r3 @ compare unsigned index, length 2198 bcs common_errArrayIndex @ index >= length, bail 2199 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2200 GET_VREG(r2, r9) @ r2<- vAA 2201 GET_INST_OPCODE(ip) @ extract opcode from rINST 2202 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2203 GOTO_OPCODE(ip) @ jump to next instruction 2204 2205 2206 2207/* ------------------------------ */ 2208 .balign 64 2209.L_OP_APUT_CHAR: /* 0x50 */ 2210/* File: armv5te/OP_APUT_CHAR.S */ 2211/* File: armv5te/OP_APUT.S */ 2212 /* 2213 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2214 * 2215 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2216 * instructions. We use a pair of FETCH_Bs instead. 2217 * 2218 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2219 */ 2220 /* op vAA, vBB, vCC */ 2221 FETCH_B(r2, 1, 0) @ r2<- BB 2222 mov r9, rINST, lsr #8 @ r9<- AA 2223 FETCH_B(r3, 1, 1) @ r3<- CC 2224 GET_VREG(r0, r2) @ r0<- vBB (array object) 2225 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2226 cmp r0, #0 @ null array object? 2227 beq common_errNullObject @ yes, bail 2228 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2229 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2230 cmp r1, r3 @ compare unsigned index, length 2231 bcs common_errArrayIndex @ index >= length, bail 2232 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2233 GET_VREG(r2, r9) @ r2<- vAA 2234 GET_INST_OPCODE(ip) @ extract opcode from rINST 2235 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2236 GOTO_OPCODE(ip) @ jump to next instruction 2237 2238 2239 2240/* ------------------------------ */ 2241 .balign 64 2242.L_OP_APUT_SHORT: /* 0x51 */ 2243/* File: armv5te/OP_APUT_SHORT.S */ 2244/* File: armv5te/OP_APUT.S */ 2245 /* 2246 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2247 * 2248 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2249 * instructions. We use a pair of FETCH_Bs instead. 2250 * 2251 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2252 */ 2253 /* op vAA, vBB, vCC */ 2254 FETCH_B(r2, 1, 0) @ r2<- BB 2255 mov r9, rINST, lsr #8 @ r9<- AA 2256 FETCH_B(r3, 1, 1) @ r3<- CC 2257 GET_VREG(r0, r2) @ r0<- vBB (array object) 2258 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2259 cmp r0, #0 @ null array object? 2260 beq common_errNullObject @ yes, bail 2261 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2262 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2263 cmp r1, r3 @ compare unsigned index, length 2264 bcs common_errArrayIndex @ index >= length, bail 2265 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2266 GET_VREG(r2, r9) @ r2<- vAA 2267 GET_INST_OPCODE(ip) @ extract opcode from rINST 2268 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2269 GOTO_OPCODE(ip) @ jump to next instruction 2270 2271 2272 2273/* ------------------------------ */ 2274 .balign 64 2275.L_OP_IGET: /* 0x52 */ 2276/* File: armv5te/OP_IGET.S */ 2277 /* 2278 * General 32-bit instance field get. 2279 * 2280 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2281 */ 2282 /* op vA, vB, field@CCCC */ 2283 mov r0, rINST, lsr #12 @ r0<- B 2284 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2285 FETCH(r1, 1) @ r1<- field ref CCCC 2286 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2287 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2288 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2289 cmp r0, #0 @ is resolved entry null? 2290 bne .LOP_IGET_finish @ no, already resolved 22918: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2292 EXPORT_PC() @ resolve() could throw 2293 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2294 bl dvmResolveInstField @ r0<- resolved InstField ptr 2295 cmp r0, #0 2296 bne .LOP_IGET_finish 2297 b common_exceptionThrown 2298 2299/* ------------------------------ */ 2300 .balign 64 2301.L_OP_IGET_WIDE: /* 0x53 */ 2302/* File: armv4t/OP_IGET_WIDE.S */ 2303 /* 2304 * Wide 32-bit instance field get. 2305 */ 2306 /* iget-wide vA, vB, field@CCCC */ 2307 mov r0, rINST, lsr #12 @ r0<- B 2308 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2309 FETCH(r1, 1) @ r1<- field ref CCCC 2310 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2311 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2312 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2313 cmp r0, #0 @ is resolved entry null? 2314 bne .LOP_IGET_WIDE_finish @ no, already resolved 23158: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2316 EXPORT_PC() @ resolve() could throw 2317 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2318 bl dvmResolveInstField @ r0<- resolved InstField ptr 2319 cmp r0, #0 2320 bne .LOP_IGET_WIDE_finish 2321 b common_exceptionThrown 2322 2323/* ------------------------------ */ 2324 .balign 64 2325.L_OP_IGET_OBJECT: /* 0x54 */ 2326/* File: armv5te/OP_IGET_OBJECT.S */ 2327/* File: armv5te/OP_IGET.S */ 2328 /* 2329 * General 32-bit instance field get. 2330 * 2331 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2332 */ 2333 /* op vA, vB, field@CCCC */ 2334 mov r0, rINST, lsr #12 @ r0<- B 2335 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2336 FETCH(r1, 1) @ r1<- field ref CCCC 2337 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2338 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2339 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2340 cmp r0, #0 @ is resolved entry null? 2341 bne .LOP_IGET_OBJECT_finish @ no, already resolved 23428: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2343 EXPORT_PC() @ resolve() could throw 2344 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2345 bl dvmResolveInstField @ r0<- resolved InstField ptr 2346 cmp r0, #0 2347 bne .LOP_IGET_OBJECT_finish 2348 b common_exceptionThrown 2349 2350 2351/* ------------------------------ */ 2352 .balign 64 2353.L_OP_IGET_BOOLEAN: /* 0x55 */ 2354/* File: armv5te/OP_IGET_BOOLEAN.S */ 2355@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2356/* File: armv5te/OP_IGET.S */ 2357 /* 2358 * General 32-bit instance field get. 2359 * 2360 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2361 */ 2362 /* op vA, vB, field@CCCC */ 2363 mov r0, rINST, lsr #12 @ r0<- B 2364 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2365 FETCH(r1, 1) @ r1<- field ref CCCC 2366 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2367 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2368 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2369 cmp r0, #0 @ is resolved entry null? 2370 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 23718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2372 EXPORT_PC() @ resolve() could throw 2373 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2374 bl dvmResolveInstField @ r0<- resolved InstField ptr 2375 cmp r0, #0 2376 bne .LOP_IGET_BOOLEAN_finish 2377 b common_exceptionThrown 2378 2379 2380/* ------------------------------ */ 2381 .balign 64 2382.L_OP_IGET_BYTE: /* 0x56 */ 2383/* File: armv5te/OP_IGET_BYTE.S */ 2384@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2385/* File: armv5te/OP_IGET.S */ 2386 /* 2387 * General 32-bit instance field get. 2388 * 2389 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2390 */ 2391 /* op vA, vB, field@CCCC */ 2392 mov r0, rINST, lsr #12 @ r0<- B 2393 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2394 FETCH(r1, 1) @ r1<- field ref CCCC 2395 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2396 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2397 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2398 cmp r0, #0 @ is resolved entry null? 2399 bne .LOP_IGET_BYTE_finish @ no, already resolved 24008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2401 EXPORT_PC() @ resolve() could throw 2402 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2403 bl dvmResolveInstField @ r0<- resolved InstField ptr 2404 cmp r0, #0 2405 bne .LOP_IGET_BYTE_finish 2406 b common_exceptionThrown 2407 2408 2409/* ------------------------------ */ 2410 .balign 64 2411.L_OP_IGET_CHAR: /* 0x57 */ 2412/* File: armv5te/OP_IGET_CHAR.S */ 2413@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2414/* File: armv5te/OP_IGET.S */ 2415 /* 2416 * General 32-bit instance field get. 2417 * 2418 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2419 */ 2420 /* op vA, vB, field@CCCC */ 2421 mov r0, rINST, lsr #12 @ r0<- B 2422 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2423 FETCH(r1, 1) @ r1<- field ref CCCC 2424 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2425 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2426 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2427 cmp r0, #0 @ is resolved entry null? 2428 bne .LOP_IGET_CHAR_finish @ no, already resolved 24298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2430 EXPORT_PC() @ resolve() could throw 2431 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2432 bl dvmResolveInstField @ r0<- resolved InstField ptr 2433 cmp r0, #0 2434 bne .LOP_IGET_CHAR_finish 2435 b common_exceptionThrown 2436 2437 2438/* ------------------------------ */ 2439 .balign 64 2440.L_OP_IGET_SHORT: /* 0x58 */ 2441/* File: armv5te/OP_IGET_SHORT.S */ 2442@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2443/* File: armv5te/OP_IGET.S */ 2444 /* 2445 * General 32-bit instance field get. 2446 * 2447 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2448 */ 2449 /* op vA, vB, field@CCCC */ 2450 mov r0, rINST, lsr #12 @ r0<- B 2451 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2452 FETCH(r1, 1) @ r1<- field ref CCCC 2453 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2454 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2455 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2456 cmp r0, #0 @ is resolved entry null? 2457 bne .LOP_IGET_SHORT_finish @ no, already resolved 24588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2459 EXPORT_PC() @ resolve() could throw 2460 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2461 bl dvmResolveInstField @ r0<- resolved InstField ptr 2462 cmp r0, #0 2463 bne .LOP_IGET_SHORT_finish 2464 b common_exceptionThrown 2465 2466 2467/* ------------------------------ */ 2468 .balign 64 2469.L_OP_IPUT: /* 0x59 */ 2470/* File: armv5te/OP_IPUT.S */ 2471 /* 2472 * General 32-bit instance field put. 2473 * 2474 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2475 */ 2476 /* op vA, vB, field@CCCC */ 2477 mov r0, rINST, lsr #12 @ r0<- B 2478 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2479 FETCH(r1, 1) @ r1<- field ref CCCC 2480 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2481 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2482 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2483 cmp r0, #0 @ is resolved entry null? 2484 bne .LOP_IPUT_finish @ no, already resolved 24858: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2486 EXPORT_PC() @ resolve() could throw 2487 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2488 bl dvmResolveInstField @ r0<- resolved InstField ptr 2489 cmp r0, #0 @ success? 2490 bne .LOP_IPUT_finish @ yes, finish up 2491 b common_exceptionThrown 2492 2493/* ------------------------------ */ 2494 .balign 64 2495.L_OP_IPUT_WIDE: /* 0x5a */ 2496/* File: armv4t/OP_IPUT_WIDE.S */ 2497 /* iput-wide vA, vB, field@CCCC */ 2498 mov r0, rINST, lsr #12 @ r0<- B 2499 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2500 FETCH(r1, 1) @ r1<- field ref CCCC 2501 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2502 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2503 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2504 cmp r0, #0 @ is resolved entry null? 2505 bne .LOP_IPUT_WIDE_finish @ no, already resolved 25068: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2507 EXPORT_PC() @ resolve() could throw 2508 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2509 bl dvmResolveInstField @ r0<- resolved InstField ptr 2510 cmp r0, #0 @ success? 2511 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2512 b common_exceptionThrown 2513 2514/* ------------------------------ */ 2515 .balign 64 2516.L_OP_IPUT_OBJECT: /* 0x5b */ 2517/* File: armv5te/OP_IPUT_OBJECT.S */ 2518/* File: armv5te/OP_IPUT.S */ 2519 /* 2520 * General 32-bit instance field put. 2521 * 2522 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2523 */ 2524 /* op vA, vB, field@CCCC */ 2525 mov r0, rINST, lsr #12 @ r0<- B 2526 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2527 FETCH(r1, 1) @ r1<- field ref CCCC 2528 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2529 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2530 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2531 cmp r0, #0 @ is resolved entry null? 2532 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 25338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2534 EXPORT_PC() @ resolve() could throw 2535 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2536 bl dvmResolveInstField @ r0<- resolved InstField ptr 2537 cmp r0, #0 @ success? 2538 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2539 b common_exceptionThrown 2540 2541 2542/* ------------------------------ */ 2543 .balign 64 2544.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2545/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2546@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2547/* File: armv5te/OP_IPUT.S */ 2548 /* 2549 * General 32-bit instance field put. 2550 * 2551 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2552 */ 2553 /* op vA, vB, field@CCCC */ 2554 mov r0, rINST, lsr #12 @ r0<- B 2555 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2556 FETCH(r1, 1) @ r1<- field ref CCCC 2557 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2558 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2559 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2560 cmp r0, #0 @ is resolved entry null? 2561 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 25628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2563 EXPORT_PC() @ resolve() could throw 2564 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2565 bl dvmResolveInstField @ r0<- resolved InstField ptr 2566 cmp r0, #0 @ success? 2567 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2568 b common_exceptionThrown 2569 2570 2571/* ------------------------------ */ 2572 .balign 64 2573.L_OP_IPUT_BYTE: /* 0x5d */ 2574/* File: armv5te/OP_IPUT_BYTE.S */ 2575@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2576/* File: armv5te/OP_IPUT.S */ 2577 /* 2578 * General 32-bit instance field put. 2579 * 2580 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2581 */ 2582 /* op vA, vB, field@CCCC */ 2583 mov r0, rINST, lsr #12 @ r0<- B 2584 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2585 FETCH(r1, 1) @ r1<- field ref CCCC 2586 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2587 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2588 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2589 cmp r0, #0 @ is resolved entry null? 2590 bne .LOP_IPUT_BYTE_finish @ no, already resolved 25918: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2592 EXPORT_PC() @ resolve() could throw 2593 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2594 bl dvmResolveInstField @ r0<- resolved InstField ptr 2595 cmp r0, #0 @ success? 2596 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2597 b common_exceptionThrown 2598 2599 2600/* ------------------------------ */ 2601 .balign 64 2602.L_OP_IPUT_CHAR: /* 0x5e */ 2603/* File: armv5te/OP_IPUT_CHAR.S */ 2604@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2605/* File: armv5te/OP_IPUT.S */ 2606 /* 2607 * General 32-bit instance field put. 2608 * 2609 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2610 */ 2611 /* op vA, vB, field@CCCC */ 2612 mov r0, rINST, lsr #12 @ r0<- B 2613 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2614 FETCH(r1, 1) @ r1<- field ref CCCC 2615 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2616 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2617 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2618 cmp r0, #0 @ is resolved entry null? 2619 bne .LOP_IPUT_CHAR_finish @ no, already resolved 26208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2621 EXPORT_PC() @ resolve() could throw 2622 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2623 bl dvmResolveInstField @ r0<- resolved InstField ptr 2624 cmp r0, #0 @ success? 2625 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2626 b common_exceptionThrown 2627 2628 2629/* ------------------------------ */ 2630 .balign 64 2631.L_OP_IPUT_SHORT: /* 0x5f */ 2632/* File: armv5te/OP_IPUT_SHORT.S */ 2633@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2634/* File: armv5te/OP_IPUT.S */ 2635 /* 2636 * General 32-bit instance field put. 2637 * 2638 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2639 */ 2640 /* op vA, vB, field@CCCC */ 2641 mov r0, rINST, lsr #12 @ r0<- B 2642 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2643 FETCH(r1, 1) @ r1<- field ref CCCC 2644 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2645 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2646 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2647 cmp r0, #0 @ is resolved entry null? 2648 bne .LOP_IPUT_SHORT_finish @ no, already resolved 26498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2650 EXPORT_PC() @ resolve() could throw 2651 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2652 bl dvmResolveInstField @ r0<- resolved InstField ptr 2653 cmp r0, #0 @ success? 2654 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2655 b common_exceptionThrown 2656 2657 2658/* ------------------------------ */ 2659 .balign 64 2660.L_OP_SGET: /* 0x60 */ 2661/* File: armv5te/OP_SGET.S */ 2662 /* 2663 * General 32-bit SGET handler. 2664 * 2665 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2666 */ 2667 /* op vAA, field@BBBB */ 2668 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2669 FETCH(r1, 1) @ r1<- field ref BBBB 2670 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2671 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2672 cmp r0, #0 @ is resolved entry null? 2673 beq .LOP_SGET_resolve @ yes, do resolve 2674.LOP_SGET_finish: @ field ptr in r0 2675 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2676 mov r2, rINST, lsr #8 @ r2<- AA 2677 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2678 SET_VREG(r1, r2) @ fp[AA]<- r1 2679 GET_INST_OPCODE(ip) @ extract opcode from rINST 2680 GOTO_OPCODE(ip) @ jump to next instruction 2681 2682/* ------------------------------ */ 2683 .balign 64 2684.L_OP_SGET_WIDE: /* 0x61 */ 2685/* File: armv4t/OP_SGET_WIDE.S */ 2686 /* 2687 * 64-bit SGET handler. 2688 */ 2689 /* sget-wide vAA, field@BBBB */ 2690 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2691 FETCH(r1, 1) @ r1<- field ref BBBB 2692 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2693 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2694 cmp r0, #0 @ is resolved entry null? 2695 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2696.LOP_SGET_WIDE_finish: 2697 mov r1, rINST, lsr #8 @ r1<- AA 2698 add r0, r0, #offStaticField_value 2699 ldmia r0, {r2-r3} @ r2/r3<- field value (aligned) 2700 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2701 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2702 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2703 GET_INST_OPCODE(ip) @ extract opcode from rINST 2704 GOTO_OPCODE(ip) @ jump to next instruction 2705 2706/* ------------------------------ */ 2707 .balign 64 2708.L_OP_SGET_OBJECT: /* 0x62 */ 2709/* File: armv5te/OP_SGET_OBJECT.S */ 2710/* File: armv5te/OP_SGET.S */ 2711 /* 2712 * General 32-bit SGET handler. 2713 * 2714 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2715 */ 2716 /* op vAA, field@BBBB */ 2717 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2718 FETCH(r1, 1) @ r1<- field ref BBBB 2719 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2720 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2721 cmp r0, #0 @ is resolved entry null? 2722 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2723.LOP_SGET_OBJECT_finish: @ field ptr in r0 2724 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2725 mov r2, rINST, lsr #8 @ r2<- AA 2726 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2727 SET_VREG(r1, r2) @ fp[AA]<- r1 2728 GET_INST_OPCODE(ip) @ extract opcode from rINST 2729 GOTO_OPCODE(ip) @ jump to next instruction 2730 2731 2732/* ------------------------------ */ 2733 .balign 64 2734.L_OP_SGET_BOOLEAN: /* 0x63 */ 2735/* File: armv5te/OP_SGET_BOOLEAN.S */ 2736/* File: armv5te/OP_SGET.S */ 2737 /* 2738 * General 32-bit SGET handler. 2739 * 2740 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2741 */ 2742 /* op vAA, field@BBBB */ 2743 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2744 FETCH(r1, 1) @ r1<- field ref BBBB 2745 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2746 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2747 cmp r0, #0 @ is resolved entry null? 2748 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2749.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2750 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2751 mov r2, rINST, lsr #8 @ r2<- AA 2752 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2753 SET_VREG(r1, r2) @ fp[AA]<- r1 2754 GET_INST_OPCODE(ip) @ extract opcode from rINST 2755 GOTO_OPCODE(ip) @ jump to next instruction 2756 2757 2758/* ------------------------------ */ 2759 .balign 64 2760.L_OP_SGET_BYTE: /* 0x64 */ 2761/* File: armv5te/OP_SGET_BYTE.S */ 2762/* File: armv5te/OP_SGET.S */ 2763 /* 2764 * General 32-bit SGET handler. 2765 * 2766 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2767 */ 2768 /* op vAA, field@BBBB */ 2769 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2770 FETCH(r1, 1) @ r1<- field ref BBBB 2771 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2772 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2773 cmp r0, #0 @ is resolved entry null? 2774 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2775.LOP_SGET_BYTE_finish: @ field ptr in r0 2776 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2777 mov r2, rINST, lsr #8 @ r2<- AA 2778 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2779 SET_VREG(r1, r2) @ fp[AA]<- r1 2780 GET_INST_OPCODE(ip) @ extract opcode from rINST 2781 GOTO_OPCODE(ip) @ jump to next instruction 2782 2783 2784/* ------------------------------ */ 2785 .balign 64 2786.L_OP_SGET_CHAR: /* 0x65 */ 2787/* File: armv5te/OP_SGET_CHAR.S */ 2788/* File: armv5te/OP_SGET.S */ 2789 /* 2790 * General 32-bit SGET handler. 2791 * 2792 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2793 */ 2794 /* op vAA, field@BBBB */ 2795 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2796 FETCH(r1, 1) @ r1<- field ref BBBB 2797 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2798 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2799 cmp r0, #0 @ is resolved entry null? 2800 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2801.LOP_SGET_CHAR_finish: @ field ptr in r0 2802 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2803 mov r2, rINST, lsr #8 @ r2<- AA 2804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2805 SET_VREG(r1, r2) @ fp[AA]<- r1 2806 GET_INST_OPCODE(ip) @ extract opcode from rINST 2807 GOTO_OPCODE(ip) @ jump to next instruction 2808 2809 2810/* ------------------------------ */ 2811 .balign 64 2812.L_OP_SGET_SHORT: /* 0x66 */ 2813/* File: armv5te/OP_SGET_SHORT.S */ 2814/* File: armv5te/OP_SGET.S */ 2815 /* 2816 * General 32-bit SGET handler. 2817 * 2818 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2819 */ 2820 /* op vAA, field@BBBB */ 2821 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2822 FETCH(r1, 1) @ r1<- field ref BBBB 2823 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2824 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2825 cmp r0, #0 @ is resolved entry null? 2826 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2827.LOP_SGET_SHORT_finish: @ field ptr in r0 2828 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2829 mov r2, rINST, lsr #8 @ r2<- AA 2830 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2831 SET_VREG(r1, r2) @ fp[AA]<- r1 2832 GET_INST_OPCODE(ip) @ extract opcode from rINST 2833 GOTO_OPCODE(ip) @ jump to next instruction 2834 2835 2836/* ------------------------------ */ 2837 .balign 64 2838.L_OP_SPUT: /* 0x67 */ 2839/* File: armv5te/OP_SPUT.S */ 2840 /* 2841 * General 32-bit SPUT handler. 2842 * 2843 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2844 */ 2845 /* op vAA, field@BBBB */ 2846 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2847 FETCH(r1, 1) @ r1<- field ref BBBB 2848 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2849 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2850 cmp r0, #0 @ is resolved entry null? 2851 beq .LOP_SPUT_resolve @ yes, do resolve 2852.LOP_SPUT_finish: @ field ptr in r0 2853 mov r2, rINST, lsr #8 @ r2<- AA 2854 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2855 GET_VREG(r1, r2) @ r1<- fp[AA] 2856 GET_INST_OPCODE(ip) @ extract opcode from rINST 2857 str r1, [r0, #offStaticField_value] @ field<- vAA 2858 GOTO_OPCODE(ip) @ jump to next instruction 2859 2860/* ------------------------------ */ 2861 .balign 64 2862.L_OP_SPUT_WIDE: /* 0x68 */ 2863/* File: armv4t/OP_SPUT_WIDE.S */ 2864 /* 2865 * 64-bit SPUT handler. 2866 */ 2867 /* sput-wide vAA, field@BBBB */ 2868 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2869 FETCH(r1, 1) @ r1<- field ref BBBB 2870 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2871 mov r9, rINST, lsr #8 @ r9<- AA 2872 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2873 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2874 cmp r0, #0 @ is resolved entry null? 2875 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2876.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 2877 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2878 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 2879 GET_INST_OPCODE(ip) @ extract opcode from rINST 2880 add r0, r0, #offStaticField_value 2881 stmia r0, {r2-r3} @ field<- vAA/vAA+1 2882 GOTO_OPCODE(ip) @ jump to next instruction 2883 2884/* ------------------------------ */ 2885 .balign 64 2886.L_OP_SPUT_OBJECT: /* 0x69 */ 2887/* File: armv5te/OP_SPUT_OBJECT.S */ 2888/* File: armv5te/OP_SPUT.S */ 2889 /* 2890 * General 32-bit SPUT handler. 2891 * 2892 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2893 */ 2894 /* op vAA, field@BBBB */ 2895 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2896 FETCH(r1, 1) @ r1<- field ref BBBB 2897 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2898 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2899 cmp r0, #0 @ is resolved entry null? 2900 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 2901.LOP_SPUT_OBJECT_finish: @ field ptr in r0 2902 mov r2, rINST, lsr #8 @ r2<- AA 2903 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2904 GET_VREG(r1, r2) @ r1<- fp[AA] 2905 GET_INST_OPCODE(ip) @ extract opcode from rINST 2906 str r1, [r0, #offStaticField_value] @ field<- vAA 2907 GOTO_OPCODE(ip) @ jump to next instruction 2908 2909 2910/* ------------------------------ */ 2911 .balign 64 2912.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2913/* File: armv5te/OP_SPUT_BOOLEAN.S */ 2914/* File: armv5te/OP_SPUT.S */ 2915 /* 2916 * General 32-bit SPUT handler. 2917 * 2918 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2919 */ 2920 /* op vAA, field@BBBB */ 2921 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2922 FETCH(r1, 1) @ r1<- field ref BBBB 2923 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2924 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2925 cmp r0, #0 @ is resolved entry null? 2926 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 2927.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 2928 mov r2, rINST, lsr #8 @ r2<- AA 2929 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2930 GET_VREG(r1, r2) @ r1<- fp[AA] 2931 GET_INST_OPCODE(ip) @ extract opcode from rINST 2932 str r1, [r0, #offStaticField_value] @ field<- vAA 2933 GOTO_OPCODE(ip) @ jump to next instruction 2934 2935 2936/* ------------------------------ */ 2937 .balign 64 2938.L_OP_SPUT_BYTE: /* 0x6b */ 2939/* File: armv5te/OP_SPUT_BYTE.S */ 2940/* File: armv5te/OP_SPUT.S */ 2941 /* 2942 * General 32-bit SPUT handler. 2943 * 2944 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2945 */ 2946 /* op vAA, field@BBBB */ 2947 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2948 FETCH(r1, 1) @ r1<- field ref BBBB 2949 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2950 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2951 cmp r0, #0 @ is resolved entry null? 2952 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 2953.LOP_SPUT_BYTE_finish: @ field ptr in r0 2954 mov r2, rINST, lsr #8 @ r2<- AA 2955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2956 GET_VREG(r1, r2) @ r1<- fp[AA] 2957 GET_INST_OPCODE(ip) @ extract opcode from rINST 2958 str r1, [r0, #offStaticField_value] @ field<- vAA 2959 GOTO_OPCODE(ip) @ jump to next instruction 2960 2961 2962/* ------------------------------ */ 2963 .balign 64 2964.L_OP_SPUT_CHAR: /* 0x6c */ 2965/* File: armv5te/OP_SPUT_CHAR.S */ 2966/* File: armv5te/OP_SPUT.S */ 2967 /* 2968 * General 32-bit SPUT handler. 2969 * 2970 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2971 */ 2972 /* op vAA, field@BBBB */ 2973 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2974 FETCH(r1, 1) @ r1<- field ref BBBB 2975 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2976 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2977 cmp r0, #0 @ is resolved entry null? 2978 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 2979.LOP_SPUT_CHAR_finish: @ field ptr in r0 2980 mov r2, rINST, lsr #8 @ r2<- AA 2981 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2982 GET_VREG(r1, r2) @ r1<- fp[AA] 2983 GET_INST_OPCODE(ip) @ extract opcode from rINST 2984 str r1, [r0, #offStaticField_value] @ field<- vAA 2985 GOTO_OPCODE(ip) @ jump to next instruction 2986 2987 2988/* ------------------------------ */ 2989 .balign 64 2990.L_OP_SPUT_SHORT: /* 0x6d */ 2991/* File: armv5te/OP_SPUT_SHORT.S */ 2992/* File: armv5te/OP_SPUT.S */ 2993 /* 2994 * General 32-bit SPUT handler. 2995 * 2996 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2997 */ 2998 /* op vAA, field@BBBB */ 2999 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3000 FETCH(r1, 1) @ r1<- field ref BBBB 3001 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3002 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3003 cmp r0, #0 @ is resolved entry null? 3004 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3005.LOP_SPUT_SHORT_finish: @ field ptr in r0 3006 mov r2, rINST, lsr #8 @ r2<- AA 3007 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3008 GET_VREG(r1, r2) @ r1<- fp[AA] 3009 GET_INST_OPCODE(ip) @ extract opcode from rINST 3010 str r1, [r0, #offStaticField_value] @ field<- vAA 3011 GOTO_OPCODE(ip) @ jump to next instruction 3012 3013 3014/* ------------------------------ */ 3015 .balign 64 3016.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3017/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3018 /* 3019 * Handle a virtual method call. 3020 * 3021 * for: invoke-virtual, invoke-virtual/range 3022 */ 3023 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3024 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3025 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3026 FETCH(r1, 1) @ r1<- BBBB 3027 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3028 FETCH(r10, 2) @ r10<- GFED or CCCC 3029 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3030 .if (!0) 3031 and r10, r10, #15 @ r10<- D (or stays CCCC) 3032 .endif 3033 cmp r0, #0 @ already resolved? 3034 EXPORT_PC() @ must export for invoke 3035 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3036 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3037 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3038 mov r2, #METHOD_VIRTUAL @ resolver method type 3039 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3040 cmp r0, #0 @ got null? 3041 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3042 b common_exceptionThrown @ yes, handle exception 3043 3044/* ------------------------------ */ 3045 .balign 64 3046.L_OP_INVOKE_SUPER: /* 0x6f */ 3047/* File: armv5te/OP_INVOKE_SUPER.S */ 3048 /* 3049 * Handle a "super" method call. 3050 * 3051 * for: invoke-super, invoke-super/range 3052 */ 3053 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3054 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3055 FETCH(r10, 2) @ r10<- GFED or CCCC 3056 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3057 .if (!0) 3058 and r10, r10, #15 @ r10<- D (or stays CCCC) 3059 .endif 3060 FETCH(r1, 1) @ r1<- BBBB 3061 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3062 GET_VREG(r2, r10) @ r2<- "this" ptr 3063 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3064 cmp r2, #0 @ null "this"? 3065 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3066 beq common_errNullObject @ null "this", throw exception 3067 cmp r0, #0 @ already resolved? 3068 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3069 EXPORT_PC() @ must export for invoke 3070 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3071 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3072 3073/* ------------------------------ */ 3074 .balign 64 3075.L_OP_INVOKE_DIRECT: /* 0x70 */ 3076/* File: armv5te/OP_INVOKE_DIRECT.S */ 3077 /* 3078 * Handle a direct method call. 3079 * 3080 * (We could defer the "is 'this' pointer null" test to the common 3081 * method invocation code, and use a flag to indicate that static 3082 * calls don't count. If we do this as part of copying the arguments 3083 * out we could avoiding loading the first arg twice.) 3084 * 3085 * for: invoke-direct, invoke-direct/range 3086 */ 3087 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3088 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3089 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3090 FETCH(r1, 1) @ r1<- BBBB 3091 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3092 FETCH(r10, 2) @ r10<- GFED or CCCC 3093 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3094 .if (!0) 3095 and r10, r10, #15 @ r10<- D (or stays CCCC) 3096 .endif 3097 cmp r0, #0 @ already resolved? 3098 EXPORT_PC() @ must export for invoke 3099 GET_VREG(r2, r10) @ r2<- "this" ptr 3100 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3101.LOP_INVOKE_DIRECT_finish: 3102 cmp r2, #0 @ null "this" ref? 3103 bne common_invokeMethodNoRange @ no, continue on 3104 b common_errNullObject @ yes, throw exception 3105 3106/* ------------------------------ */ 3107 .balign 64 3108.L_OP_INVOKE_STATIC: /* 0x71 */ 3109/* File: armv5te/OP_INVOKE_STATIC.S */ 3110 /* 3111 * Handle a static method call. 3112 * 3113 * for: invoke-static, invoke-static/range 3114 */ 3115 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3116 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3117 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3118 FETCH(r1, 1) @ r1<- BBBB 3119 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3120 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3121 cmp r0, #0 @ already resolved? 3122 EXPORT_PC() @ must export for invoke 3123 bne common_invokeMethodNoRange @ yes, continue on 31240: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3125 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3126 mov r2, #METHOD_STATIC @ resolver method type 3127 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3128 cmp r0, #0 @ got null? 3129 bne common_invokeMethodNoRange @ no, continue 3130 b common_exceptionThrown @ yes, handle exception 3131 3132 3133/* ------------------------------ */ 3134 .balign 64 3135.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3136/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3137 /* 3138 * Handle an interface method call. 3139 * 3140 * for: invoke-interface, invoke-interface/range 3141 */ 3142 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3143 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3144 FETCH(r2, 2) @ r2<- FEDC or CCCC 3145 FETCH(r1, 1) @ r1<- BBBB 3146 .if (!0) 3147 and r2, r2, #15 @ r2<- C (or stays CCCC) 3148 .endif 3149 EXPORT_PC() @ must export for invoke 3150 GET_VREG(r0, r2) @ r0<- first arg ("this") 3151 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3152 cmp r0, #0 @ null obj? 3153 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3154 beq common_errNullObject @ yes, fail 3155 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3156 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3157 cmp r0, #0 @ failed? 3158 beq common_exceptionThrown @ yes, handle exception 3159 b common_invokeMethodNoRange @ jump to common handler 3160 3161 3162/* ------------------------------ */ 3163 .balign 64 3164.L_OP_UNUSED_73: /* 0x73 */ 3165/* File: armv5te/OP_UNUSED_73.S */ 3166/* File: armv5te/unused.S */ 3167 bl common_abort 3168 3169 3170 3171/* ------------------------------ */ 3172 .balign 64 3173.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3174/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3175/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3176 /* 3177 * Handle a virtual method call. 3178 * 3179 * for: invoke-virtual, invoke-virtual/range 3180 */ 3181 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3182 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3183 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3184 FETCH(r1, 1) @ r1<- BBBB 3185 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3186 FETCH(r10, 2) @ r10<- GFED or CCCC 3187 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3188 .if (!1) 3189 and r10, r10, #15 @ r10<- D (or stays CCCC) 3190 .endif 3191 cmp r0, #0 @ already resolved? 3192 EXPORT_PC() @ must export for invoke 3193 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3194 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3195 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3196 mov r2, #METHOD_VIRTUAL @ resolver method type 3197 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3198 cmp r0, #0 @ got null? 3199 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3200 b common_exceptionThrown @ yes, handle exception 3201 3202 3203/* ------------------------------ */ 3204 .balign 64 3205.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3206/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3207/* File: armv5te/OP_INVOKE_SUPER.S */ 3208 /* 3209 * Handle a "super" method call. 3210 * 3211 * for: invoke-super, invoke-super/range 3212 */ 3213 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3214 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3215 FETCH(r10, 2) @ r10<- GFED or CCCC 3216 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3217 .if (!1) 3218 and r10, r10, #15 @ r10<- D (or stays CCCC) 3219 .endif 3220 FETCH(r1, 1) @ r1<- BBBB 3221 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3222 GET_VREG(r2, r10) @ r2<- "this" ptr 3223 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3224 cmp r2, #0 @ null "this"? 3225 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3226 beq common_errNullObject @ null "this", throw exception 3227 cmp r0, #0 @ already resolved? 3228 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3229 EXPORT_PC() @ must export for invoke 3230 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3231 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3232 3233 3234/* ------------------------------ */ 3235 .balign 64 3236.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3237/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3238/* File: armv5te/OP_INVOKE_DIRECT.S */ 3239 /* 3240 * Handle a direct method call. 3241 * 3242 * (We could defer the "is 'this' pointer null" test to the common 3243 * method invocation code, and use a flag to indicate that static 3244 * calls don't count. If we do this as part of copying the arguments 3245 * out we could avoiding loading the first arg twice.) 3246 * 3247 * for: invoke-direct, invoke-direct/range 3248 */ 3249 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3250 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3251 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3252 FETCH(r1, 1) @ r1<- BBBB 3253 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3254 FETCH(r10, 2) @ r10<- GFED or CCCC 3255 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3256 .if (!1) 3257 and r10, r10, #15 @ r10<- D (or stays CCCC) 3258 .endif 3259 cmp r0, #0 @ already resolved? 3260 EXPORT_PC() @ must export for invoke 3261 GET_VREG(r2, r10) @ r2<- "this" ptr 3262 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3263.LOP_INVOKE_DIRECT_RANGE_finish: 3264 cmp r2, #0 @ null "this" ref? 3265 bne common_invokeMethodRange @ no, continue on 3266 b common_errNullObject @ yes, throw exception 3267 3268 3269/* ------------------------------ */ 3270 .balign 64 3271.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3272/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3273/* File: armv5te/OP_INVOKE_STATIC.S */ 3274 /* 3275 * Handle a static method call. 3276 * 3277 * for: invoke-static, invoke-static/range 3278 */ 3279 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3280 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3281 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3282 FETCH(r1, 1) @ r1<- BBBB 3283 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3284 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3285 cmp r0, #0 @ already resolved? 3286 EXPORT_PC() @ must export for invoke 3287 bne common_invokeMethodRange @ yes, continue on 32880: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3289 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3290 mov r2, #METHOD_STATIC @ resolver method type 3291 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3292 cmp r0, #0 @ got null? 3293 bne common_invokeMethodRange @ no, continue 3294 b common_exceptionThrown @ yes, handle exception 3295 3296 3297 3298/* ------------------------------ */ 3299 .balign 64 3300.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3301/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3302/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3303 /* 3304 * Handle an interface method call. 3305 * 3306 * for: invoke-interface, invoke-interface/range 3307 */ 3308 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3309 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3310 FETCH(r2, 2) @ r2<- FEDC or CCCC 3311 FETCH(r1, 1) @ r1<- BBBB 3312 .if (!1) 3313 and r2, r2, #15 @ r2<- C (or stays CCCC) 3314 .endif 3315 EXPORT_PC() @ must export for invoke 3316 GET_VREG(r0, r2) @ r0<- first arg ("this") 3317 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3318 cmp r0, #0 @ null obj? 3319 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3320 beq common_errNullObject @ yes, fail 3321 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3322 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3323 cmp r0, #0 @ failed? 3324 beq common_exceptionThrown @ yes, handle exception 3325 b common_invokeMethodRange @ jump to common handler 3326 3327 3328 3329/* ------------------------------ */ 3330 .balign 64 3331.L_OP_UNUSED_79: /* 0x79 */ 3332/* File: armv5te/OP_UNUSED_79.S */ 3333/* File: armv5te/unused.S */ 3334 bl common_abort 3335 3336 3337 3338/* ------------------------------ */ 3339 .balign 64 3340.L_OP_UNUSED_7A: /* 0x7a */ 3341/* File: armv5te/OP_UNUSED_7A.S */ 3342/* File: armv5te/unused.S */ 3343 bl common_abort 3344 3345 3346 3347/* ------------------------------ */ 3348 .balign 64 3349.L_OP_NEG_INT: /* 0x7b */ 3350/* File: armv5te/OP_NEG_INT.S */ 3351/* File: armv5te/unop.S */ 3352 /* 3353 * Generic 32-bit unary operation. Provide an "instr" line that 3354 * specifies an instruction that performs "result = op r0". 3355 * This could be an ARM instruction or a function call. 3356 * 3357 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3358 * int-to-byte, int-to-char, int-to-short 3359 */ 3360 /* unop vA, vB */ 3361 mov r3, rINST, lsr #12 @ r3<- B 3362 mov r9, rINST, lsr #8 @ r9<- A+ 3363 GET_VREG(r0, r3) @ r0<- vB 3364 and r9, r9, #15 3365 @ optional op; may set condition codes 3366 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3367 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3368 GET_INST_OPCODE(ip) @ extract opcode from rINST 3369 SET_VREG(r0, r9) @ vAA<- r0 3370 GOTO_OPCODE(ip) @ jump to next instruction 3371 /* 9-10 instructions */ 3372 3373 3374/* ------------------------------ */ 3375 .balign 64 3376.L_OP_NOT_INT: /* 0x7c */ 3377/* File: armv5te/OP_NOT_INT.S */ 3378/* File: armv5te/unop.S */ 3379 /* 3380 * Generic 32-bit unary operation. Provide an "instr" line that 3381 * specifies an instruction that performs "result = op r0". 3382 * This could be an ARM instruction or a function call. 3383 * 3384 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3385 * int-to-byte, int-to-char, int-to-short 3386 */ 3387 /* unop vA, vB */ 3388 mov r3, rINST, lsr #12 @ r3<- B 3389 mov r9, rINST, lsr #8 @ r9<- A+ 3390 GET_VREG(r0, r3) @ r0<- vB 3391 and r9, r9, #15 3392 @ optional op; may set condition codes 3393 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3394 mvn r0, r0 @ r0<- op, r0-r3 changed 3395 GET_INST_OPCODE(ip) @ extract opcode from rINST 3396 SET_VREG(r0, r9) @ vAA<- r0 3397 GOTO_OPCODE(ip) @ jump to next instruction 3398 /* 9-10 instructions */ 3399 3400 3401/* ------------------------------ */ 3402 .balign 64 3403.L_OP_NEG_LONG: /* 0x7d */ 3404/* File: armv5te/OP_NEG_LONG.S */ 3405/* File: armv5te/unopWide.S */ 3406 /* 3407 * Generic 64-bit unary operation. Provide an "instr" line that 3408 * specifies an instruction that performs "result = op r0/r1". 3409 * This could be an ARM instruction or a function call. 3410 * 3411 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3412 */ 3413 /* unop vA, vB */ 3414 mov r9, rINST, lsr #8 @ r9<- A+ 3415 mov r3, rINST, lsr #12 @ r3<- B 3416 and r9, r9, #15 3417 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3418 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3419 ldmia r3, {r0-r1} @ r0/r1<- vAA 3420 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3421 rsbs r0, r0, #0 @ optional op; may set condition codes 3422 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3423 GET_INST_OPCODE(ip) @ extract opcode from rINST 3424 stmia r9, {r0-r1} @ vAA<- r0/r1 3425 GOTO_OPCODE(ip) @ jump to next instruction 3426 /* 12-13 instructions */ 3427 3428 3429 3430/* ------------------------------ */ 3431 .balign 64 3432.L_OP_NOT_LONG: /* 0x7e */ 3433/* File: armv5te/OP_NOT_LONG.S */ 3434/* File: armv5te/unopWide.S */ 3435 /* 3436 * Generic 64-bit unary operation. Provide an "instr" line that 3437 * specifies an instruction that performs "result = op r0/r1". 3438 * This could be an ARM instruction or a function call. 3439 * 3440 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3441 */ 3442 /* unop vA, vB */ 3443 mov r9, rINST, lsr #8 @ r9<- A+ 3444 mov r3, rINST, lsr #12 @ r3<- B 3445 and r9, r9, #15 3446 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3447 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3448 ldmia r3, {r0-r1} @ r0/r1<- vAA 3449 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3450 mvn r0, r0 @ optional op; may set condition codes 3451 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3452 GET_INST_OPCODE(ip) @ extract opcode from rINST 3453 stmia r9, {r0-r1} @ vAA<- r0/r1 3454 GOTO_OPCODE(ip) @ jump to next instruction 3455 /* 12-13 instructions */ 3456 3457 3458 3459/* ------------------------------ */ 3460 .balign 64 3461.L_OP_NEG_FLOAT: /* 0x7f */ 3462/* File: armv5te/OP_NEG_FLOAT.S */ 3463/* File: armv5te/unop.S */ 3464 /* 3465 * Generic 32-bit unary operation. Provide an "instr" line that 3466 * specifies an instruction that performs "result = op r0". 3467 * This could be an ARM instruction or a function call. 3468 * 3469 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3470 * int-to-byte, int-to-char, int-to-short 3471 */ 3472 /* unop vA, vB */ 3473 mov r3, rINST, lsr #12 @ r3<- B 3474 mov r9, rINST, lsr #8 @ r9<- A+ 3475 GET_VREG(r0, r3) @ r0<- vB 3476 and r9, r9, #15 3477 @ optional op; may set condition codes 3478 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3479 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3480 GET_INST_OPCODE(ip) @ extract opcode from rINST 3481 SET_VREG(r0, r9) @ vAA<- r0 3482 GOTO_OPCODE(ip) @ jump to next instruction 3483 /* 9-10 instructions */ 3484 3485 3486/* ------------------------------ */ 3487 .balign 64 3488.L_OP_NEG_DOUBLE: /* 0x80 */ 3489/* File: armv5te/OP_NEG_DOUBLE.S */ 3490/* File: armv5te/unopWide.S */ 3491 /* 3492 * Generic 64-bit unary operation. Provide an "instr" line that 3493 * specifies an instruction that performs "result = op r0/r1". 3494 * This could be an ARM instruction or a function call. 3495 * 3496 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3497 */ 3498 /* unop vA, vB */ 3499 mov r9, rINST, lsr #8 @ r9<- A+ 3500 mov r3, rINST, lsr #12 @ r3<- B 3501 and r9, r9, #15 3502 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3503 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3504 ldmia r3, {r0-r1} @ r0/r1<- vAA 3505 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3506 @ optional op; may set condition codes 3507 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3508 GET_INST_OPCODE(ip) @ extract opcode from rINST 3509 stmia r9, {r0-r1} @ vAA<- r0/r1 3510 GOTO_OPCODE(ip) @ jump to next instruction 3511 /* 12-13 instructions */ 3512 3513 3514 3515/* ------------------------------ */ 3516 .balign 64 3517.L_OP_INT_TO_LONG: /* 0x81 */ 3518/* File: armv5te/OP_INT_TO_LONG.S */ 3519/* File: armv5te/unopWider.S */ 3520 /* 3521 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3522 * that specifies an instruction that performs "result = op r0", where 3523 * "result" is a 64-bit quantity in r0/r1. 3524 * 3525 * For: int-to-long, int-to-double, float-to-long, float-to-double 3526 */ 3527 /* unop vA, vB */ 3528 mov r9, rINST, lsr #8 @ r9<- A+ 3529 mov r3, rINST, lsr #12 @ r3<- B 3530 and r9, r9, #15 3531 GET_VREG(r0, r3) @ r0<- vB 3532 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3533 @ optional op; may set condition codes 3534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3535 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3536 GET_INST_OPCODE(ip) @ extract opcode from rINST 3537 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3538 GOTO_OPCODE(ip) @ jump to next instruction 3539 /* 10-11 instructions */ 3540 3541 3542/* ------------------------------ */ 3543 .balign 64 3544.L_OP_INT_TO_FLOAT: /* 0x82 */ 3545/* File: armv5te/OP_INT_TO_FLOAT.S */ 3546/* File: armv5te/unop.S */ 3547 /* 3548 * Generic 32-bit unary operation. Provide an "instr" line that 3549 * specifies an instruction that performs "result = op r0". 3550 * This could be an ARM instruction or a function call. 3551 * 3552 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3553 * int-to-byte, int-to-char, int-to-short 3554 */ 3555 /* unop vA, vB */ 3556 mov r3, rINST, lsr #12 @ r3<- B 3557 mov r9, rINST, lsr #8 @ r9<- A+ 3558 GET_VREG(r0, r3) @ r0<- vB 3559 and r9, r9, #15 3560 @ optional op; may set condition codes 3561 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3562 bl __aeabi_i2f @ r0<- op, r0-r3 changed 3563 GET_INST_OPCODE(ip) @ extract opcode from rINST 3564 SET_VREG(r0, r9) @ vAA<- r0 3565 GOTO_OPCODE(ip) @ jump to next instruction 3566 /* 9-10 instructions */ 3567 3568 3569/* ------------------------------ */ 3570 .balign 64 3571.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3572/* File: armv5te/OP_INT_TO_DOUBLE.S */ 3573/* File: armv5te/unopWider.S */ 3574 /* 3575 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3576 * that specifies an instruction that performs "result = op r0", where 3577 * "result" is a 64-bit quantity in r0/r1. 3578 * 3579 * For: int-to-long, int-to-double, float-to-long, float-to-double 3580 */ 3581 /* unop vA, vB */ 3582 mov r9, rINST, lsr #8 @ r9<- A+ 3583 mov r3, rINST, lsr #12 @ r3<- B 3584 and r9, r9, #15 3585 GET_VREG(r0, r3) @ r0<- vB 3586 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3587 @ optional op; may set condition codes 3588 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3589 bl __aeabi_i2d @ r0<- op, r0-r3 changed 3590 GET_INST_OPCODE(ip) @ extract opcode from rINST 3591 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3592 GOTO_OPCODE(ip) @ jump to next instruction 3593 /* 10-11 instructions */ 3594 3595 3596/* ------------------------------ */ 3597 .balign 64 3598.L_OP_LONG_TO_INT: /* 0x84 */ 3599/* File: armv5te/OP_LONG_TO_INT.S */ 3600/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3601/* File: armv5te/OP_MOVE.S */ 3602 /* for move, move-object, long-to-int */ 3603 /* op vA, vB */ 3604 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3605 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3606 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3607 GET_VREG(r2, r1) @ r2<- fp[B] 3608 and r0, r0, #15 3609 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3610 SET_VREG(r2, r0) @ fp[A]<- r2 3611 GOTO_OPCODE(ip) @ execute next instruction 3612 3613 3614 3615/* ------------------------------ */ 3616 .balign 64 3617.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3618/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3619/* File: armv5te/unopNarrower.S */ 3620 /* 3621 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3622 * that specifies an instruction that performs "result = op r0/r1", where 3623 * "result" is a 32-bit quantity in r0. 3624 * 3625 * For: long-to-float, double-to-int, double-to-float 3626 * 3627 * (This would work for long-to-int, but that instruction is actually 3628 * an exact match for OP_MOVE.) 3629 */ 3630 /* unop vA, vB */ 3631 mov r3, rINST, lsr #12 @ r3<- B 3632 mov r9, rINST, lsr #8 @ r9<- A+ 3633 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3634 and r9, r9, #15 3635 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3636 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3637 @ optional op; may set condition codes 3638 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3639 GET_INST_OPCODE(ip) @ extract opcode from rINST 3640 SET_VREG(r0, r9) @ vA<- r0 3641 GOTO_OPCODE(ip) @ jump to next instruction 3642 /* 10-11 instructions */ 3643 3644 3645/* ------------------------------ */ 3646 .balign 64 3647.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3648/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3649/* File: armv5te/unopWide.S */ 3650 /* 3651 * Generic 64-bit unary operation. Provide an "instr" line that 3652 * specifies an instruction that performs "result = op r0/r1". 3653 * This could be an ARM instruction or a function call. 3654 * 3655 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3656 */ 3657 /* unop vA, vB */ 3658 mov r9, rINST, lsr #8 @ r9<- A+ 3659 mov r3, rINST, lsr #12 @ r3<- B 3660 and r9, r9, #15 3661 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3662 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3663 ldmia r3, {r0-r1} @ r0/r1<- vAA 3664 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3665 @ optional op; may set condition codes 3666 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3667 GET_INST_OPCODE(ip) @ extract opcode from rINST 3668 stmia r9, {r0-r1} @ vAA<- r0/r1 3669 GOTO_OPCODE(ip) @ jump to next instruction 3670 /* 12-13 instructions */ 3671 3672 3673 3674/* ------------------------------ */ 3675 .balign 64 3676.L_OP_FLOAT_TO_INT: /* 0x87 */ 3677/* File: armv5te/OP_FLOAT_TO_INT.S */ 3678/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3679/* File: armv5te/unop.S */ 3680 /* 3681 * Generic 32-bit unary operation. Provide an "instr" line that 3682 * specifies an instruction that performs "result = op r0". 3683 * This could be an ARM instruction or a function call. 3684 * 3685 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3686 * int-to-byte, int-to-char, int-to-short 3687 */ 3688 /* unop vA, vB */ 3689 mov r3, rINST, lsr #12 @ r3<- B 3690 mov r9, rINST, lsr #8 @ r9<- A+ 3691 GET_VREG(r0, r3) @ r0<- vB 3692 and r9, r9, #15 3693 @ optional op; may set condition codes 3694 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3695 bl __aeabi_f2iz @ r0<- op, r0-r3 changed 3696 GET_INST_OPCODE(ip) @ extract opcode from rINST 3697 SET_VREG(r0, r9) @ vAA<- r0 3698 GOTO_OPCODE(ip) @ jump to next instruction 3699 /* 9-10 instructions */ 3700 3701 3702#if 0 3703@include "armv5te/unop.S" {"instr":"bl f2i_doconv"} 3704@break 3705/* 3706 * Convert the float in r0 to an int in r0. 3707 * 3708 * We have to clip values to int min/max per the specification. The 3709 * expected common case is a "reasonable" value that converts directly 3710 * to modest integer. The EABI convert function isn't doing this for us. 3711 */ 3712f2i_doconv: 3713 stmfd sp!, {r4, lr} 3714 mov r1, #0x4f000000 @ (float)maxint 3715 mov r4, r0 3716 bl __aeabi_fcmpge @ is arg >= maxint? 3717 cmp r0, #0 @ nonzero == yes 3718 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3719 ldmnefd sp!, {r4, pc} 3720 3721 mov r0, r4 @ recover arg 3722 mov r1, #0xcf000000 @ (float)minint 3723 bl __aeabi_fcmple @ is arg <= minint? 3724 cmp r0, #0 @ nonzero == yes 3725 movne r0, #0x80000000 @ return minint (80000000) 3726 ldmnefd sp!, {r4, pc} 3727 3728 mov r0, r4 @ recover arg 3729 mov r1, r4 3730 bl __aeabi_fcmpeq @ is arg == self? 3731 cmp r0, #0 @ zero == no 3732 ldmeqfd sp!, {r4, pc} @ return zero for NaN 3733 3734 mov r0, r4 @ recover arg 3735 bl __aeabi_f2iz @ convert float to int 3736 ldmfd sp!, {r4, pc} 3737#endif 3738 3739 3740/* ------------------------------ */ 3741 .balign 64 3742.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3743/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3744@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3745/* File: armv5te/unopWider.S */ 3746 /* 3747 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3748 * that specifies an instruction that performs "result = op r0", where 3749 * "result" is a 64-bit quantity in r0/r1. 3750 * 3751 * For: int-to-long, int-to-double, float-to-long, float-to-double 3752 */ 3753 /* unop vA, vB */ 3754 mov r9, rINST, lsr #8 @ r9<- A+ 3755 mov r3, rINST, lsr #12 @ r3<- B 3756 and r9, r9, #15 3757 GET_VREG(r0, r3) @ r0<- vB 3758 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3759 @ optional op; may set condition codes 3760 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3761 bl f2l_doconv @ r0<- op, r0-r3 changed 3762 GET_INST_OPCODE(ip) @ extract opcode from rINST 3763 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3764 GOTO_OPCODE(ip) @ jump to next instruction 3765 /* 10-11 instructions */ 3766 3767 3768 3769/* ------------------------------ */ 3770 .balign 64 3771.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3772/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */ 3773/* File: armv5te/unopWider.S */ 3774 /* 3775 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3776 * that specifies an instruction that performs "result = op r0", where 3777 * "result" is a 64-bit quantity in r0/r1. 3778 * 3779 * For: int-to-long, int-to-double, float-to-long, float-to-double 3780 */ 3781 /* unop vA, vB */ 3782 mov r9, rINST, lsr #8 @ r9<- A+ 3783 mov r3, rINST, lsr #12 @ r3<- B 3784 and r9, r9, #15 3785 GET_VREG(r0, r3) @ r0<- vB 3786 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3787 @ optional op; may set condition codes 3788 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3789 bl __aeabi_f2d @ r0<- op, r0-r3 changed 3790 GET_INST_OPCODE(ip) @ extract opcode from rINST 3791 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3792 GOTO_OPCODE(ip) @ jump to next instruction 3793 /* 10-11 instructions */ 3794 3795 3796/* ------------------------------ */ 3797 .balign 64 3798.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3799/* File: armv5te/OP_DOUBLE_TO_INT.S */ 3800/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3801/* File: armv5te/unopNarrower.S */ 3802 /* 3803 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3804 * that specifies an instruction that performs "result = op r0/r1", where 3805 * "result" is a 32-bit quantity in r0. 3806 * 3807 * For: long-to-float, double-to-int, double-to-float 3808 * 3809 * (This would work for long-to-int, but that instruction is actually 3810 * an exact match for OP_MOVE.) 3811 */ 3812 /* unop vA, vB */ 3813 mov r3, rINST, lsr #12 @ r3<- B 3814 mov r9, rINST, lsr #8 @ r9<- A+ 3815 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3816 and r9, r9, #15 3817 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3818 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3819 @ optional op; may set condition codes 3820 bl __aeabi_d2iz @ r0<- op, r0-r3 changed 3821 GET_INST_OPCODE(ip) @ extract opcode from rINST 3822 SET_VREG(r0, r9) @ vA<- r0 3823 GOTO_OPCODE(ip) @ jump to next instruction 3824 /* 10-11 instructions */ 3825 3826 3827#if 0 3828@include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"} 3829@break 3830/* 3831 * Convert the double in r0/r1 to an int in r0. 3832 * 3833 * We have to clip values to int min/max per the specification. The 3834 * expected common case is a "reasonable" value that converts directly 3835 * to modest integer. The EABI convert function isn't doing this for us. 3836 */ 3837d2i_doconv: 3838 stmfd sp!, {r4, r5, lr} @ save regs 3839 ldr r2, .LOP_DOUBLE_TO_INT_maxlo @ (double)maxint, lo 3840 ldr r3, .LOP_DOUBLE_TO_INT_maxhi @ (double)maxint, hi 3841 sub sp, sp, #4 @ align for EABI 3842 mov r4, r0 @ save r0 3843 mov r5, r1 @ and r1 3844 bl __aeabi_dcmpge @ is arg >= maxint? 3845 cmp r0, #0 @ nonzero == yes 3846 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3847 bne 1f 3848 3849 mov r0, r4 @ recover arg 3850 mov r1, r5 3851 ldr r3, .LOP_DOUBLE_TO_INT_min @ (double)minint, hi 3852 mov r2, #0 @ (double)minint, lo 3853 bl __aeabi_dcmple @ is arg <= minint? 3854 cmp r0, #0 @ nonzero == yes 3855 movne r0, #0x80000000 @ return minint (80000000) 3856 bne 1f 3857 3858 mov r0, r4 @ recover arg 3859 mov r1, r5 3860 mov r2, r4 @ compare against self 3861 mov r3, r5 3862 bl __aeabi_dcmpeq @ is arg == self? 3863 cmp r0, #0 @ zero == no 3864 beq 1f @ return zero for NaN 3865 3866 mov r0, r4 @ recover arg 3867 mov r1, r5 3868 bl __aeabi_d2iz @ convert double to int 3869 38701: 3871 add sp, sp, #4 3872 ldmfd sp!, {r4, r5, pc} 3873 3874.LOP_DOUBLE_TO_INT_maxlo: 3875 .word 0xffc00000 @ maxint, as a double (low word) 3876.LOP_DOUBLE_TO_INT_maxhi: 3877 .word 0x41dfffff @ maxint, as a double (high word) 3878.LOP_DOUBLE_TO_INT_min: 3879 .word 0xc1e00000 @ minint, as a double (high word) 3880#endif 3881 3882 3883/* ------------------------------ */ 3884 .balign 64 3885.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3886/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3887@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3888/* File: armv5te/unopWide.S */ 3889 /* 3890 * Generic 64-bit unary operation. Provide an "instr" line that 3891 * specifies an instruction that performs "result = op r0/r1". 3892 * This could be an ARM instruction or a function call. 3893 * 3894 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3895 */ 3896 /* unop vA, vB */ 3897 mov r9, rINST, lsr #8 @ r9<- A+ 3898 mov r3, rINST, lsr #12 @ r3<- B 3899 and r9, r9, #15 3900 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3901 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3902 ldmia r3, {r0-r1} @ r0/r1<- vAA 3903 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3904 @ optional op; may set condition codes 3905 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3906 GET_INST_OPCODE(ip) @ extract opcode from rINST 3907 stmia r9, {r0-r1} @ vAA<- r0/r1 3908 GOTO_OPCODE(ip) @ jump to next instruction 3909 /* 12-13 instructions */ 3910 3911 3912 3913 3914/* ------------------------------ */ 3915 .balign 64 3916.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3917/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */ 3918/* File: armv5te/unopNarrower.S */ 3919 /* 3920 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3921 * that specifies an instruction that performs "result = op r0/r1", where 3922 * "result" is a 32-bit quantity in r0. 3923 * 3924 * For: long-to-float, double-to-int, double-to-float 3925 * 3926 * (This would work for long-to-int, but that instruction is actually 3927 * an exact match for OP_MOVE.) 3928 */ 3929 /* unop vA, vB */ 3930 mov r3, rINST, lsr #12 @ r3<- B 3931 mov r9, rINST, lsr #8 @ r9<- A+ 3932 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3933 and r9, r9, #15 3934 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3935 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3936 @ optional op; may set condition codes 3937 bl __aeabi_d2f @ r0<- op, r0-r3 changed 3938 GET_INST_OPCODE(ip) @ extract opcode from rINST 3939 SET_VREG(r0, r9) @ vA<- r0 3940 GOTO_OPCODE(ip) @ jump to next instruction 3941 /* 10-11 instructions */ 3942 3943 3944/* ------------------------------ */ 3945 .balign 64 3946.L_OP_INT_TO_BYTE: /* 0x8d */ 3947/* File: armv5te/OP_INT_TO_BYTE.S */ 3948/* File: armv5te/unop.S */ 3949 /* 3950 * Generic 32-bit unary operation. Provide an "instr" line that 3951 * specifies an instruction that performs "result = op r0". 3952 * This could be an ARM instruction or a function call. 3953 * 3954 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3955 * int-to-byte, int-to-char, int-to-short 3956 */ 3957 /* unop vA, vB */ 3958 mov r3, rINST, lsr #12 @ r3<- B 3959 mov r9, rINST, lsr #8 @ r9<- A+ 3960 GET_VREG(r0, r3) @ r0<- vB 3961 and r9, r9, #15 3962 mov r0, r0, asl #24 @ optional op; may set condition codes 3963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3964 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3965 GET_INST_OPCODE(ip) @ extract opcode from rINST 3966 SET_VREG(r0, r9) @ vAA<- r0 3967 GOTO_OPCODE(ip) @ jump to next instruction 3968 /* 9-10 instructions */ 3969 3970 3971/* ------------------------------ */ 3972 .balign 64 3973.L_OP_INT_TO_CHAR: /* 0x8e */ 3974/* File: armv5te/OP_INT_TO_CHAR.S */ 3975/* File: armv5te/unop.S */ 3976 /* 3977 * Generic 32-bit unary operation. Provide an "instr" line that 3978 * specifies an instruction that performs "result = op r0". 3979 * This could be an ARM instruction or a function call. 3980 * 3981 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3982 * int-to-byte, int-to-char, int-to-short 3983 */ 3984 /* unop vA, vB */ 3985 mov r3, rINST, lsr #12 @ r3<- B 3986 mov r9, rINST, lsr #8 @ r9<- A+ 3987 GET_VREG(r0, r3) @ r0<- vB 3988 and r9, r9, #15 3989 mov r0, r0, asl #16 @ optional op; may set condition codes 3990 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3991 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3992 GET_INST_OPCODE(ip) @ extract opcode from rINST 3993 SET_VREG(r0, r9) @ vAA<- r0 3994 GOTO_OPCODE(ip) @ jump to next instruction 3995 /* 9-10 instructions */ 3996 3997 3998/* ------------------------------ */ 3999 .balign 64 4000.L_OP_INT_TO_SHORT: /* 0x8f */ 4001/* File: armv5te/OP_INT_TO_SHORT.S */ 4002/* File: armv5te/unop.S */ 4003 /* 4004 * Generic 32-bit unary operation. Provide an "instr" line that 4005 * specifies an instruction that performs "result = op r0". 4006 * This could be an ARM instruction or a function call. 4007 * 4008 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4009 * int-to-byte, int-to-char, int-to-short 4010 */ 4011 /* unop vA, vB */ 4012 mov r3, rINST, lsr #12 @ r3<- B 4013 mov r9, rINST, lsr #8 @ r9<- A+ 4014 GET_VREG(r0, r3) @ r0<- vB 4015 and r9, r9, #15 4016 mov r0, r0, asl #16 @ optional op; may set condition codes 4017 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4018 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4019 GET_INST_OPCODE(ip) @ extract opcode from rINST 4020 SET_VREG(r0, r9) @ vAA<- r0 4021 GOTO_OPCODE(ip) @ jump to next instruction 4022 /* 9-10 instructions */ 4023 4024 4025/* ------------------------------ */ 4026 .balign 64 4027.L_OP_ADD_INT: /* 0x90 */ 4028/* File: armv5te/OP_ADD_INT.S */ 4029/* File: armv5te/binop.S */ 4030 /* 4031 * Generic 32-bit binary operation. Provide an "instr" line that 4032 * specifies an instruction that performs "result = r0 op r1". 4033 * This could be an ARM instruction or a function call. (If the result 4034 * comes back in a register other than r0, you can override "result".) 4035 * 4036 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4037 * vCC (r1). Useful for integer division and modulus. Note that we 4038 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4039 * handles it correctly. 4040 * 4041 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4042 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4043 * mul-float, div-float, rem-float 4044 */ 4045 /* binop vAA, vBB, vCC */ 4046 FETCH(r0, 1) @ r0<- CCBB 4047 mov r9, rINST, lsr #8 @ r9<- AA 4048 mov r3, r0, lsr #8 @ r3<- CC 4049 and r2, r0, #255 @ r2<- BB 4050 GET_VREG(r1, r3) @ r1<- vCC 4051 GET_VREG(r0, r2) @ r0<- vBB 4052 .if 0 4053 cmp r1, #0 @ is second operand zero? 4054 beq common_errDivideByZero 4055 .endif 4056 4057 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4058 @ optional op; may set condition codes 4059 add r0, r0, r1 @ r0<- op, r0-r3 changed 4060 GET_INST_OPCODE(ip) @ extract opcode from rINST 4061 SET_VREG(r0, r9) @ vAA<- r0 4062 GOTO_OPCODE(ip) @ jump to next instruction 4063 /* 11-14 instructions */ 4064 4065 4066 4067/* ------------------------------ */ 4068 .balign 64 4069.L_OP_SUB_INT: /* 0x91 */ 4070/* File: armv5te/OP_SUB_INT.S */ 4071/* File: armv5te/binop.S */ 4072 /* 4073 * Generic 32-bit binary operation. Provide an "instr" line that 4074 * specifies an instruction that performs "result = r0 op r1". 4075 * This could be an ARM instruction or a function call. (If the result 4076 * comes back in a register other than r0, you can override "result".) 4077 * 4078 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4079 * vCC (r1). Useful for integer division and modulus. Note that we 4080 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4081 * handles it correctly. 4082 * 4083 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4084 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4085 * mul-float, div-float, rem-float 4086 */ 4087 /* binop vAA, vBB, vCC */ 4088 FETCH(r0, 1) @ r0<- CCBB 4089 mov r9, rINST, lsr #8 @ r9<- AA 4090 mov r3, r0, lsr #8 @ r3<- CC 4091 and r2, r0, #255 @ r2<- BB 4092 GET_VREG(r1, r3) @ r1<- vCC 4093 GET_VREG(r0, r2) @ r0<- vBB 4094 .if 0 4095 cmp r1, #0 @ is second operand zero? 4096 beq common_errDivideByZero 4097 .endif 4098 4099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4100 @ optional op; may set condition codes 4101 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4102 GET_INST_OPCODE(ip) @ extract opcode from rINST 4103 SET_VREG(r0, r9) @ vAA<- r0 4104 GOTO_OPCODE(ip) @ jump to next instruction 4105 /* 11-14 instructions */ 4106 4107 4108 4109/* ------------------------------ */ 4110 .balign 64 4111.L_OP_MUL_INT: /* 0x92 */ 4112/* File: armv5te/OP_MUL_INT.S */ 4113/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4114/* File: armv5te/binop.S */ 4115 /* 4116 * Generic 32-bit binary operation. Provide an "instr" line that 4117 * specifies an instruction that performs "result = r0 op r1". 4118 * This could be an ARM instruction or a function call. (If the result 4119 * comes back in a register other than r0, you can override "result".) 4120 * 4121 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4122 * vCC (r1). Useful for integer division and modulus. Note that we 4123 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4124 * handles it correctly. 4125 * 4126 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4127 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4128 * mul-float, div-float, rem-float 4129 */ 4130 /* binop vAA, vBB, vCC */ 4131 FETCH(r0, 1) @ r0<- CCBB 4132 mov r9, rINST, lsr #8 @ r9<- AA 4133 mov r3, r0, lsr #8 @ r3<- CC 4134 and r2, r0, #255 @ r2<- BB 4135 GET_VREG(r1, r3) @ r1<- vCC 4136 GET_VREG(r0, r2) @ r0<- vBB 4137 .if 0 4138 cmp r1, #0 @ is second operand zero? 4139 beq common_errDivideByZero 4140 .endif 4141 4142 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4143 @ optional op; may set condition codes 4144 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4145 GET_INST_OPCODE(ip) @ extract opcode from rINST 4146 SET_VREG(r0, r9) @ vAA<- r0 4147 GOTO_OPCODE(ip) @ jump to next instruction 4148 /* 11-14 instructions */ 4149 4150 4151 4152/* ------------------------------ */ 4153 .balign 64 4154.L_OP_DIV_INT: /* 0x93 */ 4155/* File: armv5te/OP_DIV_INT.S */ 4156/* File: armv5te/binop.S */ 4157 /* 4158 * Generic 32-bit binary operation. Provide an "instr" line that 4159 * specifies an instruction that performs "result = r0 op r1". 4160 * This could be an ARM instruction or a function call. (If the result 4161 * comes back in a register other than r0, you can override "result".) 4162 * 4163 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4164 * vCC (r1). Useful for integer division and modulus. Note that we 4165 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4166 * handles it correctly. 4167 * 4168 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4169 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4170 * mul-float, div-float, rem-float 4171 */ 4172 /* binop vAA, vBB, vCC */ 4173 FETCH(r0, 1) @ r0<- CCBB 4174 mov r9, rINST, lsr #8 @ r9<- AA 4175 mov r3, r0, lsr #8 @ r3<- CC 4176 and r2, r0, #255 @ r2<- BB 4177 GET_VREG(r1, r3) @ r1<- vCC 4178 GET_VREG(r0, r2) @ r0<- vBB 4179 .if 1 4180 cmp r1, #0 @ is second operand zero? 4181 beq common_errDivideByZero 4182 .endif 4183 4184 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4185 @ optional op; may set condition codes 4186 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4187 GET_INST_OPCODE(ip) @ extract opcode from rINST 4188 SET_VREG(r0, r9) @ vAA<- r0 4189 GOTO_OPCODE(ip) @ jump to next instruction 4190 /* 11-14 instructions */ 4191 4192 4193 4194/* ------------------------------ */ 4195 .balign 64 4196.L_OP_REM_INT: /* 0x94 */ 4197/* File: armv5te/OP_REM_INT.S */ 4198/* idivmod returns quotient in r0 and remainder in r1 */ 4199/* File: armv5te/binop.S */ 4200 /* 4201 * Generic 32-bit binary operation. Provide an "instr" line that 4202 * specifies an instruction that performs "result = r0 op r1". 4203 * This could be an ARM instruction or a function call. (If the result 4204 * comes back in a register other than r0, you can override "result".) 4205 * 4206 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4207 * vCC (r1). Useful for integer division and modulus. Note that we 4208 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4209 * handles it correctly. 4210 * 4211 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4212 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4213 * mul-float, div-float, rem-float 4214 */ 4215 /* binop vAA, vBB, vCC */ 4216 FETCH(r0, 1) @ r0<- CCBB 4217 mov r9, rINST, lsr #8 @ r9<- AA 4218 mov r3, r0, lsr #8 @ r3<- CC 4219 and r2, r0, #255 @ r2<- BB 4220 GET_VREG(r1, r3) @ r1<- vCC 4221 GET_VREG(r0, r2) @ r0<- vBB 4222 .if 1 4223 cmp r1, #0 @ is second operand zero? 4224 beq common_errDivideByZero 4225 .endif 4226 4227 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4228 @ optional op; may set condition codes 4229 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4230 GET_INST_OPCODE(ip) @ extract opcode from rINST 4231 SET_VREG(r1, r9) @ vAA<- r1 4232 GOTO_OPCODE(ip) @ jump to next instruction 4233 /* 11-14 instructions */ 4234 4235 4236 4237/* ------------------------------ */ 4238 .balign 64 4239.L_OP_AND_INT: /* 0x95 */ 4240/* File: armv5te/OP_AND_INT.S */ 4241/* File: armv5te/binop.S */ 4242 /* 4243 * Generic 32-bit binary operation. Provide an "instr" line that 4244 * specifies an instruction that performs "result = r0 op r1". 4245 * This could be an ARM instruction or a function call. (If the result 4246 * comes back in a register other than r0, you can override "result".) 4247 * 4248 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4249 * vCC (r1). Useful for integer division and modulus. Note that we 4250 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4251 * handles it correctly. 4252 * 4253 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4254 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4255 * mul-float, div-float, rem-float 4256 */ 4257 /* binop vAA, vBB, vCC */ 4258 FETCH(r0, 1) @ r0<- CCBB 4259 mov r9, rINST, lsr #8 @ r9<- AA 4260 mov r3, r0, lsr #8 @ r3<- CC 4261 and r2, r0, #255 @ r2<- BB 4262 GET_VREG(r1, r3) @ r1<- vCC 4263 GET_VREG(r0, r2) @ r0<- vBB 4264 .if 0 4265 cmp r1, #0 @ is second operand zero? 4266 beq common_errDivideByZero 4267 .endif 4268 4269 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4270 @ optional op; may set condition codes 4271 and r0, r0, r1 @ r0<- op, r0-r3 changed 4272 GET_INST_OPCODE(ip) @ extract opcode from rINST 4273 SET_VREG(r0, r9) @ vAA<- r0 4274 GOTO_OPCODE(ip) @ jump to next instruction 4275 /* 11-14 instructions */ 4276 4277 4278 4279/* ------------------------------ */ 4280 .balign 64 4281.L_OP_OR_INT: /* 0x96 */ 4282/* File: armv5te/OP_OR_INT.S */ 4283/* File: armv5te/binop.S */ 4284 /* 4285 * Generic 32-bit binary operation. Provide an "instr" line that 4286 * specifies an instruction that performs "result = r0 op r1". 4287 * This could be an ARM instruction or a function call. (If the result 4288 * comes back in a register other than r0, you can override "result".) 4289 * 4290 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4291 * vCC (r1). Useful for integer division and modulus. Note that we 4292 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4293 * handles it correctly. 4294 * 4295 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4296 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4297 * mul-float, div-float, rem-float 4298 */ 4299 /* binop vAA, vBB, vCC */ 4300 FETCH(r0, 1) @ r0<- CCBB 4301 mov r9, rINST, lsr #8 @ r9<- AA 4302 mov r3, r0, lsr #8 @ r3<- CC 4303 and r2, r0, #255 @ r2<- BB 4304 GET_VREG(r1, r3) @ r1<- vCC 4305 GET_VREG(r0, r2) @ r0<- vBB 4306 .if 0 4307 cmp r1, #0 @ is second operand zero? 4308 beq common_errDivideByZero 4309 .endif 4310 4311 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4312 @ optional op; may set condition codes 4313 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4314 GET_INST_OPCODE(ip) @ extract opcode from rINST 4315 SET_VREG(r0, r9) @ vAA<- r0 4316 GOTO_OPCODE(ip) @ jump to next instruction 4317 /* 11-14 instructions */ 4318 4319 4320 4321/* ------------------------------ */ 4322 .balign 64 4323.L_OP_XOR_INT: /* 0x97 */ 4324/* File: armv5te/OP_XOR_INT.S */ 4325/* File: armv5te/binop.S */ 4326 /* 4327 * Generic 32-bit binary operation. Provide an "instr" line that 4328 * specifies an instruction that performs "result = r0 op r1". 4329 * This could be an ARM instruction or a function call. (If the result 4330 * comes back in a register other than r0, you can override "result".) 4331 * 4332 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4333 * vCC (r1). Useful for integer division and modulus. Note that we 4334 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4335 * handles it correctly. 4336 * 4337 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4338 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4339 * mul-float, div-float, rem-float 4340 */ 4341 /* binop vAA, vBB, vCC */ 4342 FETCH(r0, 1) @ r0<- CCBB 4343 mov r9, rINST, lsr #8 @ r9<- AA 4344 mov r3, r0, lsr #8 @ r3<- CC 4345 and r2, r0, #255 @ r2<- BB 4346 GET_VREG(r1, r3) @ r1<- vCC 4347 GET_VREG(r0, r2) @ r0<- vBB 4348 .if 0 4349 cmp r1, #0 @ is second operand zero? 4350 beq common_errDivideByZero 4351 .endif 4352 4353 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4354 @ optional op; may set condition codes 4355 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4356 GET_INST_OPCODE(ip) @ extract opcode from rINST 4357 SET_VREG(r0, r9) @ vAA<- r0 4358 GOTO_OPCODE(ip) @ jump to next instruction 4359 /* 11-14 instructions */ 4360 4361 4362 4363/* ------------------------------ */ 4364 .balign 64 4365.L_OP_SHL_INT: /* 0x98 */ 4366/* File: armv5te/OP_SHL_INT.S */ 4367/* File: armv5te/binop.S */ 4368 /* 4369 * Generic 32-bit binary operation. Provide an "instr" line that 4370 * specifies an instruction that performs "result = r0 op r1". 4371 * This could be an ARM instruction or a function call. (If the result 4372 * comes back in a register other than r0, you can override "result".) 4373 * 4374 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4375 * vCC (r1). Useful for integer division and modulus. Note that we 4376 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4377 * handles it correctly. 4378 * 4379 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4380 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4381 * mul-float, div-float, rem-float 4382 */ 4383 /* binop vAA, vBB, vCC */ 4384 FETCH(r0, 1) @ r0<- CCBB 4385 mov r9, rINST, lsr #8 @ r9<- AA 4386 mov r3, r0, lsr #8 @ r3<- CC 4387 and r2, r0, #255 @ r2<- BB 4388 GET_VREG(r1, r3) @ r1<- vCC 4389 GET_VREG(r0, r2) @ r0<- vBB 4390 .if 0 4391 cmp r1, #0 @ is second operand zero? 4392 beq common_errDivideByZero 4393 .endif 4394 4395 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4396 and r1, r1, #31 @ optional op; may set condition codes 4397 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4398 GET_INST_OPCODE(ip) @ extract opcode from rINST 4399 SET_VREG(r0, r9) @ vAA<- r0 4400 GOTO_OPCODE(ip) @ jump to next instruction 4401 /* 11-14 instructions */ 4402 4403 4404 4405/* ------------------------------ */ 4406 .balign 64 4407.L_OP_SHR_INT: /* 0x99 */ 4408/* File: armv5te/OP_SHR_INT.S */ 4409/* File: armv5te/binop.S */ 4410 /* 4411 * Generic 32-bit binary operation. Provide an "instr" line that 4412 * specifies an instruction that performs "result = r0 op r1". 4413 * This could be an ARM instruction or a function call. (If the result 4414 * comes back in a register other than r0, you can override "result".) 4415 * 4416 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4417 * vCC (r1). Useful for integer division and modulus. Note that we 4418 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4419 * handles it correctly. 4420 * 4421 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4422 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4423 * mul-float, div-float, rem-float 4424 */ 4425 /* binop vAA, vBB, vCC */ 4426 FETCH(r0, 1) @ r0<- CCBB 4427 mov r9, rINST, lsr #8 @ r9<- AA 4428 mov r3, r0, lsr #8 @ r3<- CC 4429 and r2, r0, #255 @ r2<- BB 4430 GET_VREG(r1, r3) @ r1<- vCC 4431 GET_VREG(r0, r2) @ r0<- vBB 4432 .if 0 4433 cmp r1, #0 @ is second operand zero? 4434 beq common_errDivideByZero 4435 .endif 4436 4437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4438 and r1, r1, #31 @ optional op; may set condition codes 4439 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4440 GET_INST_OPCODE(ip) @ extract opcode from rINST 4441 SET_VREG(r0, r9) @ vAA<- r0 4442 GOTO_OPCODE(ip) @ jump to next instruction 4443 /* 11-14 instructions */ 4444 4445 4446 4447/* ------------------------------ */ 4448 .balign 64 4449.L_OP_USHR_INT: /* 0x9a */ 4450/* File: armv5te/OP_USHR_INT.S */ 4451/* File: armv5te/binop.S */ 4452 /* 4453 * Generic 32-bit binary operation. Provide an "instr" line that 4454 * specifies an instruction that performs "result = r0 op r1". 4455 * This could be an ARM instruction or a function call. (If the result 4456 * comes back in a register other than r0, you can override "result".) 4457 * 4458 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4459 * vCC (r1). Useful for integer division and modulus. Note that we 4460 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4461 * handles it correctly. 4462 * 4463 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4464 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4465 * mul-float, div-float, rem-float 4466 */ 4467 /* binop vAA, vBB, vCC */ 4468 FETCH(r0, 1) @ r0<- CCBB 4469 mov r9, rINST, lsr #8 @ r9<- AA 4470 mov r3, r0, lsr #8 @ r3<- CC 4471 and r2, r0, #255 @ r2<- BB 4472 GET_VREG(r1, r3) @ r1<- vCC 4473 GET_VREG(r0, r2) @ r0<- vBB 4474 .if 0 4475 cmp r1, #0 @ is second operand zero? 4476 beq common_errDivideByZero 4477 .endif 4478 4479 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4480 and r1, r1, #31 @ optional op; may set condition codes 4481 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4482 GET_INST_OPCODE(ip) @ extract opcode from rINST 4483 SET_VREG(r0, r9) @ vAA<- r0 4484 GOTO_OPCODE(ip) @ jump to next instruction 4485 /* 11-14 instructions */ 4486 4487 4488 4489/* ------------------------------ */ 4490 .balign 64 4491.L_OP_ADD_LONG: /* 0x9b */ 4492/* File: armv5te/OP_ADD_LONG.S */ 4493/* File: armv5te/binopWide.S */ 4494 /* 4495 * Generic 64-bit binary operation. Provide an "instr" line that 4496 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4497 * This could be an ARM instruction or a function call. (If the result 4498 * comes back in a register other than r0, you can override "result".) 4499 * 4500 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4501 * vCC (r1). Useful for integer division and modulus. 4502 * 4503 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4504 * xor-long, add-double, sub-double, mul-double, div-double, 4505 * rem-double 4506 * 4507 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4508 */ 4509 /* binop vAA, vBB, vCC */ 4510 FETCH(r0, 1) @ r0<- CCBB 4511 mov r9, rINST, lsr #8 @ r9<- AA 4512 and r2, r0, #255 @ r2<- BB 4513 mov r3, r0, lsr #8 @ r3<- CC 4514 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4515 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4516 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4517 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4518 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4519 .if 0 4520 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4521 beq common_errDivideByZero 4522 .endif 4523 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4524 4525 adds r0, r0, r2 @ optional op; may set condition codes 4526 adc r1, r1, r3 @ result<- op, r0-r3 changed 4527 GET_INST_OPCODE(ip) @ extract opcode from rINST 4528 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4529 GOTO_OPCODE(ip) @ jump to next instruction 4530 /* 14-17 instructions */ 4531 4532 4533 4534/* ------------------------------ */ 4535 .balign 64 4536.L_OP_SUB_LONG: /* 0x9c */ 4537/* File: armv5te/OP_SUB_LONG.S */ 4538/* File: armv5te/binopWide.S */ 4539 /* 4540 * Generic 64-bit binary operation. Provide an "instr" line that 4541 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4542 * This could be an ARM instruction or a function call. (If the result 4543 * comes back in a register other than r0, you can override "result".) 4544 * 4545 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4546 * vCC (r1). Useful for integer division and modulus. 4547 * 4548 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4549 * xor-long, add-double, sub-double, mul-double, div-double, 4550 * rem-double 4551 * 4552 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4553 */ 4554 /* binop vAA, vBB, vCC */ 4555 FETCH(r0, 1) @ r0<- CCBB 4556 mov r9, rINST, lsr #8 @ r9<- AA 4557 and r2, r0, #255 @ r2<- BB 4558 mov r3, r0, lsr #8 @ r3<- CC 4559 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4560 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4561 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4562 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4563 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4564 .if 0 4565 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4566 beq common_errDivideByZero 4567 .endif 4568 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4569 4570 subs r0, r0, r2 @ optional op; may set condition codes 4571 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4572 GET_INST_OPCODE(ip) @ extract opcode from rINST 4573 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4574 GOTO_OPCODE(ip) @ jump to next instruction 4575 /* 14-17 instructions */ 4576 4577 4578 4579/* ------------------------------ */ 4580 .balign 64 4581.L_OP_MUL_LONG: /* 0x9d */ 4582/* File: armv5te/OP_MUL_LONG.S */ 4583 /* 4584 * Signed 64-bit integer multiply. 4585 * 4586 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4587 * WX 4588 * x YZ 4589 * -------- 4590 * ZW ZX 4591 * YW YX 4592 * 4593 * The low word of the result holds ZX, the high word holds 4594 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4595 * it doesn't fit in the low 64 bits. 4596 * 4597 * Unlike most ARM math operations, multiply instructions have 4598 * restrictions on using the same register more than once (Rd and Rm 4599 * cannot be the same). 4600 */ 4601 /* mul-long vAA, vBB, vCC */ 4602 FETCH(r0, 1) @ r0<- CCBB 4603 and r2, r0, #255 @ r2<- BB 4604 mov r3, r0, lsr #8 @ r3<- CC 4605 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4606 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4607 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4608 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4609 mul ip, r2, r1 @ ip<- ZxW 4610 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4611 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4612 mov r0, rINST, lsr #8 @ r0<- AA 4613 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4614 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4616 b .LOP_MUL_LONG_finish 4617 4618/* ------------------------------ */ 4619 .balign 64 4620.L_OP_DIV_LONG: /* 0x9e */ 4621/* File: armv5te/OP_DIV_LONG.S */ 4622/* File: armv5te/binopWide.S */ 4623 /* 4624 * Generic 64-bit binary operation. Provide an "instr" line that 4625 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4626 * This could be an ARM instruction or a function call. (If the result 4627 * comes back in a register other than r0, you can override "result".) 4628 * 4629 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4630 * vCC (r1). Useful for integer division and modulus. 4631 * 4632 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4633 * xor-long, add-double, sub-double, mul-double, div-double, 4634 * rem-double 4635 * 4636 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4637 */ 4638 /* binop vAA, vBB, vCC */ 4639 FETCH(r0, 1) @ r0<- CCBB 4640 mov r9, rINST, lsr #8 @ r9<- AA 4641 and r2, r0, #255 @ r2<- BB 4642 mov r3, r0, lsr #8 @ r3<- CC 4643 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4644 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4645 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4646 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4647 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4648 .if 1 4649 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4650 beq common_errDivideByZero 4651 .endif 4652 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4653 4654 @ optional op; may set condition codes 4655 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4656 GET_INST_OPCODE(ip) @ extract opcode from rINST 4657 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4658 GOTO_OPCODE(ip) @ jump to next instruction 4659 /* 14-17 instructions */ 4660 4661 4662 4663/* ------------------------------ */ 4664 .balign 64 4665.L_OP_REM_LONG: /* 0x9f */ 4666/* File: armv5te/OP_REM_LONG.S */ 4667/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4668/* File: armv5te/binopWide.S */ 4669 /* 4670 * Generic 64-bit binary operation. Provide an "instr" line that 4671 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4672 * This could be an ARM instruction or a function call. (If the result 4673 * comes back in a register other than r0, you can override "result".) 4674 * 4675 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4676 * vCC (r1). Useful for integer division and modulus. 4677 * 4678 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4679 * xor-long, add-double, sub-double, mul-double, div-double, 4680 * rem-double 4681 * 4682 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4683 */ 4684 /* binop vAA, vBB, vCC */ 4685 FETCH(r0, 1) @ r0<- CCBB 4686 mov r9, rINST, lsr #8 @ r9<- AA 4687 and r2, r0, #255 @ r2<- BB 4688 mov r3, r0, lsr #8 @ r3<- CC 4689 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4690 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4691 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4692 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4693 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4694 .if 1 4695 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4696 beq common_errDivideByZero 4697 .endif 4698 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4699 4700 @ optional op; may set condition codes 4701 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4702 GET_INST_OPCODE(ip) @ extract opcode from rINST 4703 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4704 GOTO_OPCODE(ip) @ jump to next instruction 4705 /* 14-17 instructions */ 4706 4707 4708 4709/* ------------------------------ */ 4710 .balign 64 4711.L_OP_AND_LONG: /* 0xa0 */ 4712/* File: armv5te/OP_AND_LONG.S */ 4713/* File: armv5te/binopWide.S */ 4714 /* 4715 * Generic 64-bit binary operation. Provide an "instr" line that 4716 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4717 * This could be an ARM instruction or a function call. (If the result 4718 * comes back in a register other than r0, you can override "result".) 4719 * 4720 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4721 * vCC (r1). Useful for integer division and modulus. 4722 * 4723 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4724 * xor-long, add-double, sub-double, mul-double, div-double, 4725 * rem-double 4726 * 4727 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4728 */ 4729 /* binop vAA, vBB, vCC */ 4730 FETCH(r0, 1) @ r0<- CCBB 4731 mov r9, rINST, lsr #8 @ r9<- AA 4732 and r2, r0, #255 @ r2<- BB 4733 mov r3, r0, lsr #8 @ r3<- CC 4734 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4735 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4736 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4737 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4738 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4739 .if 0 4740 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4741 beq common_errDivideByZero 4742 .endif 4743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4744 4745 and r0, r0, r2 @ optional op; may set condition codes 4746 and r1, r1, r3 @ result<- op, r0-r3 changed 4747 GET_INST_OPCODE(ip) @ extract opcode from rINST 4748 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4749 GOTO_OPCODE(ip) @ jump to next instruction 4750 /* 14-17 instructions */ 4751 4752 4753 4754/* ------------------------------ */ 4755 .balign 64 4756.L_OP_OR_LONG: /* 0xa1 */ 4757/* File: armv5te/OP_OR_LONG.S */ 4758/* File: armv5te/binopWide.S */ 4759 /* 4760 * Generic 64-bit binary operation. Provide an "instr" line that 4761 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4762 * This could be an ARM instruction or a function call. (If the result 4763 * comes back in a register other than r0, you can override "result".) 4764 * 4765 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4766 * vCC (r1). Useful for integer division and modulus. 4767 * 4768 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4769 * xor-long, add-double, sub-double, mul-double, div-double, 4770 * rem-double 4771 * 4772 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4773 */ 4774 /* binop vAA, vBB, vCC */ 4775 FETCH(r0, 1) @ r0<- CCBB 4776 mov r9, rINST, lsr #8 @ r9<- AA 4777 and r2, r0, #255 @ r2<- BB 4778 mov r3, r0, lsr #8 @ r3<- CC 4779 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4780 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4781 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4782 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4783 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4784 .if 0 4785 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4786 beq common_errDivideByZero 4787 .endif 4788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4789 4790 orr r0, r0, r2 @ optional op; may set condition codes 4791 orr r1, r1, r3 @ result<- op, r0-r3 changed 4792 GET_INST_OPCODE(ip) @ extract opcode from rINST 4793 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4794 GOTO_OPCODE(ip) @ jump to next instruction 4795 /* 14-17 instructions */ 4796 4797 4798 4799/* ------------------------------ */ 4800 .balign 64 4801.L_OP_XOR_LONG: /* 0xa2 */ 4802/* File: armv5te/OP_XOR_LONG.S */ 4803/* File: armv5te/binopWide.S */ 4804 /* 4805 * Generic 64-bit binary operation. Provide an "instr" line that 4806 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4807 * This could be an ARM instruction or a function call. (If the result 4808 * comes back in a register other than r0, you can override "result".) 4809 * 4810 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4811 * vCC (r1). Useful for integer division and modulus. 4812 * 4813 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4814 * xor-long, add-double, sub-double, mul-double, div-double, 4815 * rem-double 4816 * 4817 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4818 */ 4819 /* binop vAA, vBB, vCC */ 4820 FETCH(r0, 1) @ r0<- CCBB 4821 mov r9, rINST, lsr #8 @ r9<- AA 4822 and r2, r0, #255 @ r2<- BB 4823 mov r3, r0, lsr #8 @ r3<- CC 4824 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4825 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4826 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4827 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4828 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4829 .if 0 4830 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4831 beq common_errDivideByZero 4832 .endif 4833 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4834 4835 eor r0, r0, r2 @ optional op; may set condition codes 4836 eor r1, r1, r3 @ result<- op, r0-r3 changed 4837 GET_INST_OPCODE(ip) @ extract opcode from rINST 4838 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4839 GOTO_OPCODE(ip) @ jump to next instruction 4840 /* 14-17 instructions */ 4841 4842 4843 4844/* ------------------------------ */ 4845 .balign 64 4846.L_OP_SHL_LONG: /* 0xa3 */ 4847/* File: armv5te/OP_SHL_LONG.S */ 4848 /* 4849 * Long integer shift. This is different from the generic 32/64-bit 4850 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4851 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4852 * 6 bits of the shift distance. 4853 */ 4854 /* shl-long vAA, vBB, vCC */ 4855 FETCH(r0, 1) @ r0<- CCBB 4856 mov r9, rINST, lsr #8 @ r9<- AA 4857 and r3, r0, #255 @ r3<- BB 4858 mov r0, r0, lsr #8 @ r0<- CC 4859 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4860 GET_VREG(r2, r0) @ r2<- vCC 4861 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4862 and r2, r2, #63 @ r2<- r2 & 0x3f 4863 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4864 4865 mov r1, r1, asl r2 @ r1<- r1 << r2 4866 rsb r3, r2, #32 @ r3<- 32 - r2 4867 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4868 subs ip, r2, #32 @ ip<- r2 - 32 4869 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4870 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4871 b .LOP_SHL_LONG_finish 4872 4873/* ------------------------------ */ 4874 .balign 64 4875.L_OP_SHR_LONG: /* 0xa4 */ 4876/* File: armv5te/OP_SHR_LONG.S */ 4877 /* 4878 * Long integer shift. This is different from the generic 32/64-bit 4879 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4880 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4881 * 6 bits of the shift distance. 4882 */ 4883 /* shr-long vAA, vBB, vCC */ 4884 FETCH(r0, 1) @ r0<- CCBB 4885 mov r9, rINST, lsr #8 @ r9<- AA 4886 and r3, r0, #255 @ r3<- BB 4887 mov r0, r0, lsr #8 @ r0<- CC 4888 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4889 GET_VREG(r2, r0) @ r2<- vCC 4890 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4891 and r2, r2, #63 @ r0<- r0 & 0x3f 4892 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4893 4894 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4895 rsb r3, r2, #32 @ r3<- 32 - r2 4896 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4897 subs ip, r2, #32 @ ip<- r2 - 32 4898 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4899 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4900 b .LOP_SHR_LONG_finish 4901 4902/* ------------------------------ */ 4903 .balign 64 4904.L_OP_USHR_LONG: /* 0xa5 */ 4905/* File: armv5te/OP_USHR_LONG.S */ 4906 /* 4907 * Long integer shift. This is different from the generic 32/64-bit 4908 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4909 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4910 * 6 bits of the shift distance. 4911 */ 4912 /* ushr-long vAA, vBB, vCC */ 4913 FETCH(r0, 1) @ r0<- CCBB 4914 mov r9, rINST, lsr #8 @ r9<- AA 4915 and r3, r0, #255 @ r3<- BB 4916 mov r0, r0, lsr #8 @ r0<- CC 4917 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4918 GET_VREG(r2, r0) @ r2<- vCC 4919 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4920 and r2, r2, #63 @ r0<- r0 & 0x3f 4921 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4922 4923 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4924 rsb r3, r2, #32 @ r3<- 32 - r2 4925 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4926 subs ip, r2, #32 @ ip<- r2 - 32 4927 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4929 b .LOP_USHR_LONG_finish 4930 4931/* ------------------------------ */ 4932 .balign 64 4933.L_OP_ADD_FLOAT: /* 0xa6 */ 4934/* File: armv5te/OP_ADD_FLOAT.S */ 4935/* File: armv5te/binop.S */ 4936 /* 4937 * Generic 32-bit binary operation. Provide an "instr" line that 4938 * specifies an instruction that performs "result = r0 op r1". 4939 * This could be an ARM instruction or a function call. (If the result 4940 * comes back in a register other than r0, you can override "result".) 4941 * 4942 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4943 * vCC (r1). Useful for integer division and modulus. Note that we 4944 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4945 * handles it correctly. 4946 * 4947 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4948 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4949 * mul-float, div-float, rem-float 4950 */ 4951 /* binop vAA, vBB, vCC */ 4952 FETCH(r0, 1) @ r0<- CCBB 4953 mov r9, rINST, lsr #8 @ r9<- AA 4954 mov r3, r0, lsr #8 @ r3<- CC 4955 and r2, r0, #255 @ r2<- BB 4956 GET_VREG(r1, r3) @ r1<- vCC 4957 GET_VREG(r0, r2) @ r0<- vBB 4958 .if 0 4959 cmp r1, #0 @ is second operand zero? 4960 beq common_errDivideByZero 4961 .endif 4962 4963 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4964 @ optional op; may set condition codes 4965 bl __aeabi_fadd @ r0<- op, r0-r3 changed 4966 GET_INST_OPCODE(ip) @ extract opcode from rINST 4967 SET_VREG(r0, r9) @ vAA<- r0 4968 GOTO_OPCODE(ip) @ jump to next instruction 4969 /* 11-14 instructions */ 4970 4971 4972 4973/* ------------------------------ */ 4974 .balign 64 4975.L_OP_SUB_FLOAT: /* 0xa7 */ 4976/* File: armv5te/OP_SUB_FLOAT.S */ 4977/* File: armv5te/binop.S */ 4978 /* 4979 * Generic 32-bit binary operation. Provide an "instr" line that 4980 * specifies an instruction that performs "result = r0 op r1". 4981 * This could be an ARM instruction or a function call. (If the result 4982 * comes back in a register other than r0, you can override "result".) 4983 * 4984 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4985 * vCC (r1). Useful for integer division and modulus. Note that we 4986 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4987 * handles it correctly. 4988 * 4989 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4990 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4991 * mul-float, div-float, rem-float 4992 */ 4993 /* binop vAA, vBB, vCC */ 4994 FETCH(r0, 1) @ r0<- CCBB 4995 mov r9, rINST, lsr #8 @ r9<- AA 4996 mov r3, r0, lsr #8 @ r3<- CC 4997 and r2, r0, #255 @ r2<- BB 4998 GET_VREG(r1, r3) @ r1<- vCC 4999 GET_VREG(r0, r2) @ r0<- vBB 5000 .if 0 5001 cmp r1, #0 @ is second operand zero? 5002 beq common_errDivideByZero 5003 .endif 5004 5005 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5006 @ optional op; may set condition codes 5007 bl __aeabi_fsub @ r0<- op, r0-r3 changed 5008 GET_INST_OPCODE(ip) @ extract opcode from rINST 5009 SET_VREG(r0, r9) @ vAA<- r0 5010 GOTO_OPCODE(ip) @ jump to next instruction 5011 /* 11-14 instructions */ 5012 5013 5014 5015/* ------------------------------ */ 5016 .balign 64 5017.L_OP_MUL_FLOAT: /* 0xa8 */ 5018/* File: armv5te/OP_MUL_FLOAT.S */ 5019/* File: armv5te/binop.S */ 5020 /* 5021 * Generic 32-bit binary operation. Provide an "instr" line that 5022 * specifies an instruction that performs "result = r0 op r1". 5023 * This could be an ARM instruction or a function call. (If the result 5024 * comes back in a register other than r0, you can override "result".) 5025 * 5026 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5027 * vCC (r1). Useful for integer division and modulus. Note that we 5028 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5029 * handles it correctly. 5030 * 5031 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5032 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5033 * mul-float, div-float, rem-float 5034 */ 5035 /* binop vAA, vBB, vCC */ 5036 FETCH(r0, 1) @ r0<- CCBB 5037 mov r9, rINST, lsr #8 @ r9<- AA 5038 mov r3, r0, lsr #8 @ r3<- CC 5039 and r2, r0, #255 @ r2<- BB 5040 GET_VREG(r1, r3) @ r1<- vCC 5041 GET_VREG(r0, r2) @ r0<- vBB 5042 .if 0 5043 cmp r1, #0 @ is second operand zero? 5044 beq common_errDivideByZero 5045 .endif 5046 5047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5048 @ optional op; may set condition codes 5049 bl __aeabi_fmul @ r0<- op, r0-r3 changed 5050 GET_INST_OPCODE(ip) @ extract opcode from rINST 5051 SET_VREG(r0, r9) @ vAA<- r0 5052 GOTO_OPCODE(ip) @ jump to next instruction 5053 /* 11-14 instructions */ 5054 5055 5056 5057/* ------------------------------ */ 5058 .balign 64 5059.L_OP_DIV_FLOAT: /* 0xa9 */ 5060/* File: armv5te/OP_DIV_FLOAT.S */ 5061/* File: armv5te/binop.S */ 5062 /* 5063 * Generic 32-bit binary operation. Provide an "instr" line that 5064 * specifies an instruction that performs "result = r0 op r1". 5065 * This could be an ARM instruction or a function call. (If the result 5066 * comes back in a register other than r0, you can override "result".) 5067 * 5068 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5069 * vCC (r1). Useful for integer division and modulus. Note that we 5070 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5071 * handles it correctly. 5072 * 5073 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5074 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5075 * mul-float, div-float, rem-float 5076 */ 5077 /* binop vAA, vBB, vCC */ 5078 FETCH(r0, 1) @ r0<- CCBB 5079 mov r9, rINST, lsr #8 @ r9<- AA 5080 mov r3, r0, lsr #8 @ r3<- CC 5081 and r2, r0, #255 @ r2<- BB 5082 GET_VREG(r1, r3) @ r1<- vCC 5083 GET_VREG(r0, r2) @ r0<- vBB 5084 .if 0 5085 cmp r1, #0 @ is second operand zero? 5086 beq common_errDivideByZero 5087 .endif 5088 5089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5090 @ optional op; may set condition codes 5091 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 5092 GET_INST_OPCODE(ip) @ extract opcode from rINST 5093 SET_VREG(r0, r9) @ vAA<- r0 5094 GOTO_OPCODE(ip) @ jump to next instruction 5095 /* 11-14 instructions */ 5096 5097 5098 5099/* ------------------------------ */ 5100 .balign 64 5101.L_OP_REM_FLOAT: /* 0xaa */ 5102/* File: armv5te/OP_REM_FLOAT.S */ 5103/* EABI doesn't define a float remainder function, but libm does */ 5104/* File: armv5te/binop.S */ 5105 /* 5106 * Generic 32-bit binary operation. Provide an "instr" line that 5107 * specifies an instruction that performs "result = r0 op r1". 5108 * This could be an ARM instruction or a function call. (If the result 5109 * comes back in a register other than r0, you can override "result".) 5110 * 5111 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5112 * vCC (r1). Useful for integer division and modulus. Note that we 5113 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5114 * handles it correctly. 5115 * 5116 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5117 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5118 * mul-float, div-float, rem-float 5119 */ 5120 /* binop vAA, vBB, vCC */ 5121 FETCH(r0, 1) @ r0<- CCBB 5122 mov r9, rINST, lsr #8 @ r9<- AA 5123 mov r3, r0, lsr #8 @ r3<- CC 5124 and r2, r0, #255 @ r2<- BB 5125 GET_VREG(r1, r3) @ r1<- vCC 5126 GET_VREG(r0, r2) @ r0<- vBB 5127 .if 0 5128 cmp r1, #0 @ is second operand zero? 5129 beq common_errDivideByZero 5130 .endif 5131 5132 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5133 @ optional op; may set condition codes 5134 bl fmodf @ r0<- op, r0-r3 changed 5135 GET_INST_OPCODE(ip) @ extract opcode from rINST 5136 SET_VREG(r0, r9) @ vAA<- r0 5137 GOTO_OPCODE(ip) @ jump to next instruction 5138 /* 11-14 instructions */ 5139 5140 5141 5142/* ------------------------------ */ 5143 .balign 64 5144.L_OP_ADD_DOUBLE: /* 0xab */ 5145/* File: armv5te/OP_ADD_DOUBLE.S */ 5146/* File: armv5te/binopWide.S */ 5147 /* 5148 * Generic 64-bit binary operation. Provide an "instr" line that 5149 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5150 * This could be an ARM instruction or a function call. (If the result 5151 * comes back in a register other than r0, you can override "result".) 5152 * 5153 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5154 * vCC (r1). Useful for integer division and modulus. 5155 * 5156 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5157 * xor-long, add-double, sub-double, mul-double, div-double, 5158 * rem-double 5159 * 5160 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5161 */ 5162 /* binop vAA, vBB, vCC */ 5163 FETCH(r0, 1) @ r0<- CCBB 5164 mov r9, rINST, lsr #8 @ r9<- AA 5165 and r2, r0, #255 @ r2<- BB 5166 mov r3, r0, lsr #8 @ r3<- CC 5167 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5168 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5169 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5170 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5171 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5172 .if 0 5173 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5174 beq common_errDivideByZero 5175 .endif 5176 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5177 5178 @ optional op; may set condition codes 5179 bl __aeabi_dadd @ result<- op, r0-r3 changed 5180 GET_INST_OPCODE(ip) @ extract opcode from rINST 5181 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5182 GOTO_OPCODE(ip) @ jump to next instruction 5183 /* 14-17 instructions */ 5184 5185 5186 5187/* ------------------------------ */ 5188 .balign 64 5189.L_OP_SUB_DOUBLE: /* 0xac */ 5190/* File: armv5te/OP_SUB_DOUBLE.S */ 5191/* File: armv5te/binopWide.S */ 5192 /* 5193 * Generic 64-bit binary operation. Provide an "instr" line that 5194 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5195 * This could be an ARM instruction or a function call. (If the result 5196 * comes back in a register other than r0, you can override "result".) 5197 * 5198 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5199 * vCC (r1). Useful for integer division and modulus. 5200 * 5201 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5202 * xor-long, add-double, sub-double, mul-double, div-double, 5203 * rem-double 5204 * 5205 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5206 */ 5207 /* binop vAA, vBB, vCC */ 5208 FETCH(r0, 1) @ r0<- CCBB 5209 mov r9, rINST, lsr #8 @ r9<- AA 5210 and r2, r0, #255 @ r2<- BB 5211 mov r3, r0, lsr #8 @ r3<- CC 5212 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5213 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5214 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5215 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5216 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5217 .if 0 5218 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5219 beq common_errDivideByZero 5220 .endif 5221 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5222 5223 @ optional op; may set condition codes 5224 bl __aeabi_dsub @ result<- op, r0-r3 changed 5225 GET_INST_OPCODE(ip) @ extract opcode from rINST 5226 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5227 GOTO_OPCODE(ip) @ jump to next instruction 5228 /* 14-17 instructions */ 5229 5230 5231 5232/* ------------------------------ */ 5233 .balign 64 5234.L_OP_MUL_DOUBLE: /* 0xad */ 5235/* File: armv5te/OP_MUL_DOUBLE.S */ 5236/* File: armv5te/binopWide.S */ 5237 /* 5238 * Generic 64-bit binary operation. Provide an "instr" line that 5239 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5240 * This could be an ARM instruction or a function call. (If the result 5241 * comes back in a register other than r0, you can override "result".) 5242 * 5243 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5244 * vCC (r1). Useful for integer division and modulus. 5245 * 5246 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5247 * xor-long, add-double, sub-double, mul-double, div-double, 5248 * rem-double 5249 * 5250 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5251 */ 5252 /* binop vAA, vBB, vCC */ 5253 FETCH(r0, 1) @ r0<- CCBB 5254 mov r9, rINST, lsr #8 @ r9<- AA 5255 and r2, r0, #255 @ r2<- BB 5256 mov r3, r0, lsr #8 @ r3<- CC 5257 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5258 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5259 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5260 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5261 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5262 .if 0 5263 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5264 beq common_errDivideByZero 5265 .endif 5266 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5267 5268 @ optional op; may set condition codes 5269 bl __aeabi_dmul @ result<- op, r0-r3 changed 5270 GET_INST_OPCODE(ip) @ extract opcode from rINST 5271 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5272 GOTO_OPCODE(ip) @ jump to next instruction 5273 /* 14-17 instructions */ 5274 5275 5276 5277/* ------------------------------ */ 5278 .balign 64 5279.L_OP_DIV_DOUBLE: /* 0xae */ 5280/* File: armv5te/OP_DIV_DOUBLE.S */ 5281/* File: armv5te/binopWide.S */ 5282 /* 5283 * Generic 64-bit binary operation. Provide an "instr" line that 5284 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5285 * This could be an ARM instruction or a function call. (If the result 5286 * comes back in a register other than r0, you can override "result".) 5287 * 5288 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5289 * vCC (r1). Useful for integer division and modulus. 5290 * 5291 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5292 * xor-long, add-double, sub-double, mul-double, div-double, 5293 * rem-double 5294 * 5295 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5296 */ 5297 /* binop vAA, vBB, vCC */ 5298 FETCH(r0, 1) @ r0<- CCBB 5299 mov r9, rINST, lsr #8 @ r9<- AA 5300 and r2, r0, #255 @ r2<- BB 5301 mov r3, r0, lsr #8 @ r3<- CC 5302 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5303 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5304 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5305 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5306 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5307 .if 0 5308 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5309 beq common_errDivideByZero 5310 .endif 5311 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5312 5313 @ optional op; may set condition codes 5314 bl __aeabi_ddiv @ result<- op, r0-r3 changed 5315 GET_INST_OPCODE(ip) @ extract opcode from rINST 5316 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5317 GOTO_OPCODE(ip) @ jump to next instruction 5318 /* 14-17 instructions */ 5319 5320 5321 5322/* ------------------------------ */ 5323 .balign 64 5324.L_OP_REM_DOUBLE: /* 0xaf */ 5325/* File: armv5te/OP_REM_DOUBLE.S */ 5326/* EABI doesn't define a double remainder function, but libm does */ 5327/* File: armv5te/binopWide.S */ 5328 /* 5329 * Generic 64-bit binary operation. Provide an "instr" line that 5330 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5331 * This could be an ARM instruction or a function call. (If the result 5332 * comes back in a register other than r0, you can override "result".) 5333 * 5334 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5335 * vCC (r1). Useful for integer division and modulus. 5336 * 5337 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5338 * xor-long, add-double, sub-double, mul-double, div-double, 5339 * rem-double 5340 * 5341 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5342 */ 5343 /* binop vAA, vBB, vCC */ 5344 FETCH(r0, 1) @ r0<- CCBB 5345 mov r9, rINST, lsr #8 @ r9<- AA 5346 and r2, r0, #255 @ r2<- BB 5347 mov r3, r0, lsr #8 @ r3<- CC 5348 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5349 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5350 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5351 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5352 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5353 .if 0 5354 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5355 beq common_errDivideByZero 5356 .endif 5357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5358 5359 @ optional op; may set condition codes 5360 bl fmod @ result<- op, r0-r3 changed 5361 GET_INST_OPCODE(ip) @ extract opcode from rINST 5362 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5363 GOTO_OPCODE(ip) @ jump to next instruction 5364 /* 14-17 instructions */ 5365 5366 5367 5368/* ------------------------------ */ 5369 .balign 64 5370.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5371/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5372/* File: armv5te/binop2addr.S */ 5373 /* 5374 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5375 * that specifies an instruction that performs "result = r0 op r1". 5376 * This could be an ARM instruction or a function call. (If the result 5377 * comes back in a register other than r0, you can override "result".) 5378 * 5379 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5380 * vCC (r1). Useful for integer division and modulus. 5381 * 5382 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5383 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5384 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5385 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5386 */ 5387 /* binop/2addr vA, vB */ 5388 mov r9, rINST, lsr #8 @ r9<- A+ 5389 mov r3, rINST, lsr #12 @ r3<- B 5390 and r9, r9, #15 5391 GET_VREG(r0, r9) @ r0<- vA 5392 GET_VREG(r1, r3) @ r1<- vB 5393 .if 0 5394 cmp r1, #0 @ is second operand zero? 5395 beq common_errDivideByZero 5396 .endif 5397 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5398 5399 @ optional op; may set condition codes 5400 add r0, r0, r1 @ r0<- op, r0-r3 changed 5401 GET_INST_OPCODE(ip) @ extract opcode from rINST 5402 SET_VREG(r0, r9) @ vAA<- r0 5403 GOTO_OPCODE(ip) @ jump to next instruction 5404 /* 10-13 instructions */ 5405 5406 5407 5408/* ------------------------------ */ 5409 .balign 64 5410.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5411/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5412/* File: armv5te/binop2addr.S */ 5413 /* 5414 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5415 * that specifies an instruction that performs "result = r0 op r1". 5416 * This could be an ARM instruction or a function call. (If the result 5417 * comes back in a register other than r0, you can override "result".) 5418 * 5419 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5420 * vCC (r1). Useful for integer division and modulus. 5421 * 5422 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5423 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5424 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5425 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5426 */ 5427 /* binop/2addr vA, vB */ 5428 mov r9, rINST, lsr #8 @ r9<- A+ 5429 mov r3, rINST, lsr #12 @ r3<- B 5430 and r9, r9, #15 5431 GET_VREG(r0, r9) @ r0<- vA 5432 GET_VREG(r1, r3) @ r1<- vB 5433 .if 0 5434 cmp r1, #0 @ is second operand zero? 5435 beq common_errDivideByZero 5436 .endif 5437 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5438 5439 @ optional op; may set condition codes 5440 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5441 GET_INST_OPCODE(ip) @ extract opcode from rINST 5442 SET_VREG(r0, r9) @ vAA<- r0 5443 GOTO_OPCODE(ip) @ jump to next instruction 5444 /* 10-13 instructions */ 5445 5446 5447 5448/* ------------------------------ */ 5449 .balign 64 5450.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5451/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5452/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5453/* File: armv5te/binop2addr.S */ 5454 /* 5455 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5456 * that specifies an instruction that performs "result = r0 op r1". 5457 * This could be an ARM instruction or a function call. (If the result 5458 * comes back in a register other than r0, you can override "result".) 5459 * 5460 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5461 * vCC (r1). Useful for integer division and modulus. 5462 * 5463 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5464 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5465 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5466 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5467 */ 5468 /* binop/2addr vA, vB */ 5469 mov r9, rINST, lsr #8 @ r9<- A+ 5470 mov r3, rINST, lsr #12 @ r3<- B 5471 and r9, r9, #15 5472 GET_VREG(r0, r9) @ r0<- vA 5473 GET_VREG(r1, r3) @ r1<- vB 5474 .if 0 5475 cmp r1, #0 @ is second operand zero? 5476 beq common_errDivideByZero 5477 .endif 5478 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5479 5480 @ optional op; may set condition codes 5481 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5482 GET_INST_OPCODE(ip) @ extract opcode from rINST 5483 SET_VREG(r0, r9) @ vAA<- r0 5484 GOTO_OPCODE(ip) @ jump to next instruction 5485 /* 10-13 instructions */ 5486 5487 5488 5489/* ------------------------------ */ 5490 .balign 64 5491.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5492/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5493/* File: armv5te/binop2addr.S */ 5494 /* 5495 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5496 * that specifies an instruction that performs "result = r0 op r1". 5497 * This could be an ARM instruction or a function call. (If the result 5498 * comes back in a register other than r0, you can override "result".) 5499 * 5500 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5501 * vCC (r1). Useful for integer division and modulus. 5502 * 5503 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5504 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5505 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5506 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5507 */ 5508 /* binop/2addr vA, vB */ 5509 mov r9, rINST, lsr #8 @ r9<- A+ 5510 mov r3, rINST, lsr #12 @ r3<- B 5511 and r9, r9, #15 5512 GET_VREG(r0, r9) @ r0<- vA 5513 GET_VREG(r1, r3) @ r1<- vB 5514 .if 1 5515 cmp r1, #0 @ is second operand zero? 5516 beq common_errDivideByZero 5517 .endif 5518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5519 5520 @ optional op; may set condition codes 5521 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5522 GET_INST_OPCODE(ip) @ extract opcode from rINST 5523 SET_VREG(r0, r9) @ vAA<- r0 5524 GOTO_OPCODE(ip) @ jump to next instruction 5525 /* 10-13 instructions */ 5526 5527 5528 5529/* ------------------------------ */ 5530 .balign 64 5531.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5532/* File: armv5te/OP_REM_INT_2ADDR.S */ 5533/* idivmod returns quotient in r0 and remainder in r1 */ 5534/* File: armv5te/binop2addr.S */ 5535 /* 5536 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5537 * that specifies an instruction that performs "result = r0 op r1". 5538 * This could be an ARM instruction or a function call. (If the result 5539 * comes back in a register other than r0, you can override "result".) 5540 * 5541 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5542 * vCC (r1). Useful for integer division and modulus. 5543 * 5544 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5545 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5546 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5547 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5548 */ 5549 /* binop/2addr vA, vB */ 5550 mov r9, rINST, lsr #8 @ r9<- A+ 5551 mov r3, rINST, lsr #12 @ r3<- B 5552 and r9, r9, #15 5553 GET_VREG(r0, r9) @ r0<- vA 5554 GET_VREG(r1, r3) @ r1<- vB 5555 .if 1 5556 cmp r1, #0 @ is second operand zero? 5557 beq common_errDivideByZero 5558 .endif 5559 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5560 5561 @ optional op; may set condition codes 5562 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5563 GET_INST_OPCODE(ip) @ extract opcode from rINST 5564 SET_VREG(r1, r9) @ vAA<- r1 5565 GOTO_OPCODE(ip) @ jump to next instruction 5566 /* 10-13 instructions */ 5567 5568 5569 5570/* ------------------------------ */ 5571 .balign 64 5572.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5573/* File: armv5te/OP_AND_INT_2ADDR.S */ 5574/* File: armv5te/binop2addr.S */ 5575 /* 5576 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5577 * that specifies an instruction that performs "result = r0 op r1". 5578 * This could be an ARM instruction or a function call. (If the result 5579 * comes back in a register other than r0, you can override "result".) 5580 * 5581 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5582 * vCC (r1). Useful for integer division and modulus. 5583 * 5584 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5585 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5586 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5587 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5588 */ 5589 /* binop/2addr vA, vB */ 5590 mov r9, rINST, lsr #8 @ r9<- A+ 5591 mov r3, rINST, lsr #12 @ r3<- B 5592 and r9, r9, #15 5593 GET_VREG(r0, r9) @ r0<- vA 5594 GET_VREG(r1, r3) @ r1<- vB 5595 .if 0 5596 cmp r1, #0 @ is second operand zero? 5597 beq common_errDivideByZero 5598 .endif 5599 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5600 5601 @ optional op; may set condition codes 5602 and r0, r0, r1 @ r0<- op, r0-r3 changed 5603 GET_INST_OPCODE(ip) @ extract opcode from rINST 5604 SET_VREG(r0, r9) @ vAA<- r0 5605 GOTO_OPCODE(ip) @ jump to next instruction 5606 /* 10-13 instructions */ 5607 5608 5609 5610/* ------------------------------ */ 5611 .balign 64 5612.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5613/* File: armv5te/OP_OR_INT_2ADDR.S */ 5614/* File: armv5te/binop2addr.S */ 5615 /* 5616 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5617 * that specifies an instruction that performs "result = r0 op r1". 5618 * This could be an ARM instruction or a function call. (If the result 5619 * comes back in a register other than r0, you can override "result".) 5620 * 5621 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5622 * vCC (r1). Useful for integer division and modulus. 5623 * 5624 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5625 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5626 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5627 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5628 */ 5629 /* binop/2addr vA, vB */ 5630 mov r9, rINST, lsr #8 @ r9<- A+ 5631 mov r3, rINST, lsr #12 @ r3<- B 5632 and r9, r9, #15 5633 GET_VREG(r0, r9) @ r0<- vA 5634 GET_VREG(r1, r3) @ r1<- vB 5635 .if 0 5636 cmp r1, #0 @ is second operand zero? 5637 beq common_errDivideByZero 5638 .endif 5639 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5640 5641 @ optional op; may set condition codes 5642 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5643 GET_INST_OPCODE(ip) @ extract opcode from rINST 5644 SET_VREG(r0, r9) @ vAA<- r0 5645 GOTO_OPCODE(ip) @ jump to next instruction 5646 /* 10-13 instructions */ 5647 5648 5649 5650/* ------------------------------ */ 5651 .balign 64 5652.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5653/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5654/* File: armv5te/binop2addr.S */ 5655 /* 5656 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5657 * that specifies an instruction that performs "result = r0 op r1". 5658 * This could be an ARM instruction or a function call. (If the result 5659 * comes back in a register other than r0, you can override "result".) 5660 * 5661 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5662 * vCC (r1). Useful for integer division and modulus. 5663 * 5664 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5665 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5666 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5667 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5668 */ 5669 /* binop/2addr vA, vB */ 5670 mov r9, rINST, lsr #8 @ r9<- A+ 5671 mov r3, rINST, lsr #12 @ r3<- B 5672 and r9, r9, #15 5673 GET_VREG(r0, r9) @ r0<- vA 5674 GET_VREG(r1, r3) @ r1<- vB 5675 .if 0 5676 cmp r1, #0 @ is second operand zero? 5677 beq common_errDivideByZero 5678 .endif 5679 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5680 5681 @ optional op; may set condition codes 5682 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5683 GET_INST_OPCODE(ip) @ extract opcode from rINST 5684 SET_VREG(r0, r9) @ vAA<- r0 5685 GOTO_OPCODE(ip) @ jump to next instruction 5686 /* 10-13 instructions */ 5687 5688 5689 5690/* ------------------------------ */ 5691 .balign 64 5692.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5693/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5694/* File: armv5te/binop2addr.S */ 5695 /* 5696 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5697 * that specifies an instruction that performs "result = r0 op r1". 5698 * This could be an ARM instruction or a function call. (If the result 5699 * comes back in a register other than r0, you can override "result".) 5700 * 5701 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5702 * vCC (r1). Useful for integer division and modulus. 5703 * 5704 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5705 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5706 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5707 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5708 */ 5709 /* binop/2addr vA, vB */ 5710 mov r9, rINST, lsr #8 @ r9<- A+ 5711 mov r3, rINST, lsr #12 @ r3<- B 5712 and r9, r9, #15 5713 GET_VREG(r0, r9) @ r0<- vA 5714 GET_VREG(r1, r3) @ r1<- vB 5715 .if 0 5716 cmp r1, #0 @ is second operand zero? 5717 beq common_errDivideByZero 5718 .endif 5719 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5720 5721 and r1, r1, #31 @ optional op; may set condition codes 5722 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5723 GET_INST_OPCODE(ip) @ extract opcode from rINST 5724 SET_VREG(r0, r9) @ vAA<- r0 5725 GOTO_OPCODE(ip) @ jump to next instruction 5726 /* 10-13 instructions */ 5727 5728 5729 5730/* ------------------------------ */ 5731 .balign 64 5732.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5733/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5734/* File: armv5te/binop2addr.S */ 5735 /* 5736 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5737 * that specifies an instruction that performs "result = r0 op r1". 5738 * This could be an ARM instruction or a function call. (If the result 5739 * comes back in a register other than r0, you can override "result".) 5740 * 5741 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5742 * vCC (r1). Useful for integer division and modulus. 5743 * 5744 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5745 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5746 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5747 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5748 */ 5749 /* binop/2addr vA, vB */ 5750 mov r9, rINST, lsr #8 @ r9<- A+ 5751 mov r3, rINST, lsr #12 @ r3<- B 5752 and r9, r9, #15 5753 GET_VREG(r0, r9) @ r0<- vA 5754 GET_VREG(r1, r3) @ r1<- vB 5755 .if 0 5756 cmp r1, #0 @ is second operand zero? 5757 beq common_errDivideByZero 5758 .endif 5759 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5760 5761 and r1, r1, #31 @ optional op; may set condition codes 5762 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5763 GET_INST_OPCODE(ip) @ extract opcode from rINST 5764 SET_VREG(r0, r9) @ vAA<- r0 5765 GOTO_OPCODE(ip) @ jump to next instruction 5766 /* 10-13 instructions */ 5767 5768 5769 5770/* ------------------------------ */ 5771 .balign 64 5772.L_OP_USHR_INT_2ADDR: /* 0xba */ 5773/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5774/* File: armv5te/binop2addr.S */ 5775 /* 5776 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5777 * that specifies an instruction that performs "result = r0 op r1". 5778 * This could be an ARM instruction or a function call. (If the result 5779 * comes back in a register other than r0, you can override "result".) 5780 * 5781 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5782 * vCC (r1). Useful for integer division and modulus. 5783 * 5784 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5785 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5786 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5787 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5788 */ 5789 /* binop/2addr vA, vB */ 5790 mov r9, rINST, lsr #8 @ r9<- A+ 5791 mov r3, rINST, lsr #12 @ r3<- B 5792 and r9, r9, #15 5793 GET_VREG(r0, r9) @ r0<- vA 5794 GET_VREG(r1, r3) @ r1<- vB 5795 .if 0 5796 cmp r1, #0 @ is second operand zero? 5797 beq common_errDivideByZero 5798 .endif 5799 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5800 5801 and r1, r1, #31 @ optional op; may set condition codes 5802 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5803 GET_INST_OPCODE(ip) @ extract opcode from rINST 5804 SET_VREG(r0, r9) @ vAA<- r0 5805 GOTO_OPCODE(ip) @ jump to next instruction 5806 /* 10-13 instructions */ 5807 5808 5809 5810/* ------------------------------ */ 5811 .balign 64 5812.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5813/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5814/* File: armv5te/binopWide2addr.S */ 5815 /* 5816 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5817 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5818 * This could be an ARM instruction or a function call. (If the result 5819 * comes back in a register other than r0, you can override "result".) 5820 * 5821 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5822 * vCC (r1). Useful for integer division and modulus. 5823 * 5824 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5825 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5826 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5827 * rem-double/2addr 5828 */ 5829 /* binop/2addr vA, vB */ 5830 mov r9, rINST, lsr #8 @ r9<- A+ 5831 mov r1, rINST, lsr #12 @ r1<- B 5832 and r9, r9, #15 5833 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5834 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5835 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5836 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5837 .if 0 5838 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5839 beq common_errDivideByZero 5840 .endif 5841 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5842 5843 adds r0, r0, r2 @ optional op; may set condition codes 5844 adc r1, r1, r3 @ result<- op, r0-r3 changed 5845 GET_INST_OPCODE(ip) @ extract opcode from rINST 5846 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5847 GOTO_OPCODE(ip) @ jump to next instruction 5848 /* 12-15 instructions */ 5849 5850 5851 5852/* ------------------------------ */ 5853 .balign 64 5854.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5855/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5856/* File: armv5te/binopWide2addr.S */ 5857 /* 5858 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5859 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5860 * This could be an ARM instruction or a function call. (If the result 5861 * comes back in a register other than r0, you can override "result".) 5862 * 5863 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5864 * vCC (r1). Useful for integer division and modulus. 5865 * 5866 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5867 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5868 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5869 * rem-double/2addr 5870 */ 5871 /* binop/2addr vA, vB */ 5872 mov r9, rINST, lsr #8 @ r9<- A+ 5873 mov r1, rINST, lsr #12 @ r1<- B 5874 and r9, r9, #15 5875 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5876 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5877 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5878 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5879 .if 0 5880 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5881 beq common_errDivideByZero 5882 .endif 5883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5884 5885 subs r0, r0, r2 @ optional op; may set condition codes 5886 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5887 GET_INST_OPCODE(ip) @ extract opcode from rINST 5888 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5889 GOTO_OPCODE(ip) @ jump to next instruction 5890 /* 12-15 instructions */ 5891 5892 5893 5894/* ------------------------------ */ 5895 .balign 64 5896.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5897/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5898 /* 5899 * Signed 64-bit integer multiply, "/2addr" version. 5900 * 5901 * See OP_MUL_LONG for an explanation. 5902 * 5903 * We get a little tight on registers, so to avoid looking up &fp[A] 5904 * again we stuff it into rINST. 5905 */ 5906 /* mul-long/2addr vA, vB */ 5907 mov r9, rINST, lsr #8 @ r9<- A+ 5908 mov r1, rINST, lsr #12 @ r1<- B 5909 and r9, r9, #15 5910 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5911 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5912 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5913 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5914 mul ip, r2, r1 @ ip<- ZxW 5915 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5916 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5917 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5918 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5919 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5920 GET_INST_OPCODE(ip) @ extract opcode from rINST 5921 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5922 GOTO_OPCODE(ip) @ jump to next instruction 5923 5924 5925/* ------------------------------ */ 5926 .balign 64 5927.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5928/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5929/* File: armv5te/binopWide2addr.S */ 5930 /* 5931 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5932 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5933 * This could be an ARM instruction or a function call. (If the result 5934 * comes back in a register other than r0, you can override "result".) 5935 * 5936 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5937 * vCC (r1). Useful for integer division and modulus. 5938 * 5939 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5940 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5941 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5942 * rem-double/2addr 5943 */ 5944 /* binop/2addr vA, vB */ 5945 mov r9, rINST, lsr #8 @ r9<- A+ 5946 mov r1, rINST, lsr #12 @ r1<- B 5947 and r9, r9, #15 5948 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5949 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5950 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5951 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5952 .if 1 5953 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5954 beq common_errDivideByZero 5955 .endif 5956 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5957 5958 @ optional op; may set condition codes 5959 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5960 GET_INST_OPCODE(ip) @ extract opcode from rINST 5961 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5962 GOTO_OPCODE(ip) @ jump to next instruction 5963 /* 12-15 instructions */ 5964 5965 5966 5967/* ------------------------------ */ 5968 .balign 64 5969.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5970/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5971/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5972/* File: armv5te/binopWide2addr.S */ 5973 /* 5974 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5975 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5976 * This could be an ARM instruction or a function call. (If the result 5977 * comes back in a register other than r0, you can override "result".) 5978 * 5979 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5980 * vCC (r1). Useful for integer division and modulus. 5981 * 5982 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5983 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5984 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5985 * rem-double/2addr 5986 */ 5987 /* binop/2addr vA, vB */ 5988 mov r9, rINST, lsr #8 @ r9<- A+ 5989 mov r1, rINST, lsr #12 @ r1<- B 5990 and r9, r9, #15 5991 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5992 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5993 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5994 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5995 .if 1 5996 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5997 beq common_errDivideByZero 5998 .endif 5999 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6000 6001 @ optional op; may set condition codes 6002 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 6003 GET_INST_OPCODE(ip) @ extract opcode from rINST 6004 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 6005 GOTO_OPCODE(ip) @ jump to next instruction 6006 /* 12-15 instructions */ 6007 6008 6009 6010/* ------------------------------ */ 6011 .balign 64 6012.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 6013/* File: armv5te/OP_AND_LONG_2ADDR.S */ 6014/* File: armv5te/binopWide2addr.S */ 6015 /* 6016 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6017 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6018 * This could be an ARM instruction or a function call. (If the result 6019 * comes back in a register other than r0, you can override "result".) 6020 * 6021 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6022 * vCC (r1). Useful for integer division and modulus. 6023 * 6024 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6025 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6026 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6027 * rem-double/2addr 6028 */ 6029 /* binop/2addr vA, vB */ 6030 mov r9, rINST, lsr #8 @ r9<- A+ 6031 mov r1, rINST, lsr #12 @ r1<- B 6032 and r9, r9, #15 6033 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6034 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6035 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6036 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6037 .if 0 6038 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6039 beq common_errDivideByZero 6040 .endif 6041 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6042 6043 and r0, r0, r2 @ optional op; may set condition codes 6044 and r1, r1, r3 @ result<- op, r0-r3 changed 6045 GET_INST_OPCODE(ip) @ extract opcode from rINST 6046 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6047 GOTO_OPCODE(ip) @ jump to next instruction 6048 /* 12-15 instructions */ 6049 6050 6051 6052/* ------------------------------ */ 6053 .balign 64 6054.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6055/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6056/* File: armv5te/binopWide2addr.S */ 6057 /* 6058 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6059 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6060 * This could be an ARM instruction or a function call. (If the result 6061 * comes back in a register other than r0, you can override "result".) 6062 * 6063 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6064 * vCC (r1). Useful for integer division and modulus. 6065 * 6066 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6067 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6068 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6069 * rem-double/2addr 6070 */ 6071 /* binop/2addr vA, vB */ 6072 mov r9, rINST, lsr #8 @ r9<- A+ 6073 mov r1, rINST, lsr #12 @ r1<- B 6074 and r9, r9, #15 6075 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6076 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6077 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6078 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6079 .if 0 6080 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6081 beq common_errDivideByZero 6082 .endif 6083 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6084 6085 orr r0, r0, r2 @ optional op; may set condition codes 6086 orr r1, r1, r3 @ result<- op, r0-r3 changed 6087 GET_INST_OPCODE(ip) @ extract opcode from rINST 6088 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6089 GOTO_OPCODE(ip) @ jump to next instruction 6090 /* 12-15 instructions */ 6091 6092 6093 6094/* ------------------------------ */ 6095 .balign 64 6096.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6097/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6098/* File: armv5te/binopWide2addr.S */ 6099 /* 6100 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6101 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6102 * This could be an ARM instruction or a function call. (If the result 6103 * comes back in a register other than r0, you can override "result".) 6104 * 6105 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6106 * vCC (r1). Useful for integer division and modulus. 6107 * 6108 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6109 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6110 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6111 * rem-double/2addr 6112 */ 6113 /* binop/2addr vA, vB */ 6114 mov r9, rINST, lsr #8 @ r9<- A+ 6115 mov r1, rINST, lsr #12 @ r1<- B 6116 and r9, r9, #15 6117 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6118 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6119 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6120 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6121 .if 0 6122 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6123 beq common_errDivideByZero 6124 .endif 6125 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6126 6127 eor r0, r0, r2 @ optional op; may set condition codes 6128 eor r1, r1, r3 @ result<- op, r0-r3 changed 6129 GET_INST_OPCODE(ip) @ extract opcode from rINST 6130 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6131 GOTO_OPCODE(ip) @ jump to next instruction 6132 /* 12-15 instructions */ 6133 6134 6135 6136/* ------------------------------ */ 6137 .balign 64 6138.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6139/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6140 /* 6141 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6142 * 32-bit shift distance. 6143 */ 6144 /* shl-long/2addr vA, vB */ 6145 mov r9, rINST, lsr #8 @ r9<- A+ 6146 mov r3, rINST, lsr #12 @ r3<- B 6147 and r9, r9, #15 6148 GET_VREG(r2, r3) @ r2<- vB 6149 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6150 and r2, r2, #63 @ r2<- r2 & 0x3f 6151 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6152 6153 mov r1, r1, asl r2 @ r1<- r1 << r2 6154 rsb r3, r2, #32 @ r3<- 32 - r2 6155 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6156 subs ip, r2, #32 @ ip<- r2 - 32 6157 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6158 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6159 mov r0, r0, asl r2 @ r0<- r0 << r2 6160 b .LOP_SHL_LONG_2ADDR_finish 6161 6162/* ------------------------------ */ 6163 .balign 64 6164.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6165/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6166 /* 6167 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6168 * 32-bit shift distance. 6169 */ 6170 /* shr-long/2addr vA, vB */ 6171 mov r9, rINST, lsr #8 @ r9<- A+ 6172 mov r3, rINST, lsr #12 @ r3<- B 6173 and r9, r9, #15 6174 GET_VREG(r2, r3) @ r2<- vB 6175 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6176 and r2, r2, #63 @ r2<- r2 & 0x3f 6177 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6178 6179 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6180 rsb r3, r2, #32 @ r3<- 32 - r2 6181 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6182 subs ip, r2, #32 @ ip<- r2 - 32 6183 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6184 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6185 mov r1, r1, asr r2 @ r1<- r1 >> r2 6186 b .LOP_SHR_LONG_2ADDR_finish 6187 6188/* ------------------------------ */ 6189 .balign 64 6190.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6191/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6192 /* 6193 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6194 * 32-bit shift distance. 6195 */ 6196 /* ushr-long/2addr vA, vB */ 6197 mov r9, rINST, lsr #8 @ r9<- A+ 6198 mov r3, rINST, lsr #12 @ r3<- B 6199 and r9, r9, #15 6200 GET_VREG(r2, r3) @ r2<- vB 6201 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6202 and r2, r2, #63 @ r2<- r2 & 0x3f 6203 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6204 6205 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6206 rsb r3, r2, #32 @ r3<- 32 - r2 6207 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6208 subs ip, r2, #32 @ ip<- r2 - 32 6209 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6210 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6211 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6212 b .LOP_USHR_LONG_2ADDR_finish 6213 6214/* ------------------------------ */ 6215 .balign 64 6216.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6217/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */ 6218/* File: armv5te/binop2addr.S */ 6219 /* 6220 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6221 * that specifies an instruction that performs "result = r0 op r1". 6222 * This could be an ARM instruction or a function call. (If the result 6223 * comes back in a register other than r0, you can override "result".) 6224 * 6225 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6226 * vCC (r1). Useful for integer division and modulus. 6227 * 6228 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6229 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6230 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6231 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6232 */ 6233 /* binop/2addr vA, vB */ 6234 mov r9, rINST, lsr #8 @ r9<- A+ 6235 mov r3, rINST, lsr #12 @ r3<- B 6236 and r9, r9, #15 6237 GET_VREG(r0, r9) @ r0<- vA 6238 GET_VREG(r1, r3) @ r1<- vB 6239 .if 0 6240 cmp r1, #0 @ is second operand zero? 6241 beq common_errDivideByZero 6242 .endif 6243 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6244 6245 @ optional op; may set condition codes 6246 bl __aeabi_fadd @ r0<- op, r0-r3 changed 6247 GET_INST_OPCODE(ip) @ extract opcode from rINST 6248 SET_VREG(r0, r9) @ vAA<- r0 6249 GOTO_OPCODE(ip) @ jump to next instruction 6250 /* 10-13 instructions */ 6251 6252 6253 6254/* ------------------------------ */ 6255 .balign 64 6256.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6257/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */ 6258/* File: armv5te/binop2addr.S */ 6259 /* 6260 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6261 * that specifies an instruction that performs "result = r0 op r1". 6262 * This could be an ARM instruction or a function call. (If the result 6263 * comes back in a register other than r0, you can override "result".) 6264 * 6265 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6266 * vCC (r1). Useful for integer division and modulus. 6267 * 6268 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6269 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6270 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6271 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6272 */ 6273 /* binop/2addr vA, vB */ 6274 mov r9, rINST, lsr #8 @ r9<- A+ 6275 mov r3, rINST, lsr #12 @ r3<- B 6276 and r9, r9, #15 6277 GET_VREG(r0, r9) @ r0<- vA 6278 GET_VREG(r1, r3) @ r1<- vB 6279 .if 0 6280 cmp r1, #0 @ is second operand zero? 6281 beq common_errDivideByZero 6282 .endif 6283 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6284 6285 @ optional op; may set condition codes 6286 bl __aeabi_fsub @ r0<- op, r0-r3 changed 6287 GET_INST_OPCODE(ip) @ extract opcode from rINST 6288 SET_VREG(r0, r9) @ vAA<- r0 6289 GOTO_OPCODE(ip) @ jump to next instruction 6290 /* 10-13 instructions */ 6291 6292 6293 6294/* ------------------------------ */ 6295 .balign 64 6296.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6297/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */ 6298/* File: armv5te/binop2addr.S */ 6299 /* 6300 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6301 * that specifies an instruction that performs "result = r0 op r1". 6302 * This could be an ARM instruction or a function call. (If the result 6303 * comes back in a register other than r0, you can override "result".) 6304 * 6305 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6306 * vCC (r1). Useful for integer division and modulus. 6307 * 6308 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6309 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6310 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6311 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6312 */ 6313 /* binop/2addr vA, vB */ 6314 mov r9, rINST, lsr #8 @ r9<- A+ 6315 mov r3, rINST, lsr #12 @ r3<- B 6316 and r9, r9, #15 6317 GET_VREG(r0, r9) @ r0<- vA 6318 GET_VREG(r1, r3) @ r1<- vB 6319 .if 0 6320 cmp r1, #0 @ is second operand zero? 6321 beq common_errDivideByZero 6322 .endif 6323 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6324 6325 @ optional op; may set condition codes 6326 bl __aeabi_fmul @ r0<- op, r0-r3 changed 6327 GET_INST_OPCODE(ip) @ extract opcode from rINST 6328 SET_VREG(r0, r9) @ vAA<- r0 6329 GOTO_OPCODE(ip) @ jump to next instruction 6330 /* 10-13 instructions */ 6331 6332 6333 6334/* ------------------------------ */ 6335 .balign 64 6336.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6337/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */ 6338/* File: armv5te/binop2addr.S */ 6339 /* 6340 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6341 * that specifies an instruction that performs "result = r0 op r1". 6342 * This could be an ARM instruction or a function call. (If the result 6343 * comes back in a register other than r0, you can override "result".) 6344 * 6345 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6346 * vCC (r1). Useful for integer division and modulus. 6347 * 6348 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6349 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6350 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6351 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6352 */ 6353 /* binop/2addr vA, vB */ 6354 mov r9, rINST, lsr #8 @ r9<- A+ 6355 mov r3, rINST, lsr #12 @ r3<- B 6356 and r9, r9, #15 6357 GET_VREG(r0, r9) @ r0<- vA 6358 GET_VREG(r1, r3) @ r1<- vB 6359 .if 0 6360 cmp r1, #0 @ is second operand zero? 6361 beq common_errDivideByZero 6362 .endif 6363 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6364 6365 @ optional op; may set condition codes 6366 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 6367 GET_INST_OPCODE(ip) @ extract opcode from rINST 6368 SET_VREG(r0, r9) @ vAA<- r0 6369 GOTO_OPCODE(ip) @ jump to next instruction 6370 /* 10-13 instructions */ 6371 6372 6373 6374/* ------------------------------ */ 6375 .balign 64 6376.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6377/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6378/* EABI doesn't define a float remainder function, but libm does */ 6379/* File: armv5te/binop2addr.S */ 6380 /* 6381 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6382 * that specifies an instruction that performs "result = r0 op r1". 6383 * This could be an ARM instruction or a function call. (If the result 6384 * comes back in a register other than r0, you can override "result".) 6385 * 6386 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6387 * vCC (r1). Useful for integer division and modulus. 6388 * 6389 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6390 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6391 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6392 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6393 */ 6394 /* binop/2addr vA, vB */ 6395 mov r9, rINST, lsr #8 @ r9<- A+ 6396 mov r3, rINST, lsr #12 @ r3<- B 6397 and r9, r9, #15 6398 GET_VREG(r0, r9) @ r0<- vA 6399 GET_VREG(r1, r3) @ r1<- vB 6400 .if 0 6401 cmp r1, #0 @ is second operand zero? 6402 beq common_errDivideByZero 6403 .endif 6404 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6405 6406 @ optional op; may set condition codes 6407 bl fmodf @ r0<- op, r0-r3 changed 6408 GET_INST_OPCODE(ip) @ extract opcode from rINST 6409 SET_VREG(r0, r9) @ vAA<- r0 6410 GOTO_OPCODE(ip) @ jump to next instruction 6411 /* 10-13 instructions */ 6412 6413 6414 6415/* ------------------------------ */ 6416 .balign 64 6417.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6418/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */ 6419/* File: armv5te/binopWide2addr.S */ 6420 /* 6421 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6422 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6423 * This could be an ARM instruction or a function call. (If the result 6424 * comes back in a register other than r0, you can override "result".) 6425 * 6426 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6427 * vCC (r1). Useful for integer division and modulus. 6428 * 6429 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6430 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6431 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6432 * rem-double/2addr 6433 */ 6434 /* binop/2addr vA, vB */ 6435 mov r9, rINST, lsr #8 @ r9<- A+ 6436 mov r1, rINST, lsr #12 @ r1<- B 6437 and r9, r9, #15 6438 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6439 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6440 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6441 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6442 .if 0 6443 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6444 beq common_errDivideByZero 6445 .endif 6446 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6447 6448 @ optional op; may set condition codes 6449 bl __aeabi_dadd @ result<- op, r0-r3 changed 6450 GET_INST_OPCODE(ip) @ extract opcode from rINST 6451 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6452 GOTO_OPCODE(ip) @ jump to next instruction 6453 /* 12-15 instructions */ 6454 6455 6456 6457/* ------------------------------ */ 6458 .balign 64 6459.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6460/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */ 6461/* File: armv5te/binopWide2addr.S */ 6462 /* 6463 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6464 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6465 * This could be an ARM instruction or a function call. (If the result 6466 * comes back in a register other than r0, you can override "result".) 6467 * 6468 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6469 * vCC (r1). Useful for integer division and modulus. 6470 * 6471 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6472 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6473 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6474 * rem-double/2addr 6475 */ 6476 /* binop/2addr vA, vB */ 6477 mov r9, rINST, lsr #8 @ r9<- A+ 6478 mov r1, rINST, lsr #12 @ r1<- B 6479 and r9, r9, #15 6480 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6481 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6482 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6483 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6484 .if 0 6485 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6486 beq common_errDivideByZero 6487 .endif 6488 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6489 6490 @ optional op; may set condition codes 6491 bl __aeabi_dsub @ result<- op, r0-r3 changed 6492 GET_INST_OPCODE(ip) @ extract opcode from rINST 6493 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6494 GOTO_OPCODE(ip) @ jump to next instruction 6495 /* 12-15 instructions */ 6496 6497 6498 6499/* ------------------------------ */ 6500 .balign 64 6501.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6502/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */ 6503/* File: armv5te/binopWide2addr.S */ 6504 /* 6505 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6506 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6507 * This could be an ARM instruction or a function call. (If the result 6508 * comes back in a register other than r0, you can override "result".) 6509 * 6510 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6511 * vCC (r1). Useful for integer division and modulus. 6512 * 6513 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6514 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6515 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6516 * rem-double/2addr 6517 */ 6518 /* binop/2addr vA, vB */ 6519 mov r9, rINST, lsr #8 @ r9<- A+ 6520 mov r1, rINST, lsr #12 @ r1<- B 6521 and r9, r9, #15 6522 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6523 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6524 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6525 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6526 .if 0 6527 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6528 beq common_errDivideByZero 6529 .endif 6530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6531 6532 @ optional op; may set condition codes 6533 bl __aeabi_dmul @ result<- op, r0-r3 changed 6534 GET_INST_OPCODE(ip) @ extract opcode from rINST 6535 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6536 GOTO_OPCODE(ip) @ jump to next instruction 6537 /* 12-15 instructions */ 6538 6539 6540 6541/* ------------------------------ */ 6542 .balign 64 6543.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6544/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */ 6545/* File: armv5te/binopWide2addr.S */ 6546 /* 6547 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6548 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6549 * This could be an ARM instruction or a function call. (If the result 6550 * comes back in a register other than r0, you can override "result".) 6551 * 6552 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6553 * vCC (r1). Useful for integer division and modulus. 6554 * 6555 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6556 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6557 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6558 * rem-double/2addr 6559 */ 6560 /* binop/2addr vA, vB */ 6561 mov r9, rINST, lsr #8 @ r9<- A+ 6562 mov r1, rINST, lsr #12 @ r1<- B 6563 and r9, r9, #15 6564 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6565 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6566 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6567 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6568 .if 0 6569 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6570 beq common_errDivideByZero 6571 .endif 6572 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6573 6574 @ optional op; may set condition codes 6575 bl __aeabi_ddiv @ result<- op, r0-r3 changed 6576 GET_INST_OPCODE(ip) @ extract opcode from rINST 6577 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6578 GOTO_OPCODE(ip) @ jump to next instruction 6579 /* 12-15 instructions */ 6580 6581 6582 6583/* ------------------------------ */ 6584 .balign 64 6585.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6586/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6587/* EABI doesn't define a double remainder function, but libm does */ 6588/* File: armv5te/binopWide2addr.S */ 6589 /* 6590 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6591 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6592 * This could be an ARM instruction or a function call. (If the result 6593 * comes back in a register other than r0, you can override "result".) 6594 * 6595 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6596 * vCC (r1). Useful for integer division and modulus. 6597 * 6598 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6599 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6600 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6601 * rem-double/2addr 6602 */ 6603 /* binop/2addr vA, vB */ 6604 mov r9, rINST, lsr #8 @ r9<- A+ 6605 mov r1, rINST, lsr #12 @ r1<- B 6606 and r9, r9, #15 6607 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6608 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6609 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6610 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6611 .if 0 6612 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6613 beq common_errDivideByZero 6614 .endif 6615 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6616 6617 @ optional op; may set condition codes 6618 bl fmod @ result<- op, r0-r3 changed 6619 GET_INST_OPCODE(ip) @ extract opcode from rINST 6620 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6621 GOTO_OPCODE(ip) @ jump to next instruction 6622 /* 12-15 instructions */ 6623 6624 6625 6626/* ------------------------------ */ 6627 .balign 64 6628.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6629/* File: armv5te/OP_ADD_INT_LIT16.S */ 6630/* File: armv5te/binopLit16.S */ 6631 /* 6632 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6633 * that specifies an instruction that performs "result = r0 op r1". 6634 * This could be an ARM instruction or a function call. (If the result 6635 * comes back in a register other than r0, you can override "result".) 6636 * 6637 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6638 * vCC (r1). Useful for integer division and modulus. 6639 * 6640 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6641 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6642 */ 6643 /* binop/lit16 vA, vB, #+CCCC */ 6644 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6645 mov r2, rINST, lsr #12 @ r2<- B 6646 mov r9, rINST, lsr #8 @ r9<- A+ 6647 GET_VREG(r0, r2) @ r0<- vB 6648 and r9, r9, #15 6649 .if 0 6650 cmp r1, #0 @ is second operand zero? 6651 beq common_errDivideByZero 6652 .endif 6653 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6654 6655 add r0, r0, r1 @ r0<- op, r0-r3 changed 6656 GET_INST_OPCODE(ip) @ extract opcode from rINST 6657 SET_VREG(r0, r9) @ vAA<- r0 6658 GOTO_OPCODE(ip) @ jump to next instruction 6659 /* 10-13 instructions */ 6660 6661 6662 6663/* ------------------------------ */ 6664 .balign 64 6665.L_OP_RSUB_INT: /* 0xd1 */ 6666/* File: armv5te/OP_RSUB_INT.S */ 6667/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6668/* File: armv5te/binopLit16.S */ 6669 /* 6670 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6671 * that specifies an instruction that performs "result = r0 op r1". 6672 * This could be an ARM instruction or a function call. (If the result 6673 * comes back in a register other than r0, you can override "result".) 6674 * 6675 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6676 * vCC (r1). Useful for integer division and modulus. 6677 * 6678 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6679 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6680 */ 6681 /* binop/lit16 vA, vB, #+CCCC */ 6682 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6683 mov r2, rINST, lsr #12 @ r2<- B 6684 mov r9, rINST, lsr #8 @ r9<- A+ 6685 GET_VREG(r0, r2) @ r0<- vB 6686 and r9, r9, #15 6687 .if 0 6688 cmp r1, #0 @ is second operand zero? 6689 beq common_errDivideByZero 6690 .endif 6691 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6692 6693 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6694 GET_INST_OPCODE(ip) @ extract opcode from rINST 6695 SET_VREG(r0, r9) @ vAA<- r0 6696 GOTO_OPCODE(ip) @ jump to next instruction 6697 /* 10-13 instructions */ 6698 6699 6700 6701/* ------------------------------ */ 6702 .balign 64 6703.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6704/* File: armv5te/OP_MUL_INT_LIT16.S */ 6705/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6706/* File: armv5te/binopLit16.S */ 6707 /* 6708 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6709 * that specifies an instruction that performs "result = r0 op r1". 6710 * This could be an ARM instruction or a function call. (If the result 6711 * comes back in a register other than r0, you can override "result".) 6712 * 6713 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6714 * vCC (r1). Useful for integer division and modulus. 6715 * 6716 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6717 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6718 */ 6719 /* binop/lit16 vA, vB, #+CCCC */ 6720 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6721 mov r2, rINST, lsr #12 @ r2<- B 6722 mov r9, rINST, lsr #8 @ r9<- A+ 6723 GET_VREG(r0, r2) @ r0<- vB 6724 and r9, r9, #15 6725 .if 0 6726 cmp r1, #0 @ is second operand zero? 6727 beq common_errDivideByZero 6728 .endif 6729 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6730 6731 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6732 GET_INST_OPCODE(ip) @ extract opcode from rINST 6733 SET_VREG(r0, r9) @ vAA<- r0 6734 GOTO_OPCODE(ip) @ jump to next instruction 6735 /* 10-13 instructions */ 6736 6737 6738 6739/* ------------------------------ */ 6740 .balign 64 6741.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6742/* File: armv5te/OP_DIV_INT_LIT16.S */ 6743/* File: armv5te/binopLit16.S */ 6744 /* 6745 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6746 * that specifies an instruction that performs "result = r0 op r1". 6747 * This could be an ARM instruction or a function call. (If the result 6748 * comes back in a register other than r0, you can override "result".) 6749 * 6750 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6751 * vCC (r1). Useful for integer division and modulus. 6752 * 6753 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6754 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6755 */ 6756 /* binop/lit16 vA, vB, #+CCCC */ 6757 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6758 mov r2, rINST, lsr #12 @ r2<- B 6759 mov r9, rINST, lsr #8 @ r9<- A+ 6760 GET_VREG(r0, r2) @ r0<- vB 6761 and r9, r9, #15 6762 .if 1 6763 cmp r1, #0 @ is second operand zero? 6764 beq common_errDivideByZero 6765 .endif 6766 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6767 6768 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6769 GET_INST_OPCODE(ip) @ extract opcode from rINST 6770 SET_VREG(r0, r9) @ vAA<- r0 6771 GOTO_OPCODE(ip) @ jump to next instruction 6772 /* 10-13 instructions */ 6773 6774 6775 6776/* ------------------------------ */ 6777 .balign 64 6778.L_OP_REM_INT_LIT16: /* 0xd4 */ 6779/* File: armv5te/OP_REM_INT_LIT16.S */ 6780/* idivmod returns quotient in r0 and remainder in r1 */ 6781/* File: armv5te/binopLit16.S */ 6782 /* 6783 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6784 * that specifies an instruction that performs "result = r0 op r1". 6785 * This could be an ARM instruction or a function call. (If the result 6786 * comes back in a register other than r0, you can override "result".) 6787 * 6788 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6789 * vCC (r1). Useful for integer division and modulus. 6790 * 6791 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6792 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6793 */ 6794 /* binop/lit16 vA, vB, #+CCCC */ 6795 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6796 mov r2, rINST, lsr #12 @ r2<- B 6797 mov r9, rINST, lsr #8 @ r9<- A+ 6798 GET_VREG(r0, r2) @ r0<- vB 6799 and r9, r9, #15 6800 .if 1 6801 cmp r1, #0 @ is second operand zero? 6802 beq common_errDivideByZero 6803 .endif 6804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6805 6806 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6807 GET_INST_OPCODE(ip) @ extract opcode from rINST 6808 SET_VREG(r1, r9) @ vAA<- r1 6809 GOTO_OPCODE(ip) @ jump to next instruction 6810 /* 10-13 instructions */ 6811 6812 6813 6814/* ------------------------------ */ 6815 .balign 64 6816.L_OP_AND_INT_LIT16: /* 0xd5 */ 6817/* File: armv5te/OP_AND_INT_LIT16.S */ 6818/* File: armv5te/binopLit16.S */ 6819 /* 6820 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6821 * that specifies an instruction that performs "result = r0 op r1". 6822 * This could be an ARM instruction or a function call. (If the result 6823 * comes back in a register other than r0, you can override "result".) 6824 * 6825 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6826 * vCC (r1). Useful for integer division and modulus. 6827 * 6828 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6829 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6830 */ 6831 /* binop/lit16 vA, vB, #+CCCC */ 6832 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6833 mov r2, rINST, lsr #12 @ r2<- B 6834 mov r9, rINST, lsr #8 @ r9<- A+ 6835 GET_VREG(r0, r2) @ r0<- vB 6836 and r9, r9, #15 6837 .if 0 6838 cmp r1, #0 @ is second operand zero? 6839 beq common_errDivideByZero 6840 .endif 6841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6842 6843 and r0, r0, r1 @ r0<- op, r0-r3 changed 6844 GET_INST_OPCODE(ip) @ extract opcode from rINST 6845 SET_VREG(r0, r9) @ vAA<- r0 6846 GOTO_OPCODE(ip) @ jump to next instruction 6847 /* 10-13 instructions */ 6848 6849 6850 6851/* ------------------------------ */ 6852 .balign 64 6853.L_OP_OR_INT_LIT16: /* 0xd6 */ 6854/* File: armv5te/OP_OR_INT_LIT16.S */ 6855/* File: armv5te/binopLit16.S */ 6856 /* 6857 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6858 * that specifies an instruction that performs "result = r0 op r1". 6859 * This could be an ARM instruction or a function call. (If the result 6860 * comes back in a register other than r0, you can override "result".) 6861 * 6862 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6863 * vCC (r1). Useful for integer division and modulus. 6864 * 6865 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6866 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6867 */ 6868 /* binop/lit16 vA, vB, #+CCCC */ 6869 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6870 mov r2, rINST, lsr #12 @ r2<- B 6871 mov r9, rINST, lsr #8 @ r9<- A+ 6872 GET_VREG(r0, r2) @ r0<- vB 6873 and r9, r9, #15 6874 .if 0 6875 cmp r1, #0 @ is second operand zero? 6876 beq common_errDivideByZero 6877 .endif 6878 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6879 6880 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6881 GET_INST_OPCODE(ip) @ extract opcode from rINST 6882 SET_VREG(r0, r9) @ vAA<- r0 6883 GOTO_OPCODE(ip) @ jump to next instruction 6884 /* 10-13 instructions */ 6885 6886 6887 6888/* ------------------------------ */ 6889 .balign 64 6890.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6891/* File: armv5te/OP_XOR_INT_LIT16.S */ 6892/* File: armv5te/binopLit16.S */ 6893 /* 6894 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6895 * that specifies an instruction that performs "result = r0 op r1". 6896 * This could be an ARM instruction or a function call. (If the result 6897 * comes back in a register other than r0, you can override "result".) 6898 * 6899 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6900 * vCC (r1). Useful for integer division and modulus. 6901 * 6902 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6903 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6904 */ 6905 /* binop/lit16 vA, vB, #+CCCC */ 6906 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6907 mov r2, rINST, lsr #12 @ r2<- B 6908 mov r9, rINST, lsr #8 @ r9<- A+ 6909 GET_VREG(r0, r2) @ r0<- vB 6910 and r9, r9, #15 6911 .if 0 6912 cmp r1, #0 @ is second operand zero? 6913 beq common_errDivideByZero 6914 .endif 6915 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6916 6917 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6918 GET_INST_OPCODE(ip) @ extract opcode from rINST 6919 SET_VREG(r0, r9) @ vAA<- r0 6920 GOTO_OPCODE(ip) @ jump to next instruction 6921 /* 10-13 instructions */ 6922 6923 6924 6925/* ------------------------------ */ 6926 .balign 64 6927.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6928/* File: armv5te/OP_ADD_INT_LIT8.S */ 6929/* File: armv5te/binopLit8.S */ 6930 /* 6931 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6932 * that specifies an instruction that performs "result = r0 op r1". 6933 * This could be an ARM instruction or a function call. (If the result 6934 * comes back in a register other than r0, you can override "result".) 6935 * 6936 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6937 * vCC (r1). Useful for integer division and modulus. 6938 * 6939 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6940 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6941 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6942 */ 6943 /* binop/lit8 vAA, vBB, #+CC */ 6944 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6945 mov r9, rINST, lsr #8 @ r9<- AA 6946 and r2, r3, #255 @ r2<- BB 6947 GET_VREG(r0, r2) @ r0<- vBB 6948 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6949 .if 0 6950 @cmp r1, #0 @ is second operand zero? 6951 beq common_errDivideByZero 6952 .endif 6953 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6954 6955 @ optional op; may set condition codes 6956 add r0, r0, r1 @ r0<- op, r0-r3 changed 6957 GET_INST_OPCODE(ip) @ extract opcode from rINST 6958 SET_VREG(r0, r9) @ vAA<- r0 6959 GOTO_OPCODE(ip) @ jump to next instruction 6960 /* 10-12 instructions */ 6961 6962 6963 6964/* ------------------------------ */ 6965 .balign 64 6966.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6967/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6968/* File: armv5te/binopLit8.S */ 6969 /* 6970 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6971 * that specifies an instruction that performs "result = r0 op r1". 6972 * This could be an ARM instruction or a function call. (If the result 6973 * comes back in a register other than r0, you can override "result".) 6974 * 6975 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6976 * vCC (r1). Useful for integer division and modulus. 6977 * 6978 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6979 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6980 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6981 */ 6982 /* binop/lit8 vAA, vBB, #+CC */ 6983 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6984 mov r9, rINST, lsr #8 @ r9<- AA 6985 and r2, r3, #255 @ r2<- BB 6986 GET_VREG(r0, r2) @ r0<- vBB 6987 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6988 .if 0 6989 @cmp r1, #0 @ is second operand zero? 6990 beq common_errDivideByZero 6991 .endif 6992 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6993 6994 @ optional op; may set condition codes 6995 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6996 GET_INST_OPCODE(ip) @ extract opcode from rINST 6997 SET_VREG(r0, r9) @ vAA<- r0 6998 GOTO_OPCODE(ip) @ jump to next instruction 6999 /* 10-12 instructions */ 7000 7001 7002 7003/* ------------------------------ */ 7004 .balign 64 7005.L_OP_MUL_INT_LIT8: /* 0xda */ 7006/* File: armv5te/OP_MUL_INT_LIT8.S */ 7007/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 7008/* File: armv5te/binopLit8.S */ 7009 /* 7010 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7011 * that specifies an instruction that performs "result = r0 op r1". 7012 * This could be an ARM instruction or a function call. (If the result 7013 * comes back in a register other than r0, you can override "result".) 7014 * 7015 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7016 * vCC (r1). Useful for integer division and modulus. 7017 * 7018 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7019 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7020 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7021 */ 7022 /* binop/lit8 vAA, vBB, #+CC */ 7023 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7024 mov r9, rINST, lsr #8 @ r9<- AA 7025 and r2, r3, #255 @ r2<- BB 7026 GET_VREG(r0, r2) @ r0<- vBB 7027 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7028 .if 0 7029 @cmp r1, #0 @ is second operand zero? 7030 beq common_errDivideByZero 7031 .endif 7032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7033 7034 @ optional op; may set condition codes 7035 mul r0, r1, r0 @ r0<- op, r0-r3 changed 7036 GET_INST_OPCODE(ip) @ extract opcode from rINST 7037 SET_VREG(r0, r9) @ vAA<- r0 7038 GOTO_OPCODE(ip) @ jump to next instruction 7039 /* 10-12 instructions */ 7040 7041 7042 7043/* ------------------------------ */ 7044 .balign 64 7045.L_OP_DIV_INT_LIT8: /* 0xdb */ 7046/* File: armv5te/OP_DIV_INT_LIT8.S */ 7047/* File: armv5te/binopLit8.S */ 7048 /* 7049 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7050 * that specifies an instruction that performs "result = r0 op r1". 7051 * This could be an ARM instruction or a function call. (If the result 7052 * comes back in a register other than r0, you can override "result".) 7053 * 7054 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7055 * vCC (r1). Useful for integer division and modulus. 7056 * 7057 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7058 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7059 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7060 */ 7061 /* binop/lit8 vAA, vBB, #+CC */ 7062 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7063 mov r9, rINST, lsr #8 @ r9<- AA 7064 and r2, r3, #255 @ r2<- BB 7065 GET_VREG(r0, r2) @ r0<- vBB 7066 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7067 .if 1 7068 @cmp r1, #0 @ is second operand zero? 7069 beq common_errDivideByZero 7070 .endif 7071 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7072 7073 @ optional op; may set condition codes 7074 bl __aeabi_idiv @ r0<- op, r0-r3 changed 7075 GET_INST_OPCODE(ip) @ extract opcode from rINST 7076 SET_VREG(r0, r9) @ vAA<- r0 7077 GOTO_OPCODE(ip) @ jump to next instruction 7078 /* 10-12 instructions */ 7079 7080 7081 7082/* ------------------------------ */ 7083 .balign 64 7084.L_OP_REM_INT_LIT8: /* 0xdc */ 7085/* File: armv5te/OP_REM_INT_LIT8.S */ 7086/* idivmod returns quotient in r0 and remainder in r1 */ 7087/* File: armv5te/binopLit8.S */ 7088 /* 7089 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7090 * that specifies an instruction that performs "result = r0 op r1". 7091 * This could be an ARM instruction or a function call. (If the result 7092 * comes back in a register other than r0, you can override "result".) 7093 * 7094 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7095 * vCC (r1). Useful for integer division and modulus. 7096 * 7097 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7098 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7099 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7100 */ 7101 /* binop/lit8 vAA, vBB, #+CC */ 7102 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7103 mov r9, rINST, lsr #8 @ r9<- AA 7104 and r2, r3, #255 @ r2<- BB 7105 GET_VREG(r0, r2) @ r0<- vBB 7106 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7107 .if 1 7108 @cmp r1, #0 @ is second operand zero? 7109 beq common_errDivideByZero 7110 .endif 7111 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7112 7113 @ optional op; may set condition codes 7114 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 7115 GET_INST_OPCODE(ip) @ extract opcode from rINST 7116 SET_VREG(r1, r9) @ vAA<- r1 7117 GOTO_OPCODE(ip) @ jump to next instruction 7118 /* 10-12 instructions */ 7119 7120 7121 7122/* ------------------------------ */ 7123 .balign 64 7124.L_OP_AND_INT_LIT8: /* 0xdd */ 7125/* File: armv5te/OP_AND_INT_LIT8.S */ 7126/* File: armv5te/binopLit8.S */ 7127 /* 7128 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7129 * that specifies an instruction that performs "result = r0 op r1". 7130 * This could be an ARM instruction or a function call. (If the result 7131 * comes back in a register other than r0, you can override "result".) 7132 * 7133 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7134 * vCC (r1). Useful for integer division and modulus. 7135 * 7136 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7137 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7138 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7139 */ 7140 /* binop/lit8 vAA, vBB, #+CC */ 7141 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7142 mov r9, rINST, lsr #8 @ r9<- AA 7143 and r2, r3, #255 @ r2<- BB 7144 GET_VREG(r0, r2) @ r0<- vBB 7145 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7146 .if 0 7147 @cmp r1, #0 @ is second operand zero? 7148 beq common_errDivideByZero 7149 .endif 7150 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7151 7152 @ optional op; may set condition codes 7153 and r0, r0, r1 @ r0<- op, r0-r3 changed 7154 GET_INST_OPCODE(ip) @ extract opcode from rINST 7155 SET_VREG(r0, r9) @ vAA<- r0 7156 GOTO_OPCODE(ip) @ jump to next instruction 7157 /* 10-12 instructions */ 7158 7159 7160 7161/* ------------------------------ */ 7162 .balign 64 7163.L_OP_OR_INT_LIT8: /* 0xde */ 7164/* File: armv5te/OP_OR_INT_LIT8.S */ 7165/* File: armv5te/binopLit8.S */ 7166 /* 7167 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7168 * that specifies an instruction that performs "result = r0 op r1". 7169 * This could be an ARM instruction or a function call. (If the result 7170 * comes back in a register other than r0, you can override "result".) 7171 * 7172 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7173 * vCC (r1). Useful for integer division and modulus. 7174 * 7175 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7176 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7177 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7178 */ 7179 /* binop/lit8 vAA, vBB, #+CC */ 7180 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7181 mov r9, rINST, lsr #8 @ r9<- AA 7182 and r2, r3, #255 @ r2<- BB 7183 GET_VREG(r0, r2) @ r0<- vBB 7184 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7185 .if 0 7186 @cmp r1, #0 @ is second operand zero? 7187 beq common_errDivideByZero 7188 .endif 7189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7190 7191 @ optional op; may set condition codes 7192 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7193 GET_INST_OPCODE(ip) @ extract opcode from rINST 7194 SET_VREG(r0, r9) @ vAA<- r0 7195 GOTO_OPCODE(ip) @ jump to next instruction 7196 /* 10-12 instructions */ 7197 7198 7199 7200/* ------------------------------ */ 7201 .balign 64 7202.L_OP_XOR_INT_LIT8: /* 0xdf */ 7203/* File: armv5te/OP_XOR_INT_LIT8.S */ 7204/* File: armv5te/binopLit8.S */ 7205 /* 7206 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7207 * that specifies an instruction that performs "result = r0 op r1". 7208 * This could be an ARM instruction or a function call. (If the result 7209 * comes back in a register other than r0, you can override "result".) 7210 * 7211 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7212 * vCC (r1). Useful for integer division and modulus. 7213 * 7214 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7215 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7216 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7217 */ 7218 /* binop/lit8 vAA, vBB, #+CC */ 7219 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7220 mov r9, rINST, lsr #8 @ r9<- AA 7221 and r2, r3, #255 @ r2<- BB 7222 GET_VREG(r0, r2) @ r0<- vBB 7223 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7224 .if 0 7225 @cmp r1, #0 @ is second operand zero? 7226 beq common_errDivideByZero 7227 .endif 7228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7229 7230 @ optional op; may set condition codes 7231 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7232 GET_INST_OPCODE(ip) @ extract opcode from rINST 7233 SET_VREG(r0, r9) @ vAA<- r0 7234 GOTO_OPCODE(ip) @ jump to next instruction 7235 /* 10-12 instructions */ 7236 7237 7238 7239/* ------------------------------ */ 7240 .balign 64 7241.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7242/* File: armv5te/OP_SHL_INT_LIT8.S */ 7243/* File: armv5te/binopLit8.S */ 7244 /* 7245 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7246 * that specifies an instruction that performs "result = r0 op r1". 7247 * This could be an ARM instruction or a function call. (If the result 7248 * comes back in a register other than r0, you can override "result".) 7249 * 7250 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7251 * vCC (r1). Useful for integer division and modulus. 7252 * 7253 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7254 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7255 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7256 */ 7257 /* binop/lit8 vAA, vBB, #+CC */ 7258 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7259 mov r9, rINST, lsr #8 @ r9<- AA 7260 and r2, r3, #255 @ r2<- BB 7261 GET_VREG(r0, r2) @ r0<- vBB 7262 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7263 .if 0 7264 @cmp r1, #0 @ is second operand zero? 7265 beq common_errDivideByZero 7266 .endif 7267 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7268 7269 and r1, r1, #31 @ optional op; may set condition codes 7270 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7271 GET_INST_OPCODE(ip) @ extract opcode from rINST 7272 SET_VREG(r0, r9) @ vAA<- r0 7273 GOTO_OPCODE(ip) @ jump to next instruction 7274 /* 10-12 instructions */ 7275 7276 7277 7278/* ------------------------------ */ 7279 .balign 64 7280.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7281/* File: armv5te/OP_SHR_INT_LIT8.S */ 7282/* File: armv5te/binopLit8.S */ 7283 /* 7284 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7285 * that specifies an instruction that performs "result = r0 op r1". 7286 * This could be an ARM instruction or a function call. (If the result 7287 * comes back in a register other than r0, you can override "result".) 7288 * 7289 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7290 * vCC (r1). Useful for integer division and modulus. 7291 * 7292 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7293 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7294 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7295 */ 7296 /* binop/lit8 vAA, vBB, #+CC */ 7297 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7298 mov r9, rINST, lsr #8 @ r9<- AA 7299 and r2, r3, #255 @ r2<- BB 7300 GET_VREG(r0, r2) @ r0<- vBB 7301 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7302 .if 0 7303 @cmp r1, #0 @ is second operand zero? 7304 beq common_errDivideByZero 7305 .endif 7306 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7307 7308 and r1, r1, #31 @ optional op; may set condition codes 7309 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7310 GET_INST_OPCODE(ip) @ extract opcode from rINST 7311 SET_VREG(r0, r9) @ vAA<- r0 7312 GOTO_OPCODE(ip) @ jump to next instruction 7313 /* 10-12 instructions */ 7314 7315 7316 7317/* ------------------------------ */ 7318 .balign 64 7319.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7320/* File: armv5te/OP_USHR_INT_LIT8.S */ 7321/* File: armv5te/binopLit8.S */ 7322 /* 7323 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7324 * that specifies an instruction that performs "result = r0 op r1". 7325 * This could be an ARM instruction or a function call. (If the result 7326 * comes back in a register other than r0, you can override "result".) 7327 * 7328 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7329 * vCC (r1). Useful for integer division and modulus. 7330 * 7331 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7332 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7333 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7334 */ 7335 /* binop/lit8 vAA, vBB, #+CC */ 7336 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7337 mov r9, rINST, lsr #8 @ r9<- AA 7338 and r2, r3, #255 @ r2<- BB 7339 GET_VREG(r0, r2) @ r0<- vBB 7340 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7341 .if 0 7342 @cmp r1, #0 @ is second operand zero? 7343 beq common_errDivideByZero 7344 .endif 7345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7346 7347 and r1, r1, #31 @ optional op; may set condition codes 7348 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7349 GET_INST_OPCODE(ip) @ extract opcode from rINST 7350 SET_VREG(r0, r9) @ vAA<- r0 7351 GOTO_OPCODE(ip) @ jump to next instruction 7352 /* 10-12 instructions */ 7353 7354 7355 7356/* ------------------------------ */ 7357 .balign 64 7358.L_OP_UNUSED_E3: /* 0xe3 */ 7359/* File: armv5te/OP_UNUSED_E3.S */ 7360/* File: armv5te/unused.S */ 7361 bl common_abort 7362 7363 7364 7365/* ------------------------------ */ 7366 .balign 64 7367.L_OP_UNUSED_E4: /* 0xe4 */ 7368/* File: armv5te/OP_UNUSED_E4.S */ 7369/* File: armv5te/unused.S */ 7370 bl common_abort 7371 7372 7373 7374/* ------------------------------ */ 7375 .balign 64 7376.L_OP_UNUSED_E5: /* 0xe5 */ 7377/* File: armv5te/OP_UNUSED_E5.S */ 7378/* File: armv5te/unused.S */ 7379 bl common_abort 7380 7381 7382 7383/* ------------------------------ */ 7384 .balign 64 7385.L_OP_UNUSED_E6: /* 0xe6 */ 7386/* File: armv5te/OP_UNUSED_E6.S */ 7387/* File: armv5te/unused.S */ 7388 bl common_abort 7389 7390 7391 7392/* ------------------------------ */ 7393 .balign 64 7394.L_OP_UNUSED_E7: /* 0xe7 */ 7395/* File: armv5te/OP_UNUSED_E7.S */ 7396/* File: armv5te/unused.S */ 7397 bl common_abort 7398 7399 7400 7401/* ------------------------------ */ 7402 .balign 64 7403.L_OP_UNUSED_E8: /* 0xe8 */ 7404/* File: armv5te/OP_UNUSED_E8.S */ 7405/* File: armv5te/unused.S */ 7406 bl common_abort 7407 7408 7409 7410/* ------------------------------ */ 7411 .balign 64 7412.L_OP_UNUSED_E9: /* 0xe9 */ 7413/* File: armv5te/OP_UNUSED_E9.S */ 7414/* File: armv5te/unused.S */ 7415 bl common_abort 7416 7417 7418 7419/* ------------------------------ */ 7420 .balign 64 7421.L_OP_UNUSED_EA: /* 0xea */ 7422/* File: armv5te/OP_UNUSED_EA.S */ 7423/* File: armv5te/unused.S */ 7424 bl common_abort 7425 7426 7427 7428/* ------------------------------ */ 7429 .balign 64 7430.L_OP_UNUSED_EB: /* 0xeb */ 7431/* File: armv5te/OP_UNUSED_EB.S */ 7432/* File: armv5te/unused.S */ 7433 bl common_abort 7434 7435 7436 7437/* ------------------------------ */ 7438 .balign 64 7439.L_OP_UNUSED_EC: /* 0xec */ 7440/* File: armv5te/OP_UNUSED_EC.S */ 7441/* File: armv5te/unused.S */ 7442 bl common_abort 7443 7444 7445 7446/* ------------------------------ */ 7447 .balign 64 7448.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7449/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7450 /* 7451 * Handle a throw-verification-error instruction. This throws an 7452 * exception for an error discovered during verification. The 7453 * exception is indicated by AA, with some detail provided by BBBB. 7454 */ 7455 /* op AA, ref@BBBB */ 7456 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- glue->methodClassDex 7457 FETCH(r2, 1) @ r2<- BBBB 7458 mov r1, rINST, lsr #8 @ r1<- AA 7459 bl dvmThrowVerificationError @ always throws 7460 b common_exceptionThrown @ handle exception 7461 7462 7463/* ------------------------------ */ 7464 .balign 64 7465.L_OP_EXECUTE_INLINE: /* 0xee */ 7466/* File: armv5te/OP_EXECUTE_INLINE.S */ 7467 /* 7468 * Execute a "native inline" instruction. 7469 * 7470 * We need to call: 7471 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7472 * 7473 * The first four args are in r0-r3, but the last two must be pushed 7474 * onto the stack. 7475 */ 7476 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7477 FETCH(r10, 1) @ r10<- BBBB 7478 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7479 EXPORT_PC() @ can throw 7480 sub sp, sp, #8 @ make room for arg(s) 7481 mov r0, rINST, lsr #12 @ r0<- B 7482 str r1, [sp] @ push &glue->retval 7483 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7484 add sp, sp, #8 @ pop stack 7485 cmp r0, #0 @ test boolean result of inline 7486 beq common_exceptionThrown @ returned false, handle exception 7487 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7488 GET_INST_OPCODE(ip) @ extract opcode from rINST 7489 GOTO_OPCODE(ip) @ jump to next instruction 7490 7491/* ------------------------------ */ 7492 .balign 64 7493.L_OP_UNUSED_EF: /* 0xef */ 7494/* File: armv5te/OP_UNUSED_EF.S */ 7495/* File: armv5te/unused.S */ 7496 bl common_abort 7497 7498 7499 7500/* ------------------------------ */ 7501 .balign 64 7502.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7503/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7504 /* 7505 * invoke-direct-empty is a no-op in a "standard" interpreter. 7506 */ 7507 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7508 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7509 GOTO_OPCODE(ip) @ execute it 7510 7511/* ------------------------------ */ 7512 .balign 64 7513.L_OP_UNUSED_F1: /* 0xf1 */ 7514/* File: armv5te/OP_UNUSED_F1.S */ 7515/* File: armv5te/unused.S */ 7516 bl common_abort 7517 7518 7519 7520/* ------------------------------ */ 7521 .balign 64 7522.L_OP_IGET_QUICK: /* 0xf2 */ 7523/* File: armv5te/OP_IGET_QUICK.S */ 7524 /* For: iget-quick, iget-object-quick */ 7525 /* op vA, vB, offset@CCCC */ 7526 mov r2, rINST, lsr #12 @ r2<- B 7527 GET_VREG(r3, r2) @ r3<- object we're operating on 7528 FETCH(r1, 1) @ r1<- field byte offset 7529 cmp r3, #0 @ check object for null 7530 mov r2, rINST, lsr #8 @ r2<- A(+) 7531 beq common_errNullObject @ object was null 7532 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7534 and r2, r2, #15 7535 GET_INST_OPCODE(ip) @ extract opcode from rINST 7536 SET_VREG(r0, r2) @ fp[A]<- r0 7537 GOTO_OPCODE(ip) @ jump to next instruction 7538 7539 7540/* ------------------------------ */ 7541 .balign 64 7542.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7543/* File: armv4t/OP_IGET_WIDE_QUICK.S */ 7544 /* iget-wide-quick vA, vB, offset@CCCC */ 7545 mov r2, rINST, lsr #12 @ r2<- B 7546 GET_VREG(r3, r2) @ r3<- object we're operating on 7547 FETCH(r1, 1) @ r1<- field byte offset 7548 cmp r3, #0 @ check object for null 7549 mov r2, rINST, lsr #8 @ r2<- A(+) 7550 beq common_errNullObject @ object was null 7551 add r9, r3, r1 @ r9<- object + offset 7552 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64 bits, aligned) 7553 and r2, r2, #15 @ r2<- A 7554 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7555 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7556 GET_INST_OPCODE(ip) @ extract opcode from rINST 7557 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7558 GOTO_OPCODE(ip) @ jump to next instruction 7559 7560 7561/* ------------------------------ */ 7562 .balign 64 7563.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7564/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7565/* File: armv5te/OP_IGET_QUICK.S */ 7566 /* For: iget-quick, iget-object-quick */ 7567 /* op vA, vB, offset@CCCC */ 7568 mov r2, rINST, lsr #12 @ r2<- B 7569 GET_VREG(r3, r2) @ r3<- object we're operating on 7570 FETCH(r1, 1) @ r1<- field byte offset 7571 cmp r3, #0 @ check object for null 7572 mov r2, rINST, lsr #8 @ r2<- A(+) 7573 beq common_errNullObject @ object was null 7574 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7575 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7576 and r2, r2, #15 7577 GET_INST_OPCODE(ip) @ extract opcode from rINST 7578 SET_VREG(r0, r2) @ fp[A]<- r0 7579 GOTO_OPCODE(ip) @ jump to next instruction 7580 7581 7582 7583/* ------------------------------ */ 7584 .balign 64 7585.L_OP_IPUT_QUICK: /* 0xf5 */ 7586/* File: armv5te/OP_IPUT_QUICK.S */ 7587 /* For: iput-quick, iput-object-quick */ 7588 /* op vA, vB, offset@CCCC */ 7589 mov r2, rINST, lsr #12 @ r2<- B 7590 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7591 FETCH(r1, 1) @ r1<- field byte offset 7592 cmp r3, #0 @ check object for null 7593 mov r2, rINST, lsr #8 @ r2<- A(+) 7594 beq common_errNullObject @ object was null 7595 and r2, r2, #15 7596 GET_VREG(r0, r2) @ r0<- fp[A] 7597 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7598 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7599 GET_INST_OPCODE(ip) @ extract opcode from rINST 7600 GOTO_OPCODE(ip) @ jump to next instruction 7601 7602 7603/* ------------------------------ */ 7604 .balign 64 7605.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7606/* File: armv4t/OP_IPUT_WIDE_QUICK.S */ 7607 /* iput-wide-quick vA, vB, offset@CCCC */ 7608 mov r0, rINST, lsr #8 @ r0<- A(+) 7609 mov r1, rINST, lsr #12 @ r1<- B 7610 and r0, r0, #15 7611 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7612 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7613 cmp r2, #0 @ check object for null 7614 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7615 beq common_errNullObject @ object was null 7616 FETCH(r3, 1) @ r3<- field byte offset 7617 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7618 add r2, r2, r3 @ r2<- object + byte offset 7619 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1 7620 GET_INST_OPCODE(ip) @ extract opcode from rINST 7621 GOTO_OPCODE(ip) @ jump to next instruction 7622 7623 7624/* ------------------------------ */ 7625 .balign 64 7626.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7627/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7628/* File: armv5te/OP_IPUT_QUICK.S */ 7629 /* For: iput-quick, iput-object-quick */ 7630 /* op vA, vB, offset@CCCC */ 7631 mov r2, rINST, lsr #12 @ r2<- B 7632 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7633 FETCH(r1, 1) @ r1<- field byte offset 7634 cmp r3, #0 @ check object for null 7635 mov r2, rINST, lsr #8 @ r2<- A(+) 7636 beq common_errNullObject @ object was null 7637 and r2, r2, #15 7638 GET_VREG(r0, r2) @ r0<- fp[A] 7639 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7640 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7641 GET_INST_OPCODE(ip) @ extract opcode from rINST 7642 GOTO_OPCODE(ip) @ jump to next instruction 7643 7644 7645 7646/* ------------------------------ */ 7647 .balign 64 7648.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7649/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7650 /* 7651 * Handle an optimized virtual method call. 7652 * 7653 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7654 */ 7655 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7656 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7657 FETCH(r3, 2) @ r3<- FEDC or CCCC 7658 FETCH(r1, 1) @ r1<- BBBB 7659 .if (!0) 7660 and r3, r3, #15 @ r3<- C (or stays CCCC) 7661 .endif 7662 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7663 cmp r2, #0 @ is "this" null? 7664 beq common_errNullObject @ null "this", throw exception 7665 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7666 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7667 EXPORT_PC() @ invoke must export 7668 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7669 bl common_invokeMethodNoRange @ continue on 7670 7671/* ------------------------------ */ 7672 .balign 64 7673.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7674/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7675/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7676 /* 7677 * Handle an optimized virtual method call. 7678 * 7679 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7680 */ 7681 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7682 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7683 FETCH(r3, 2) @ r3<- FEDC or CCCC 7684 FETCH(r1, 1) @ r1<- BBBB 7685 .if (!1) 7686 and r3, r3, #15 @ r3<- C (or stays CCCC) 7687 .endif 7688 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7689 cmp r2, #0 @ is "this" null? 7690 beq common_errNullObject @ null "this", throw exception 7691 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7692 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7693 EXPORT_PC() @ invoke must export 7694 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7695 bl common_invokeMethodRange @ continue on 7696 7697 7698/* ------------------------------ */ 7699 .balign 64 7700.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7701/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7702 /* 7703 * Handle an optimized "super" method call. 7704 * 7705 * for: [opt] invoke-super-quick, invoke-super-quick/range 7706 */ 7707 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7708 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7709 FETCH(r10, 2) @ r10<- GFED or CCCC 7710 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7711 .if (!0) 7712 and r10, r10, #15 @ r10<- D (or stays CCCC) 7713 .endif 7714 FETCH(r1, 1) @ r1<- BBBB 7715 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7716 EXPORT_PC() @ must export for invoke 7717 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7718 GET_VREG(r3, r10) @ r3<- "this" 7719 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7720 cmp r3, #0 @ null "this" ref? 7721 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7722 beq common_errNullObject @ "this" is null, throw exception 7723 bl common_invokeMethodNoRange @ continue on 7724 7725 7726/* ------------------------------ */ 7727 .balign 64 7728.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7729/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7730/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7731 /* 7732 * Handle an optimized "super" method call. 7733 * 7734 * for: [opt] invoke-super-quick, invoke-super-quick/range 7735 */ 7736 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7737 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7738 FETCH(r10, 2) @ r10<- GFED or CCCC 7739 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7740 .if (!1) 7741 and r10, r10, #15 @ r10<- D (or stays CCCC) 7742 .endif 7743 FETCH(r1, 1) @ r1<- BBBB 7744 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7745 EXPORT_PC() @ must export for invoke 7746 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7747 GET_VREG(r3, r10) @ r3<- "this" 7748 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7749 cmp r3, #0 @ null "this" ref? 7750 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7751 beq common_errNullObject @ "this" is null, throw exception 7752 bl common_invokeMethodRange @ continue on 7753 7754 7755 7756/* ------------------------------ */ 7757 .balign 64 7758.L_OP_UNUSED_FC: /* 0xfc */ 7759/* File: armv5te/OP_UNUSED_FC.S */ 7760/* File: armv5te/unused.S */ 7761 bl common_abort 7762 7763 7764 7765/* ------------------------------ */ 7766 .balign 64 7767.L_OP_UNUSED_FD: /* 0xfd */ 7768/* File: armv5te/OP_UNUSED_FD.S */ 7769/* File: armv5te/unused.S */ 7770 bl common_abort 7771 7772 7773 7774/* ------------------------------ */ 7775 .balign 64 7776.L_OP_UNUSED_FE: /* 0xfe */ 7777/* File: armv5te/OP_UNUSED_FE.S */ 7778/* File: armv5te/unused.S */ 7779 bl common_abort 7780 7781 7782 7783/* ------------------------------ */ 7784 .balign 64 7785.L_OP_UNUSED_FF: /* 0xff */ 7786/* File: armv5te/OP_UNUSED_FF.S */ 7787/* File: armv5te/unused.S */ 7788 bl common_abort 7789 7790 7791 7792 7793 .balign 64 7794 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7795 .global dvmAsmInstructionEnd 7796dvmAsmInstructionEnd: 7797 7798/* 7799 * =========================================================================== 7800 * Sister implementations 7801 * =========================================================================== 7802 */ 7803 .global dvmAsmSisterStart 7804 .type dvmAsmSisterStart, %function 7805 .text 7806 .balign 4 7807dvmAsmSisterStart: 7808 7809/* continuation for OP_CONST_STRING */ 7810 7811 /* 7812 * Continuation if the String has not yet been resolved. 7813 * r1: BBBB (String ref) 7814 * r9: target register 7815 */ 7816.LOP_CONST_STRING_resolve: 7817 EXPORT_PC() 7818 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7819 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7820 bl dvmResolveString @ r0<- String reference 7821 cmp r0, #0 @ failed? 7822 beq common_exceptionThrown @ yup, handle the exception 7823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7824 GET_INST_OPCODE(ip) @ extract opcode from rINST 7825 SET_VREG(r0, r9) @ vAA<- r0 7826 GOTO_OPCODE(ip) @ jump to next instruction 7827 7828 7829/* continuation for OP_CONST_STRING_JUMBO */ 7830 7831 /* 7832 * Continuation if the String has not yet been resolved. 7833 * r1: BBBBBBBB (String ref) 7834 * r9: target register 7835 */ 7836.LOP_CONST_STRING_JUMBO_resolve: 7837 EXPORT_PC() 7838 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7839 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7840 bl dvmResolveString @ r0<- String reference 7841 cmp r0, #0 @ failed? 7842 beq common_exceptionThrown @ yup, handle the exception 7843 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7844 GET_INST_OPCODE(ip) @ extract opcode from rINST 7845 SET_VREG(r0, r9) @ vAA<- r0 7846 GOTO_OPCODE(ip) @ jump to next instruction 7847 7848 7849/* continuation for OP_CONST_CLASS */ 7850 7851 /* 7852 * Continuation if the Class has not yet been resolved. 7853 * r1: BBBB (Class ref) 7854 * r9: target register 7855 */ 7856.LOP_CONST_CLASS_resolve: 7857 EXPORT_PC() 7858 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7859 mov r2, #1 @ r2<- true 7860 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7861 bl dvmResolveClass @ r0<- Class reference 7862 cmp r0, #0 @ failed? 7863 beq common_exceptionThrown @ yup, handle the exception 7864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7865 GET_INST_OPCODE(ip) @ extract opcode from rINST 7866 SET_VREG(r0, r9) @ vAA<- r0 7867 GOTO_OPCODE(ip) @ jump to next instruction 7868 7869 7870/* continuation for OP_CHECK_CAST */ 7871 7872 /* 7873 * Trivial test failed, need to perform full check. This is common. 7874 * r0 holds obj->clazz 7875 * r1 holds class resolved from BBBB 7876 * r9 holds object 7877 */ 7878.LOP_CHECK_CAST_fullcheck: 7879 bl dvmInstanceofNonTrivial @ r0<- boolean result 7880 cmp r0, #0 @ failed? 7881 bne .LOP_CHECK_CAST_okay @ no, success 7882 7883 @ A cast has failed. We need to throw a ClassCastException with the 7884 @ class of the object that failed to be cast. 7885 EXPORT_PC() @ about to throw 7886 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7887 ldr r0, .LstrClassCastExceptionPtr 7888 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7889 bl dvmThrowExceptionWithClassMessage 7890 b common_exceptionThrown 7891 7892 /* 7893 * Resolution required. This is the least-likely path. 7894 * 7895 * r2 holds BBBB 7896 * r9 holds object 7897 */ 7898.LOP_CHECK_CAST_resolve: 7899 EXPORT_PC() @ resolve() could throw 7900 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7901 mov r1, r2 @ r1<- BBBB 7902 mov r2, #0 @ r2<- false 7903 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7904 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7905 cmp r0, #0 @ got null? 7906 beq common_exceptionThrown @ yes, handle exception 7907 mov r1, r0 @ r1<- class resolved from BBB 7908 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7909 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7910 7911.LstrClassCastExceptionPtr: 7912 .word .LstrClassCastException 7913 7914 7915/* continuation for OP_INSTANCE_OF */ 7916 7917 /* 7918 * Trivial test failed, need to perform full check. This is common. 7919 * r0 holds obj->clazz 7920 * r1 holds class resolved from BBBB 7921 * r9 holds A 7922 */ 7923.LOP_INSTANCE_OF_fullcheck: 7924 bl dvmInstanceofNonTrivial @ r0<- boolean result 7925 @ fall through to OP_INSTANCE_OF_store 7926 7927 /* 7928 * r0 holds boolean result 7929 * r9 holds A 7930 */ 7931.LOP_INSTANCE_OF_store: 7932 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7933 SET_VREG(r0, r9) @ vA<- r0 7934 GET_INST_OPCODE(ip) @ extract opcode from rINST 7935 GOTO_OPCODE(ip) @ jump to next instruction 7936 7937 /* 7938 * Trivial test succeeded, save and bail. 7939 * r9 holds A 7940 */ 7941.LOP_INSTANCE_OF_trivial: 7942 mov r0, #1 @ indicate success 7943 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7945 SET_VREG(r0, r9) @ vA<- r0 7946 GET_INST_OPCODE(ip) @ extract opcode from rINST 7947 GOTO_OPCODE(ip) @ jump to next instruction 7948 7949 /* 7950 * Resolution required. This is the least-likely path. 7951 * 7952 * r3 holds BBBB 7953 * r9 holds A 7954 */ 7955.LOP_INSTANCE_OF_resolve: 7956 EXPORT_PC() @ resolve() could throw 7957 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7958 mov r1, r3 @ r1<- BBBB 7959 mov r2, #1 @ r2<- true 7960 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7961 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7962 cmp r0, #0 @ got null? 7963 beq common_exceptionThrown @ yes, handle exception 7964 mov r1, r0 @ r1<- class resolved from BBB 7965 mov r3, rINST, lsr #12 @ r3<- B 7966 GET_VREG(r0, r3) @ r0<- vB (object) 7967 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7968 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7969 7970 7971/* continuation for OP_NEW_INSTANCE */ 7972 7973 .balign 32 @ minimize cache lines 7974.LOP_NEW_INSTANCE_finish: @ r0=class 7975 bl dvmAllocObject @ r0<- new object 7976 mov r3, rINST, lsr #8 @ r3<- AA 7977 cmp r0, #0 @ failed? 7978 beq common_exceptionThrown @ yes, handle the exception 7979 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7980 GET_INST_OPCODE(ip) @ extract opcode from rINST 7981 SET_VREG(r0, r3) @ vAA<- r0 7982 GOTO_OPCODE(ip) @ jump to next instruction 7983 7984 /* 7985 * Class initialization required. 7986 * 7987 * r0 holds class object 7988 */ 7989.LOP_NEW_INSTANCE_needinit: 7990 mov r9, r0 @ save r0 7991 bl dvmInitClass @ initialize class 7992 cmp r0, #0 @ check boolean result 7993 mov r0, r9 @ restore r0 7994 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7995 b common_exceptionThrown @ failed, deal with init exception 7996 7997 /* 7998 * Resolution required. This is the least-likely path. 7999 * 8000 * r1 holds BBBB 8001 */ 8002.LOP_NEW_INSTANCE_resolve: 8003 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8004 mov r2, #0 @ r2<- false 8005 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8006 bl dvmResolveClass @ r0<- resolved ClassObject ptr 8007 cmp r0, #0 @ got null? 8008 bne .LOP_NEW_INSTANCE_resolved @ no, continue 8009 b common_exceptionThrown @ yes, handle exception 8010 8011 /* 8012 * We can't instantiate an abstract class or interface, so throw an 8013 * InstantiationError with the class descriptor as the message. 8014 * 8015 * r0 holds class object 8016 */ 8017.LOP_NEW_INSTANCE_abstract: 8018 ldr r1, [r0, #offClassObject_descriptor] 8019 ldr r0, .LstrInstantiationErrorPtr 8020 bl dvmThrowExceptionWithClassMessage 8021 b common_exceptionThrown 8022 8023.LstrInstantiationErrorPtr: 8024 .word .LstrInstantiationError 8025 8026 8027/* continuation for OP_NEW_ARRAY */ 8028 8029 8030 /* 8031 * Resolve class. (This is an uncommon case.) 8032 * 8033 * r1 holds array length 8034 * r2 holds class ref CCCC 8035 */ 8036.LOP_NEW_ARRAY_resolve: 8037 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8038 mov r9, r1 @ r9<- length (save) 8039 mov r1, r2 @ r1<- CCCC 8040 mov r2, #0 @ r2<- false 8041 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8042 bl dvmResolveClass @ r0<- call(clazz, ref) 8043 cmp r0, #0 @ got null? 8044 mov r1, r9 @ r1<- length (restore) 8045 beq common_exceptionThrown @ yes, handle exception 8046 @ fall through to OP_NEW_ARRAY_finish 8047 8048 /* 8049 * Finish allocation. 8050 * 8051 * r0 holds class 8052 * r1 holds array length 8053 */ 8054.LOP_NEW_ARRAY_finish: 8055 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8056 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8057 cmp r0, #0 @ failed? 8058 mov r2, rINST, lsr #8 @ r2<- A+ 8059 beq common_exceptionThrown @ yes, handle the exception 8060 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8061 and r2, r2, #15 @ r2<- A 8062 GET_INST_OPCODE(ip) @ extract opcode from rINST 8063 SET_VREG(r0, r2) @ vA<- r0 8064 GOTO_OPCODE(ip) @ jump to next instruction 8065 8066 8067/* continuation for OP_FILLED_NEW_ARRAY */ 8068 8069 /* 8070 * On entry: 8071 * r0 holds array class 8072 * r10 holds AA or BA 8073 */ 8074.LOP_FILLED_NEW_ARRAY_continue: 8075 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8076 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8077 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8078 .if 0 8079 mov r1, r10 @ r1<- AA (length) 8080 .else 8081 mov r1, r10, lsr #4 @ r1<- B (length) 8082 .endif 8083 cmp r3, #'I' @ array of ints? 8084 cmpne r3, #'L' @ array of objects? 8085 cmpne r3, #'[' @ array of arrays? 8086 mov r9, r1 @ save length in r9 8087 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8088 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8089 cmp r0, #0 @ null return? 8090 beq common_exceptionThrown @ alloc failed, handle exception 8091 8092 FETCH(r1, 2) @ r1<- FEDC or CCCC 8093 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8094 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8095 subs r9, r9, #1 @ length--, check for neg 8096 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8097 bmi 2f @ was zero, bail 8098 8099 @ copy values from registers into the array 8100 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8101 .if 0 8102 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81031: ldr r3, [r2], #4 @ r3<- *r2++ 8104 subs r9, r9, #1 @ count-- 8105 str r3, [r0], #4 @ *contents++ = vX 8106 bpl 1b 8107 @ continue at 2 8108 .else 8109 cmp r9, #4 @ length was initially 5? 8110 and r2, r10, #15 @ r2<- A 8111 bne 1f @ <= 4 args, branch 8112 GET_VREG(r3, r2) @ r3<- vA 8113 sub r9, r9, #1 @ count-- 8114 str r3, [r0, #16] @ contents[4] = vA 81151: and r2, r1, #15 @ r2<- F/E/D/C 8116 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8117 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8118 subs r9, r9, #1 @ count-- 8119 str r3, [r0], #4 @ *contents++ = vX 8120 bpl 1b 8121 @ continue at 2 8122 .endif 8123 81242: 8125 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8126 GOTO_OPCODE(ip) @ execute it 8127 8128 /* 8129 * Throw an exception indicating that we have not implemented this 8130 * mode of filled-new-array. 8131 */ 8132.LOP_FILLED_NEW_ARRAY_notimpl: 8133 ldr r0, .L_strInternalError 8134 ldr r1, .L_strFilledNewArrayNotImpl 8135 bl dvmThrowException 8136 b common_exceptionThrown 8137 8138 .if (!0) @ define in one or the other, not both 8139.L_strFilledNewArrayNotImpl: 8140 .word .LstrFilledNewArrayNotImpl 8141.L_strInternalError: 8142 .word .LstrInternalError 8143 .endif 8144 8145 8146/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8147 8148 /* 8149 * On entry: 8150 * r0 holds array class 8151 * r10 holds AA or BA 8152 */ 8153.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8154 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8155 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8156 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8157 .if 1 8158 mov r1, r10 @ r1<- AA (length) 8159 .else 8160 mov r1, r10, lsr #4 @ r1<- B (length) 8161 .endif 8162 cmp r3, #'I' @ array of ints? 8163 cmpne r3, #'L' @ array of objects? 8164 cmpne r3, #'[' @ array of arrays? 8165 mov r9, r1 @ save length in r9 8166 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8167 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8168 cmp r0, #0 @ null return? 8169 beq common_exceptionThrown @ alloc failed, handle exception 8170 8171 FETCH(r1, 2) @ r1<- FEDC or CCCC 8172 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8173 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8174 subs r9, r9, #1 @ length--, check for neg 8175 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8176 bmi 2f @ was zero, bail 8177 8178 @ copy values from registers into the array 8179 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8180 .if 1 8181 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81821: ldr r3, [r2], #4 @ r3<- *r2++ 8183 subs r9, r9, #1 @ count-- 8184 str r3, [r0], #4 @ *contents++ = vX 8185 bpl 1b 8186 @ continue at 2 8187 .else 8188 cmp r9, #4 @ length was initially 5? 8189 and r2, r10, #15 @ r2<- A 8190 bne 1f @ <= 4 args, branch 8191 GET_VREG(r3, r2) @ r3<- vA 8192 sub r9, r9, #1 @ count-- 8193 str r3, [r0, #16] @ contents[4] = vA 81941: and r2, r1, #15 @ r2<- F/E/D/C 8195 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8196 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8197 subs r9, r9, #1 @ count-- 8198 str r3, [r0], #4 @ *contents++ = vX 8199 bpl 1b 8200 @ continue at 2 8201 .endif 8202 82032: 8204 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8205 GOTO_OPCODE(ip) @ execute it 8206 8207 /* 8208 * Throw an exception indicating that we have not implemented this 8209 * mode of filled-new-array. 8210 */ 8211.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8212 ldr r0, .L_strInternalError 8213 ldr r1, .L_strFilledNewArrayNotImpl 8214 bl dvmThrowException 8215 b common_exceptionThrown 8216 8217 .if (!1) @ define in one or the other, not both 8218.L_strFilledNewArrayNotImpl: 8219 .word .LstrFilledNewArrayNotImpl 8220.L_strInternalError: 8221 .word .LstrInternalError 8222 .endif 8223 8224 8225/* continuation for OP_CMPL_FLOAT */ 8226 8227 @ Test for NaN with a second comparison. EABI forbids testing bit 8228 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8229 @ make the library call. 8230.LOP_CMPL_FLOAT_gt_or_nan: 8231 mov r1, r9 @ reverse order 8232 mov r0, r10 8233 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8234 @bleq common_abort 8235 movcc r1, #1 @ (greater than) r1<- 1 8236 bcc .LOP_CMPL_FLOAT_finish 8237 mvn r1, #0 @ r1<- 1 or -1 for NaN 8238 b .LOP_CMPL_FLOAT_finish 8239 8240 8241#if 0 /* "clasic" form */ 8242 FETCH(r0, 1) @ r0<- CCBB 8243 and r2, r0, #255 @ r2<- BB 8244 mov r3, r0, lsr #8 @ r3<- CC 8245 GET_VREG(r9, r2) @ r9<- vBB 8246 GET_VREG(r10, r3) @ r10<- vCC 8247 mov r0, r9 @ r0<- vBB 8248 mov r1, r10 @ r1<- vCC 8249 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8250 cmp r0, #0 @ equal? 8251 movne r1, #0 @ yes, result is 0 8252 bne OP_CMPL_FLOAT_finish 8253 mov r0, r9 @ r0<- vBB 8254 mov r1, r10 @ r1<- vCC 8255 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8256 cmp r0, #0 @ less than? 8257 b OP_CMPL_FLOAT_continue 8258@%break 8259 8260OP_CMPL_FLOAT_continue: 8261 mvnne r1, #0 @ yes, result is -1 8262 bne OP_CMPL_FLOAT_finish 8263 mov r0, r9 @ r0<- vBB 8264 mov r1, r10 @ r1<- vCC 8265 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8266 cmp r0, #0 @ greater than? 8267 beq OP_CMPL_FLOAT_nan @ no, must be NaN 8268 mov r1, #1 @ yes, result is 1 8269 @ fall through to _finish 8270 8271OP_CMPL_FLOAT_finish: 8272 mov r3, rINST, lsr #8 @ r3<- AA 8273 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8274 SET_VREG(r1, r3) @ vAA<- r1 8275 GET_INST_OPCODE(ip) @ extract opcode from rINST 8276 GOTO_OPCODE(ip) @ jump to next instruction 8277 8278 /* 8279 * This is expected to be uncommon, so we double-branch (once to here, 8280 * again back to _finish). 8281 */ 8282OP_CMPL_FLOAT_nan: 8283 mvn r1, #0 @ r1<- 1 or -1 for NaN 8284 b OP_CMPL_FLOAT_finish 8285 8286#endif 8287 8288 8289/* continuation for OP_CMPG_FLOAT */ 8290 8291 @ Test for NaN with a second comparison. EABI forbids testing bit 8292 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8293 @ make the library call. 8294.LOP_CMPG_FLOAT_gt_or_nan: 8295 mov r1, r9 @ reverse order 8296 mov r0, r10 8297 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8298 @bleq common_abort 8299 movcc r1, #1 @ (greater than) r1<- 1 8300 bcc .LOP_CMPG_FLOAT_finish 8301 mov r1, #1 @ r1<- 1 or -1 for NaN 8302 b .LOP_CMPG_FLOAT_finish 8303 8304 8305#if 0 /* "clasic" form */ 8306 FETCH(r0, 1) @ r0<- CCBB 8307 and r2, r0, #255 @ r2<- BB 8308 mov r3, r0, lsr #8 @ r3<- CC 8309 GET_VREG(r9, r2) @ r9<- vBB 8310 GET_VREG(r10, r3) @ r10<- vCC 8311 mov r0, r9 @ r0<- vBB 8312 mov r1, r10 @ r1<- vCC 8313 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8314 cmp r0, #0 @ equal? 8315 movne r1, #0 @ yes, result is 0 8316 bne OP_CMPG_FLOAT_finish 8317 mov r0, r9 @ r0<- vBB 8318 mov r1, r10 @ r1<- vCC 8319 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8320 cmp r0, #0 @ less than? 8321 b OP_CMPG_FLOAT_continue 8322@%break 8323 8324OP_CMPG_FLOAT_continue: 8325 mvnne r1, #0 @ yes, result is -1 8326 bne OP_CMPG_FLOAT_finish 8327 mov r0, r9 @ r0<- vBB 8328 mov r1, r10 @ r1<- vCC 8329 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8330 cmp r0, #0 @ greater than? 8331 beq OP_CMPG_FLOAT_nan @ no, must be NaN 8332 mov r1, #1 @ yes, result is 1 8333 @ fall through to _finish 8334 8335OP_CMPG_FLOAT_finish: 8336 mov r3, rINST, lsr #8 @ r3<- AA 8337 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8338 SET_VREG(r1, r3) @ vAA<- r1 8339 GET_INST_OPCODE(ip) @ extract opcode from rINST 8340 GOTO_OPCODE(ip) @ jump to next instruction 8341 8342 /* 8343 * This is expected to be uncommon, so we double-branch (once to here, 8344 * again back to _finish). 8345 */ 8346OP_CMPG_FLOAT_nan: 8347 mov r1, #1 @ r1<- 1 or -1 for NaN 8348 b OP_CMPG_FLOAT_finish 8349 8350#endif 8351 8352 8353/* continuation for OP_CMPL_DOUBLE */ 8354 8355 @ Test for NaN with a second comparison. EABI forbids testing bit 8356 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8357 @ make the library call. 8358.LOP_CMPL_DOUBLE_gt_or_nan: 8359 ldmia r10, {r0-r1} @ reverse order 8360 ldmia r9, {r2-r3} 8361 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8362 @bleq common_abort 8363 movcc r1, #1 @ (greater than) r1<- 1 8364 bcc .LOP_CMPL_DOUBLE_finish 8365 mvn r1, #0 @ r1<- 1 or -1 for NaN 8366 b .LOP_CMPL_DOUBLE_finish 8367 8368 8369/* continuation for OP_CMPG_DOUBLE */ 8370 8371 @ Test for NaN with a second comparison. EABI forbids testing bit 8372 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8373 @ make the library call. 8374.LOP_CMPG_DOUBLE_gt_or_nan: 8375 ldmia r10, {r0-r1} @ reverse order 8376 ldmia r9, {r2-r3} 8377 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8378 @bleq common_abort 8379 movcc r1, #1 @ (greater than) r1<- 1 8380 bcc .LOP_CMPG_DOUBLE_finish 8381 mov r1, #1 @ r1<- 1 or -1 for NaN 8382 b .LOP_CMPG_DOUBLE_finish 8383 8384 8385/* continuation for OP_CMP_LONG */ 8386 8387.LOP_CMP_LONG_less: 8388 mvn r1, #0 @ r1<- -1 8389 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8390 @ instead, we just replicate the tail end. 8391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8392 SET_VREG(r1, r9) @ vAA<- r1 8393 GET_INST_OPCODE(ip) @ extract opcode from rINST 8394 GOTO_OPCODE(ip) @ jump to next instruction 8395 8396.LOP_CMP_LONG_greater: 8397 mov r1, #1 @ r1<- 1 8398 @ fall through to _finish 8399 8400.LOP_CMP_LONG_finish: 8401 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8402 SET_VREG(r1, r9) @ vAA<- r1 8403 GET_INST_OPCODE(ip) @ extract opcode from rINST 8404 GOTO_OPCODE(ip) @ jump to next instruction 8405 8406 8407/* continuation for OP_AGET_WIDE */ 8408 8409.LOP_AGET_WIDE_finish: 8410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8411 add r0, r0, #offArrayObject_contents 8412 ldmia r0, {r2-r3} @ r2/r3 <- vBB[vCC] 8413 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8414 GET_INST_OPCODE(ip) @ extract opcode from rINST 8415 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8416 GOTO_OPCODE(ip) @ jump to next instruction 8417 8418 8419/* continuation for OP_APUT_WIDE */ 8420 8421.LOP_APUT_WIDE_finish: 8422 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8423 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8424 GET_INST_OPCODE(ip) @ extract opcode from rINST 8425 add r0, #offArrayObject_contents 8426 stmia r0, {r2-r3} @ vBB[vCC] <- r2/r3 8427 GOTO_OPCODE(ip) @ jump to next instruction 8428 8429 8430/* continuation for OP_APUT_OBJECT */ 8431 /* 8432 * On entry: 8433 * r1 = vBB (arrayObj) 8434 * r9 = vAA (obj) 8435 * r10 = offset into array (vBB + vCC * width) 8436 */ 8437.LOP_APUT_OBJECT_finish: 8438 cmp r9, #0 @ storing null reference? 8439 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8440 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8441 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8442 bl dvmCanPutArrayElement @ test object type vs. array type 8443 cmp r0, #0 @ okay? 8444 beq common_errArrayStore @ no 8445.LOP_APUT_OBJECT_skip_check: 8446 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8447 GET_INST_OPCODE(ip) @ extract opcode from rINST 8448 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8449 GOTO_OPCODE(ip) @ jump to next instruction 8450 8451 8452/* continuation for OP_IGET */ 8453 8454 /* 8455 * Currently: 8456 * r0 holds resolved field 8457 * r9 holds object 8458 */ 8459.LOP_IGET_finish: 8460 @bl common_squeak0 8461 cmp r9, #0 @ check object for null 8462 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8463 beq common_errNullObject @ object was null 8464 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8465 mov r2, rINST, lsr #8 @ r2<- A+ 8466 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8467 and r2, r2, #15 @ r2<- A 8468 GET_INST_OPCODE(ip) @ extract opcode from rINST 8469 SET_VREG(r0, r2) @ fp[A]<- r0 8470 GOTO_OPCODE(ip) @ jump to next instruction 8471 8472 8473/* continuation for OP_IGET_WIDE */ 8474 8475 /* 8476 * Currently: 8477 * r0 holds resolved field 8478 * r9 holds object 8479 */ 8480.LOP_IGET_WIDE_finish: 8481 cmp r9, #0 @ check object for null 8482 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8483 beq common_errNullObject @ object was null 8484 mov r2, rINST, lsr #8 @ r2<- A+ 8485 add r9, r9, r3 @ r9<- obj + field offset 8486 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok) 8487 and r2, r2, #15 @ r2<- A 8488 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8489 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8490 GET_INST_OPCODE(ip) @ extract opcode from rINST 8491 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8492 GOTO_OPCODE(ip) @ jump to next instruction 8493 8494 8495/* continuation for OP_IGET_OBJECT */ 8496 8497 /* 8498 * Currently: 8499 * r0 holds resolved field 8500 * r9 holds object 8501 */ 8502.LOP_IGET_OBJECT_finish: 8503 @bl common_squeak0 8504 cmp r9, #0 @ check object for null 8505 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8506 beq common_errNullObject @ object was null 8507 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8508 mov r2, rINST, lsr #8 @ r2<- A+ 8509 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8510 and r2, r2, #15 @ r2<- A 8511 GET_INST_OPCODE(ip) @ extract opcode from rINST 8512 SET_VREG(r0, r2) @ fp[A]<- r0 8513 GOTO_OPCODE(ip) @ jump to next instruction 8514 8515 8516/* continuation for OP_IGET_BOOLEAN */ 8517 8518 /* 8519 * Currently: 8520 * r0 holds resolved field 8521 * r9 holds object 8522 */ 8523.LOP_IGET_BOOLEAN_finish: 8524 @bl common_squeak1 8525 cmp r9, #0 @ check object for null 8526 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8527 beq common_errNullObject @ object was null 8528 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8529 mov r2, rINST, lsr #8 @ r2<- A+ 8530 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8531 and r2, r2, #15 @ r2<- A 8532 GET_INST_OPCODE(ip) @ extract opcode from rINST 8533 SET_VREG(r0, r2) @ fp[A]<- r0 8534 GOTO_OPCODE(ip) @ jump to next instruction 8535 8536 8537/* continuation for OP_IGET_BYTE */ 8538 8539 /* 8540 * Currently: 8541 * r0 holds resolved field 8542 * r9 holds object 8543 */ 8544.LOP_IGET_BYTE_finish: 8545 @bl common_squeak2 8546 cmp r9, #0 @ check object for null 8547 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8548 beq common_errNullObject @ object was null 8549 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8550 mov r2, rINST, lsr #8 @ r2<- A+ 8551 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8552 and r2, r2, #15 @ r2<- A 8553 GET_INST_OPCODE(ip) @ extract opcode from rINST 8554 SET_VREG(r0, r2) @ fp[A]<- r0 8555 GOTO_OPCODE(ip) @ jump to next instruction 8556 8557 8558/* continuation for OP_IGET_CHAR */ 8559 8560 /* 8561 * Currently: 8562 * r0 holds resolved field 8563 * r9 holds object 8564 */ 8565.LOP_IGET_CHAR_finish: 8566 @bl common_squeak3 8567 cmp r9, #0 @ check object for null 8568 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8569 beq common_errNullObject @ object was null 8570 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8571 mov r2, rINST, lsr #8 @ r2<- A+ 8572 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8573 and r2, r2, #15 @ r2<- A 8574 GET_INST_OPCODE(ip) @ extract opcode from rINST 8575 SET_VREG(r0, r2) @ fp[A]<- r0 8576 GOTO_OPCODE(ip) @ jump to next instruction 8577 8578 8579/* continuation for OP_IGET_SHORT */ 8580 8581 /* 8582 * Currently: 8583 * r0 holds resolved field 8584 * r9 holds object 8585 */ 8586.LOP_IGET_SHORT_finish: 8587 @bl common_squeak4 8588 cmp r9, #0 @ check object for null 8589 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8590 beq common_errNullObject @ object was null 8591 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8592 mov r2, rINST, lsr #8 @ r2<- A+ 8593 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8594 and r2, r2, #15 @ r2<- A 8595 GET_INST_OPCODE(ip) @ extract opcode from rINST 8596 SET_VREG(r0, r2) @ fp[A]<- r0 8597 GOTO_OPCODE(ip) @ jump to next instruction 8598 8599 8600/* continuation for OP_IPUT */ 8601 8602 /* 8603 * Currently: 8604 * r0 holds resolved field 8605 * r9 holds object 8606 */ 8607.LOP_IPUT_finish: 8608 @bl common_squeak0 8609 mov r1, rINST, lsr #8 @ r1<- A+ 8610 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8611 and r1, r1, #15 @ r1<- A 8612 cmp r9, #0 @ check object for null 8613 GET_VREG(r0, r1) @ r0<- fp[A] 8614 beq common_errNullObject @ object was null 8615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8616 GET_INST_OPCODE(ip) @ extract opcode from rINST 8617 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8618 GOTO_OPCODE(ip) @ jump to next instruction 8619 8620 8621/* continuation for OP_IPUT_WIDE */ 8622 8623 /* 8624 * Currently: 8625 * r0 holds resolved field 8626 * r9 holds object 8627 */ 8628.LOP_IPUT_WIDE_finish: 8629 mov r2, rINST, lsr #8 @ r2<- A+ 8630 cmp r9, #0 @ check object for null 8631 and r2, r2, #15 @ r2<- A 8632 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8633 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8634 beq common_errNullObject @ object was null 8635 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8636 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8637 GET_INST_OPCODE(ip) @ extract opcode from rINST 8638 add r9, r9, r3 @ r9<- object + byte offset 8639 stmia r9, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1 8640 GOTO_OPCODE(ip) @ jump to next instruction 8641 8642 8643/* continuation for OP_IPUT_OBJECT */ 8644 8645 /* 8646 * Currently: 8647 * r0 holds resolved field 8648 * r9 holds object 8649 */ 8650.LOP_IPUT_OBJECT_finish: 8651 @bl common_squeak0 8652 mov r1, rINST, lsr #8 @ r1<- A+ 8653 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8654 and r1, r1, #15 @ r1<- A 8655 cmp r9, #0 @ check object for null 8656 GET_VREG(r0, r1) @ r0<- fp[A] 8657 beq common_errNullObject @ object was null 8658 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8659 GET_INST_OPCODE(ip) @ extract opcode from rINST 8660 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8661 GOTO_OPCODE(ip) @ jump to next instruction 8662 8663 8664/* continuation for OP_IPUT_BOOLEAN */ 8665 8666 /* 8667 * Currently: 8668 * r0 holds resolved field 8669 * r9 holds object 8670 */ 8671.LOP_IPUT_BOOLEAN_finish: 8672 @bl common_squeak1 8673 mov r1, rINST, lsr #8 @ r1<- A+ 8674 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8675 and r1, r1, #15 @ r1<- A 8676 cmp r9, #0 @ check object for null 8677 GET_VREG(r0, r1) @ r0<- fp[A] 8678 beq common_errNullObject @ object was null 8679 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8680 GET_INST_OPCODE(ip) @ extract opcode from rINST 8681 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8682 GOTO_OPCODE(ip) @ jump to next instruction 8683 8684 8685/* continuation for OP_IPUT_BYTE */ 8686 8687 /* 8688 * Currently: 8689 * r0 holds resolved field 8690 * r9 holds object 8691 */ 8692.LOP_IPUT_BYTE_finish: 8693 @bl common_squeak2 8694 mov r1, rINST, lsr #8 @ r1<- A+ 8695 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8696 and r1, r1, #15 @ r1<- A 8697 cmp r9, #0 @ check object for null 8698 GET_VREG(r0, r1) @ r0<- fp[A] 8699 beq common_errNullObject @ object was null 8700 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8701 GET_INST_OPCODE(ip) @ extract opcode from rINST 8702 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8703 GOTO_OPCODE(ip) @ jump to next instruction 8704 8705 8706/* continuation for OP_IPUT_CHAR */ 8707 8708 /* 8709 * Currently: 8710 * r0 holds resolved field 8711 * r9 holds object 8712 */ 8713.LOP_IPUT_CHAR_finish: 8714 @bl common_squeak3 8715 mov r1, rINST, lsr #8 @ r1<- A+ 8716 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8717 and r1, r1, #15 @ r1<- A 8718 cmp r9, #0 @ check object for null 8719 GET_VREG(r0, r1) @ r0<- fp[A] 8720 beq common_errNullObject @ object was null 8721 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8722 GET_INST_OPCODE(ip) @ extract opcode from rINST 8723 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8724 GOTO_OPCODE(ip) @ jump to next instruction 8725 8726 8727/* continuation for OP_IPUT_SHORT */ 8728 8729 /* 8730 * Currently: 8731 * r0 holds resolved field 8732 * r9 holds object 8733 */ 8734.LOP_IPUT_SHORT_finish: 8735 @bl common_squeak4 8736 mov r1, rINST, lsr #8 @ r1<- A+ 8737 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8738 and r1, r1, #15 @ r1<- A 8739 cmp r9, #0 @ check object for null 8740 GET_VREG(r0, r1) @ r0<- fp[A] 8741 beq common_errNullObject @ object was null 8742 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8743 GET_INST_OPCODE(ip) @ extract opcode from rINST 8744 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8745 GOTO_OPCODE(ip) @ jump to next instruction 8746 8747 8748/* continuation for OP_SGET */ 8749 8750 /* 8751 * Continuation if the field has not yet been resolved. 8752 * r1: BBBB field ref 8753 */ 8754.LOP_SGET_resolve: 8755 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8756 EXPORT_PC() @ resolve() could throw, so export now 8757 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8758 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8759 cmp r0, #0 @ success? 8760 bne .LOP_SGET_finish @ yes, finish 8761 b common_exceptionThrown @ no, handle exception 8762 8763 8764/* continuation for OP_SGET_WIDE */ 8765 8766 /* 8767 * Continuation if the field has not yet been resolved. 8768 * r1: BBBB field ref 8769 */ 8770.LOP_SGET_WIDE_resolve: 8771 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8772 EXPORT_PC() @ resolve() could throw, so export now 8773 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8774 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8775 cmp r0, #0 @ success? 8776 bne .LOP_SGET_WIDE_finish @ yes, finish 8777 b common_exceptionThrown @ no, handle exception 8778 8779 8780/* continuation for OP_SGET_OBJECT */ 8781 8782 /* 8783 * Continuation if the field has not yet been resolved. 8784 * r1: BBBB field ref 8785 */ 8786.LOP_SGET_OBJECT_resolve: 8787 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8788 EXPORT_PC() @ resolve() could throw, so export now 8789 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8790 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8791 cmp r0, #0 @ success? 8792 bne .LOP_SGET_OBJECT_finish @ yes, finish 8793 b common_exceptionThrown @ no, handle exception 8794 8795 8796/* continuation for OP_SGET_BOOLEAN */ 8797 8798 /* 8799 * Continuation if the field has not yet been resolved. 8800 * r1: BBBB field ref 8801 */ 8802.LOP_SGET_BOOLEAN_resolve: 8803 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8804 EXPORT_PC() @ resolve() could throw, so export now 8805 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8806 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8807 cmp r0, #0 @ success? 8808 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8809 b common_exceptionThrown @ no, handle exception 8810 8811 8812/* continuation for OP_SGET_BYTE */ 8813 8814 /* 8815 * Continuation if the field has not yet been resolved. 8816 * r1: BBBB field ref 8817 */ 8818.LOP_SGET_BYTE_resolve: 8819 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8820 EXPORT_PC() @ resolve() could throw, so export now 8821 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8822 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8823 cmp r0, #0 @ success? 8824 bne .LOP_SGET_BYTE_finish @ yes, finish 8825 b common_exceptionThrown @ no, handle exception 8826 8827 8828/* continuation for OP_SGET_CHAR */ 8829 8830 /* 8831 * Continuation if the field has not yet been resolved. 8832 * r1: BBBB field ref 8833 */ 8834.LOP_SGET_CHAR_resolve: 8835 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8836 EXPORT_PC() @ resolve() could throw, so export now 8837 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8838 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8839 cmp r0, #0 @ success? 8840 bne .LOP_SGET_CHAR_finish @ yes, finish 8841 b common_exceptionThrown @ no, handle exception 8842 8843 8844/* continuation for OP_SGET_SHORT */ 8845 8846 /* 8847 * Continuation if the field has not yet been resolved. 8848 * r1: BBBB field ref 8849 */ 8850.LOP_SGET_SHORT_resolve: 8851 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8852 EXPORT_PC() @ resolve() could throw, so export now 8853 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8854 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8855 cmp r0, #0 @ success? 8856 bne .LOP_SGET_SHORT_finish @ yes, finish 8857 b common_exceptionThrown @ no, handle exception 8858 8859 8860/* continuation for OP_SPUT */ 8861 8862 /* 8863 * Continuation if the field has not yet been resolved. 8864 * r1: BBBB field ref 8865 */ 8866.LOP_SPUT_resolve: 8867 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8868 EXPORT_PC() @ resolve() could throw, so export now 8869 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8870 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8871 cmp r0, #0 @ success? 8872 bne .LOP_SPUT_finish @ yes, finish 8873 b common_exceptionThrown @ no, handle exception 8874 8875 8876/* continuation for OP_SPUT_WIDE */ 8877 8878 /* 8879 * Continuation if the field has not yet been resolved. 8880 * r1: BBBB field ref 8881 * r9: &fp[AA] 8882 */ 8883.LOP_SPUT_WIDE_resolve: 8884 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8885 EXPORT_PC() @ resolve() could throw, so export now 8886 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8887 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8888 cmp r0, #0 @ success? 8889 bne .LOP_SPUT_WIDE_finish @ yes, finish 8890 b common_exceptionThrown @ no, handle exception 8891 8892 8893/* continuation for OP_SPUT_OBJECT */ 8894 8895 /* 8896 * Continuation if the field has not yet been resolved. 8897 * r1: BBBB field ref 8898 */ 8899.LOP_SPUT_OBJECT_resolve: 8900 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8901 EXPORT_PC() @ resolve() could throw, so export now 8902 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8903 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8904 cmp r0, #0 @ success? 8905 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8906 b common_exceptionThrown @ no, handle exception 8907 8908 8909/* continuation for OP_SPUT_BOOLEAN */ 8910 8911 /* 8912 * Continuation if the field has not yet been resolved. 8913 * r1: BBBB field ref 8914 */ 8915.LOP_SPUT_BOOLEAN_resolve: 8916 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8917 EXPORT_PC() @ resolve() could throw, so export now 8918 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8919 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8920 cmp r0, #0 @ success? 8921 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8922 b common_exceptionThrown @ no, handle exception 8923 8924 8925/* continuation for OP_SPUT_BYTE */ 8926 8927 /* 8928 * Continuation if the field has not yet been resolved. 8929 * r1: BBBB field ref 8930 */ 8931.LOP_SPUT_BYTE_resolve: 8932 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8933 EXPORT_PC() @ resolve() could throw, so export now 8934 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8935 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8936 cmp r0, #0 @ success? 8937 bne .LOP_SPUT_BYTE_finish @ yes, finish 8938 b common_exceptionThrown @ no, handle exception 8939 8940 8941/* continuation for OP_SPUT_CHAR */ 8942 8943 /* 8944 * Continuation if the field has not yet been resolved. 8945 * r1: BBBB field ref 8946 */ 8947.LOP_SPUT_CHAR_resolve: 8948 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8949 EXPORT_PC() @ resolve() could throw, so export now 8950 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8951 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8952 cmp r0, #0 @ success? 8953 bne .LOP_SPUT_CHAR_finish @ yes, finish 8954 b common_exceptionThrown @ no, handle exception 8955 8956 8957/* continuation for OP_SPUT_SHORT */ 8958 8959 /* 8960 * Continuation if the field has not yet been resolved. 8961 * r1: BBBB field ref 8962 */ 8963.LOP_SPUT_SHORT_resolve: 8964 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8965 EXPORT_PC() @ resolve() could throw, so export now 8966 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8967 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8968 cmp r0, #0 @ success? 8969 bne .LOP_SPUT_SHORT_finish @ yes, finish 8970 b common_exceptionThrown @ no, handle exception 8971 8972 8973/* continuation for OP_INVOKE_VIRTUAL */ 8974 8975 /* 8976 * At this point: 8977 * r0 = resolved base method 8978 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8979 */ 8980.LOP_INVOKE_VIRTUAL_continue: 8981 GET_VREG(r1, r10) @ r1<- "this" ptr 8982 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8983 cmp r1, #0 @ is "this" null? 8984 beq common_errNullObject @ null "this", throw exception 8985 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8986 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8987 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8988 bl common_invokeMethodNoRange @ continue on 8989 8990 8991/* continuation for OP_INVOKE_SUPER */ 8992 8993 /* 8994 * At this point: 8995 * r0 = resolved base method 8996 * r9 = method->clazz 8997 */ 8998.LOP_INVOKE_SUPER_continue: 8999 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9000 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9001 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9002 EXPORT_PC() @ must export for invoke 9003 cmp r2, r3 @ compare (methodIndex, vtableCount) 9004 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 9005 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9006 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9007 bl common_invokeMethodNoRange @ continue on 9008 9009.LOP_INVOKE_SUPER_resolve: 9010 mov r0, r9 @ r0<- method->clazz 9011 mov r2, #METHOD_VIRTUAL @ resolver method type 9012 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9013 cmp r0, #0 @ got null? 9014 bne .LOP_INVOKE_SUPER_continue @ no, continue 9015 b common_exceptionThrown @ yes, handle exception 9016 9017 /* 9018 * Throw a NoSuchMethodError with the method name as the message. 9019 * r0 = resolved base method 9020 */ 9021.LOP_INVOKE_SUPER_nsm: 9022 ldr r1, [r0, #offMethod_name] @ r1<- method name 9023 b common_errNoSuchMethod 9024 9025 9026/* continuation for OP_INVOKE_DIRECT */ 9027 9028 /* 9029 * On entry: 9030 * r1 = reference (BBBB or CCCC) 9031 * r10 = "this" register 9032 */ 9033.LOP_INVOKE_DIRECT_resolve: 9034 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9035 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9036 mov r2, #METHOD_DIRECT @ resolver method type 9037 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9038 cmp r0, #0 @ got null? 9039 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9040 bne .LOP_INVOKE_DIRECT_finish @ no, continue 9041 b common_exceptionThrown @ yes, handle exception 9042 9043 9044/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 9045 9046 /* 9047 * At this point: 9048 * r0 = resolved base method 9049 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9050 */ 9051.LOP_INVOKE_VIRTUAL_RANGE_continue: 9052 GET_VREG(r1, r10) @ r1<- "this" ptr 9053 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9054 cmp r1, #0 @ is "this" null? 9055 beq common_errNullObject @ null "this", throw exception 9056 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9057 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9058 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9059 bl common_invokeMethodRange @ continue on 9060 9061 9062/* continuation for OP_INVOKE_SUPER_RANGE */ 9063 9064 /* 9065 * At this point: 9066 * r0 = resolved base method 9067 * r9 = method->clazz 9068 */ 9069.LOP_INVOKE_SUPER_RANGE_continue: 9070 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9071 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9072 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9073 EXPORT_PC() @ must export for invoke 9074 cmp r2, r3 @ compare (methodIndex, vtableCount) 9075 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 9076 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9077 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9078 bl common_invokeMethodRange @ continue on 9079 9080.LOP_INVOKE_SUPER_RANGE_resolve: 9081 mov r0, r9 @ r0<- method->clazz 9082 mov r2, #METHOD_VIRTUAL @ resolver method type 9083 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9084 cmp r0, #0 @ got null? 9085 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 9086 b common_exceptionThrown @ yes, handle exception 9087 9088 /* 9089 * Throw a NoSuchMethodError with the method name as the message. 9090 * r0 = resolved base method 9091 */ 9092.LOP_INVOKE_SUPER_RANGE_nsm: 9093 ldr r1, [r0, #offMethod_name] @ r1<- method name 9094 b common_errNoSuchMethod 9095 9096 9097/* continuation for OP_INVOKE_DIRECT_RANGE */ 9098 9099 /* 9100 * On entry: 9101 * r1 = reference (BBBB or CCCC) 9102 * r10 = "this" register 9103 */ 9104.LOP_INVOKE_DIRECT_RANGE_resolve: 9105 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9106 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9107 mov r2, #METHOD_DIRECT @ resolver method type 9108 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9109 cmp r0, #0 @ got null? 9110 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9111 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 9112 b common_exceptionThrown @ yes, handle exception 9113 9114 9115/* continuation for OP_FLOAT_TO_LONG */ 9116/* 9117 * Convert the float in r0 to a long in r0/r1. 9118 * 9119 * We have to clip values to long min/max per the specification. The 9120 * expected common case is a "reasonable" value that converts directly 9121 * to modest integer. The EABI convert function isn't doing this for us. 9122 */ 9123f2l_doconv: 9124 stmfd sp!, {r4, lr} 9125 mov r1, #0x5f000000 @ (float)maxlong 9126 mov r4, r0 9127 bl __aeabi_fcmpge @ is arg >= maxlong? 9128 cmp r0, #0 @ nonzero == yes 9129 mvnne r0, #0 @ return maxlong (7fffffff) 9130 mvnne r1, #0x80000000 9131 ldmnefd sp!, {r4, pc} 9132 9133 mov r0, r4 @ recover arg 9134 mov r1, #0xdf000000 @ (float)minlong 9135 bl __aeabi_fcmple @ is arg <= minlong? 9136 cmp r0, #0 @ nonzero == yes 9137 movne r0, #0 @ return minlong (80000000) 9138 movne r1, #0x80000000 9139 ldmnefd sp!, {r4, pc} 9140 9141 mov r0, r4 @ recover arg 9142 mov r1, r4 9143 bl __aeabi_fcmpeq @ is arg == self? 9144 cmp r0, #0 @ zero == no 9145 moveq r1, #0 @ return zero for NaN 9146 ldmeqfd sp!, {r4, pc} 9147 9148 mov r0, r4 @ recover arg 9149 bl __aeabi_f2lz @ convert float to long 9150 ldmfd sp!, {r4, pc} 9151 9152 9153/* continuation for OP_DOUBLE_TO_LONG */ 9154/* 9155 * Convert the double in r0/r1 to a long in r0/r1. 9156 * 9157 * We have to clip values to long min/max per the specification. The 9158 * expected common case is a "reasonable" value that converts directly 9159 * to modest integer. The EABI convert function isn't doing this for us. 9160 */ 9161d2l_doconv: 9162 stmfd sp!, {r4, r5, lr} @ save regs 9163 ldr r3, .LOP_DOUBLE_TO_LONG_max @ (double)maxlong, hi 9164 sub sp, sp, #4 @ align for EABI 9165 mov r2, #0 @ (double)maxlong, lo 9166 mov r4, r0 @ save r0 9167 mov r5, r1 @ and r1 9168 bl __aeabi_dcmpge @ is arg >= maxlong? 9169 cmp r0, #0 @ nonzero == yes 9170 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9171 mvnne r1, #0x80000000 9172 bne 1f 9173 9174 mov r0, r4 @ recover arg 9175 mov r1, r5 9176 ldr r3, .LOP_DOUBLE_TO_LONG_min @ (double)minlong, hi 9177 mov r2, #0 @ (double)minlong, lo 9178 bl __aeabi_dcmple @ is arg <= minlong? 9179 cmp r0, #0 @ nonzero == yes 9180 movne r0, #0 @ return minlong (8000000000000000) 9181 movne r1, #0x80000000 9182 bne 1f 9183 9184 mov r0, r4 @ recover arg 9185 mov r1, r5 9186 mov r2, r4 @ compare against self 9187 mov r3, r5 9188 bl __aeabi_dcmpeq @ is arg == self? 9189 cmp r0, #0 @ zero == no 9190 moveq r1, #0 @ return zero for NaN 9191 beq 1f 9192 9193 mov r0, r4 @ recover arg 9194 mov r1, r5 9195 bl __aeabi_d2lz @ convert double to long 9196 91971: 9198 add sp, sp, #4 9199 ldmfd sp!, {r4, r5, pc} 9200 9201.LOP_DOUBLE_TO_LONG_max: 9202 .word 0x43e00000 @ maxlong, as a double (high word) 9203.LOP_DOUBLE_TO_LONG_min: 9204 .word 0xc3e00000 @ minlong, as a double (high word) 9205 9206 9207/* continuation for OP_MUL_LONG */ 9208 9209.LOP_MUL_LONG_finish: 9210 GET_INST_OPCODE(ip) @ extract opcode from rINST 9211 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9212 GOTO_OPCODE(ip) @ jump to next instruction 9213 9214 9215/* continuation for OP_SHL_LONG */ 9216 9217.LOP_SHL_LONG_finish: 9218 mov r0, r0, asl r2 @ r0<- r0 << r2 9219 GET_INST_OPCODE(ip) @ extract opcode from rINST 9220 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9221 GOTO_OPCODE(ip) @ jump to next instruction 9222 9223 9224/* continuation for OP_SHR_LONG */ 9225 9226.LOP_SHR_LONG_finish: 9227 mov r1, r1, asr r2 @ r1<- r1 >> r2 9228 GET_INST_OPCODE(ip) @ extract opcode from rINST 9229 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9230 GOTO_OPCODE(ip) @ jump to next instruction 9231 9232 9233/* continuation for OP_USHR_LONG */ 9234 9235.LOP_USHR_LONG_finish: 9236 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9237 GET_INST_OPCODE(ip) @ extract opcode from rINST 9238 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9239 GOTO_OPCODE(ip) @ jump to next instruction 9240 9241 9242/* continuation for OP_SHL_LONG_2ADDR */ 9243 9244.LOP_SHL_LONG_2ADDR_finish: 9245 GET_INST_OPCODE(ip) @ extract opcode from rINST 9246 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9247 GOTO_OPCODE(ip) @ jump to next instruction 9248 9249 9250/* continuation for OP_SHR_LONG_2ADDR */ 9251 9252.LOP_SHR_LONG_2ADDR_finish: 9253 GET_INST_OPCODE(ip) @ extract opcode from rINST 9254 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9255 GOTO_OPCODE(ip) @ jump to next instruction 9256 9257 9258/* continuation for OP_USHR_LONG_2ADDR */ 9259 9260.LOP_USHR_LONG_2ADDR_finish: 9261 GET_INST_OPCODE(ip) @ extract opcode from rINST 9262 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9263 GOTO_OPCODE(ip) @ jump to next instruction 9264 9265 9266/* continuation for OP_EXECUTE_INLINE */ 9267 9268 /* 9269 * Extract args, call function. 9270 * r0 = #of args (0-4) 9271 * r10 = call index 9272 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9273 * 9274 * Other ideas: 9275 * - Use a jump table from the main piece to jump directly into the 9276 * AND/LDR pairs. Costs a data load, saves a branch. 9277 * - Have five separate pieces that do the loading, so we can work the 9278 * interleave a little better. Increases code size. 9279 */ 9280.LOP_EXECUTE_INLINE_continue: 9281 rsb r0, r0, #4 @ r0<- 4-r0 9282 FETCH(r9, 2) @ r9<- FEDC 9283 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9284 bl common_abort @ (skipped due to ARM prefetch) 92854: and ip, r9, #0xf000 @ isolate F 9286 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92873: and ip, r9, #0x0f00 @ isolate E 9288 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92892: and ip, r9, #0x00f0 @ isolate D 9290 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92911: and ip, r9, #0x000f @ isolate C 9292 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92930: 9294 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9295 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9296 @ (not reached) 9297 9298.LOP_EXECUTE_INLINE_table: 9299 .word gDvmInlineOpsTable 9300 9301 9302 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9303 .global dvmAsmSisterEnd 9304dvmAsmSisterEnd: 9305 9306/* File: armv5te/footer.S */ 9307/* 9308 * =========================================================================== 9309 * Common subroutines and data 9310 * =========================================================================== 9311 */ 9312 9313 .text 9314 .align 2 9315 9316/* 9317 * Common code when a backward branch is taken. 9318 * 9319 * On entry: 9320 * r9 is PC adjustment *in bytes* 9321 */ 9322common_backwardBranch: 9323 mov r0, #kInterpEntryInstr 9324 bl common_periodicChecks 9325 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9326 GET_INST_OPCODE(ip) @ extract opcode from rINST 9327 GOTO_OPCODE(ip) @ jump to next instruction 9328 9329 9330/* 9331 * Need to see if the thread needs to be suspended or debugger/profiler 9332 * activity has begun. 9333 * 9334 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9335 * have to do the second ldr. 9336 * 9337 * TODO: reduce this so we're just checking a single location. 9338 * 9339 * On entry: 9340 * r0 is reentry type, e.g. kInterpEntryInstr 9341 * r9 is trampoline PC adjustment *in bytes* 9342 */ 9343common_periodicChecks: 9344 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9345 9346#if defined(WITH_DEBUGGER) 9347 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9348#endif 9349#if defined(WITH_PROFILER) 9350 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9351#endif 9352 9353 ldr r3, [r3] @ r3<- suspendCount (int) 9354 9355#if defined(WITH_DEBUGGER) 9356 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9357#endif 9358#if defined (WITH_PROFILER) 9359 ldr r2, [r2] @ r2<- activeProfilers (int) 9360#endif 9361 9362 cmp r3, #0 @ suspend pending? 9363 bne 2f @ yes, do full suspension check 9364 9365#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9366# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9367 orrs r1, r1, r2 @ r1<- r1 | r2 9368 cmp r1, #0 @ debugger attached or profiler started? 9369# elif defined(WITH_DEBUGGER) 9370 cmp r1, #0 @ debugger attached? 9371# elif defined(WITH_PROFILER) 9372 cmp r2, #0 @ profiler started? 9373# endif 9374 bne 3f @ debugger/profiler, switch interp 9375#endif 9376 9377 bx lr @ nothing to do, return 9378 93792: @ check suspend 9380 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9381 EXPORT_PC() @ need for precise GC 9382 b dvmCheckSuspendPending @ suspend if necessary, then return 9383 93843: @ debugger/profiler enabled, bail out 9385 add rPC, rPC, r9 @ update rPC 9386 str r0, [rGLUE, #offGlue_entryPoint] 9387 mov r1, #1 @ "want switch" = true 9388 b common_gotoBail 9389 9390 9391/* 9392 * The equivalent of "goto bail", this calls through the "bail handler". 9393 * 9394 * State registers will be saved to the "glue" area before bailing. 9395 * 9396 * On entry: 9397 * r1 is "bool changeInterp", indicating if we want to switch to the 9398 * other interpreter or just bail all the way out 9399 */ 9400common_gotoBail: 9401 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9402 mov r0, rGLUE @ r0<- glue ptr 9403 b dvmMterpStdBail @ call(glue, changeInterp) 9404 9405 @add r1, r1, #1 @ using (boolean+1) 9406 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9407 @bl _longjmp @ does not return 9408 @bl common_abort 9409 9410 9411/* 9412 * Common code for method invocation with range. 9413 * 9414 * On entry: 9415 * r0 is "Method* methodToCall", the method we're trying to call 9416 */ 9417common_invokeMethodRange: 9418.LinvokeNewRange: 9419 @ prepare to copy args to "outs" area of current frame 9420 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9421 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9422 beq .LinvokeArgsDone @ if no args, skip the rest 9423 FETCH(r1, 2) @ r1<- CCCC 9424 9425 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9426 @ (very few methods have > 10 args; could unroll for common cases) 9427 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9428 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9429 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 94301: ldr r1, [r3], #4 @ val = *fp++ 9431 subs r2, r2, #1 @ count-- 9432 str r1, [r10], #4 @ *outs++ = val 9433 bne 1b @ ...while count != 0 9434 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9435 b .LinvokeArgsDone 9436 9437/* 9438 * Common code for method invocation without range. 9439 * 9440 * On entry: 9441 * r0 is "Method* methodToCall", the method we're trying to call 9442 */ 9443common_invokeMethodNoRange: 9444.LinvokeNewNoRange: 9445 @ prepare to copy args to "outs" area of current frame 9446 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9447 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9448 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9449 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9450 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9451 beq .LinvokeArgsDone 9452 9453 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9454.LinvokeNonRange: 9455 rsb r2, r2, #5 @ r2<- 5-r2 9456 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9457 bl common_abort @ (skipped due to ARM prefetch) 94585: and ip, rINST, #0x0f00 @ isolate A 9459 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9460 mov r0, r0 @ nop 9461 str r2, [r10, #-4]! @ *--outs = vA 94624: and ip, r1, #0xf000 @ isolate G 9463 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9464 mov r0, r0 @ nop 9465 str r2, [r10, #-4]! @ *--outs = vG 94663: and ip, r1, #0x0f00 @ isolate F 9467 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9468 mov r0, r0 @ nop 9469 str r2, [r10, #-4]! @ *--outs = vF 94702: and ip, r1, #0x00f0 @ isolate E 9471 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9472 mov r0, r0 @ nop 9473 str r2, [r10, #-4]! @ *--outs = vE 94741: and ip, r1, #0x000f @ isolate D 9475 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9476 mov r0, r0 @ nop 9477 str r2, [r10, #-4]! @ *--outs = vD 94780: @ fall through to .LinvokeArgsDone 9479 9480.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9481 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9482 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9483 @ find space for the new stack frame, check for overflow 9484 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9485 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9486 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9487@ bl common_dumpRegs 9488 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9489 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9490 cmp r3, r9 @ bottom < interpStackEnd? 9491 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9492 blt .LstackOverflow @ yes, this frame will overflow stack 9493 9494 @ set up newSaveArea 9495#ifdef EASY_GDB 9496 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9497 str ip, [r10, #offStackSaveArea_prevSave] 9498#endif 9499 str rFP, [r10, #offStackSaveArea_prevFrame] 9500 str rPC, [r10, #offStackSaveArea_savedPc] 9501 str r0, [r10, #offStackSaveArea_method] 9502 tst r3, #ACC_NATIVE 9503 bne .LinvokeNative 9504 9505 /* 9506 stmfd sp!, {r0-r3} 9507 bl common_printNewline 9508 mov r0, rFP 9509 mov r1, #0 9510 bl dvmDumpFp 9511 ldmfd sp!, {r0-r3} 9512 stmfd sp!, {r0-r3} 9513 mov r0, r1 9514 mov r1, r10 9515 bl dvmDumpFp 9516 bl common_printNewline 9517 ldmfd sp!, {r0-r3} 9518 */ 9519 9520 ldrh r9, [r2] @ r9 <- load INST from new PC 9521 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9522 mov rPC, r2 @ publish new rPC 9523 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9524 9525 @ Update "glue" values for the new method 9526 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9527 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9528 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9529 mov rFP, r1 @ fp = newFp 9530 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9531 mov rINST, r9 @ publish new rINST 9532 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9533 GOTO_OPCODE(ip) @ jump to next instruction 9534 9535.LinvokeNative: 9536 @ Prep for the native call 9537 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9538 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9539 ldr r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext 9540 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9541 str r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext 9542 mov r9, r3 @ r9<- glue->self (preserve) 9543 9544 mov r2, r0 @ r2<- methodToCall 9545 mov r0, r1 @ r0<- newFp (points to args) 9546 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9547 9548#ifdef ASSIST_DEBUGGER 9549 /* insert fake function header to help gdb find the stack frame */ 9550 b .Lskip 9551 .type dalvik_mterp, %function 9552dalvik_mterp: 9553 .fnstart 9554 MTERP_ENTRY1 9555 MTERP_ENTRY2 9556.Lskip: 9557#endif 9558 9559 @mov lr, pc @ set return addr 9560 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9561 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9562 9563 @ native return; r9=self, r10=newSaveArea 9564 @ equivalent to dvmPopJniLocals 9565 ldr r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop 9566 ldr r1, [r9, #offThread_exception] @ check for exception 9567 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9568 cmp r1, #0 @ null? 9569 str r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0 9570 bne common_exceptionThrown @ no, handle exception 9571 9572 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9573 GET_INST_OPCODE(ip) @ extract opcode from rINST 9574 GOTO_OPCODE(ip) @ jump to next instruction 9575 9576.LstackOverflow: 9577 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9578 bl dvmHandleStackOverflow 9579 b common_exceptionThrown 9580#ifdef ASSIST_DEBUGGER 9581 .fnend 9582#endif 9583 9584 9585 /* 9586 * Common code for method invocation, calling through "glue code". 9587 * 9588 * TODO: now that we have range and non-range invoke handlers, this 9589 * needs to be split into two. Maybe just create entry points 9590 * that set r9 and jump here? 9591 * 9592 * On entry: 9593 * r0 is "Method* methodToCall", the method we're trying to call 9594 * r9 is "bool methodCallRange", indicating if this is a /range variant 9595 */ 9596 .if 0 9597.LinvokeOld: 9598 sub sp, sp, #8 @ space for args + pad 9599 FETCH(ip, 2) @ ip<- FEDC or CCCC 9600 mov r2, r0 @ A2<- methodToCall 9601 mov r0, rGLUE @ A0<- glue 9602 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9603 mov r1, r9 @ A1<- methodCallRange 9604 mov r3, rINST, lsr #8 @ A3<- AA 9605 str ip, [sp, #0] @ A4<- ip 9606 bl dvmMterp_invokeMethod @ call the C invokeMethod 9607 add sp, sp, #8 @ remove arg area 9608 b common_resumeAfterGlueCall @ continue to next instruction 9609 .endif 9610 9611 9612 9613/* 9614 * Common code for handling a return instruction. 9615 * 9616 * This does not return. 9617 */ 9618common_returnFromMethod: 9619.LreturnNew: 9620 mov r0, #kInterpEntryReturn 9621 mov r9, #0 9622 bl common_periodicChecks 9623 9624 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9625 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9626 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9627 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9628 @ r2<- method we're returning to 9629 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9630 cmp r2, #0 @ is this a break frame? 9631 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9632 mov r1, #0 @ "want switch" = false 9633 beq common_gotoBail @ break frame, bail out completely 9634 9635 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9636 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9637 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9638 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9639 GET_INST_OPCODE(ip) @ extract opcode from rINST 9640 mov rPC, r9 @ publish new rPC 9641 str r1, [rGLUE, #offGlue_methodClassDex] 9642 GOTO_OPCODE(ip) @ jump to next instruction 9643 9644 /* 9645 * Return handling, calls through "glue code". 9646 */ 9647 .if 0 9648.LreturnOld: 9649 SAVE_PC_FP_TO_GLUE() @ export state 9650 mov r0, rGLUE @ arg to function 9651 bl dvmMterp_returnFromMethod 9652 b common_resumeAfterGlueCall 9653 .endif 9654 9655 9656/* 9657 * Somebody has thrown an exception. Handle it. 9658 * 9659 * If the exception processing code returns to us (instead of falling 9660 * out of the interpreter), continue with whatever the next instruction 9661 * now happens to be. 9662 * 9663 * This does not return. 9664 */ 9665common_exceptionThrown: 9666.LexceptionNew: 9667 mov r0, #kInterpEntryThrow 9668 mov r9, #0 9669 bl common_periodicChecks 9670 9671 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9672 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9673 mov r1, r10 @ r1<- self 9674 mov r0, r9 @ r0<- exception 9675 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9676 mov r3, #0 @ r3<- NULL 9677 str r3, [r10, #offThread_exception] @ self->exception = NULL 9678 9679 /* set up args and a local for "&fp" */ 9680 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9681 str rFP, [sp, #-4]! @ *--sp = fp 9682 mov ip, sp @ ip<- &fp 9683 mov r3, #0 @ r3<- false 9684 str ip, [sp, #-4]! @ *--sp = &fp 9685 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9686 mov r0, r10 @ r0<- self 9687 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9688 mov r2, r9 @ r2<- exception 9689 sub r1, rPC, r1 @ r1<- pc - method->insns 9690 mov r1, r1, asr #1 @ r1<- offset in code units 9691 9692 /* call, r0 gets catchRelPc (a code-unit offset) */ 9693 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9694 9695 /* fix earlier stack overflow if necessary; may trash rFP */ 9696 ldrb r1, [r10, #offThread_stackOverflowed] 9697 cmp r1, #0 @ did we overflow earlier? 9698 beq 1f @ no, skip ahead 9699 mov rFP, r0 @ save relPc result in rFP 9700 mov r0, r10 @ r0<- self 9701 bl dvmCleanupStackOverflow @ call(self) 9702 mov r0, rFP @ restore result 97031: 9704 9705 /* update frame pointer and check result from dvmFindCatchBlock */ 9706 ldr rFP, [sp, #4] @ retrieve the updated rFP 9707 cmp r0, #0 @ is catchRelPc < 0? 9708 add sp, sp, #8 @ restore stack 9709 bmi .LnotCaughtLocally 9710 9711 /* adjust locals to match self->curFrame and updated PC */ 9712 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9713 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9714 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9715 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9716 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9717 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9718 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9719 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9720 9721 /* release the tracked alloc on the exception */ 9722 mov r0, r9 @ r0<- exception 9723 mov r1, r10 @ r1<- self 9724 bl dvmReleaseTrackedAlloc @ release the exception 9725 9726 /* restore the exception if the handler wants it */ 9727 FETCH_INST() @ load rINST from rPC 9728 GET_INST_OPCODE(ip) @ extract opcode from rINST 9729 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9730 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9731 GOTO_OPCODE(ip) @ jump to next instruction 9732 9733.LnotCaughtLocally: @ r9=exception, r10=self 9734 /* fix stack overflow if necessary */ 9735 ldrb r1, [r10, #offThread_stackOverflowed] 9736 cmp r1, #0 @ did we overflow earlier? 9737 movne r0, r10 @ if yes: r0<- self 9738 blne dvmCleanupStackOverflow @ if yes: call(self) 9739 9740 @ may want to show "not caught locally" debug messages here 9741#if DVM_SHOW_EXCEPTION >= 2 9742 /* call __android_log_print(prio, tag, format, ...) */ 9743 /* "Exception %s from %s:%d not caught locally" */ 9744 @ dvmLineNumFromPC(method, pc - method->insns) 9745 ldr r0, [rGLUE, #offGlue_method] 9746 ldr r1, [r0, #offMethod_insns] 9747 sub r1, rPC, r1 9748 asr r1, r1, #1 9749 bl dvmLineNumFromPC 9750 str r0, [sp, #-4]! 9751 @ dvmGetMethodSourceFile(method) 9752 ldr r0, [rGLUE, #offGlue_method] 9753 bl dvmGetMethodSourceFile 9754 str r0, [sp, #-4]! 9755 @ exception->clazz->descriptor 9756 ldr r3, [r9, #offObject_clazz] 9757 ldr r3, [r3, #offClassObject_descriptor] 9758 @ 9759 ldr r2, strExceptionNotCaughtLocally 9760 ldr r1, strLogTag 9761 mov r0, #3 @ LOG_DEBUG 9762 bl __android_log_print 9763#endif 9764 str r9, [r10, #offThread_exception] @ restore exception 9765 mov r0, r9 @ r0<- exception 9766 mov r1, r10 @ r1<- self 9767 bl dvmReleaseTrackedAlloc @ release the exception 9768 mov r1, #0 @ "want switch" = false 9769 b common_gotoBail @ bail out 9770 9771 9772 /* 9773 * Exception handling, calls through "glue code". 9774 */ 9775 .if 0 9776.LexceptionOld: 9777 SAVE_PC_FP_TO_GLUE() @ export state 9778 mov r0, rGLUE @ arg to function 9779 bl dvmMterp_exceptionThrown 9780 b common_resumeAfterGlueCall 9781 .endif 9782 9783 9784/* 9785 * After returning from a "glued" function, pull out the updated 9786 * values and start executing at the next instruction. 9787 */ 9788common_resumeAfterGlueCall: 9789 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9790 FETCH_INST() @ load rINST from rPC 9791 GET_INST_OPCODE(ip) @ extract opcode from rINST 9792 GOTO_OPCODE(ip) @ jump to next instruction 9793 9794/* 9795 * Invalid array index. 9796 */ 9797common_errArrayIndex: 9798 EXPORT_PC() 9799 ldr r0, strArrayIndexException 9800 mov r1, #0 9801 bl dvmThrowException 9802 b common_exceptionThrown 9803 9804/* 9805 * Invalid array value. 9806 */ 9807common_errArrayStore: 9808 EXPORT_PC() 9809 ldr r0, strArrayStoreException 9810 mov r1, #0 9811 bl dvmThrowException 9812 b common_exceptionThrown 9813 9814/* 9815 * Integer divide or mod by zero. 9816 */ 9817common_errDivideByZero: 9818 EXPORT_PC() 9819 ldr r0, strArithmeticException 9820 ldr r1, strDivideByZero 9821 bl dvmThrowException 9822 b common_exceptionThrown 9823 9824/* 9825 * Attempt to allocate an array with a negative size. 9826 */ 9827common_errNegativeArraySize: 9828 EXPORT_PC() 9829 ldr r0, strNegativeArraySizeException 9830 mov r1, #0 9831 bl dvmThrowException 9832 b common_exceptionThrown 9833 9834/* 9835 * Invocation of a non-existent method. 9836 */ 9837common_errNoSuchMethod: 9838 EXPORT_PC() 9839 ldr r0, strNoSuchMethodError 9840 mov r1, #0 9841 bl dvmThrowException 9842 b common_exceptionThrown 9843 9844/* 9845 * We encountered a null object when we weren't expecting one. We 9846 * export the PC, throw a NullPointerException, and goto the exception 9847 * processing code. 9848 */ 9849common_errNullObject: 9850 EXPORT_PC() 9851 ldr r0, strNullPointerException 9852 mov r1, #0 9853 bl dvmThrowException 9854 b common_exceptionThrown 9855 9856/* 9857 * For debugging, cause an immediate fault. The source address will 9858 * be in lr (use a bl instruction to jump here). 9859 */ 9860common_abort: 9861 ldr pc, .LdeadFood 9862.LdeadFood: 9863 .word 0xdeadf00d 9864 9865/* 9866 * Spit out a "we were here", preserving all registers. (The attempt 9867 * to save ip won't work, but we need to save an even number of 9868 * registers for EABI 64-bit stack alignment.) 9869 */ 9870 .macro SQUEAK num 9871common_squeak\num: 9872 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9873 ldr r0, strSqueak 9874 mov r1, #\num 9875 bl printf 9876 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9877 bx lr 9878 .endm 9879 9880 SQUEAK 0 9881 SQUEAK 1 9882 SQUEAK 2 9883 SQUEAK 3 9884 SQUEAK 4 9885 SQUEAK 5 9886 9887/* 9888 * Spit out the number in r0, preserving registers. 9889 */ 9890common_printNum: 9891 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9892 mov r1, r0 9893 ldr r0, strSqueak 9894 bl printf 9895 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9896 bx lr 9897 9898/* 9899 * Print a newline, preserving registers. 9900 */ 9901common_printNewline: 9902 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9903 ldr r0, strNewline 9904 bl printf 9905 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9906 bx lr 9907 9908 /* 9909 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9910 */ 9911common_printHex: 9912 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9913 mov r1, r0 9914 ldr r0, strPrintHex 9915 bl printf 9916 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9917 bx lr 9918 9919/* 9920 * Print the 64-bit quantity in r0-r1, preserving registers. 9921 */ 9922common_printLong: 9923 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9924 mov r3, r1 9925 mov r2, r0 9926 ldr r0, strPrintLong 9927 bl printf 9928 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9929 bx lr 9930 9931/* 9932 * Print full method info. Pass the Method* in r0. Preserves regs. 9933 */ 9934common_printMethod: 9935 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9936 bl dvmMterpPrintMethod 9937 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9938 bx lr 9939 9940/* 9941 * Call a C helper function that dumps regs and possibly some 9942 * additional info. Requires the C function to be compiled in. 9943 */ 9944 .if 0 9945common_dumpRegs: 9946 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9947 bl dvmMterpDumpArmRegs 9948 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9949 bx lr 9950 .endif 9951 9952 9953/* 9954 * String references, must be close to the code that uses them. 9955 */ 9956 .align 2 9957strArithmeticException: 9958 .word .LstrArithmeticException 9959strArrayIndexException: 9960 .word .LstrArrayIndexException 9961strArrayStoreException: 9962 .word .LstrArrayStoreException 9963strDivideByZero: 9964 .word .LstrDivideByZero 9965strNegativeArraySizeException: 9966 .word .LstrNegativeArraySizeException 9967strNoSuchMethodError: 9968 .word .LstrNoSuchMethodError 9969strNullPointerException: 9970 .word .LstrNullPointerException 9971 9972strLogTag: 9973 .word .LstrLogTag 9974strExceptionNotCaughtLocally: 9975 .word .LstrExceptionNotCaughtLocally 9976 9977strNewline: 9978 .word .LstrNewline 9979strSqueak: 9980 .word .LstrSqueak 9981strPrintHex: 9982 .word .LstrPrintHex 9983strPrintLong: 9984 .word .LstrPrintLong 9985 9986/* 9987 * Zero-terminated ASCII string data. 9988 * 9989 * On ARM we have two choices: do like gcc does, and LDR from a .word 9990 * with the address, or use an ADR pseudo-op to get the address 9991 * directly. ADR saves 4 bytes and an indirection, but it's using a 9992 * PC-relative addressing mode and hence has a limited range, which 9993 * makes it not work well with mergeable string sections. 9994 */ 9995 .section .rodata.str1.4,"aMS",%progbits,1 9996 9997.LstrBadEntryPoint: 9998 .asciz "Bad entry point %d\n" 9999.LstrArithmeticException: 10000 .asciz "Ljava/lang/ArithmeticException;" 10001.LstrArrayIndexException: 10002 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10003.LstrArrayStoreException: 10004 .asciz "Ljava/lang/ArrayStoreException;" 10005.LstrClassCastException: 10006 .asciz "Ljava/lang/ClassCastException;" 10007.LstrDivideByZero: 10008 .asciz "divide by zero" 10009.LstrFilledNewArrayNotImpl: 10010 .asciz "filled-new-array only implemented for objects and 'int'" 10011.LstrInternalError: 10012 .asciz "Ljava/lang/InternalError;" 10013.LstrInstantiationError: 10014 .asciz "Ljava/lang/InstantiationError;" 10015.LstrNegativeArraySizeException: 10016 .asciz "Ljava/lang/NegativeArraySizeException;" 10017.LstrNoSuchMethodError: 10018 .asciz "Ljava/lang/NoSuchMethodError;" 10019.LstrNullPointerException: 10020 .asciz "Ljava/lang/NullPointerException;" 10021 10022.LstrLogTag: 10023 .asciz "mterp" 10024.LstrExceptionNotCaughtLocally: 10025 .asciz "Exception %s from %s:%d not caught locally\n" 10026 10027.LstrNewline: 10028 .asciz "\n" 10029.LstrSqueak: 10030 .asciz "<%d>" 10031.LstrPrintHex: 10032 .asciz "<0x%x>" 10033.LstrPrintLong: 10034 .asciz "<%lld>" 10035 10036 10037