InterpAsm-armv5te-vfp.S revision a80b76553c2b9f33c4063ae8c69c5362d961de81
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rIBASE interpreted instruction base pointer, used for computed goto 67 r8 rINST first 16-bit code unit of current instruction 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rIBASE r7 79#define rINST r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178 179/* 180 * Get/set the 32-bit value from a Dalvik register. 181 */ 182#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 183#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 184 185/* 186 * Convert a virtual register index into an address. 187 */ 188#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 189 add _reg, rFP, _vreg, lsl #2 190 191/* 192 * This is a #include, not a %include, because we want the C pre-processor 193 * to expand the macros into assembler assignment statements. 194 */ 195#include "../common/asm-constants.h" 196 197 198/* File: armv5te/platform.S */ 199/* 200 * =========================================================================== 201 * CPU-version-specific defines 202 * =========================================================================== 203 */ 204 205/* 206 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 207 * one-way branch. 208 * 209 * May modify IP. Does not modify LR. 210 */ 211.macro LDR_PC source 212 ldr pc, \source 213.endm 214 215/* 216 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 217 * Jump to subroutine. 218 * 219 * May modify IP and LR. 220 */ 221.macro LDR_PC_LR source 222 mov lr, pc 223 ldr pc, \source 224.endm 225 226/* 227 * Macro for "LDMFD SP!, {...regs...,PC}". 228 * 229 * May modify IP and LR. 230 */ 231.macro LDMFD_PC regs 232 ldmfd sp!, {\regs,pc} 233.endm 234 235 236/* File: armv5te/entry.S */ 237/* 238 * Copyright (C) 2008 The Android Open Source Project 239 * 240 * Licensed under the Apache License, Version 2.0 (the "License"); 241 * you may not use this file except in compliance with the License. 242 * You may obtain a copy of the License at 243 * 244 * http://www.apache.org/licenses/LICENSE-2.0 245 * 246 * Unless required by applicable law or agreed to in writing, software 247 * distributed under the License is distributed on an "AS IS" BASIS, 248 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 249 * See the License for the specific language governing permissions and 250 * limitations under the License. 251 */ 252/* 253 * Interpreter entry point. 254 */ 255 256/* 257 * We don't have formal stack frames, so gdb scans upward in the code 258 * to find the start of the function (a label with the %function type), 259 * and then looks at the next few instructions to figure out what 260 * got pushed onto the stack. From this it figures out how to restore 261 * the registers, including PC, for the previous stack frame. If gdb 262 * sees a non-function label, it stops scanning, so either we need to 263 * have nothing but assembler-local labels between the entry point and 264 * the break, or we need to fake it out. 265 * 266 * When this is defined, we add some stuff to make gdb less confused. 267 */ 268#define ASSIST_DEBUGGER 1 269 270 .text 271 .align 2 272 .global dvmMterpStdRun 273 .type dvmMterpStdRun, %function 274 275/* 276 * On entry: 277 * r0 MterpGlue* glue 278 * 279 * This function returns a boolean "changeInterp" value. The return comes 280 * via a call to dvmMterpStdBail(). 281 */ 282dvmMterpStdRun: 283#define MTERP_ENTRY1 \ 284 .save {r4-r10,fp,lr}; \ 285 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 286#define MTERP_ENTRY2 \ 287 .pad #4; \ 288 sub sp, sp, #4 @ align 64 289 290 .fnstart 291 MTERP_ENTRY1 292 MTERP_ENTRY2 293 294 /* save stack pointer, add magic word for debuggerd */ 295 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 296 297 /* set up "named" registers, figure out entry point */ 298 mov rGLUE, r0 @ set rGLUE 299 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 300 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 301 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 302 cmp r1, #kInterpEntryInstr @ usual case? 303 bne .Lnot_instr @ no, handle it 304 305 /* start executing the instruction at rPC */ 306 FETCH_INST() @ load rINST from rPC 307 GET_INST_OPCODE(ip) @ extract opcode from rINST 308 GOTO_OPCODE(ip) @ jump to next instruction 309 310.Lnot_instr: 311 cmp r1, #kInterpEntryReturn @ were we returning from a method? 312 beq common_returnFromMethod 313 314.Lnot_return: 315 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 316 beq common_exceptionThrown 317 318.Lbad_arg: 319 ldr r0, strBadEntryPoint 320 @ r1 holds value of entryPoint 321 bl printf 322 bl dvmAbort 323 .fnend 324 325 326 .global dvmMterpStdBail 327 .type dvmMterpStdBail, %function 328 329/* 330 * Restore the stack pointer and PC from the save point established on entry. 331 * This is essentially the same as a longjmp, but should be cheaper. The 332 * last instruction causes us to return to whoever called dvmMterpStdRun. 333 * 334 * We pushed some registers on the stack in dvmMterpStdRun, then saved 335 * SP and LR. Here we restore SP, restore the registers, and then restore 336 * LR to PC. 337 * 338 * On entry: 339 * r0 MterpGlue* glue 340 * r1 bool changeInterp 341 */ 342dvmMterpStdBail: 343 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 344 mov r0, r1 @ return the changeInterp value 345 add sp, sp, #4 @ un-align 64 346 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 347 348 349/* 350 * String references. 351 */ 352strBadEntryPoint: 353 .word .LstrBadEntryPoint 354 355 356 357 .global dvmAsmInstructionStart 358 .type dvmAsmInstructionStart, %function 359dvmAsmInstructionStart = .L_OP_NOP 360 .text 361 362/* ------------------------------ */ 363 .balign 64 364.L_OP_NOP: /* 0x00 */ 365/* File: armv5te/OP_NOP.S */ 366 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 367 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 368 GOTO_OPCODE(ip) @ execute it 369 370#ifdef ASSIST_DEBUGGER 371 /* insert fake function header to help gdb find the stack frame */ 372 .type dalvik_inst, %function 373dalvik_inst: 374 .fnstart 375 MTERP_ENTRY1 376 MTERP_ENTRY2 377 .fnend 378#endif 379 380 381/* ------------------------------ */ 382 .balign 64 383.L_OP_MOVE: /* 0x01 */ 384/* File: armv5te/OP_MOVE.S */ 385 /* for move, move-object, long-to-int */ 386 /* op vA, vB */ 387 mov r1, rINST, lsr #12 @ r1<- B from 15:12 388 mov r0, rINST, lsr #8 @ r0<- A from 11:8 389 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 390 GET_VREG(r2, r1) @ r2<- fp[B] 391 and r0, r0, #15 392 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 393 SET_VREG(r2, r0) @ fp[A]<- r2 394 GOTO_OPCODE(ip) @ execute next instruction 395 396 397/* ------------------------------ */ 398 .balign 64 399.L_OP_MOVE_FROM16: /* 0x02 */ 400/* File: armv5te/OP_MOVE_FROM16.S */ 401 /* for: move/from16, move-object/from16 */ 402 /* op vAA, vBBBB */ 403 FETCH(r1, 1) @ r1<- BBBB 404 mov r0, rINST, lsr #8 @ r0<- AA 405 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 406 GET_VREG(r2, r1) @ r2<- fp[BBBB] 407 GET_INST_OPCODE(ip) @ extract opcode from rINST 408 SET_VREG(r2, r0) @ fp[AA]<- r2 409 GOTO_OPCODE(ip) @ jump to next instruction 410 411 412/* ------------------------------ */ 413 .balign 64 414.L_OP_MOVE_16: /* 0x03 */ 415/* File: armv5te/OP_MOVE_16.S */ 416 /* for: move/16, move-object/16 */ 417 /* op vAAAA, vBBBB */ 418 FETCH(r1, 2) @ r1<- BBBB 419 FETCH(r0, 1) @ r0<- AAAA 420 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 421 GET_VREG(r2, r1) @ r2<- fp[BBBB] 422 GET_INST_OPCODE(ip) @ extract opcode from rINST 423 SET_VREG(r2, r0) @ fp[AAAA]<- r2 424 GOTO_OPCODE(ip) @ jump to next instruction 425 426 427/* ------------------------------ */ 428 .balign 64 429.L_OP_MOVE_WIDE: /* 0x04 */ 430/* File: armv5te/OP_MOVE_WIDE.S */ 431 /* move-wide vA, vB */ 432 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 433 mov r2, rINST, lsr #8 @ r2<- A(+) 434 mov r3, rINST, lsr #12 @ r3<- B 435 and r2, r2, #15 436 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 437 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 438 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 439 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 440 GET_INST_OPCODE(ip) @ extract opcode from rINST 441 stmia r2, {r0-r1} @ fp[A]<- r0/r1 442 GOTO_OPCODE(ip) @ jump to next instruction 443 444 445/* ------------------------------ */ 446 .balign 64 447.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 448/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 449 /* move-wide/from16 vAA, vBBBB */ 450 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 451 FETCH(r3, 1) @ r3<- BBBB 452 mov r2, rINST, lsr #8 @ r2<- AA 453 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 454 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 455 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 457 GET_INST_OPCODE(ip) @ extract opcode from rINST 458 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 459 GOTO_OPCODE(ip) @ jump to next instruction 460 461 462/* ------------------------------ */ 463 .balign 64 464.L_OP_MOVE_WIDE_16: /* 0x06 */ 465/* File: armv5te/OP_MOVE_WIDE_16.S */ 466 /* move-wide/16 vAAAA, vBBBB */ 467 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 468 FETCH(r3, 2) @ r3<- BBBB 469 FETCH(r2, 1) @ r2<- AAAA 470 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 471 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 472 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 473 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 474 GET_INST_OPCODE(ip) @ extract opcode from rINST 475 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 476 GOTO_OPCODE(ip) @ jump to next instruction 477 478 479/* ------------------------------ */ 480 .balign 64 481.L_OP_MOVE_OBJECT: /* 0x07 */ 482/* File: armv5te/OP_MOVE_OBJECT.S */ 483/* File: armv5te/OP_MOVE.S */ 484 /* for move, move-object, long-to-int */ 485 /* op vA, vB */ 486 mov r1, rINST, lsr #12 @ r1<- B from 15:12 487 mov r0, rINST, lsr #8 @ r0<- A from 11:8 488 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 489 GET_VREG(r2, r1) @ r2<- fp[B] 490 and r0, r0, #15 491 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 492 SET_VREG(r2, r0) @ fp[A]<- r2 493 GOTO_OPCODE(ip) @ execute next instruction 494 495 496 497/* ------------------------------ */ 498 .balign 64 499.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 500/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 501/* File: armv5te/OP_MOVE_FROM16.S */ 502 /* for: move/from16, move-object/from16 */ 503 /* op vAA, vBBBB */ 504 FETCH(r1, 1) @ r1<- BBBB 505 mov r0, rINST, lsr #8 @ r0<- AA 506 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 507 GET_VREG(r2, r1) @ r2<- fp[BBBB] 508 GET_INST_OPCODE(ip) @ extract opcode from rINST 509 SET_VREG(r2, r0) @ fp[AA]<- r2 510 GOTO_OPCODE(ip) @ jump to next instruction 511 512 513 514/* ------------------------------ */ 515 .balign 64 516.L_OP_MOVE_OBJECT_16: /* 0x09 */ 517/* File: armv5te/OP_MOVE_OBJECT_16.S */ 518/* File: armv5te/OP_MOVE_16.S */ 519 /* for: move/16, move-object/16 */ 520 /* op vAAAA, vBBBB */ 521 FETCH(r1, 2) @ r1<- BBBB 522 FETCH(r0, 1) @ r0<- AAAA 523 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 524 GET_VREG(r2, r1) @ r2<- fp[BBBB] 525 GET_INST_OPCODE(ip) @ extract opcode from rINST 526 SET_VREG(r2, r0) @ fp[AAAA]<- r2 527 GOTO_OPCODE(ip) @ jump to next instruction 528 529 530 531/* ------------------------------ */ 532 .balign 64 533.L_OP_MOVE_RESULT: /* 0x0a */ 534/* File: armv5te/OP_MOVE_RESULT.S */ 535 /* for: move-result, move-result-object */ 536 /* op vAA */ 537 mov r2, rINST, lsr #8 @ r2<- AA 538 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 539 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 540 GET_INST_OPCODE(ip) @ extract opcode from rINST 541 SET_VREG(r0, r2) @ fp[AA]<- r0 542 GOTO_OPCODE(ip) @ jump to next instruction 543 544 545/* ------------------------------ */ 546 .balign 64 547.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 548/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 549 /* move-result-wide vAA */ 550 mov r2, rINST, lsr #8 @ r2<- AA 551 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 552 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 553 ldmia r3, {r0-r1} @ r0/r1<- retval.j 554 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 555 GET_INST_OPCODE(ip) @ extract opcode from rINST 556 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 557 GOTO_OPCODE(ip) @ jump to next instruction 558 559 560/* ------------------------------ */ 561 .balign 64 562.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 563/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 564/* File: armv5te/OP_MOVE_RESULT.S */ 565 /* for: move-result, move-result-object */ 566 /* op vAA */ 567 mov r2, rINST, lsr #8 @ r2<- AA 568 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 569 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 570 GET_INST_OPCODE(ip) @ extract opcode from rINST 571 SET_VREG(r0, r2) @ fp[AA]<- r0 572 GOTO_OPCODE(ip) @ jump to next instruction 573 574 575 576/* ------------------------------ */ 577 .balign 64 578.L_OP_MOVE_EXCEPTION: /* 0x0d */ 579/* File: armv5te/OP_MOVE_EXCEPTION.S */ 580 /* move-exception vAA */ 581 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 582 mov r2, rINST, lsr #8 @ r2<- AA 583 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 584 mov r1, #0 @ r1<- 0 585 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 586 SET_VREG(r3, r2) @ fp[AA]<- exception obj 587 GET_INST_OPCODE(ip) @ extract opcode from rINST 588 str r1, [r0, #offThread_exception] @ dvmClearException bypass 589 GOTO_OPCODE(ip) @ jump to next instruction 590 591 592/* ------------------------------ */ 593 .balign 64 594.L_OP_RETURN_VOID: /* 0x0e */ 595/* File: armv5te/OP_RETURN_VOID.S */ 596 b common_returnFromMethod 597 598 599/* ------------------------------ */ 600 .balign 64 601.L_OP_RETURN: /* 0x0f */ 602/* File: armv5te/OP_RETURN.S */ 603 /* 604 * Return a 32-bit value. Copies the return value into the "glue" 605 * structure, then jumps to the return handler. 606 * 607 * for: return, return-object 608 */ 609 /* op vAA */ 610 mov r2, rINST, lsr #8 @ r2<- AA 611 GET_VREG(r0, r2) @ r0<- vAA 612 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 613 b common_returnFromMethod 614 615 616/* ------------------------------ */ 617 .balign 64 618.L_OP_RETURN_WIDE: /* 0x10 */ 619/* File: armv5te/OP_RETURN_WIDE.S */ 620 /* 621 * Return a 64-bit value. Copies the return value into the "glue" 622 * structure, then jumps to the return handler. 623 */ 624 /* return-wide vAA */ 625 mov r2, rINST, lsr #8 @ r2<- AA 626 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 627 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 628 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 629 stmia r3, {r0-r1} @ retval<- r0/r1 630 b common_returnFromMethod 631 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN_OBJECT: /* 0x11 */ 636/* File: armv5te/OP_RETURN_OBJECT.S */ 637/* File: armv5te/OP_RETURN.S */ 638 /* 639 * Return a 32-bit value. Copies the return value into the "glue" 640 * structure, then jumps to the return handler. 641 * 642 * for: return, return-object 643 */ 644 /* op vAA */ 645 mov r2, rINST, lsr #8 @ r2<- AA 646 GET_VREG(r0, r2) @ r0<- vAA 647 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 648 b common_returnFromMethod 649 650 651 652/* ------------------------------ */ 653 .balign 64 654.L_OP_CONST_4: /* 0x12 */ 655/* File: armv5te/OP_CONST_4.S */ 656 /* const/4 vA, #+B */ 657 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 658 mov r0, rINST, lsr #8 @ r0<- A+ 659 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 660 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 661 and r0, r0, #15 662 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 663 SET_VREG(r1, r0) @ fp[A]<- r1 664 GOTO_OPCODE(ip) @ execute next instruction 665 666 667/* ------------------------------ */ 668 .balign 64 669.L_OP_CONST_16: /* 0x13 */ 670/* File: armv5te/OP_CONST_16.S */ 671 /* const/16 vAA, #+BBBB */ 672 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 673 mov r3, rINST, lsr #8 @ r3<- AA 674 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 675 SET_VREG(r0, r3) @ vAA<- r0 676 GET_INST_OPCODE(ip) @ extract opcode from rINST 677 GOTO_OPCODE(ip) @ jump to next instruction 678 679 680/* ------------------------------ */ 681 .balign 64 682.L_OP_CONST: /* 0x14 */ 683/* File: armv5te/OP_CONST.S */ 684 /* const vAA, #+BBBBbbbb */ 685 mov r3, rINST, lsr #8 @ r3<- AA 686 FETCH(r0, 1) @ r0<- bbbb (low) 687 FETCH(r1, 2) @ r1<- BBBB (high) 688 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 689 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 690 GET_INST_OPCODE(ip) @ extract opcode from rINST 691 SET_VREG(r0, r3) @ vAA<- r0 692 GOTO_OPCODE(ip) @ jump to next instruction 693 694 695/* ------------------------------ */ 696 .balign 64 697.L_OP_CONST_HIGH16: /* 0x15 */ 698/* File: armv5te/OP_CONST_HIGH16.S */ 699 /* const/high16 vAA, #+BBBB0000 */ 700 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 701 mov r3, rINST, lsr #8 @ r3<- AA 702 mov r0, r0, lsl #16 @ r0<- BBBB0000 703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 704 SET_VREG(r0, r3) @ vAA<- r0 705 GET_INST_OPCODE(ip) @ extract opcode from rINST 706 GOTO_OPCODE(ip) @ jump to next instruction 707 708 709/* ------------------------------ */ 710 .balign 64 711.L_OP_CONST_WIDE_16: /* 0x16 */ 712/* File: armv5te/OP_CONST_WIDE_16.S */ 713 /* const-wide/16 vAA, #+BBBB */ 714 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 715 mov r3, rINST, lsr #8 @ r3<- AA 716 mov r1, r0, asr #31 @ r1<- ssssssss 717 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 718 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 719 GET_INST_OPCODE(ip) @ extract opcode from rINST 720 stmia r3, {r0-r1} @ vAA<- r0/r1 721 GOTO_OPCODE(ip) @ jump to next instruction 722 723 724/* ------------------------------ */ 725 .balign 64 726.L_OP_CONST_WIDE_32: /* 0x17 */ 727/* File: armv5te/OP_CONST_WIDE_32.S */ 728 /* const-wide/32 vAA, #+BBBBbbbb */ 729 FETCH(r0, 1) @ r0<- 0000bbbb (low) 730 mov r3, rINST, lsr #8 @ r3<- AA 731 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 732 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 733 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 734 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 735 mov r1, r0, asr #31 @ r1<- ssssssss 736 GET_INST_OPCODE(ip) @ extract opcode from rINST 737 stmia r3, {r0-r1} @ vAA<- r0/r1 738 GOTO_OPCODE(ip) @ jump to next instruction 739 740 741/* ------------------------------ */ 742 .balign 64 743.L_OP_CONST_WIDE: /* 0x18 */ 744/* File: armv5te/OP_CONST_WIDE.S */ 745 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 746 FETCH(r0, 1) @ r0<- bbbb (low) 747 FETCH(r1, 2) @ r1<- BBBB (low middle) 748 FETCH(r2, 3) @ r2<- hhhh (high middle) 749 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 750 FETCH(r3, 4) @ r3<- HHHH (high) 751 mov r9, rINST, lsr #8 @ r9<- AA 752 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 753 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 754 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 755 GET_INST_OPCODE(ip) @ extract opcode from rINST 756 stmia r9, {r0-r1} @ vAA<- r0/r1 757 GOTO_OPCODE(ip) @ jump to next instruction 758 759 760/* ------------------------------ */ 761 .balign 64 762.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 763/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 764 /* const-wide/high16 vAA, #+BBBB000000000000 */ 765 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 766 mov r3, rINST, lsr #8 @ r3<- AA 767 mov r0, #0 @ r0<- 00000000 768 mov r1, r1, lsl #16 @ r1<- BBBB0000 769 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 770 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 771 GET_INST_OPCODE(ip) @ extract opcode from rINST 772 stmia r3, {r0-r1} @ vAA<- r0/r1 773 GOTO_OPCODE(ip) @ jump to next instruction 774 775 776/* ------------------------------ */ 777 .balign 64 778.L_OP_CONST_STRING: /* 0x1a */ 779/* File: armv5te/OP_CONST_STRING.S */ 780 /* const/string vAA, String@BBBB */ 781 FETCH(r1, 1) @ r1<- BBBB 782 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 783 mov r9, rINST, lsr #8 @ r9<- AA 784 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 785 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 786 cmp r0, #0 @ not yet resolved? 787 beq .LOP_CONST_STRING_resolve 788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 789 GET_INST_OPCODE(ip) @ extract opcode from rINST 790 SET_VREG(r0, r9) @ vAA<- r0 791 GOTO_OPCODE(ip) @ jump to next instruction 792 793/* ------------------------------ */ 794 .balign 64 795.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 796/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 797 /* const/string vAA, String@BBBBBBBB */ 798 FETCH(r0, 1) @ r0<- bbbb (low) 799 FETCH(r1, 2) @ r1<- BBBB (high) 800 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 801 mov r9, rINST, lsr #8 @ r9<- AA 802 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 803 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 804 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 805 cmp r0, #0 806 beq .LOP_CONST_STRING_JUMBO_resolve 807 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 808 GET_INST_OPCODE(ip) @ extract opcode from rINST 809 SET_VREG(r0, r9) @ vAA<- r0 810 GOTO_OPCODE(ip) @ jump to next instruction 811 812/* ------------------------------ */ 813 .balign 64 814.L_OP_CONST_CLASS: /* 0x1c */ 815/* File: armv5te/OP_CONST_CLASS.S */ 816 /* const/class vAA, Class@BBBB */ 817 FETCH(r1, 1) @ r1<- BBBB 818 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 819 mov r9, rINST, lsr #8 @ r9<- AA 820 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 821 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 822 cmp r0, #0 @ not yet resolved? 823 beq .LOP_CONST_CLASS_resolve 824 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 825 GET_INST_OPCODE(ip) @ extract opcode from rINST 826 SET_VREG(r0, r9) @ vAA<- r0 827 GOTO_OPCODE(ip) @ jump to next instruction 828 829/* ------------------------------ */ 830 .balign 64 831.L_OP_MONITOR_ENTER: /* 0x1d */ 832/* File: armv5te/OP_MONITOR_ENTER.S */ 833 /* 834 * Synchronize on an object. 835 */ 836 /* monitor-enter vAA */ 837 mov r2, rINST, lsr #8 @ r2<- AA 838 GET_VREG(r1, r2) @ r1<- vAA (object) 839 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 840 cmp r1, #0 @ null object? 841 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 842 beq common_errNullObject @ null object, throw an exception 843 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 844 bl dvmLockObject @ call(self, obj) 845#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 846 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 847 ldr r1, [r0, #offThread_exception] @ check for exception 848 cmp r1, #0 849 bne common_exceptionThrown @ exception raised, bail out 850#endif 851 GET_INST_OPCODE(ip) @ extract opcode from rINST 852 GOTO_OPCODE(ip) @ jump to next instruction 853 854 855/* ------------------------------ */ 856 .balign 64 857.L_OP_MONITOR_EXIT: /* 0x1e */ 858/* File: armv5te/OP_MONITOR_EXIT.S */ 859 /* 860 * Unlock an object. 861 * 862 * Exceptions that occur when unlocking a monitor need to appear as 863 * if they happened at the following instruction. See the Dalvik 864 * instruction spec. 865 */ 866 /* monitor-exit vAA */ 867 mov r2, rINST, lsr #8 @ r2<- AA 868 EXPORT_PC() @ before fetch: export the PC 869 GET_VREG(r1, r2) @ r1<- vAA (object) 870 cmp r1, #0 @ null object? 871 beq common_errNullObject @ yes 872 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 873 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 874 cmp r0, #0 @ failed? 875 beq common_exceptionThrown @ yes, exception is pending 876 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 877 GET_INST_OPCODE(ip) @ extract opcode from rINST 878 GOTO_OPCODE(ip) @ jump to next instruction 879 880 881/* ------------------------------ */ 882 .balign 64 883.L_OP_CHECK_CAST: /* 0x1f */ 884/* File: armv5te/OP_CHECK_CAST.S */ 885 /* 886 * Check to see if a cast from one class to another is allowed. 887 */ 888 /* check-cast vAA, class@BBBB */ 889 mov r3, rINST, lsr #8 @ r3<- AA 890 FETCH(r2, 1) @ r2<- BBBB 891 GET_VREG(r9, r3) @ r9<- object 892 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 893 cmp r9, #0 @ is object null? 894 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 895 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 896 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 897 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 898 cmp r1, #0 @ have we resolved this before? 899 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 900.LOP_CHECK_CAST_resolved: 901 cmp r0, r1 @ same class (trivial success)? 902 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 903.LOP_CHECK_CAST_okay: 904 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 905 GET_INST_OPCODE(ip) @ extract opcode from rINST 906 GOTO_OPCODE(ip) @ jump to next instruction 907 908/* ------------------------------ */ 909 .balign 64 910.L_OP_INSTANCE_OF: /* 0x20 */ 911/* File: armv5te/OP_INSTANCE_OF.S */ 912 /* 913 * Check to see if an object reference is an instance of a class. 914 * 915 * Most common situation is a non-null object, being compared against 916 * an already-resolved class. 917 */ 918 /* instance-of vA, vB, class@CCCC */ 919 mov r3, rINST, lsr #12 @ r3<- B 920 mov r9, rINST, lsr #8 @ r9<- A+ 921 GET_VREG(r0, r3) @ r0<- vB (object) 922 and r9, r9, #15 @ r9<- A 923 cmp r0, #0 @ is object null? 924 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 925 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 926 FETCH(r3, 1) @ r3<- CCCC 927 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 928 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 929 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 930 cmp r1, #0 @ have we resolved this before? 931 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 932.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 933 cmp r0, r1 @ same class (trivial success)? 934 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 935 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 936 937/* ------------------------------ */ 938 .balign 64 939.L_OP_ARRAY_LENGTH: /* 0x21 */ 940/* File: armv5te/OP_ARRAY_LENGTH.S */ 941 /* 942 * Return the length of an array. 943 */ 944 mov r1, rINST, lsr #12 @ r1<- B 945 mov r2, rINST, lsr #8 @ r2<- A+ 946 GET_VREG(r0, r1) @ r0<- vB (object ref) 947 and r2, r2, #15 @ r2<- A 948 cmp r0, #0 @ is object null? 949 beq common_errNullObject @ yup, fail 950 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 951 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 952 GET_INST_OPCODE(ip) @ extract opcode from rINST 953 SET_VREG(r3, r2) @ vB<- length 954 GOTO_OPCODE(ip) @ jump to next instruction 955 956 957/* ------------------------------ */ 958 .balign 64 959.L_OP_NEW_INSTANCE: /* 0x22 */ 960/* File: armv5te/OP_NEW_INSTANCE.S */ 961 /* 962 * Create a new instance of a class. 963 */ 964 /* new-instance vAA, class@BBBB */ 965 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 966 FETCH(r1, 1) @ r1<- BBBB 967 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 968 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 969 EXPORT_PC() @ req'd for init, resolve, alloc 970 cmp r0, #0 @ already resolved? 971 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 972.LOP_NEW_INSTANCE_resolved: @ r0=class 973 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 974 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 975 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 976.LOP_NEW_INSTANCE_initialized: @ r0=class 977 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 978 bl dvmAllocObject @ r0<- new object 979 b .LOP_NEW_INSTANCE_finish @ continue 980 981/* ------------------------------ */ 982 .balign 64 983.L_OP_NEW_ARRAY: /* 0x23 */ 984/* File: armv5te/OP_NEW_ARRAY.S */ 985 /* 986 * Allocate an array of objects, specified with the array class 987 * and a count. 988 * 989 * The verifier guarantees that this is an array class, so we don't 990 * check for it here. 991 */ 992 /* new-array vA, vB, class@CCCC */ 993 mov r0, rINST, lsr #12 @ r0<- B 994 FETCH(r2, 1) @ r2<- CCCC 995 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 996 GET_VREG(r1, r0) @ r1<- vB (array length) 997 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 998 cmp r1, #0 @ check length 999 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1000 bmi common_errNegativeArraySize @ negative length, bail 1001 cmp r0, #0 @ already resolved? 1002 EXPORT_PC() @ req'd for resolve, alloc 1003 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1004 b .LOP_NEW_ARRAY_resolve @ do resolve now 1005 1006/* ------------------------------ */ 1007 .balign 64 1008.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1009/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1010 /* 1011 * Create a new array with elements filled from registers. 1012 * 1013 * for: filled-new-array, filled-new-array/range 1014 */ 1015 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1016 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1017 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1018 FETCH(r1, 1) @ r1<- BBBB 1019 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1020 EXPORT_PC() @ need for resolve and alloc 1021 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1022 mov r10, rINST, lsr #8 @ r10<- AA or BA 1023 cmp r0, #0 @ already resolved? 1024 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10258: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1026 mov r2, #0 @ r2<- false 1027 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1028 bl dvmResolveClass @ r0<- call(clazz, ref) 1029 cmp r0, #0 @ got null? 1030 beq common_exceptionThrown @ yes, handle exception 1031 b .LOP_FILLED_NEW_ARRAY_continue 1032 1033/* ------------------------------ */ 1034 .balign 64 1035.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1036/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1037/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1038 /* 1039 * Create a new array with elements filled from registers. 1040 * 1041 * for: filled-new-array, filled-new-array/range 1042 */ 1043 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1044 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1045 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1046 FETCH(r1, 1) @ r1<- BBBB 1047 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1048 EXPORT_PC() @ need for resolve and alloc 1049 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1050 mov r10, rINST, lsr #8 @ r10<- AA or BA 1051 cmp r0, #0 @ already resolved? 1052 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10538: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1054 mov r2, #0 @ r2<- false 1055 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1056 bl dvmResolveClass @ r0<- call(clazz, ref) 1057 cmp r0, #0 @ got null? 1058 beq common_exceptionThrown @ yes, handle exception 1059 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1060 1061 1062/* ------------------------------ */ 1063 .balign 64 1064.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1065/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1066 /* fill-array-data vAA, +BBBBBBBB */ 1067 FETCH(r0, 1) @ r0<- bbbb (lo) 1068 FETCH(r1, 2) @ r1<- BBBB (hi) 1069 mov r3, rINST, lsr #8 @ r3<- AA 1070 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1071 GET_VREG(r0, r3) @ r0<- vAA (array object) 1072 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1073 EXPORT_PC(); 1074 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1075 cmp r0, #0 @ 0 means an exception is thrown 1076 beq common_exceptionThrown @ has exception 1077 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1078 GET_INST_OPCODE(ip) @ extract opcode from rINST 1079 GOTO_OPCODE(ip) @ jump to next instruction 1080 1081/* ------------------------------ */ 1082 .balign 64 1083.L_OP_THROW: /* 0x27 */ 1084/* File: armv5te/OP_THROW.S */ 1085 /* 1086 * Throw an exception object in the current thread. 1087 */ 1088 /* throw vAA */ 1089 mov r2, rINST, lsr #8 @ r2<- AA 1090 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1091 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1092 cmp r1, #0 @ null object? 1093 beq common_errNullObject @ yes, throw an NPE instead 1094 @ bypass dvmSetException, just store it 1095 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1096 b common_exceptionThrown 1097 1098 1099/* ------------------------------ */ 1100 .balign 64 1101.L_OP_GOTO: /* 0x28 */ 1102/* File: armv5te/OP_GOTO.S */ 1103 /* 1104 * Unconditional branch, 8-bit offset. 1105 * 1106 * The branch distance is a signed code-unit offset, which we need to 1107 * double to get a byte offset. 1108 */ 1109 /* goto +AA */ 1110 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1111 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1112 mov r9, r9, lsl #1 @ r9<- byte offset 1113 bmi common_backwardBranch @ backward branch, do periodic checks 1114 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1115 GET_INST_OPCODE(ip) @ extract opcode from rINST 1116 GOTO_OPCODE(ip) @ jump to next instruction 1117 1118 1119/* ------------------------------ */ 1120 .balign 64 1121.L_OP_GOTO_16: /* 0x29 */ 1122/* File: armv5te/OP_GOTO_16.S */ 1123 /* 1124 * Unconditional branch, 16-bit offset. 1125 * 1126 * The branch distance is a signed code-unit offset, which we need to 1127 * double to get a byte offset. 1128 */ 1129 /* goto/16 +AAAA */ 1130 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1131 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1132 bmi common_backwardBranch @ backward branch, do periodic checks 1133 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1134 GET_INST_OPCODE(ip) @ extract opcode from rINST 1135 GOTO_OPCODE(ip) @ jump to next instruction 1136 1137 1138/* ------------------------------ */ 1139 .balign 64 1140.L_OP_GOTO_32: /* 0x2a */ 1141/* File: armv5te/OP_GOTO_32.S */ 1142 /* 1143 * Unconditional branch, 32-bit offset. 1144 * 1145 * The branch distance is a signed code-unit offset, which we need to 1146 * double to get a byte offset. 1147 * 1148 * Unlike most opcodes, this one is allowed to branch to itself, so 1149 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1150 * instruction doesn't affect the V flag, so we need to clear it 1151 * explicitly. 1152 */ 1153 /* goto/32 +AAAAAAAA */ 1154 FETCH(r0, 1) @ r0<- aaaa (lo) 1155 FETCH(r1, 2) @ r1<- AAAA (hi) 1156 cmp ip, ip @ (clear V flag during stall) 1157 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1158 mov r9, r0, asl #1 @ r9<- byte offset 1159 ble common_backwardBranch @ backward branch, do periodic checks 1160 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1161 GET_INST_OPCODE(ip) @ extract opcode from rINST 1162 GOTO_OPCODE(ip) @ jump to next instruction 1163 1164 1165/* ------------------------------ */ 1166 .balign 64 1167.L_OP_PACKED_SWITCH: /* 0x2b */ 1168/* File: armv5te/OP_PACKED_SWITCH.S */ 1169 /* 1170 * Handle a packed-switch or sparse-switch instruction. In both cases 1171 * we decode it and hand it off to a helper function. 1172 * 1173 * We don't really expect backward branches in a switch statement, but 1174 * they're perfectly legal, so we check for them here. 1175 * 1176 * for: packed-switch, sparse-switch 1177 */ 1178 /* op vAA, +BBBB */ 1179 FETCH(r0, 1) @ r0<- bbbb (lo) 1180 FETCH(r1, 2) @ r1<- BBBB (hi) 1181 mov r3, rINST, lsr #8 @ r3<- AA 1182 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1183 GET_VREG(r1, r3) @ r1<- vAA 1184 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1185 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1186 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1187 bmi common_backwardBranch @ backward branch, do periodic checks 1188 beq common_backwardBranch @ (want to use BLE but V is unknown) 1189 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1190 GET_INST_OPCODE(ip) @ extract opcode from rINST 1191 GOTO_OPCODE(ip) @ jump to next instruction 1192 1193 1194/* ------------------------------ */ 1195 .balign 64 1196.L_OP_SPARSE_SWITCH: /* 0x2c */ 1197/* File: armv5te/OP_SPARSE_SWITCH.S */ 1198/* File: armv5te/OP_PACKED_SWITCH.S */ 1199 /* 1200 * Handle a packed-switch or sparse-switch instruction. In both cases 1201 * we decode it and hand it off to a helper function. 1202 * 1203 * We don't really expect backward branches in a switch statement, but 1204 * they're perfectly legal, so we check for them here. 1205 * 1206 * for: packed-switch, sparse-switch 1207 */ 1208 /* op vAA, +BBBB */ 1209 FETCH(r0, 1) @ r0<- bbbb (lo) 1210 FETCH(r1, 2) @ r1<- BBBB (hi) 1211 mov r3, rINST, lsr #8 @ r3<- AA 1212 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1213 GET_VREG(r1, r3) @ r1<- vAA 1214 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1215 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1216 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1217 bmi common_backwardBranch @ backward branch, do periodic checks 1218 beq common_backwardBranch @ (want to use BLE but V is unknown) 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 GET_INST_OPCODE(ip) @ extract opcode from rINST 1221 GOTO_OPCODE(ip) @ jump to next instruction 1222 1223 1224 1225/* ------------------------------ */ 1226 .balign 64 1227.L_OP_CMPL_FLOAT: /* 0x2d */ 1228/* File: vfp/OP_CMPL_FLOAT.S */ 1229 /* 1230 * Compare two floating-point values. Puts 0, 1, or -1 into the 1231 * destination register based on the results of the comparison. 1232 * 1233 * int compare(x, y) { 1234 * if (x == y) { 1235 * return 0; 1236 * } else if (x > y) { 1237 * return 1; 1238 * } else if (x < y) { 1239 * return -1; 1240 * } else { 1241 * return -1; 1242 * } 1243 * } 1244 */ 1245 /* op vAA, vBB, vCC */ 1246 FETCH(r0, 1) @ r0<- CCBB 1247 and r2, r0, #255 @ r2<- BB 1248 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1249 flds s0, [r2] @ s0<- vBB 1250 mov r3, r0, lsr #8 @ r3<- CC 1251 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1252 flds s1, [r3] @ s1<- vCC 1253 mov r9, rINST, lsr #8 @ r9<- AA 1254 fcmpes s0, s1 @ compare (vBB, vCC) 1255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1256 mvn r0, #0 @ r0<- -1 (default) 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 fmstat @ export status flags 1259 movgt r0, #1 @ (greater than) r1<- 1 1260 moveq r0, #0 @ (equal) r1<- 0 1261 bl .LOP_CMPL_FLOAT_finish @ argh 1262 1263 1264/* ------------------------------ */ 1265 .balign 64 1266.L_OP_CMPG_FLOAT: /* 0x2e */ 1267/* File: vfp/OP_CMPG_FLOAT.S */ 1268 /* 1269 * Compare two floating-point values. Puts 0, 1, or -1 into the 1270 * destination register based on the results of the comparison. 1271 * 1272 * int compare(x, y) { 1273 * if (x == y) { 1274 * return 0; 1275 * } else if (x < y) { 1276 * return -1; 1277 * } else if (x > y) { 1278 * return 1; 1279 * } else { 1280 * return 1; 1281 * } 1282 * } 1283 */ 1284 /* op vAA, vBB, vCC */ 1285 FETCH(r0, 1) @ r0<- CCBB 1286 and r2, r0, #255 @ r2<- BB 1287 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1288 flds s0, [r2] @ s0<- vBB 1289 mov r3, r0, lsr #8 @ r3<- CC 1290 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1291 flds s1, [r3] @ s1<- vCC 1292 mov r9, rINST, lsr #8 @ r9<- AA 1293 fcmpes s0, s1 @ compare (vBB, vCC) 1294 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1295 mov r0, #1 @ r0<- 1 (default) 1296 GET_INST_OPCODE(ip) @ extract opcode from rINST 1297 fmstat @ export status flags 1298 mvnmi r0, #0 @ (less than) r1<- -1 1299 moveq r0, #0 @ (equal) r1<- 0 1300 bl .LOP_CMPG_FLOAT_finish @ argh 1301 1302 1303/* ------------------------------ */ 1304 .balign 64 1305.L_OP_CMPL_DOUBLE: /* 0x2f */ 1306/* File: vfp/OP_CMPL_DOUBLE.S */ 1307 /* 1308 * Compare two floating-point values. Puts 0, 1, or -1 into the 1309 * destination register based on the results of the comparison. 1310 * 1311 * int compare(x, y) { 1312 * if (x == y) { 1313 * return 0; 1314 * } else if (x > y) { 1315 * return 1; 1316 * } else if (x < y) { 1317 * return -1; 1318 * } else { 1319 * return -1; 1320 * } 1321 * } 1322 */ 1323 /* op vAA, vBB, vCC */ 1324 FETCH(r0, 1) @ r0<- CCBB 1325 and r2, r0, #255 @ r2<- BB 1326 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1327 fldd d0, [r2] @ d0<- vBB 1328 mov r3, r0, lsr #8 @ r3<- CC 1329 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1330 fldd d1, [r3] @ d1<- vCC 1331 mov r9, rINST, lsr #8 @ r9<- AA 1332 fcmped d0, d1 @ compare (vBB, vCC) 1333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1334 mvn r0, #0 @ r0<- -1 (default) 1335 GET_INST_OPCODE(ip) @ extract opcode from rINST 1336 fmstat @ export status flags 1337 movgt r0, #1 @ (greater than) r1<- 1 1338 moveq r0, #0 @ (equal) r1<- 0 1339 bl .LOP_CMPL_DOUBLE_finish @ argh 1340 1341 1342/* ------------------------------ */ 1343 .balign 64 1344.L_OP_CMPG_DOUBLE: /* 0x30 */ 1345/* File: vfp/OP_CMPG_DOUBLE.S */ 1346 /* 1347 * Compare two floating-point values. Puts 0, 1, or -1 into the 1348 * destination register based on the results of the comparison. 1349 * 1350 * int compare(x, y) { 1351 * if (x == y) { 1352 * return 0; 1353 * } else if (x < y) { 1354 * return -1; 1355 * } else if (x > y) { 1356 * return 1; 1357 * } else { 1358 * return 1; 1359 * } 1360 * } 1361 */ 1362 /* op vAA, vBB, vCC */ 1363 FETCH(r0, 1) @ r0<- CCBB 1364 and r2, r0, #255 @ r2<- BB 1365 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1366 fldd d0, [r2] @ d0<- vBB 1367 mov r3, r0, lsr #8 @ r3<- CC 1368 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1369 fldd d1, [r3] @ d1<- vCC 1370 mov r9, rINST, lsr #8 @ r9<- AA 1371 fcmped d0, d1 @ compare (vBB, vCC) 1372 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1373 mov r0, #1 @ r0<- 1 (default) 1374 GET_INST_OPCODE(ip) @ extract opcode from rINST 1375 fmstat @ export status flags 1376 mvnmi r0, #0 @ (less than) r1<- -1 1377 moveq r0, #0 @ (equal) r1<- 0 1378 bl .LOP_CMPG_DOUBLE_finish @ argh 1379 1380 1381/* ------------------------------ */ 1382 .balign 64 1383.L_OP_CMP_LONG: /* 0x31 */ 1384/* File: armv5te/OP_CMP_LONG.S */ 1385 /* 1386 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1387 * register based on the results of the comparison. 1388 * 1389 * We load the full values with LDM, but in practice many values could 1390 * be resolved by only looking at the high word. This could be made 1391 * faster or slower by splitting the LDM into a pair of LDRs. 1392 * 1393 * If we just wanted to set condition flags, we could do this: 1394 * subs ip, r0, r2 1395 * sbcs ip, r1, r3 1396 * subeqs ip, r0, r2 1397 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1398 * integer value, which we can do with 2 conditional mov/mvn instructions 1399 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1400 * us a constant 5-cycle path plus a branch at the end to the 1401 * instruction epilogue code. The multi-compare approach below needs 1402 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1403 * in the worst case (the 64-bit values are equal). 1404 */ 1405 /* cmp-long vAA, vBB, vCC */ 1406 FETCH(r0, 1) @ r0<- CCBB 1407 mov r9, rINST, lsr #8 @ r9<- AA 1408 and r2, r0, #255 @ r2<- BB 1409 mov r3, r0, lsr #8 @ r3<- CC 1410 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1411 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1412 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1413 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1414 cmp r1, r3 @ compare (vBB+1, vCC+1) 1415 blt .LOP_CMP_LONG_less @ signed compare on high part 1416 bgt .LOP_CMP_LONG_greater 1417 subs r1, r0, r2 @ r1<- r0 - r2 1418 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1419 bne .LOP_CMP_LONG_less 1420 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1421 1422/* ------------------------------ */ 1423 .balign 64 1424.L_OP_IF_EQ: /* 0x32 */ 1425/* File: armv5te/OP_IF_EQ.S */ 1426/* File: armv5te/bincmp.S */ 1427 /* 1428 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1429 * fragment that specifies the *reverse* comparison to perform, e.g. 1430 * for "if-le" you would use "gt". 1431 * 1432 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1433 */ 1434 /* if-cmp vA, vB, +CCCC */ 1435 mov r0, rINST, lsr #8 @ r0<- A+ 1436 mov r1, rINST, lsr #12 @ r1<- B 1437 and r0, r0, #15 1438 GET_VREG(r3, r1) @ r3<- vB 1439 GET_VREG(r2, r0) @ r2<- vA 1440 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1441 cmp r2, r3 @ compare (vA, vB) 1442 bne 1f @ branch to 1 if comparison failed 1443 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1444 movs r9, r9, asl #1 @ convert to bytes, check sign 1445 bmi common_backwardBranch @ yes, do periodic checks 14461: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1447 GET_INST_OPCODE(ip) @ extract opcode from rINST 1448 GOTO_OPCODE(ip) @ jump to next instruction 1449 1450 1451 1452/* ------------------------------ */ 1453 .balign 64 1454.L_OP_IF_NE: /* 0x33 */ 1455/* File: armv5te/OP_IF_NE.S */ 1456/* File: armv5te/bincmp.S */ 1457 /* 1458 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1459 * fragment that specifies the *reverse* comparison to perform, e.g. 1460 * for "if-le" you would use "gt". 1461 * 1462 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1463 */ 1464 /* if-cmp vA, vB, +CCCC */ 1465 mov r0, rINST, lsr #8 @ r0<- A+ 1466 mov r1, rINST, lsr #12 @ r1<- B 1467 and r0, r0, #15 1468 GET_VREG(r3, r1) @ r3<- vB 1469 GET_VREG(r2, r0) @ r2<- vA 1470 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1471 cmp r2, r3 @ compare (vA, vB) 1472 beq 1f @ branch to 1 if comparison failed 1473 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1474 movs r9, r9, asl #1 @ convert to bytes, check sign 1475 bmi common_backwardBranch @ yes, do periodic checks 14761: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1477 GET_INST_OPCODE(ip) @ extract opcode from rINST 1478 GOTO_OPCODE(ip) @ jump to next instruction 1479 1480 1481 1482/* ------------------------------ */ 1483 .balign 64 1484.L_OP_IF_LT: /* 0x34 */ 1485/* File: armv5te/OP_IF_LT.S */ 1486/* File: armv5te/bincmp.S */ 1487 /* 1488 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1489 * fragment that specifies the *reverse* comparison to perform, e.g. 1490 * for "if-le" you would use "gt". 1491 * 1492 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1493 */ 1494 /* if-cmp vA, vB, +CCCC */ 1495 mov r0, rINST, lsr #8 @ r0<- A+ 1496 mov r1, rINST, lsr #12 @ r1<- B 1497 and r0, r0, #15 1498 GET_VREG(r3, r1) @ r3<- vB 1499 GET_VREG(r2, r0) @ r2<- vA 1500 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1501 cmp r2, r3 @ compare (vA, vB) 1502 bge 1f @ branch to 1 if comparison failed 1503 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1504 movs r9, r9, asl #1 @ convert to bytes, check sign 1505 bmi common_backwardBranch @ yes, do periodic checks 15061: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1507 GET_INST_OPCODE(ip) @ extract opcode from rINST 1508 GOTO_OPCODE(ip) @ jump to next instruction 1509 1510 1511 1512/* ------------------------------ */ 1513 .balign 64 1514.L_OP_IF_GE: /* 0x35 */ 1515/* File: armv5te/OP_IF_GE.S */ 1516/* File: armv5te/bincmp.S */ 1517 /* 1518 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1519 * fragment that specifies the *reverse* comparison to perform, e.g. 1520 * for "if-le" you would use "gt". 1521 * 1522 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1523 */ 1524 /* if-cmp vA, vB, +CCCC */ 1525 mov r0, rINST, lsr #8 @ r0<- A+ 1526 mov r1, rINST, lsr #12 @ r1<- B 1527 and r0, r0, #15 1528 GET_VREG(r3, r1) @ r3<- vB 1529 GET_VREG(r2, r0) @ r2<- vA 1530 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1531 cmp r2, r3 @ compare (vA, vB) 1532 blt 1f @ branch to 1 if comparison failed 1533 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1534 movs r9, r9, asl #1 @ convert to bytes, check sign 1535 bmi common_backwardBranch @ yes, do periodic checks 15361: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1537 GET_INST_OPCODE(ip) @ extract opcode from rINST 1538 GOTO_OPCODE(ip) @ jump to next instruction 1539 1540 1541 1542/* ------------------------------ */ 1543 .balign 64 1544.L_OP_IF_GT: /* 0x36 */ 1545/* File: armv5te/OP_IF_GT.S */ 1546/* File: armv5te/bincmp.S */ 1547 /* 1548 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1549 * fragment that specifies the *reverse* comparison to perform, e.g. 1550 * for "if-le" you would use "gt". 1551 * 1552 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1553 */ 1554 /* if-cmp vA, vB, +CCCC */ 1555 mov r0, rINST, lsr #8 @ r0<- A+ 1556 mov r1, rINST, lsr #12 @ r1<- B 1557 and r0, r0, #15 1558 GET_VREG(r3, r1) @ r3<- vB 1559 GET_VREG(r2, r0) @ r2<- vA 1560 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1561 cmp r2, r3 @ compare (vA, vB) 1562 ble 1f @ branch to 1 if comparison failed 1563 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1564 movs r9, r9, asl #1 @ convert to bytes, check sign 1565 bmi common_backwardBranch @ yes, do periodic checks 15661: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 GET_INST_OPCODE(ip) @ extract opcode from rINST 1568 GOTO_OPCODE(ip) @ jump to next instruction 1569 1570 1571 1572/* ------------------------------ */ 1573 .balign 64 1574.L_OP_IF_LE: /* 0x37 */ 1575/* File: armv5te/OP_IF_LE.S */ 1576/* File: armv5te/bincmp.S */ 1577 /* 1578 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1579 * fragment that specifies the *reverse* comparison to perform, e.g. 1580 * for "if-le" you would use "gt". 1581 * 1582 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1583 */ 1584 /* if-cmp vA, vB, +CCCC */ 1585 mov r0, rINST, lsr #8 @ r0<- A+ 1586 mov r1, rINST, lsr #12 @ r1<- B 1587 and r0, r0, #15 1588 GET_VREG(r3, r1) @ r3<- vB 1589 GET_VREG(r2, r0) @ r2<- vA 1590 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1591 cmp r2, r3 @ compare (vA, vB) 1592 bgt 1f @ branch to 1 if comparison failed 1593 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1594 movs r9, r9, asl #1 @ convert to bytes, check sign 1595 bmi common_backwardBranch @ yes, do periodic checks 15961: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1597 GET_INST_OPCODE(ip) @ extract opcode from rINST 1598 GOTO_OPCODE(ip) @ jump to next instruction 1599 1600 1601 1602/* ------------------------------ */ 1603 .balign 64 1604.L_OP_IF_EQZ: /* 0x38 */ 1605/* File: armv5te/OP_IF_EQZ.S */ 1606/* File: armv5te/zcmp.S */ 1607 /* 1608 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1609 * fragment that specifies the *reverse* comparison to perform, e.g. 1610 * for "if-le" you would use "gt". 1611 * 1612 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1613 */ 1614 /* if-cmp vAA, +BBBB */ 1615 mov r0, rINST, lsr #8 @ r0<- AA 1616 GET_VREG(r2, r0) @ r2<- vAA 1617 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1618 cmp r2, #0 @ compare (vA, 0) 1619 bne 1f @ branch to 1 if comparison failed 1620 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1621 movs r9, r9, asl #1 @ convert to bytes, check sign 1622 bmi common_backwardBranch @ backward branch, do periodic checks 16231: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1624 GET_INST_OPCODE(ip) @ extract opcode from rINST 1625 GOTO_OPCODE(ip) @ jump to next instruction 1626 1627 1628 1629/* ------------------------------ */ 1630 .balign 64 1631.L_OP_IF_NEZ: /* 0x39 */ 1632/* File: armv5te/OP_IF_NEZ.S */ 1633/* File: armv5te/zcmp.S */ 1634 /* 1635 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1636 * fragment that specifies the *reverse* comparison to perform, e.g. 1637 * for "if-le" you would use "gt". 1638 * 1639 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1640 */ 1641 /* if-cmp vAA, +BBBB */ 1642 mov r0, rINST, lsr #8 @ r0<- AA 1643 GET_VREG(r2, r0) @ r2<- vAA 1644 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1645 cmp r2, #0 @ compare (vA, 0) 1646 beq 1f @ branch to 1 if comparison failed 1647 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1648 movs r9, r9, asl #1 @ convert to bytes, check sign 1649 bmi common_backwardBranch @ backward branch, do periodic checks 16501: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1651 GET_INST_OPCODE(ip) @ extract opcode from rINST 1652 GOTO_OPCODE(ip) @ jump to next instruction 1653 1654 1655 1656/* ------------------------------ */ 1657 .balign 64 1658.L_OP_IF_LTZ: /* 0x3a */ 1659/* File: armv5te/OP_IF_LTZ.S */ 1660/* File: armv5te/zcmp.S */ 1661 /* 1662 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1663 * fragment that specifies the *reverse* comparison to perform, e.g. 1664 * for "if-le" you would use "gt". 1665 * 1666 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1667 */ 1668 /* if-cmp vAA, +BBBB */ 1669 mov r0, rINST, lsr #8 @ r0<- AA 1670 GET_VREG(r2, r0) @ r2<- vAA 1671 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1672 cmp r2, #0 @ compare (vA, 0) 1673 bge 1f @ branch to 1 if comparison failed 1674 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1675 movs r9, r9, asl #1 @ convert to bytes, check sign 1676 bmi common_backwardBranch @ backward branch, do periodic checks 16771: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 GET_INST_OPCODE(ip) @ extract opcode from rINST 1679 GOTO_OPCODE(ip) @ jump to next instruction 1680 1681 1682 1683/* ------------------------------ */ 1684 .balign 64 1685.L_OP_IF_GEZ: /* 0x3b */ 1686/* File: armv5te/OP_IF_GEZ.S */ 1687/* File: armv5te/zcmp.S */ 1688 /* 1689 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1690 * fragment that specifies the *reverse* comparison to perform, e.g. 1691 * for "if-le" you would use "gt". 1692 * 1693 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1694 */ 1695 /* if-cmp vAA, +BBBB */ 1696 mov r0, rINST, lsr #8 @ r0<- AA 1697 GET_VREG(r2, r0) @ r2<- vAA 1698 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1699 cmp r2, #0 @ compare (vA, 0) 1700 blt 1f @ branch to 1 if comparison failed 1701 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1702 movs r9, r9, asl #1 @ convert to bytes, check sign 1703 bmi common_backwardBranch @ backward branch, do periodic checks 17041: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1705 GET_INST_OPCODE(ip) @ extract opcode from rINST 1706 GOTO_OPCODE(ip) @ jump to next instruction 1707 1708 1709 1710/* ------------------------------ */ 1711 .balign 64 1712.L_OP_IF_GTZ: /* 0x3c */ 1713/* File: armv5te/OP_IF_GTZ.S */ 1714/* File: armv5te/zcmp.S */ 1715 /* 1716 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1717 * fragment that specifies the *reverse* comparison to perform, e.g. 1718 * for "if-le" you would use "gt". 1719 * 1720 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1721 */ 1722 /* if-cmp vAA, +BBBB */ 1723 mov r0, rINST, lsr #8 @ r0<- AA 1724 GET_VREG(r2, r0) @ r2<- vAA 1725 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1726 cmp r2, #0 @ compare (vA, 0) 1727 ble 1f @ branch to 1 if comparison failed 1728 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1729 movs r9, r9, asl #1 @ convert to bytes, check sign 1730 bmi common_backwardBranch @ backward branch, do periodic checks 17311: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1732 GET_INST_OPCODE(ip) @ extract opcode from rINST 1733 GOTO_OPCODE(ip) @ jump to next instruction 1734 1735 1736 1737/* ------------------------------ */ 1738 .balign 64 1739.L_OP_IF_LEZ: /* 0x3d */ 1740/* File: armv5te/OP_IF_LEZ.S */ 1741/* File: armv5te/zcmp.S */ 1742 /* 1743 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1744 * fragment that specifies the *reverse* comparison to perform, e.g. 1745 * for "if-le" you would use "gt". 1746 * 1747 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1748 */ 1749 /* if-cmp vAA, +BBBB */ 1750 mov r0, rINST, lsr #8 @ r0<- AA 1751 GET_VREG(r2, r0) @ r2<- vAA 1752 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1753 cmp r2, #0 @ compare (vA, 0) 1754 bgt 1f @ branch to 1 if comparison failed 1755 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1756 movs r9, r9, asl #1 @ convert to bytes, check sign 1757 bmi common_backwardBranch @ backward branch, do periodic checks 17581: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1759 GET_INST_OPCODE(ip) @ extract opcode from rINST 1760 GOTO_OPCODE(ip) @ jump to next instruction 1761 1762 1763 1764/* ------------------------------ */ 1765 .balign 64 1766.L_OP_UNUSED_3E: /* 0x3e */ 1767/* File: armv5te/OP_UNUSED_3E.S */ 1768/* File: armv5te/unused.S */ 1769 bl common_abort 1770 1771 1772 1773/* ------------------------------ */ 1774 .balign 64 1775.L_OP_UNUSED_3F: /* 0x3f */ 1776/* File: armv5te/OP_UNUSED_3F.S */ 1777/* File: armv5te/unused.S */ 1778 bl common_abort 1779 1780 1781 1782/* ------------------------------ */ 1783 .balign 64 1784.L_OP_UNUSED_40: /* 0x40 */ 1785/* File: armv5te/OP_UNUSED_40.S */ 1786/* File: armv5te/unused.S */ 1787 bl common_abort 1788 1789 1790 1791/* ------------------------------ */ 1792 .balign 64 1793.L_OP_UNUSED_41: /* 0x41 */ 1794/* File: armv5te/OP_UNUSED_41.S */ 1795/* File: armv5te/unused.S */ 1796 bl common_abort 1797 1798 1799 1800/* ------------------------------ */ 1801 .balign 64 1802.L_OP_UNUSED_42: /* 0x42 */ 1803/* File: armv5te/OP_UNUSED_42.S */ 1804/* File: armv5te/unused.S */ 1805 bl common_abort 1806 1807 1808 1809/* ------------------------------ */ 1810 .balign 64 1811.L_OP_UNUSED_43: /* 0x43 */ 1812/* File: armv5te/OP_UNUSED_43.S */ 1813/* File: armv5te/unused.S */ 1814 bl common_abort 1815 1816 1817 1818/* ------------------------------ */ 1819 .balign 64 1820.L_OP_AGET: /* 0x44 */ 1821/* File: armv5te/OP_AGET.S */ 1822 /* 1823 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1824 * 1825 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1826 * instructions. We use a pair of FETCH_Bs instead. 1827 * 1828 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1829 */ 1830 /* op vAA, vBB, vCC */ 1831 FETCH_B(r2, 1, 0) @ r2<- BB 1832 mov r9, rINST, lsr #8 @ r9<- AA 1833 FETCH_B(r3, 1, 1) @ r3<- CC 1834 GET_VREG(r0, r2) @ r0<- vBB (array object) 1835 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1836 cmp r0, #0 @ null array object? 1837 beq common_errNullObject @ yes, bail 1838 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1839 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1840 cmp r1, r3 @ compare unsigned index, length 1841 bcs common_errArrayIndex @ index >= length, bail 1842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1843 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1844 GET_INST_OPCODE(ip) @ extract opcode from rINST 1845 SET_VREG(r2, r9) @ vAA<- r2 1846 GOTO_OPCODE(ip) @ jump to next instruction 1847 1848 1849/* ------------------------------ */ 1850 .balign 64 1851.L_OP_AGET_WIDE: /* 0x45 */ 1852/* File: armv5te/OP_AGET_WIDE.S */ 1853 /* 1854 * Array get, 64 bits. vAA <- vBB[vCC]. 1855 * 1856 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1857 */ 1858 /* aget-wide vAA, vBB, vCC */ 1859 FETCH(r0, 1) @ r0<- CCBB 1860 mov r9, rINST, lsr #8 @ r9<- AA 1861 and r2, r0, #255 @ r2<- BB 1862 mov r3, r0, lsr #8 @ r3<- CC 1863 GET_VREG(r0, r2) @ r0<- vBB (array object) 1864 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1865 cmp r0, #0 @ null array object? 1866 beq common_errNullObject @ yes, bail 1867 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1868 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 1869 cmp r1, r3 @ compare unsigned index, length 1870 bcc .LOP_AGET_WIDE_finish @ okay, continue below 1871 b common_errArrayIndex @ index >= length, bail 1872 @ May want to swap the order of these two branches depending on how the 1873 @ branch prediction (if any) handles conditional forward branches vs. 1874 @ unconditional forward branches. 1875 1876/* ------------------------------ */ 1877 .balign 64 1878.L_OP_AGET_OBJECT: /* 0x46 */ 1879/* File: armv5te/OP_AGET_OBJECT.S */ 1880/* File: armv5te/OP_AGET.S */ 1881 /* 1882 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1883 * 1884 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1885 * instructions. We use a pair of FETCH_Bs instead. 1886 * 1887 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1888 */ 1889 /* op vAA, vBB, vCC */ 1890 FETCH_B(r2, 1, 0) @ r2<- BB 1891 mov r9, rINST, lsr #8 @ r9<- AA 1892 FETCH_B(r3, 1, 1) @ r3<- CC 1893 GET_VREG(r0, r2) @ r0<- vBB (array object) 1894 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1895 cmp r0, #0 @ null array object? 1896 beq common_errNullObject @ yes, bail 1897 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1898 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1899 cmp r1, r3 @ compare unsigned index, length 1900 bcs common_errArrayIndex @ index >= length, bail 1901 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1902 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1903 GET_INST_OPCODE(ip) @ extract opcode from rINST 1904 SET_VREG(r2, r9) @ vAA<- r2 1905 GOTO_OPCODE(ip) @ jump to next instruction 1906 1907 1908 1909/* ------------------------------ */ 1910 .balign 64 1911.L_OP_AGET_BOOLEAN: /* 0x47 */ 1912/* File: armv5te/OP_AGET_BOOLEAN.S */ 1913/* File: armv5te/OP_AGET.S */ 1914 /* 1915 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1916 * 1917 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1918 * instructions. We use a pair of FETCH_Bs instead. 1919 * 1920 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1921 */ 1922 /* op vAA, vBB, vCC */ 1923 FETCH_B(r2, 1, 0) @ r2<- BB 1924 mov r9, rINST, lsr #8 @ r9<- AA 1925 FETCH_B(r3, 1, 1) @ r3<- CC 1926 GET_VREG(r0, r2) @ r0<- vBB (array object) 1927 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1928 cmp r0, #0 @ null array object? 1929 beq common_errNullObject @ yes, bail 1930 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1931 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1932 cmp r1, r3 @ compare unsigned index, length 1933 bcs common_errArrayIndex @ index >= length, bail 1934 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1935 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1936 GET_INST_OPCODE(ip) @ extract opcode from rINST 1937 SET_VREG(r2, r9) @ vAA<- r2 1938 GOTO_OPCODE(ip) @ jump to next instruction 1939 1940 1941 1942/* ------------------------------ */ 1943 .balign 64 1944.L_OP_AGET_BYTE: /* 0x48 */ 1945/* File: armv5te/OP_AGET_BYTE.S */ 1946/* File: armv5te/OP_AGET.S */ 1947 /* 1948 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1949 * 1950 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1951 * instructions. We use a pair of FETCH_Bs instead. 1952 * 1953 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1954 */ 1955 /* op vAA, vBB, vCC */ 1956 FETCH_B(r2, 1, 0) @ r2<- BB 1957 mov r9, rINST, lsr #8 @ r9<- AA 1958 FETCH_B(r3, 1, 1) @ r3<- CC 1959 GET_VREG(r0, r2) @ r0<- vBB (array object) 1960 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1961 cmp r0, #0 @ null array object? 1962 beq common_errNullObject @ yes, bail 1963 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1964 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1965 cmp r1, r3 @ compare unsigned index, length 1966 bcs common_errArrayIndex @ index >= length, bail 1967 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1968 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1969 GET_INST_OPCODE(ip) @ extract opcode from rINST 1970 SET_VREG(r2, r9) @ vAA<- r2 1971 GOTO_OPCODE(ip) @ jump to next instruction 1972 1973 1974 1975/* ------------------------------ */ 1976 .balign 64 1977.L_OP_AGET_CHAR: /* 0x49 */ 1978/* File: armv5te/OP_AGET_CHAR.S */ 1979/* File: armv5te/OP_AGET.S */ 1980 /* 1981 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1982 * 1983 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1984 * instructions. We use a pair of FETCH_Bs instead. 1985 * 1986 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1987 */ 1988 /* op vAA, vBB, vCC */ 1989 FETCH_B(r2, 1, 0) @ r2<- BB 1990 mov r9, rINST, lsr #8 @ r9<- AA 1991 FETCH_B(r3, 1, 1) @ r3<- CC 1992 GET_VREG(r0, r2) @ r0<- vBB (array object) 1993 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1994 cmp r0, #0 @ null array object? 1995 beq common_errNullObject @ yes, bail 1996 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1997 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 1998 cmp r1, r3 @ compare unsigned index, length 1999 bcs common_errArrayIndex @ index >= length, bail 2000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2001 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2002 GET_INST_OPCODE(ip) @ extract opcode from rINST 2003 SET_VREG(r2, r9) @ vAA<- r2 2004 GOTO_OPCODE(ip) @ jump to next instruction 2005 2006 2007 2008/* ------------------------------ */ 2009 .balign 64 2010.L_OP_AGET_SHORT: /* 0x4a */ 2011/* File: armv5te/OP_AGET_SHORT.S */ 2012/* File: armv5te/OP_AGET.S */ 2013 /* 2014 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2015 * 2016 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2017 * instructions. We use a pair of FETCH_Bs instead. 2018 * 2019 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2020 */ 2021 /* op vAA, vBB, vCC */ 2022 FETCH_B(r2, 1, 0) @ r2<- BB 2023 mov r9, rINST, lsr #8 @ r9<- AA 2024 FETCH_B(r3, 1, 1) @ r3<- CC 2025 GET_VREG(r0, r2) @ r0<- vBB (array object) 2026 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2027 cmp r0, #0 @ null array object? 2028 beq common_errNullObject @ yes, bail 2029 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2030 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2031 cmp r1, r3 @ compare unsigned index, length 2032 bcs common_errArrayIndex @ index >= length, bail 2033 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2034 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2035 GET_INST_OPCODE(ip) @ extract opcode from rINST 2036 SET_VREG(r2, r9) @ vAA<- r2 2037 GOTO_OPCODE(ip) @ jump to next instruction 2038 2039 2040 2041/* ------------------------------ */ 2042 .balign 64 2043.L_OP_APUT: /* 0x4b */ 2044/* File: armv5te/OP_APUT.S */ 2045 /* 2046 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2047 * 2048 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2049 * instructions. We use a pair of FETCH_Bs instead. 2050 * 2051 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2052 */ 2053 /* op vAA, vBB, vCC */ 2054 FETCH_B(r2, 1, 0) @ r2<- BB 2055 mov r9, rINST, lsr #8 @ r9<- AA 2056 FETCH_B(r3, 1, 1) @ r3<- CC 2057 GET_VREG(r0, r2) @ r0<- vBB (array object) 2058 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2059 cmp r0, #0 @ null array object? 2060 beq common_errNullObject @ yes, bail 2061 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2062 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2063 cmp r1, r3 @ compare unsigned index, length 2064 bcs common_errArrayIndex @ index >= length, bail 2065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2066 GET_VREG(r2, r9) @ r2<- vAA 2067 GET_INST_OPCODE(ip) @ extract opcode from rINST 2068 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2069 GOTO_OPCODE(ip) @ jump to next instruction 2070 2071 2072/* ------------------------------ */ 2073 .balign 64 2074.L_OP_APUT_WIDE: /* 0x4c */ 2075/* File: armv5te/OP_APUT_WIDE.S */ 2076 /* 2077 * Array put, 64 bits. vBB[vCC] <- vAA. 2078 * 2079 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2080 */ 2081 /* aput-wide vAA, vBB, vCC */ 2082 FETCH(r0, 1) @ r0<- CCBB 2083 mov r9, rINST, lsr #8 @ r9<- AA 2084 and r2, r0, #255 @ r2<- BB 2085 mov r3, r0, lsr #8 @ r3<- CC 2086 GET_VREG(r0, r2) @ r0<- vBB (array object) 2087 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2088 cmp r0, #0 @ null array object? 2089 beq common_errNullObject @ yes, bail 2090 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2091 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2092 cmp r1, r3 @ compare unsigned index, length 2093 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2094 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2095 b common_errArrayIndex @ index >= length, bail 2096 @ May want to swap the order of these two branches depending on how the 2097 @ branch prediction (if any) handles conditional forward branches vs. 2098 @ unconditional forward branches. 2099 2100/* ------------------------------ */ 2101 .balign 64 2102.L_OP_APUT_OBJECT: /* 0x4d */ 2103/* File: armv5te/OP_APUT_OBJECT.S */ 2104 /* 2105 * Store an object into an array. vBB[vCC] <- vAA. 2106 * 2107 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2108 * instructions. We use a pair of FETCH_Bs instead. 2109 */ 2110 /* op vAA, vBB, vCC */ 2111 FETCH(r0, 1) @ r0<- CCBB 2112 mov r9, rINST, lsr #8 @ r9<- AA 2113 and r2, r0, #255 @ r2<- BB 2114 mov r3, r0, lsr #8 @ r3<- CC 2115 GET_VREG(r1, r2) @ r1<- vBB (array object) 2116 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2117 cmp r1, #0 @ null array object? 2118 GET_VREG(r9, r9) @ r9<- vAA 2119 beq common_errNullObject @ yes, bail 2120 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2121 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2122 cmp r0, r3 @ compare unsigned index, length 2123 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2124 b common_errArrayIndex @ index >= length, bail 2125 2126 2127/* ------------------------------ */ 2128 .balign 64 2129.L_OP_APUT_BOOLEAN: /* 0x4e */ 2130/* File: armv5te/OP_APUT_BOOLEAN.S */ 2131/* File: armv5te/OP_APUT.S */ 2132 /* 2133 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2134 * 2135 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2136 * instructions. We use a pair of FETCH_Bs instead. 2137 * 2138 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2139 */ 2140 /* op vAA, vBB, vCC */ 2141 FETCH_B(r2, 1, 0) @ r2<- BB 2142 mov r9, rINST, lsr #8 @ r9<- AA 2143 FETCH_B(r3, 1, 1) @ r3<- CC 2144 GET_VREG(r0, r2) @ r0<- vBB (array object) 2145 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2146 cmp r0, #0 @ null array object? 2147 beq common_errNullObject @ yes, bail 2148 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2149 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2150 cmp r1, r3 @ compare unsigned index, length 2151 bcs common_errArrayIndex @ index >= length, bail 2152 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2153 GET_VREG(r2, r9) @ r2<- vAA 2154 GET_INST_OPCODE(ip) @ extract opcode from rINST 2155 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2156 GOTO_OPCODE(ip) @ jump to next instruction 2157 2158 2159 2160/* ------------------------------ */ 2161 .balign 64 2162.L_OP_APUT_BYTE: /* 0x4f */ 2163/* File: armv5te/OP_APUT_BYTE.S */ 2164/* File: armv5te/OP_APUT.S */ 2165 /* 2166 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2167 * 2168 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2169 * instructions. We use a pair of FETCH_Bs instead. 2170 * 2171 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2172 */ 2173 /* op vAA, vBB, vCC */ 2174 FETCH_B(r2, 1, 0) @ r2<- BB 2175 mov r9, rINST, lsr #8 @ r9<- AA 2176 FETCH_B(r3, 1, 1) @ r3<- CC 2177 GET_VREG(r0, r2) @ r0<- vBB (array object) 2178 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2179 cmp r0, #0 @ null array object? 2180 beq common_errNullObject @ yes, bail 2181 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2182 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2183 cmp r1, r3 @ compare unsigned index, length 2184 bcs common_errArrayIndex @ index >= length, bail 2185 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2186 GET_VREG(r2, r9) @ r2<- vAA 2187 GET_INST_OPCODE(ip) @ extract opcode from rINST 2188 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2189 GOTO_OPCODE(ip) @ jump to next instruction 2190 2191 2192 2193/* ------------------------------ */ 2194 .balign 64 2195.L_OP_APUT_CHAR: /* 0x50 */ 2196/* File: armv5te/OP_APUT_CHAR.S */ 2197/* File: armv5te/OP_APUT.S */ 2198 /* 2199 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2200 * 2201 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2202 * instructions. We use a pair of FETCH_Bs instead. 2203 * 2204 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2205 */ 2206 /* op vAA, vBB, vCC */ 2207 FETCH_B(r2, 1, 0) @ r2<- BB 2208 mov r9, rINST, lsr #8 @ r9<- AA 2209 FETCH_B(r3, 1, 1) @ r3<- CC 2210 GET_VREG(r0, r2) @ r0<- vBB (array object) 2211 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2212 cmp r0, #0 @ null array object? 2213 beq common_errNullObject @ yes, bail 2214 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2215 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2216 cmp r1, r3 @ compare unsigned index, length 2217 bcs common_errArrayIndex @ index >= length, bail 2218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2219 GET_VREG(r2, r9) @ r2<- vAA 2220 GET_INST_OPCODE(ip) @ extract opcode from rINST 2221 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2222 GOTO_OPCODE(ip) @ jump to next instruction 2223 2224 2225 2226/* ------------------------------ */ 2227 .balign 64 2228.L_OP_APUT_SHORT: /* 0x51 */ 2229/* File: armv5te/OP_APUT_SHORT.S */ 2230/* File: armv5te/OP_APUT.S */ 2231 /* 2232 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2233 * 2234 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2235 * instructions. We use a pair of FETCH_Bs instead. 2236 * 2237 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2238 */ 2239 /* op vAA, vBB, vCC */ 2240 FETCH_B(r2, 1, 0) @ r2<- BB 2241 mov r9, rINST, lsr #8 @ r9<- AA 2242 FETCH_B(r3, 1, 1) @ r3<- CC 2243 GET_VREG(r0, r2) @ r0<- vBB (array object) 2244 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2245 cmp r0, #0 @ null array object? 2246 beq common_errNullObject @ yes, bail 2247 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2248 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2249 cmp r1, r3 @ compare unsigned index, length 2250 bcs common_errArrayIndex @ index >= length, bail 2251 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2252 GET_VREG(r2, r9) @ r2<- vAA 2253 GET_INST_OPCODE(ip) @ extract opcode from rINST 2254 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2255 GOTO_OPCODE(ip) @ jump to next instruction 2256 2257 2258 2259/* ------------------------------ */ 2260 .balign 64 2261.L_OP_IGET: /* 0x52 */ 2262/* File: armv5te/OP_IGET.S */ 2263 /* 2264 * General 32-bit instance field get. 2265 * 2266 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2267 */ 2268 /* op vA, vB, field@CCCC */ 2269 mov r0, rINST, lsr #12 @ r0<- B 2270 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2271 FETCH(r1, 1) @ r1<- field ref CCCC 2272 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2273 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2274 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2275 cmp r0, #0 @ is resolved entry null? 2276 bne .LOP_IGET_finish @ no, already resolved 22778: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2278 EXPORT_PC() @ resolve() could throw 2279 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2280 bl dvmResolveInstField @ r0<- resolved InstField ptr 2281 cmp r0, #0 2282 bne .LOP_IGET_finish 2283 b common_exceptionThrown 2284 2285/* ------------------------------ */ 2286 .balign 64 2287.L_OP_IGET_WIDE: /* 0x53 */ 2288/* File: armv5te/OP_IGET_WIDE.S */ 2289 /* 2290 * Wide 32-bit instance field get. 2291 */ 2292 /* iget-wide vA, vB, field@CCCC */ 2293 mov r0, rINST, lsr #12 @ r0<- B 2294 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2295 FETCH(r1, 1) @ r1<- field ref CCCC 2296 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2297 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2298 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2299 cmp r0, #0 @ is resolved entry null? 2300 bne .LOP_IGET_WIDE_finish @ no, already resolved 23018: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2302 EXPORT_PC() @ resolve() could throw 2303 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2304 bl dvmResolveInstField @ r0<- resolved InstField ptr 2305 cmp r0, #0 2306 bne .LOP_IGET_WIDE_finish 2307 b common_exceptionThrown 2308 2309/* ------------------------------ */ 2310 .balign 64 2311.L_OP_IGET_OBJECT: /* 0x54 */ 2312/* File: armv5te/OP_IGET_OBJECT.S */ 2313/* File: armv5te/OP_IGET.S */ 2314 /* 2315 * General 32-bit instance field get. 2316 * 2317 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2318 */ 2319 /* op vA, vB, field@CCCC */ 2320 mov r0, rINST, lsr #12 @ r0<- B 2321 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2322 FETCH(r1, 1) @ r1<- field ref CCCC 2323 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2324 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2325 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2326 cmp r0, #0 @ is resolved entry null? 2327 bne .LOP_IGET_OBJECT_finish @ no, already resolved 23288: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2329 EXPORT_PC() @ resolve() could throw 2330 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2331 bl dvmResolveInstField @ r0<- resolved InstField ptr 2332 cmp r0, #0 2333 bne .LOP_IGET_OBJECT_finish 2334 b common_exceptionThrown 2335 2336 2337/* ------------------------------ */ 2338 .balign 64 2339.L_OP_IGET_BOOLEAN: /* 0x55 */ 2340/* File: armv5te/OP_IGET_BOOLEAN.S */ 2341@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2342/* File: armv5te/OP_IGET.S */ 2343 /* 2344 * General 32-bit instance field get. 2345 * 2346 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2347 */ 2348 /* op vA, vB, field@CCCC */ 2349 mov r0, rINST, lsr #12 @ r0<- B 2350 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2351 FETCH(r1, 1) @ r1<- field ref CCCC 2352 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2353 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2354 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2355 cmp r0, #0 @ is resolved entry null? 2356 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 23578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2358 EXPORT_PC() @ resolve() could throw 2359 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2360 bl dvmResolveInstField @ r0<- resolved InstField ptr 2361 cmp r0, #0 2362 bne .LOP_IGET_BOOLEAN_finish 2363 b common_exceptionThrown 2364 2365 2366/* ------------------------------ */ 2367 .balign 64 2368.L_OP_IGET_BYTE: /* 0x56 */ 2369/* File: armv5te/OP_IGET_BYTE.S */ 2370@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2371/* File: armv5te/OP_IGET.S */ 2372 /* 2373 * General 32-bit instance field get. 2374 * 2375 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2376 */ 2377 /* op vA, vB, field@CCCC */ 2378 mov r0, rINST, lsr #12 @ r0<- B 2379 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2380 FETCH(r1, 1) @ r1<- field ref CCCC 2381 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2382 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2383 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2384 cmp r0, #0 @ is resolved entry null? 2385 bne .LOP_IGET_BYTE_finish @ no, already resolved 23868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2387 EXPORT_PC() @ resolve() could throw 2388 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2389 bl dvmResolveInstField @ r0<- resolved InstField ptr 2390 cmp r0, #0 2391 bne .LOP_IGET_BYTE_finish 2392 b common_exceptionThrown 2393 2394 2395/* ------------------------------ */ 2396 .balign 64 2397.L_OP_IGET_CHAR: /* 0x57 */ 2398/* File: armv5te/OP_IGET_CHAR.S */ 2399@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2400/* File: armv5te/OP_IGET.S */ 2401 /* 2402 * General 32-bit instance field get. 2403 * 2404 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2405 */ 2406 /* op vA, vB, field@CCCC */ 2407 mov r0, rINST, lsr #12 @ r0<- B 2408 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2409 FETCH(r1, 1) @ r1<- field ref CCCC 2410 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2411 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2412 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2413 cmp r0, #0 @ is resolved entry null? 2414 bne .LOP_IGET_CHAR_finish @ no, already resolved 24158: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2416 EXPORT_PC() @ resolve() could throw 2417 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2418 bl dvmResolveInstField @ r0<- resolved InstField ptr 2419 cmp r0, #0 2420 bne .LOP_IGET_CHAR_finish 2421 b common_exceptionThrown 2422 2423 2424/* ------------------------------ */ 2425 .balign 64 2426.L_OP_IGET_SHORT: /* 0x58 */ 2427/* File: armv5te/OP_IGET_SHORT.S */ 2428@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2429/* File: armv5te/OP_IGET.S */ 2430 /* 2431 * General 32-bit instance field get. 2432 * 2433 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2434 */ 2435 /* op vA, vB, field@CCCC */ 2436 mov r0, rINST, lsr #12 @ r0<- B 2437 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2438 FETCH(r1, 1) @ r1<- field ref CCCC 2439 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2440 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2441 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2442 cmp r0, #0 @ is resolved entry null? 2443 bne .LOP_IGET_SHORT_finish @ no, already resolved 24448: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2445 EXPORT_PC() @ resolve() could throw 2446 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2447 bl dvmResolveInstField @ r0<- resolved InstField ptr 2448 cmp r0, #0 2449 bne .LOP_IGET_SHORT_finish 2450 b common_exceptionThrown 2451 2452 2453/* ------------------------------ */ 2454 .balign 64 2455.L_OP_IPUT: /* 0x59 */ 2456/* File: armv5te/OP_IPUT.S */ 2457 /* 2458 * General 32-bit instance field put. 2459 * 2460 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2461 */ 2462 /* op vA, vB, field@CCCC */ 2463 mov r0, rINST, lsr #12 @ r0<- B 2464 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2465 FETCH(r1, 1) @ r1<- field ref CCCC 2466 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2467 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2468 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2469 cmp r0, #0 @ is resolved entry null? 2470 bne .LOP_IPUT_finish @ no, already resolved 24718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2472 EXPORT_PC() @ resolve() could throw 2473 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2474 bl dvmResolveInstField @ r0<- resolved InstField ptr 2475 cmp r0, #0 @ success? 2476 bne .LOP_IPUT_finish @ yes, finish up 2477 b common_exceptionThrown 2478 2479/* ------------------------------ */ 2480 .balign 64 2481.L_OP_IPUT_WIDE: /* 0x5a */ 2482/* File: armv5te/OP_IPUT_WIDE.S */ 2483 /* iput-wide vA, vB, field@CCCC */ 2484 mov r0, rINST, lsr #12 @ r0<- B 2485 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2486 FETCH(r1, 1) @ r1<- field ref CCCC 2487 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2488 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2489 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2490 cmp r0, #0 @ is resolved entry null? 2491 bne .LOP_IPUT_WIDE_finish @ no, already resolved 24928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2493 EXPORT_PC() @ resolve() could throw 2494 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2495 bl dvmResolveInstField @ r0<- resolved InstField ptr 2496 cmp r0, #0 @ success? 2497 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2498 b common_exceptionThrown 2499 2500/* ------------------------------ */ 2501 .balign 64 2502.L_OP_IPUT_OBJECT: /* 0x5b */ 2503/* File: armv5te/OP_IPUT_OBJECT.S */ 2504/* File: armv5te/OP_IPUT.S */ 2505 /* 2506 * General 32-bit instance field put. 2507 * 2508 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2509 */ 2510 /* op vA, vB, field@CCCC */ 2511 mov r0, rINST, lsr #12 @ r0<- B 2512 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2513 FETCH(r1, 1) @ r1<- field ref CCCC 2514 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2515 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2516 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2517 cmp r0, #0 @ is resolved entry null? 2518 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 25198: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2520 EXPORT_PC() @ resolve() could throw 2521 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2522 bl dvmResolveInstField @ r0<- resolved InstField ptr 2523 cmp r0, #0 @ success? 2524 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2525 b common_exceptionThrown 2526 2527 2528/* ------------------------------ */ 2529 .balign 64 2530.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2531/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2532@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2533/* File: armv5te/OP_IPUT.S */ 2534 /* 2535 * General 32-bit instance field put. 2536 * 2537 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2538 */ 2539 /* op vA, vB, field@CCCC */ 2540 mov r0, rINST, lsr #12 @ r0<- B 2541 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2542 FETCH(r1, 1) @ r1<- field ref CCCC 2543 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2544 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2545 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2546 cmp r0, #0 @ is resolved entry null? 2547 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 25488: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2549 EXPORT_PC() @ resolve() could throw 2550 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2551 bl dvmResolveInstField @ r0<- resolved InstField ptr 2552 cmp r0, #0 @ success? 2553 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2554 b common_exceptionThrown 2555 2556 2557/* ------------------------------ */ 2558 .balign 64 2559.L_OP_IPUT_BYTE: /* 0x5d */ 2560/* File: armv5te/OP_IPUT_BYTE.S */ 2561@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2562/* File: armv5te/OP_IPUT.S */ 2563 /* 2564 * General 32-bit instance field put. 2565 * 2566 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2567 */ 2568 /* op vA, vB, field@CCCC */ 2569 mov r0, rINST, lsr #12 @ r0<- B 2570 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2571 FETCH(r1, 1) @ r1<- field ref CCCC 2572 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2573 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2574 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2575 cmp r0, #0 @ is resolved entry null? 2576 bne .LOP_IPUT_BYTE_finish @ no, already resolved 25778: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2578 EXPORT_PC() @ resolve() could throw 2579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2580 bl dvmResolveInstField @ r0<- resolved InstField ptr 2581 cmp r0, #0 @ success? 2582 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2583 b common_exceptionThrown 2584 2585 2586/* ------------------------------ */ 2587 .balign 64 2588.L_OP_IPUT_CHAR: /* 0x5e */ 2589/* File: armv5te/OP_IPUT_CHAR.S */ 2590@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2591/* File: armv5te/OP_IPUT.S */ 2592 /* 2593 * General 32-bit instance field put. 2594 * 2595 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2596 */ 2597 /* op vA, vB, field@CCCC */ 2598 mov r0, rINST, lsr #12 @ r0<- B 2599 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2600 FETCH(r1, 1) @ r1<- field ref CCCC 2601 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2602 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2603 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2604 cmp r0, #0 @ is resolved entry null? 2605 bne .LOP_IPUT_CHAR_finish @ no, already resolved 26068: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2607 EXPORT_PC() @ resolve() could throw 2608 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2609 bl dvmResolveInstField @ r0<- resolved InstField ptr 2610 cmp r0, #0 @ success? 2611 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2612 b common_exceptionThrown 2613 2614 2615/* ------------------------------ */ 2616 .balign 64 2617.L_OP_IPUT_SHORT: /* 0x5f */ 2618/* File: armv5te/OP_IPUT_SHORT.S */ 2619@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2620/* File: armv5te/OP_IPUT.S */ 2621 /* 2622 * General 32-bit instance field put. 2623 * 2624 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2625 */ 2626 /* op vA, vB, field@CCCC */ 2627 mov r0, rINST, lsr #12 @ r0<- B 2628 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2629 FETCH(r1, 1) @ r1<- field ref CCCC 2630 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2631 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2632 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2633 cmp r0, #0 @ is resolved entry null? 2634 bne .LOP_IPUT_SHORT_finish @ no, already resolved 26358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2636 EXPORT_PC() @ resolve() could throw 2637 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2638 bl dvmResolveInstField @ r0<- resolved InstField ptr 2639 cmp r0, #0 @ success? 2640 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2641 b common_exceptionThrown 2642 2643 2644/* ------------------------------ */ 2645 .balign 64 2646.L_OP_SGET: /* 0x60 */ 2647/* File: armv5te/OP_SGET.S */ 2648 /* 2649 * General 32-bit SGET handler. 2650 * 2651 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2652 */ 2653 /* op vAA, field@BBBB */ 2654 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2655 FETCH(r1, 1) @ r1<- field ref BBBB 2656 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2657 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2658 cmp r0, #0 @ is resolved entry null? 2659 beq .LOP_SGET_resolve @ yes, do resolve 2660.LOP_SGET_finish: @ field ptr in r0 2661 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2662 mov r2, rINST, lsr #8 @ r2<- AA 2663 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2664 SET_VREG(r1, r2) @ fp[AA]<- r1 2665 GET_INST_OPCODE(ip) @ extract opcode from rINST 2666 GOTO_OPCODE(ip) @ jump to next instruction 2667 2668/* ------------------------------ */ 2669 .balign 64 2670.L_OP_SGET_WIDE: /* 0x61 */ 2671/* File: armv5te/OP_SGET_WIDE.S */ 2672 /* 2673 * 64-bit SGET handler. 2674 */ 2675 /* sget-wide vAA, field@BBBB */ 2676 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2677 FETCH(r1, 1) @ r1<- field ref BBBB 2678 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2679 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2680 cmp r0, #0 @ is resolved entry null? 2681 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2682.LOP_SGET_WIDE_finish: 2683 mov r1, rINST, lsr #8 @ r1<- AA 2684 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2685 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2687 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2688 GET_INST_OPCODE(ip) @ extract opcode from rINST 2689 GOTO_OPCODE(ip) @ jump to next instruction 2690 2691/* ------------------------------ */ 2692 .balign 64 2693.L_OP_SGET_OBJECT: /* 0x62 */ 2694/* File: armv5te/OP_SGET_OBJECT.S */ 2695/* File: armv5te/OP_SGET.S */ 2696 /* 2697 * General 32-bit SGET handler. 2698 * 2699 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2700 */ 2701 /* op vAA, field@BBBB */ 2702 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2703 FETCH(r1, 1) @ r1<- field ref BBBB 2704 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2705 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2706 cmp r0, #0 @ is resolved entry null? 2707 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2708.LOP_SGET_OBJECT_finish: @ field ptr in r0 2709 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2710 mov r2, rINST, lsr #8 @ r2<- AA 2711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2712 SET_VREG(r1, r2) @ fp[AA]<- r1 2713 GET_INST_OPCODE(ip) @ extract opcode from rINST 2714 GOTO_OPCODE(ip) @ jump to next instruction 2715 2716 2717/* ------------------------------ */ 2718 .balign 64 2719.L_OP_SGET_BOOLEAN: /* 0x63 */ 2720/* File: armv5te/OP_SGET_BOOLEAN.S */ 2721/* File: armv5te/OP_SGET.S */ 2722 /* 2723 * General 32-bit SGET handler. 2724 * 2725 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2726 */ 2727 /* op vAA, field@BBBB */ 2728 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2729 FETCH(r1, 1) @ r1<- field ref BBBB 2730 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2731 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2732 cmp r0, #0 @ is resolved entry null? 2733 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2734.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2735 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2736 mov r2, rINST, lsr #8 @ r2<- AA 2737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2738 SET_VREG(r1, r2) @ fp[AA]<- r1 2739 GET_INST_OPCODE(ip) @ extract opcode from rINST 2740 GOTO_OPCODE(ip) @ jump to next instruction 2741 2742 2743/* ------------------------------ */ 2744 .balign 64 2745.L_OP_SGET_BYTE: /* 0x64 */ 2746/* File: armv5te/OP_SGET_BYTE.S */ 2747/* File: armv5te/OP_SGET.S */ 2748 /* 2749 * General 32-bit SGET handler. 2750 * 2751 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2752 */ 2753 /* op vAA, field@BBBB */ 2754 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2755 FETCH(r1, 1) @ r1<- field ref BBBB 2756 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2757 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2758 cmp r0, #0 @ is resolved entry null? 2759 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2760.LOP_SGET_BYTE_finish: @ field ptr in r0 2761 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2762 mov r2, rINST, lsr #8 @ r2<- AA 2763 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2764 SET_VREG(r1, r2) @ fp[AA]<- r1 2765 GET_INST_OPCODE(ip) @ extract opcode from rINST 2766 GOTO_OPCODE(ip) @ jump to next instruction 2767 2768 2769/* ------------------------------ */ 2770 .balign 64 2771.L_OP_SGET_CHAR: /* 0x65 */ 2772/* File: armv5te/OP_SGET_CHAR.S */ 2773/* File: armv5te/OP_SGET.S */ 2774 /* 2775 * General 32-bit SGET handler. 2776 * 2777 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2778 */ 2779 /* op vAA, field@BBBB */ 2780 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2781 FETCH(r1, 1) @ r1<- field ref BBBB 2782 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2783 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2784 cmp r0, #0 @ is resolved entry null? 2785 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2786.LOP_SGET_CHAR_finish: @ field ptr in r0 2787 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2788 mov r2, rINST, lsr #8 @ r2<- AA 2789 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2790 SET_VREG(r1, r2) @ fp[AA]<- r1 2791 GET_INST_OPCODE(ip) @ extract opcode from rINST 2792 GOTO_OPCODE(ip) @ jump to next instruction 2793 2794 2795/* ------------------------------ */ 2796 .balign 64 2797.L_OP_SGET_SHORT: /* 0x66 */ 2798/* File: armv5te/OP_SGET_SHORT.S */ 2799/* File: armv5te/OP_SGET.S */ 2800 /* 2801 * General 32-bit SGET handler. 2802 * 2803 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2804 */ 2805 /* op vAA, field@BBBB */ 2806 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2807 FETCH(r1, 1) @ r1<- field ref BBBB 2808 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2809 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2810 cmp r0, #0 @ is resolved entry null? 2811 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2812.LOP_SGET_SHORT_finish: @ field ptr in r0 2813 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2814 mov r2, rINST, lsr #8 @ r2<- AA 2815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2816 SET_VREG(r1, r2) @ fp[AA]<- r1 2817 GET_INST_OPCODE(ip) @ extract opcode from rINST 2818 GOTO_OPCODE(ip) @ jump to next instruction 2819 2820 2821/* ------------------------------ */ 2822 .balign 64 2823.L_OP_SPUT: /* 0x67 */ 2824/* File: armv5te/OP_SPUT.S */ 2825 /* 2826 * General 32-bit SPUT handler. 2827 * 2828 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2829 */ 2830 /* op vAA, field@BBBB */ 2831 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2832 FETCH(r1, 1) @ r1<- field ref BBBB 2833 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2834 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2835 cmp r0, #0 @ is resolved entry null? 2836 beq .LOP_SPUT_resolve @ yes, do resolve 2837.LOP_SPUT_finish: @ field ptr in r0 2838 mov r2, rINST, lsr #8 @ r2<- AA 2839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2840 GET_VREG(r1, r2) @ r1<- fp[AA] 2841 GET_INST_OPCODE(ip) @ extract opcode from rINST 2842 str r1, [r0, #offStaticField_value] @ field<- vAA 2843 GOTO_OPCODE(ip) @ jump to next instruction 2844 2845/* ------------------------------ */ 2846 .balign 64 2847.L_OP_SPUT_WIDE: /* 0x68 */ 2848/* File: armv5te/OP_SPUT_WIDE.S */ 2849 /* 2850 * 64-bit SPUT handler. 2851 */ 2852 /* sput-wide vAA, field@BBBB */ 2853 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2854 FETCH(r1, 1) @ r1<- field ref BBBB 2855 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2856 mov r9, rINST, lsr #8 @ r9<- AA 2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2858 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2859 cmp r0, #0 @ is resolved entry null? 2860 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2861.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 2862 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2863 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 2864 GET_INST_OPCODE(ip) @ extract opcode from rINST 2865 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 2866 GOTO_OPCODE(ip) @ jump to next instruction 2867 2868/* ------------------------------ */ 2869 .balign 64 2870.L_OP_SPUT_OBJECT: /* 0x69 */ 2871/* File: armv5te/OP_SPUT_OBJECT.S */ 2872/* File: armv5te/OP_SPUT.S */ 2873 /* 2874 * General 32-bit SPUT handler. 2875 * 2876 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2877 */ 2878 /* op vAA, field@BBBB */ 2879 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2880 FETCH(r1, 1) @ r1<- field ref BBBB 2881 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2882 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2883 cmp r0, #0 @ is resolved entry null? 2884 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 2885.LOP_SPUT_OBJECT_finish: @ field ptr in r0 2886 mov r2, rINST, lsr #8 @ r2<- AA 2887 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2888 GET_VREG(r1, r2) @ r1<- fp[AA] 2889 GET_INST_OPCODE(ip) @ extract opcode from rINST 2890 str r1, [r0, #offStaticField_value] @ field<- vAA 2891 GOTO_OPCODE(ip) @ jump to next instruction 2892 2893 2894/* ------------------------------ */ 2895 .balign 64 2896.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2897/* File: armv5te/OP_SPUT_BOOLEAN.S */ 2898/* File: armv5te/OP_SPUT.S */ 2899 /* 2900 * General 32-bit SPUT handler. 2901 * 2902 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2903 */ 2904 /* op vAA, field@BBBB */ 2905 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2906 FETCH(r1, 1) @ r1<- field ref BBBB 2907 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2908 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2909 cmp r0, #0 @ is resolved entry null? 2910 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 2911.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 2912 mov r2, rINST, lsr #8 @ r2<- AA 2913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2914 GET_VREG(r1, r2) @ r1<- fp[AA] 2915 GET_INST_OPCODE(ip) @ extract opcode from rINST 2916 str r1, [r0, #offStaticField_value] @ field<- vAA 2917 GOTO_OPCODE(ip) @ jump to next instruction 2918 2919 2920/* ------------------------------ */ 2921 .balign 64 2922.L_OP_SPUT_BYTE: /* 0x6b */ 2923/* File: armv5te/OP_SPUT_BYTE.S */ 2924/* File: armv5te/OP_SPUT.S */ 2925 /* 2926 * General 32-bit SPUT handler. 2927 * 2928 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2929 */ 2930 /* op vAA, field@BBBB */ 2931 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2932 FETCH(r1, 1) @ r1<- field ref BBBB 2933 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2934 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2935 cmp r0, #0 @ is resolved entry null? 2936 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 2937.LOP_SPUT_BYTE_finish: @ field ptr in r0 2938 mov r2, rINST, lsr #8 @ r2<- AA 2939 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2940 GET_VREG(r1, r2) @ r1<- fp[AA] 2941 GET_INST_OPCODE(ip) @ extract opcode from rINST 2942 str r1, [r0, #offStaticField_value] @ field<- vAA 2943 GOTO_OPCODE(ip) @ jump to next instruction 2944 2945 2946/* ------------------------------ */ 2947 .balign 64 2948.L_OP_SPUT_CHAR: /* 0x6c */ 2949/* File: armv5te/OP_SPUT_CHAR.S */ 2950/* File: armv5te/OP_SPUT.S */ 2951 /* 2952 * General 32-bit SPUT handler. 2953 * 2954 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2955 */ 2956 /* op vAA, field@BBBB */ 2957 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2958 FETCH(r1, 1) @ r1<- field ref BBBB 2959 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2960 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2961 cmp r0, #0 @ is resolved entry null? 2962 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 2963.LOP_SPUT_CHAR_finish: @ field ptr in r0 2964 mov r2, rINST, lsr #8 @ r2<- AA 2965 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2966 GET_VREG(r1, r2) @ r1<- fp[AA] 2967 GET_INST_OPCODE(ip) @ extract opcode from rINST 2968 str r1, [r0, #offStaticField_value] @ field<- vAA 2969 GOTO_OPCODE(ip) @ jump to next instruction 2970 2971 2972/* ------------------------------ */ 2973 .balign 64 2974.L_OP_SPUT_SHORT: /* 0x6d */ 2975/* File: armv5te/OP_SPUT_SHORT.S */ 2976/* File: armv5te/OP_SPUT.S */ 2977 /* 2978 * General 32-bit SPUT handler. 2979 * 2980 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2981 */ 2982 /* op vAA, field@BBBB */ 2983 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2984 FETCH(r1, 1) @ r1<- field ref BBBB 2985 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2986 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2987 cmp r0, #0 @ is resolved entry null? 2988 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 2989.LOP_SPUT_SHORT_finish: @ field ptr in r0 2990 mov r2, rINST, lsr #8 @ r2<- AA 2991 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2992 GET_VREG(r1, r2) @ r1<- fp[AA] 2993 GET_INST_OPCODE(ip) @ extract opcode from rINST 2994 str r1, [r0, #offStaticField_value] @ field<- vAA 2995 GOTO_OPCODE(ip) @ jump to next instruction 2996 2997 2998/* ------------------------------ */ 2999 .balign 64 3000.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3001/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3002 /* 3003 * Handle a virtual method call. 3004 * 3005 * for: invoke-virtual, invoke-virtual/range 3006 */ 3007 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3008 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3009 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3010 FETCH(r1, 1) @ r1<- BBBB 3011 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3012 FETCH(r10, 2) @ r10<- GFED or CCCC 3013 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3014 .if (!0) 3015 and r10, r10, #15 @ r10<- D (or stays CCCC) 3016 .endif 3017 cmp r0, #0 @ already resolved? 3018 EXPORT_PC() @ must export for invoke 3019 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3020 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3021 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3022 mov r2, #METHOD_VIRTUAL @ resolver method type 3023 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3024 cmp r0, #0 @ got null? 3025 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3026 b common_exceptionThrown @ yes, handle exception 3027 3028/* ------------------------------ */ 3029 .balign 64 3030.L_OP_INVOKE_SUPER: /* 0x6f */ 3031/* File: armv5te/OP_INVOKE_SUPER.S */ 3032 /* 3033 * Handle a "super" method call. 3034 * 3035 * for: invoke-super, invoke-super/range 3036 */ 3037 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3038 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3039 FETCH(r10, 2) @ r10<- GFED or CCCC 3040 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3041 .if (!0) 3042 and r10, r10, #15 @ r10<- D (or stays CCCC) 3043 .endif 3044 FETCH(r1, 1) @ r1<- BBBB 3045 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3046 GET_VREG(r2, r10) @ r2<- "this" ptr 3047 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3048 cmp r2, #0 @ null "this"? 3049 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3050 beq common_errNullObject @ null "this", throw exception 3051 cmp r0, #0 @ already resolved? 3052 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3053 EXPORT_PC() @ must export for invoke 3054 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3055 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3056 3057/* ------------------------------ */ 3058 .balign 64 3059.L_OP_INVOKE_DIRECT: /* 0x70 */ 3060/* File: armv5te/OP_INVOKE_DIRECT.S */ 3061 /* 3062 * Handle a direct method call. 3063 * 3064 * (We could defer the "is 'this' pointer null" test to the common 3065 * method invocation code, and use a flag to indicate that static 3066 * calls don't count. If we do this as part of copying the arguments 3067 * out we could avoiding loading the first arg twice.) 3068 * 3069 * for: invoke-direct, invoke-direct/range 3070 */ 3071 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3072 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3073 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3074 FETCH(r1, 1) @ r1<- BBBB 3075 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3076 FETCH(r10, 2) @ r10<- GFED or CCCC 3077 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3078 .if (!0) 3079 and r10, r10, #15 @ r10<- D (or stays CCCC) 3080 .endif 3081 cmp r0, #0 @ already resolved? 3082 EXPORT_PC() @ must export for invoke 3083 GET_VREG(r2, r10) @ r2<- "this" ptr 3084 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3085.LOP_INVOKE_DIRECT_finish: 3086 cmp r2, #0 @ null "this" ref? 3087 bne common_invokeMethodNoRange @ no, continue on 3088 b common_errNullObject @ yes, throw exception 3089 3090/* ------------------------------ */ 3091 .balign 64 3092.L_OP_INVOKE_STATIC: /* 0x71 */ 3093/* File: armv5te/OP_INVOKE_STATIC.S */ 3094 /* 3095 * Handle a static method call. 3096 * 3097 * for: invoke-static, invoke-static/range 3098 */ 3099 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3100 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3101 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3102 FETCH(r1, 1) @ r1<- BBBB 3103 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3104 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3105 cmp r0, #0 @ already resolved? 3106 EXPORT_PC() @ must export for invoke 3107 bne common_invokeMethodNoRange @ yes, continue on 31080: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3109 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3110 mov r2, #METHOD_STATIC @ resolver method type 3111 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3112 cmp r0, #0 @ got null? 3113 bne common_invokeMethodNoRange @ no, continue 3114 b common_exceptionThrown @ yes, handle exception 3115 3116 3117/* ------------------------------ */ 3118 .balign 64 3119.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3120/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3121 /* 3122 * Handle an interface method call. 3123 * 3124 * for: invoke-interface, invoke-interface/range 3125 */ 3126 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3127 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3128 FETCH(r2, 2) @ r2<- FEDC or CCCC 3129 FETCH(r1, 1) @ r1<- BBBB 3130 .if (!0) 3131 and r2, r2, #15 @ r2<- C (or stays CCCC) 3132 .endif 3133 EXPORT_PC() @ must export for invoke 3134 GET_VREG(r0, r2) @ r0<- first arg ("this") 3135 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3136 cmp r0, #0 @ null obj? 3137 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3138 beq common_errNullObject @ yes, fail 3139 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3140 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3141 cmp r0, #0 @ failed? 3142 beq common_exceptionThrown @ yes, handle exception 3143 b common_invokeMethodNoRange @ jump to common handler 3144 3145 3146/* ------------------------------ */ 3147 .balign 64 3148.L_OP_UNUSED_73: /* 0x73 */ 3149/* File: armv5te/OP_UNUSED_73.S */ 3150/* File: armv5te/unused.S */ 3151 bl common_abort 3152 3153 3154 3155/* ------------------------------ */ 3156 .balign 64 3157.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3158/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3159/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3160 /* 3161 * Handle a virtual method call. 3162 * 3163 * for: invoke-virtual, invoke-virtual/range 3164 */ 3165 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3166 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3167 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3168 FETCH(r1, 1) @ r1<- BBBB 3169 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3170 FETCH(r10, 2) @ r10<- GFED or CCCC 3171 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3172 .if (!1) 3173 and r10, r10, #15 @ r10<- D (or stays CCCC) 3174 .endif 3175 cmp r0, #0 @ already resolved? 3176 EXPORT_PC() @ must export for invoke 3177 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3178 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3179 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3180 mov r2, #METHOD_VIRTUAL @ resolver method type 3181 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3182 cmp r0, #0 @ got null? 3183 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3184 b common_exceptionThrown @ yes, handle exception 3185 3186 3187/* ------------------------------ */ 3188 .balign 64 3189.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3190/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3191/* File: armv5te/OP_INVOKE_SUPER.S */ 3192 /* 3193 * Handle a "super" method call. 3194 * 3195 * for: invoke-super, invoke-super/range 3196 */ 3197 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3198 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3199 FETCH(r10, 2) @ r10<- GFED or CCCC 3200 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3201 .if (!1) 3202 and r10, r10, #15 @ r10<- D (or stays CCCC) 3203 .endif 3204 FETCH(r1, 1) @ r1<- BBBB 3205 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3206 GET_VREG(r2, r10) @ r2<- "this" ptr 3207 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3208 cmp r2, #0 @ null "this"? 3209 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3210 beq common_errNullObject @ null "this", throw exception 3211 cmp r0, #0 @ already resolved? 3212 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3213 EXPORT_PC() @ must export for invoke 3214 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3215 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3216 3217 3218/* ------------------------------ */ 3219 .balign 64 3220.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3221/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3222/* File: armv5te/OP_INVOKE_DIRECT.S */ 3223 /* 3224 * Handle a direct method call. 3225 * 3226 * (We could defer the "is 'this' pointer null" test to the common 3227 * method invocation code, and use a flag to indicate that static 3228 * calls don't count. If we do this as part of copying the arguments 3229 * out we could avoiding loading the first arg twice.) 3230 * 3231 * for: invoke-direct, invoke-direct/range 3232 */ 3233 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3234 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3235 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3236 FETCH(r1, 1) @ r1<- BBBB 3237 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3238 FETCH(r10, 2) @ r10<- GFED or CCCC 3239 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3240 .if (!1) 3241 and r10, r10, #15 @ r10<- D (or stays CCCC) 3242 .endif 3243 cmp r0, #0 @ already resolved? 3244 EXPORT_PC() @ must export for invoke 3245 GET_VREG(r2, r10) @ r2<- "this" ptr 3246 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3247.LOP_INVOKE_DIRECT_RANGE_finish: 3248 cmp r2, #0 @ null "this" ref? 3249 bne common_invokeMethodRange @ no, continue on 3250 b common_errNullObject @ yes, throw exception 3251 3252 3253/* ------------------------------ */ 3254 .balign 64 3255.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3256/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3257/* File: armv5te/OP_INVOKE_STATIC.S */ 3258 /* 3259 * Handle a static method call. 3260 * 3261 * for: invoke-static, invoke-static/range 3262 */ 3263 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3264 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3265 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3266 FETCH(r1, 1) @ r1<- BBBB 3267 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3268 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3269 cmp r0, #0 @ already resolved? 3270 EXPORT_PC() @ must export for invoke 3271 bne common_invokeMethodRange @ yes, continue on 32720: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3273 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3274 mov r2, #METHOD_STATIC @ resolver method type 3275 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3276 cmp r0, #0 @ got null? 3277 bne common_invokeMethodRange @ no, continue 3278 b common_exceptionThrown @ yes, handle exception 3279 3280 3281 3282/* ------------------------------ */ 3283 .balign 64 3284.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3285/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3286/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3287 /* 3288 * Handle an interface method call. 3289 * 3290 * for: invoke-interface, invoke-interface/range 3291 */ 3292 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3293 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3294 FETCH(r2, 2) @ r2<- FEDC or CCCC 3295 FETCH(r1, 1) @ r1<- BBBB 3296 .if (!1) 3297 and r2, r2, #15 @ r2<- C (or stays CCCC) 3298 .endif 3299 EXPORT_PC() @ must export for invoke 3300 GET_VREG(r0, r2) @ r0<- first arg ("this") 3301 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3302 cmp r0, #0 @ null obj? 3303 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3304 beq common_errNullObject @ yes, fail 3305 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3306 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3307 cmp r0, #0 @ failed? 3308 beq common_exceptionThrown @ yes, handle exception 3309 b common_invokeMethodRange @ jump to common handler 3310 3311 3312 3313/* ------------------------------ */ 3314 .balign 64 3315.L_OP_UNUSED_79: /* 0x79 */ 3316/* File: armv5te/OP_UNUSED_79.S */ 3317/* File: armv5te/unused.S */ 3318 bl common_abort 3319 3320 3321 3322/* ------------------------------ */ 3323 .balign 64 3324.L_OP_UNUSED_7A: /* 0x7a */ 3325/* File: armv5te/OP_UNUSED_7A.S */ 3326/* File: armv5te/unused.S */ 3327 bl common_abort 3328 3329 3330 3331/* ------------------------------ */ 3332 .balign 64 3333.L_OP_NEG_INT: /* 0x7b */ 3334/* File: armv5te/OP_NEG_INT.S */ 3335/* File: armv5te/unop.S */ 3336 /* 3337 * Generic 32-bit unary operation. Provide an "instr" line that 3338 * specifies an instruction that performs "result = op r0". 3339 * This could be an ARM instruction or a function call. 3340 * 3341 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3342 * int-to-byte, int-to-char, int-to-short 3343 */ 3344 /* unop vA, vB */ 3345 mov r3, rINST, lsr #12 @ r3<- B 3346 mov r9, rINST, lsr #8 @ r9<- A+ 3347 GET_VREG(r0, r3) @ r0<- vB 3348 and r9, r9, #15 3349 @ optional op; may set condition codes 3350 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3351 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3352 GET_INST_OPCODE(ip) @ extract opcode from rINST 3353 SET_VREG(r0, r9) @ vAA<- r0 3354 GOTO_OPCODE(ip) @ jump to next instruction 3355 /* 9-10 instructions */ 3356 3357 3358/* ------------------------------ */ 3359 .balign 64 3360.L_OP_NOT_INT: /* 0x7c */ 3361/* File: armv5te/OP_NOT_INT.S */ 3362/* File: armv5te/unop.S */ 3363 /* 3364 * Generic 32-bit unary operation. Provide an "instr" line that 3365 * specifies an instruction that performs "result = op r0". 3366 * This could be an ARM instruction or a function call. 3367 * 3368 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3369 * int-to-byte, int-to-char, int-to-short 3370 */ 3371 /* unop vA, vB */ 3372 mov r3, rINST, lsr #12 @ r3<- B 3373 mov r9, rINST, lsr #8 @ r9<- A+ 3374 GET_VREG(r0, r3) @ r0<- vB 3375 and r9, r9, #15 3376 @ optional op; may set condition codes 3377 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3378 mvn r0, r0 @ r0<- op, r0-r3 changed 3379 GET_INST_OPCODE(ip) @ extract opcode from rINST 3380 SET_VREG(r0, r9) @ vAA<- r0 3381 GOTO_OPCODE(ip) @ jump to next instruction 3382 /* 9-10 instructions */ 3383 3384 3385/* ------------------------------ */ 3386 .balign 64 3387.L_OP_NEG_LONG: /* 0x7d */ 3388/* File: armv5te/OP_NEG_LONG.S */ 3389/* File: armv5te/unopWide.S */ 3390 /* 3391 * Generic 64-bit unary operation. Provide an "instr" line that 3392 * specifies an instruction that performs "result = op r0/r1". 3393 * This could be an ARM instruction or a function call. 3394 * 3395 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3396 */ 3397 /* unop vA, vB */ 3398 mov r9, rINST, lsr #8 @ r9<- A+ 3399 mov r3, rINST, lsr #12 @ r3<- B 3400 and r9, r9, #15 3401 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3402 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3403 ldmia r3, {r0-r1} @ r0/r1<- vAA 3404 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3405 rsbs r0, r0, #0 @ optional op; may set condition codes 3406 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3407 GET_INST_OPCODE(ip) @ extract opcode from rINST 3408 stmia r9, {r0-r1} @ vAA<- r0/r1 3409 GOTO_OPCODE(ip) @ jump to next instruction 3410 /* 12-13 instructions */ 3411 3412 3413 3414/* ------------------------------ */ 3415 .balign 64 3416.L_OP_NOT_LONG: /* 0x7e */ 3417/* File: armv5te/OP_NOT_LONG.S */ 3418/* File: armv5te/unopWide.S */ 3419 /* 3420 * Generic 64-bit unary operation. Provide an "instr" line that 3421 * specifies an instruction that performs "result = op r0/r1". 3422 * This could be an ARM instruction or a function call. 3423 * 3424 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3425 */ 3426 /* unop vA, vB */ 3427 mov r9, rINST, lsr #8 @ r9<- A+ 3428 mov r3, rINST, lsr #12 @ r3<- B 3429 and r9, r9, #15 3430 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3431 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3432 ldmia r3, {r0-r1} @ r0/r1<- vAA 3433 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3434 mvn r0, r0 @ optional op; may set condition codes 3435 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3436 GET_INST_OPCODE(ip) @ extract opcode from rINST 3437 stmia r9, {r0-r1} @ vAA<- r0/r1 3438 GOTO_OPCODE(ip) @ jump to next instruction 3439 /* 12-13 instructions */ 3440 3441 3442 3443/* ------------------------------ */ 3444 .balign 64 3445.L_OP_NEG_FLOAT: /* 0x7f */ 3446/* File: armv5te/OP_NEG_FLOAT.S */ 3447/* File: armv5te/unop.S */ 3448 /* 3449 * Generic 32-bit unary operation. Provide an "instr" line that 3450 * specifies an instruction that performs "result = op r0". 3451 * This could be an ARM instruction or a function call. 3452 * 3453 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3454 * int-to-byte, int-to-char, int-to-short 3455 */ 3456 /* unop vA, vB */ 3457 mov r3, rINST, lsr #12 @ r3<- B 3458 mov r9, rINST, lsr #8 @ r9<- A+ 3459 GET_VREG(r0, r3) @ r0<- vB 3460 and r9, r9, #15 3461 @ optional op; may set condition codes 3462 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3463 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3464 GET_INST_OPCODE(ip) @ extract opcode from rINST 3465 SET_VREG(r0, r9) @ vAA<- r0 3466 GOTO_OPCODE(ip) @ jump to next instruction 3467 /* 9-10 instructions */ 3468 3469 3470/* ------------------------------ */ 3471 .balign 64 3472.L_OP_NEG_DOUBLE: /* 0x80 */ 3473/* File: armv5te/OP_NEG_DOUBLE.S */ 3474/* File: armv5te/unopWide.S */ 3475 /* 3476 * Generic 64-bit unary operation. Provide an "instr" line that 3477 * specifies an instruction that performs "result = op r0/r1". 3478 * This could be an ARM instruction or a function call. 3479 * 3480 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3481 */ 3482 /* unop vA, vB */ 3483 mov r9, rINST, lsr #8 @ r9<- A+ 3484 mov r3, rINST, lsr #12 @ r3<- B 3485 and r9, r9, #15 3486 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3487 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3488 ldmia r3, {r0-r1} @ r0/r1<- vAA 3489 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3490 @ optional op; may set condition codes 3491 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3492 GET_INST_OPCODE(ip) @ extract opcode from rINST 3493 stmia r9, {r0-r1} @ vAA<- r0/r1 3494 GOTO_OPCODE(ip) @ jump to next instruction 3495 /* 12-13 instructions */ 3496 3497 3498 3499/* ------------------------------ */ 3500 .balign 64 3501.L_OP_INT_TO_LONG: /* 0x81 */ 3502/* File: armv5te/OP_INT_TO_LONG.S */ 3503/* File: armv5te/unopWider.S */ 3504 /* 3505 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3506 * that specifies an instruction that performs "result = op r0", where 3507 * "result" is a 64-bit quantity in r0/r1. 3508 * 3509 * For: int-to-long, int-to-double, float-to-long, float-to-double 3510 */ 3511 /* unop vA, vB */ 3512 mov r9, rINST, lsr #8 @ r9<- A+ 3513 mov r3, rINST, lsr #12 @ r3<- B 3514 and r9, r9, #15 3515 GET_VREG(r0, r3) @ r0<- vB 3516 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3517 @ optional op; may set condition codes 3518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3519 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3520 GET_INST_OPCODE(ip) @ extract opcode from rINST 3521 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3522 GOTO_OPCODE(ip) @ jump to next instruction 3523 /* 10-11 instructions */ 3524 3525 3526/* ------------------------------ */ 3527 .balign 64 3528.L_OP_INT_TO_FLOAT: /* 0x82 */ 3529/* File: vfp/OP_INT_TO_FLOAT.S */ 3530/* File: vfp/funop.S */ 3531 /* 3532 * Generic 32-bit unary floating-point operation. Provide an "instr" 3533 * line that specifies an instruction that performs "s1 = op s0". 3534 * 3535 * for: int-to-float, float-to-int 3536 */ 3537 /* unop vA, vB */ 3538 mov r3, rINST, lsr #12 @ r3<- B 3539 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3540 flds s0, [r3] @ s0<- vB 3541 mov r9, rINST, lsr #8 @ r9<- A+ 3542 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3543 and r9, r9, #15 @ r9<- A 3544 fsitos s1, s0 @ s1<- op 3545 GET_INST_OPCODE(ip) @ extract opcode from rINST 3546 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3547 fsts s1, [r9] @ vA<- s1 3548 GOTO_OPCODE(ip) @ jump to next instruction 3549 3550 3551/* ------------------------------ */ 3552 .balign 64 3553.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3554/* File: vfp/OP_INT_TO_DOUBLE.S */ 3555/* File: vfp/funopWider.S */ 3556 /* 3557 * Generic 32bit-to-64bit floating point unary operation. Provide an 3558 * "instr" line that specifies an instruction that performs "d0 = op s0". 3559 * 3560 * For: int-to-double, float-to-double 3561 */ 3562 /* unop vA, vB */ 3563 mov r3, rINST, lsr #12 @ r3<- B 3564 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3565 flds s0, [r3] @ s0<- vB 3566 mov r9, rINST, lsr #8 @ r9<- A+ 3567 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3568 and r9, r9, #15 @ r9<- A 3569 fsitod d0, s0 @ d0<- op 3570 GET_INST_OPCODE(ip) @ extract opcode from rINST 3571 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3572 fstd d0, [r9] @ vA<- d0 3573 GOTO_OPCODE(ip) @ jump to next instruction 3574 3575 3576/* ------------------------------ */ 3577 .balign 64 3578.L_OP_LONG_TO_INT: /* 0x84 */ 3579/* File: armv5te/OP_LONG_TO_INT.S */ 3580/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3581/* File: armv5te/OP_MOVE.S */ 3582 /* for move, move-object, long-to-int */ 3583 /* op vA, vB */ 3584 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3585 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3587 GET_VREG(r2, r1) @ r2<- fp[B] 3588 and r0, r0, #15 3589 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3590 SET_VREG(r2, r0) @ fp[A]<- r2 3591 GOTO_OPCODE(ip) @ execute next instruction 3592 3593 3594 3595/* ------------------------------ */ 3596 .balign 64 3597.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3598/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3599/* File: armv5te/unopNarrower.S */ 3600 /* 3601 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3602 * that specifies an instruction that performs "result = op r0/r1", where 3603 * "result" is a 32-bit quantity in r0. 3604 * 3605 * For: long-to-float, double-to-int, double-to-float 3606 * 3607 * (This would work for long-to-int, but that instruction is actually 3608 * an exact match for OP_MOVE.) 3609 */ 3610 /* unop vA, vB */ 3611 mov r3, rINST, lsr #12 @ r3<- B 3612 mov r9, rINST, lsr #8 @ r9<- A+ 3613 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3614 and r9, r9, #15 3615 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3616 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3617 @ optional op; may set condition codes 3618 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3619 GET_INST_OPCODE(ip) @ extract opcode from rINST 3620 SET_VREG(r0, r9) @ vA<- r0 3621 GOTO_OPCODE(ip) @ jump to next instruction 3622 /* 10-11 instructions */ 3623 3624 3625/* ------------------------------ */ 3626 .balign 64 3627.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3628/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3629/* File: armv5te/unopWide.S */ 3630 /* 3631 * Generic 64-bit unary operation. Provide an "instr" line that 3632 * specifies an instruction that performs "result = op r0/r1". 3633 * This could be an ARM instruction or a function call. 3634 * 3635 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3636 */ 3637 /* unop vA, vB */ 3638 mov r9, rINST, lsr #8 @ r9<- A+ 3639 mov r3, rINST, lsr #12 @ r3<- B 3640 and r9, r9, #15 3641 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3642 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3643 ldmia r3, {r0-r1} @ r0/r1<- vAA 3644 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3645 @ optional op; may set condition codes 3646 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3647 GET_INST_OPCODE(ip) @ extract opcode from rINST 3648 stmia r9, {r0-r1} @ vAA<- r0/r1 3649 GOTO_OPCODE(ip) @ jump to next instruction 3650 /* 12-13 instructions */ 3651 3652 3653 3654/* ------------------------------ */ 3655 .balign 64 3656.L_OP_FLOAT_TO_INT: /* 0x87 */ 3657/* File: vfp/OP_FLOAT_TO_INT.S */ 3658/* File: vfp/funop.S */ 3659 /* 3660 * Generic 32-bit unary floating-point operation. Provide an "instr" 3661 * line that specifies an instruction that performs "s1 = op s0". 3662 * 3663 * for: int-to-float, float-to-int 3664 */ 3665 /* unop vA, vB */ 3666 mov r3, rINST, lsr #12 @ r3<- B 3667 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3668 flds s0, [r3] @ s0<- vB 3669 mov r9, rINST, lsr #8 @ r9<- A+ 3670 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3671 and r9, r9, #15 @ r9<- A 3672 ftosizs s1, s0 @ s1<- op 3673 GET_INST_OPCODE(ip) @ extract opcode from rINST 3674 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3675 fsts s1, [r9] @ vA<- s1 3676 GOTO_OPCODE(ip) @ jump to next instruction 3677 3678 3679/* ------------------------------ */ 3680 .balign 64 3681.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3682/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3683@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3684/* File: armv5te/unopWider.S */ 3685 /* 3686 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3687 * that specifies an instruction that performs "result = op r0", where 3688 * "result" is a 64-bit quantity in r0/r1. 3689 * 3690 * For: int-to-long, int-to-double, float-to-long, float-to-double 3691 */ 3692 /* unop vA, vB */ 3693 mov r9, rINST, lsr #8 @ r9<- A+ 3694 mov r3, rINST, lsr #12 @ r3<- B 3695 and r9, r9, #15 3696 GET_VREG(r0, r3) @ r0<- vB 3697 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3698 @ optional op; may set condition codes 3699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3700 bl f2l_doconv @ r0<- op, r0-r3 changed 3701 GET_INST_OPCODE(ip) @ extract opcode from rINST 3702 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3703 GOTO_OPCODE(ip) @ jump to next instruction 3704 /* 10-11 instructions */ 3705 3706 3707 3708/* ------------------------------ */ 3709 .balign 64 3710.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3711/* File: vfp/OP_FLOAT_TO_DOUBLE.S */ 3712/* File: vfp/funopWider.S */ 3713 /* 3714 * Generic 32bit-to-64bit floating point unary operation. Provide an 3715 * "instr" line that specifies an instruction that performs "d0 = op s0". 3716 * 3717 * For: int-to-double, float-to-double 3718 */ 3719 /* unop vA, vB */ 3720 mov r3, rINST, lsr #12 @ r3<- B 3721 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3722 flds s0, [r3] @ s0<- vB 3723 mov r9, rINST, lsr #8 @ r9<- A+ 3724 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3725 and r9, r9, #15 @ r9<- A 3726 fcvtds d0, s0 @ d0<- op 3727 GET_INST_OPCODE(ip) @ extract opcode from rINST 3728 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3729 fstd d0, [r9] @ vA<- d0 3730 GOTO_OPCODE(ip) @ jump to next instruction 3731 3732 3733/* ------------------------------ */ 3734 .balign 64 3735.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3736/* File: vfp/OP_DOUBLE_TO_INT.S */ 3737/* File: vfp/funopNarrower.S */ 3738 /* 3739 * Generic 64bit-to-32bit unary floating point operation. Provide an 3740 * "instr" line that specifies an instruction that performs "s0 = op d0". 3741 * 3742 * For: double-to-int, double-to-float 3743 */ 3744 /* unop vA, vB */ 3745 mov r3, rINST, lsr #12 @ r3<- B 3746 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3747 fldd d0, [r3] @ d0<- vB 3748 mov r9, rINST, lsr #8 @ r9<- A+ 3749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3750 and r9, r9, #15 @ r9<- A 3751 ftosizd s0, d0 @ s0<- op 3752 GET_INST_OPCODE(ip) @ extract opcode from rINST 3753 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3754 fsts s0, [r9] @ vA<- s0 3755 GOTO_OPCODE(ip) @ jump to next instruction 3756 3757 3758/* ------------------------------ */ 3759 .balign 64 3760.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3761/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3762@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3763/* File: armv5te/unopWide.S */ 3764 /* 3765 * Generic 64-bit unary operation. Provide an "instr" line that 3766 * specifies an instruction that performs "result = op r0/r1". 3767 * This could be an ARM instruction or a function call. 3768 * 3769 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3770 */ 3771 /* unop vA, vB */ 3772 mov r9, rINST, lsr #8 @ r9<- A+ 3773 mov r3, rINST, lsr #12 @ r3<- B 3774 and r9, r9, #15 3775 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3776 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3777 ldmia r3, {r0-r1} @ r0/r1<- vAA 3778 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3779 @ optional op; may set condition codes 3780 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3781 GET_INST_OPCODE(ip) @ extract opcode from rINST 3782 stmia r9, {r0-r1} @ vAA<- r0/r1 3783 GOTO_OPCODE(ip) @ jump to next instruction 3784 /* 12-13 instructions */ 3785 3786 3787 3788 3789/* ------------------------------ */ 3790 .balign 64 3791.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3792/* File: vfp/OP_DOUBLE_TO_FLOAT.S */ 3793/* File: vfp/funopNarrower.S */ 3794 /* 3795 * Generic 64bit-to-32bit unary floating point operation. Provide an 3796 * "instr" line that specifies an instruction that performs "s0 = op d0". 3797 * 3798 * For: double-to-int, double-to-float 3799 */ 3800 /* unop vA, vB */ 3801 mov r3, rINST, lsr #12 @ r3<- B 3802 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3803 fldd d0, [r3] @ d0<- vB 3804 mov r9, rINST, lsr #8 @ r9<- A+ 3805 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3806 and r9, r9, #15 @ r9<- A 3807 fcvtsd s0, d0 @ s0<- op 3808 GET_INST_OPCODE(ip) @ extract opcode from rINST 3809 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3810 fsts s0, [r9] @ vA<- s0 3811 GOTO_OPCODE(ip) @ jump to next instruction 3812 3813 3814/* ------------------------------ */ 3815 .balign 64 3816.L_OP_INT_TO_BYTE: /* 0x8d */ 3817/* File: armv5te/OP_INT_TO_BYTE.S */ 3818/* File: armv5te/unop.S */ 3819 /* 3820 * Generic 32-bit unary operation. Provide an "instr" line that 3821 * specifies an instruction that performs "result = op r0". 3822 * This could be an ARM instruction or a function call. 3823 * 3824 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3825 * int-to-byte, int-to-char, int-to-short 3826 */ 3827 /* unop vA, vB */ 3828 mov r3, rINST, lsr #12 @ r3<- B 3829 mov r9, rINST, lsr #8 @ r9<- A+ 3830 GET_VREG(r0, r3) @ r0<- vB 3831 and r9, r9, #15 3832 mov r0, r0, asl #24 @ optional op; may set condition codes 3833 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3834 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3835 GET_INST_OPCODE(ip) @ extract opcode from rINST 3836 SET_VREG(r0, r9) @ vAA<- r0 3837 GOTO_OPCODE(ip) @ jump to next instruction 3838 /* 9-10 instructions */ 3839 3840 3841/* ------------------------------ */ 3842 .balign 64 3843.L_OP_INT_TO_CHAR: /* 0x8e */ 3844/* File: armv5te/OP_INT_TO_CHAR.S */ 3845/* File: armv5te/unop.S */ 3846 /* 3847 * Generic 32-bit unary operation. Provide an "instr" line that 3848 * specifies an instruction that performs "result = op r0". 3849 * This could be an ARM instruction or a function call. 3850 * 3851 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3852 * int-to-byte, int-to-char, int-to-short 3853 */ 3854 /* unop vA, vB */ 3855 mov r3, rINST, lsr #12 @ r3<- B 3856 mov r9, rINST, lsr #8 @ r9<- A+ 3857 GET_VREG(r0, r3) @ r0<- vB 3858 and r9, r9, #15 3859 mov r0, r0, asl #16 @ optional op; may set condition codes 3860 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3861 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3862 GET_INST_OPCODE(ip) @ extract opcode from rINST 3863 SET_VREG(r0, r9) @ vAA<- r0 3864 GOTO_OPCODE(ip) @ jump to next instruction 3865 /* 9-10 instructions */ 3866 3867 3868/* ------------------------------ */ 3869 .balign 64 3870.L_OP_INT_TO_SHORT: /* 0x8f */ 3871/* File: armv5te/OP_INT_TO_SHORT.S */ 3872/* File: armv5te/unop.S */ 3873 /* 3874 * Generic 32-bit unary operation. Provide an "instr" line that 3875 * specifies an instruction that performs "result = op r0". 3876 * This could be an ARM instruction or a function call. 3877 * 3878 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3879 * int-to-byte, int-to-char, int-to-short 3880 */ 3881 /* unop vA, vB */ 3882 mov r3, rINST, lsr #12 @ r3<- B 3883 mov r9, rINST, lsr #8 @ r9<- A+ 3884 GET_VREG(r0, r3) @ r0<- vB 3885 and r9, r9, #15 3886 mov r0, r0, asl #16 @ optional op; may set condition codes 3887 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3888 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 3889 GET_INST_OPCODE(ip) @ extract opcode from rINST 3890 SET_VREG(r0, r9) @ vAA<- r0 3891 GOTO_OPCODE(ip) @ jump to next instruction 3892 /* 9-10 instructions */ 3893 3894 3895/* ------------------------------ */ 3896 .balign 64 3897.L_OP_ADD_INT: /* 0x90 */ 3898/* File: armv5te/OP_ADD_INT.S */ 3899/* File: armv5te/binop.S */ 3900 /* 3901 * Generic 32-bit binary operation. Provide an "instr" line that 3902 * specifies an instruction that performs "result = r0 op r1". 3903 * This could be an ARM instruction or a function call. (If the result 3904 * comes back in a register other than r0, you can override "result".) 3905 * 3906 * If "chkzero" is set to 1, we perform a divide-by-zero check on 3907 * vCC (r1). Useful for integer division and modulus. Note that we 3908 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 3909 * handles it correctly. 3910 * 3911 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 3912 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 3913 * mul-float, div-float, rem-float 3914 */ 3915 /* binop vAA, vBB, vCC */ 3916 FETCH(r0, 1) @ r0<- CCBB 3917 mov r9, rINST, lsr #8 @ r9<- AA 3918 mov r3, r0, lsr #8 @ r3<- CC 3919 and r2, r0, #255 @ r2<- BB 3920 GET_VREG(r1, r3) @ r1<- vCC 3921 GET_VREG(r0, r2) @ r0<- vBB 3922 .if 0 3923 cmp r1, #0 @ is second operand zero? 3924 beq common_errDivideByZero 3925 .endif 3926 3927 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3928 @ optional op; may set condition codes 3929 add r0, r0, r1 @ r0<- op, r0-r3 changed 3930 GET_INST_OPCODE(ip) @ extract opcode from rINST 3931 SET_VREG(r0, r9) @ vAA<- r0 3932 GOTO_OPCODE(ip) @ jump to next instruction 3933 /* 11-14 instructions */ 3934 3935 3936 3937/* ------------------------------ */ 3938 .balign 64 3939.L_OP_SUB_INT: /* 0x91 */ 3940/* File: armv5te/OP_SUB_INT.S */ 3941/* File: armv5te/binop.S */ 3942 /* 3943 * Generic 32-bit binary operation. Provide an "instr" line that 3944 * specifies an instruction that performs "result = r0 op r1". 3945 * This could be an ARM instruction or a function call. (If the result 3946 * comes back in a register other than r0, you can override "result".) 3947 * 3948 * If "chkzero" is set to 1, we perform a divide-by-zero check on 3949 * vCC (r1). Useful for integer division and modulus. Note that we 3950 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 3951 * handles it correctly. 3952 * 3953 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 3954 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 3955 * mul-float, div-float, rem-float 3956 */ 3957 /* binop vAA, vBB, vCC */ 3958 FETCH(r0, 1) @ r0<- CCBB 3959 mov r9, rINST, lsr #8 @ r9<- AA 3960 mov r3, r0, lsr #8 @ r3<- CC 3961 and r2, r0, #255 @ r2<- BB 3962 GET_VREG(r1, r3) @ r1<- vCC 3963 GET_VREG(r0, r2) @ r0<- vBB 3964 .if 0 3965 cmp r1, #0 @ is second operand zero? 3966 beq common_errDivideByZero 3967 .endif 3968 3969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3970 @ optional op; may set condition codes 3971 sub r0, r0, r1 @ r0<- op, r0-r3 changed 3972 GET_INST_OPCODE(ip) @ extract opcode from rINST 3973 SET_VREG(r0, r9) @ vAA<- r0 3974 GOTO_OPCODE(ip) @ jump to next instruction 3975 /* 11-14 instructions */ 3976 3977 3978 3979/* ------------------------------ */ 3980 .balign 64 3981.L_OP_MUL_INT: /* 0x92 */ 3982/* File: armv5te/OP_MUL_INT.S */ 3983/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 3984/* File: armv5te/binop.S */ 3985 /* 3986 * Generic 32-bit binary operation. Provide an "instr" line that 3987 * specifies an instruction that performs "result = r0 op r1". 3988 * This could be an ARM instruction or a function call. (If the result 3989 * comes back in a register other than r0, you can override "result".) 3990 * 3991 * If "chkzero" is set to 1, we perform a divide-by-zero check on 3992 * vCC (r1). Useful for integer division and modulus. Note that we 3993 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 3994 * handles it correctly. 3995 * 3996 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 3997 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 3998 * mul-float, div-float, rem-float 3999 */ 4000 /* binop vAA, vBB, vCC */ 4001 FETCH(r0, 1) @ r0<- CCBB 4002 mov r9, rINST, lsr #8 @ r9<- AA 4003 mov r3, r0, lsr #8 @ r3<- CC 4004 and r2, r0, #255 @ r2<- BB 4005 GET_VREG(r1, r3) @ r1<- vCC 4006 GET_VREG(r0, r2) @ r0<- vBB 4007 .if 0 4008 cmp r1, #0 @ is second operand zero? 4009 beq common_errDivideByZero 4010 .endif 4011 4012 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4013 @ optional op; may set condition codes 4014 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4015 GET_INST_OPCODE(ip) @ extract opcode from rINST 4016 SET_VREG(r0, r9) @ vAA<- r0 4017 GOTO_OPCODE(ip) @ jump to next instruction 4018 /* 11-14 instructions */ 4019 4020 4021 4022/* ------------------------------ */ 4023 .balign 64 4024.L_OP_DIV_INT: /* 0x93 */ 4025/* File: armv5te/OP_DIV_INT.S */ 4026/* File: armv5te/binop.S */ 4027 /* 4028 * Generic 32-bit binary operation. Provide an "instr" line that 4029 * specifies an instruction that performs "result = r0 op r1". 4030 * This could be an ARM instruction or a function call. (If the result 4031 * comes back in a register other than r0, you can override "result".) 4032 * 4033 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4034 * vCC (r1). Useful for integer division and modulus. Note that we 4035 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4036 * handles it correctly. 4037 * 4038 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4039 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4040 * mul-float, div-float, rem-float 4041 */ 4042 /* binop vAA, vBB, vCC */ 4043 FETCH(r0, 1) @ r0<- CCBB 4044 mov r9, rINST, lsr #8 @ r9<- AA 4045 mov r3, r0, lsr #8 @ r3<- CC 4046 and r2, r0, #255 @ r2<- BB 4047 GET_VREG(r1, r3) @ r1<- vCC 4048 GET_VREG(r0, r2) @ r0<- vBB 4049 .if 1 4050 cmp r1, #0 @ is second operand zero? 4051 beq common_errDivideByZero 4052 .endif 4053 4054 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4055 @ optional op; may set condition codes 4056 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4057 GET_INST_OPCODE(ip) @ extract opcode from rINST 4058 SET_VREG(r0, r9) @ vAA<- r0 4059 GOTO_OPCODE(ip) @ jump to next instruction 4060 /* 11-14 instructions */ 4061 4062 4063 4064/* ------------------------------ */ 4065 .balign 64 4066.L_OP_REM_INT: /* 0x94 */ 4067/* File: armv5te/OP_REM_INT.S */ 4068/* idivmod returns quotient in r0 and remainder in r1 */ 4069/* File: armv5te/binop.S */ 4070 /* 4071 * Generic 32-bit binary operation. Provide an "instr" line that 4072 * specifies an instruction that performs "result = r0 op r1". 4073 * This could be an ARM instruction or a function call. (If the result 4074 * comes back in a register other than r0, you can override "result".) 4075 * 4076 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4077 * vCC (r1). Useful for integer division and modulus. Note that we 4078 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4079 * handles it correctly. 4080 * 4081 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4082 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4083 * mul-float, div-float, rem-float 4084 */ 4085 /* binop vAA, vBB, vCC */ 4086 FETCH(r0, 1) @ r0<- CCBB 4087 mov r9, rINST, lsr #8 @ r9<- AA 4088 mov r3, r0, lsr #8 @ r3<- CC 4089 and r2, r0, #255 @ r2<- BB 4090 GET_VREG(r1, r3) @ r1<- vCC 4091 GET_VREG(r0, r2) @ r0<- vBB 4092 .if 1 4093 cmp r1, #0 @ is second operand zero? 4094 beq common_errDivideByZero 4095 .endif 4096 4097 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4098 @ optional op; may set condition codes 4099 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4100 GET_INST_OPCODE(ip) @ extract opcode from rINST 4101 SET_VREG(r1, r9) @ vAA<- r1 4102 GOTO_OPCODE(ip) @ jump to next instruction 4103 /* 11-14 instructions */ 4104 4105 4106 4107/* ------------------------------ */ 4108 .balign 64 4109.L_OP_AND_INT: /* 0x95 */ 4110/* File: armv5te/OP_AND_INT.S */ 4111/* File: armv5te/binop.S */ 4112 /* 4113 * Generic 32-bit binary operation. Provide an "instr" line that 4114 * specifies an instruction that performs "result = r0 op r1". 4115 * This could be an ARM instruction or a function call. (If the result 4116 * comes back in a register other than r0, you can override "result".) 4117 * 4118 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4119 * vCC (r1). Useful for integer division and modulus. Note that we 4120 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4121 * handles it correctly. 4122 * 4123 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4124 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4125 * mul-float, div-float, rem-float 4126 */ 4127 /* binop vAA, vBB, vCC */ 4128 FETCH(r0, 1) @ r0<- CCBB 4129 mov r9, rINST, lsr #8 @ r9<- AA 4130 mov r3, r0, lsr #8 @ r3<- CC 4131 and r2, r0, #255 @ r2<- BB 4132 GET_VREG(r1, r3) @ r1<- vCC 4133 GET_VREG(r0, r2) @ r0<- vBB 4134 .if 0 4135 cmp r1, #0 @ is second operand zero? 4136 beq common_errDivideByZero 4137 .endif 4138 4139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4140 @ optional op; may set condition codes 4141 and r0, r0, r1 @ r0<- op, r0-r3 changed 4142 GET_INST_OPCODE(ip) @ extract opcode from rINST 4143 SET_VREG(r0, r9) @ vAA<- r0 4144 GOTO_OPCODE(ip) @ jump to next instruction 4145 /* 11-14 instructions */ 4146 4147 4148 4149/* ------------------------------ */ 4150 .balign 64 4151.L_OP_OR_INT: /* 0x96 */ 4152/* File: armv5te/OP_OR_INT.S */ 4153/* File: armv5te/binop.S */ 4154 /* 4155 * Generic 32-bit binary operation. Provide an "instr" line that 4156 * specifies an instruction that performs "result = r0 op r1". 4157 * This could be an ARM instruction or a function call. (If the result 4158 * comes back in a register other than r0, you can override "result".) 4159 * 4160 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4161 * vCC (r1). Useful for integer division and modulus. Note that we 4162 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4163 * handles it correctly. 4164 * 4165 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4166 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4167 * mul-float, div-float, rem-float 4168 */ 4169 /* binop vAA, vBB, vCC */ 4170 FETCH(r0, 1) @ r0<- CCBB 4171 mov r9, rINST, lsr #8 @ r9<- AA 4172 mov r3, r0, lsr #8 @ r3<- CC 4173 and r2, r0, #255 @ r2<- BB 4174 GET_VREG(r1, r3) @ r1<- vCC 4175 GET_VREG(r0, r2) @ r0<- vBB 4176 .if 0 4177 cmp r1, #0 @ is second operand zero? 4178 beq common_errDivideByZero 4179 .endif 4180 4181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4182 @ optional op; may set condition codes 4183 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4184 GET_INST_OPCODE(ip) @ extract opcode from rINST 4185 SET_VREG(r0, r9) @ vAA<- r0 4186 GOTO_OPCODE(ip) @ jump to next instruction 4187 /* 11-14 instructions */ 4188 4189 4190 4191/* ------------------------------ */ 4192 .balign 64 4193.L_OP_XOR_INT: /* 0x97 */ 4194/* File: armv5te/OP_XOR_INT.S */ 4195/* File: armv5te/binop.S */ 4196 /* 4197 * Generic 32-bit binary operation. Provide an "instr" line that 4198 * specifies an instruction that performs "result = r0 op r1". 4199 * This could be an ARM instruction or a function call. (If the result 4200 * comes back in a register other than r0, you can override "result".) 4201 * 4202 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4203 * vCC (r1). Useful for integer division and modulus. Note that we 4204 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4205 * handles it correctly. 4206 * 4207 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4208 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4209 * mul-float, div-float, rem-float 4210 */ 4211 /* binop vAA, vBB, vCC */ 4212 FETCH(r0, 1) @ r0<- CCBB 4213 mov r9, rINST, lsr #8 @ r9<- AA 4214 mov r3, r0, lsr #8 @ r3<- CC 4215 and r2, r0, #255 @ r2<- BB 4216 GET_VREG(r1, r3) @ r1<- vCC 4217 GET_VREG(r0, r2) @ r0<- vBB 4218 .if 0 4219 cmp r1, #0 @ is second operand zero? 4220 beq common_errDivideByZero 4221 .endif 4222 4223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4224 @ optional op; may set condition codes 4225 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4226 GET_INST_OPCODE(ip) @ extract opcode from rINST 4227 SET_VREG(r0, r9) @ vAA<- r0 4228 GOTO_OPCODE(ip) @ jump to next instruction 4229 /* 11-14 instructions */ 4230 4231 4232 4233/* ------------------------------ */ 4234 .balign 64 4235.L_OP_SHL_INT: /* 0x98 */ 4236/* File: armv5te/OP_SHL_INT.S */ 4237/* File: armv5te/binop.S */ 4238 /* 4239 * Generic 32-bit binary operation. Provide an "instr" line that 4240 * specifies an instruction that performs "result = r0 op r1". 4241 * This could be an ARM instruction or a function call. (If the result 4242 * comes back in a register other than r0, you can override "result".) 4243 * 4244 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4245 * vCC (r1). Useful for integer division and modulus. Note that we 4246 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4247 * handles it correctly. 4248 * 4249 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4250 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4251 * mul-float, div-float, rem-float 4252 */ 4253 /* binop vAA, vBB, vCC */ 4254 FETCH(r0, 1) @ r0<- CCBB 4255 mov r9, rINST, lsr #8 @ r9<- AA 4256 mov r3, r0, lsr #8 @ r3<- CC 4257 and r2, r0, #255 @ r2<- BB 4258 GET_VREG(r1, r3) @ r1<- vCC 4259 GET_VREG(r0, r2) @ r0<- vBB 4260 .if 0 4261 cmp r1, #0 @ is second operand zero? 4262 beq common_errDivideByZero 4263 .endif 4264 4265 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4266 and r1, r1, #31 @ optional op; may set condition codes 4267 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4268 GET_INST_OPCODE(ip) @ extract opcode from rINST 4269 SET_VREG(r0, r9) @ vAA<- r0 4270 GOTO_OPCODE(ip) @ jump to next instruction 4271 /* 11-14 instructions */ 4272 4273 4274 4275/* ------------------------------ */ 4276 .balign 64 4277.L_OP_SHR_INT: /* 0x99 */ 4278/* File: armv5te/OP_SHR_INT.S */ 4279/* File: armv5te/binop.S */ 4280 /* 4281 * Generic 32-bit binary operation. Provide an "instr" line that 4282 * specifies an instruction that performs "result = r0 op r1". 4283 * This could be an ARM instruction or a function call. (If the result 4284 * comes back in a register other than r0, you can override "result".) 4285 * 4286 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4287 * vCC (r1). Useful for integer division and modulus. Note that we 4288 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4289 * handles it correctly. 4290 * 4291 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4292 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4293 * mul-float, div-float, rem-float 4294 */ 4295 /* binop vAA, vBB, vCC */ 4296 FETCH(r0, 1) @ r0<- CCBB 4297 mov r9, rINST, lsr #8 @ r9<- AA 4298 mov r3, r0, lsr #8 @ r3<- CC 4299 and r2, r0, #255 @ r2<- BB 4300 GET_VREG(r1, r3) @ r1<- vCC 4301 GET_VREG(r0, r2) @ r0<- vBB 4302 .if 0 4303 cmp r1, #0 @ is second operand zero? 4304 beq common_errDivideByZero 4305 .endif 4306 4307 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4308 and r1, r1, #31 @ optional op; may set condition codes 4309 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4310 GET_INST_OPCODE(ip) @ extract opcode from rINST 4311 SET_VREG(r0, r9) @ vAA<- r0 4312 GOTO_OPCODE(ip) @ jump to next instruction 4313 /* 11-14 instructions */ 4314 4315 4316 4317/* ------------------------------ */ 4318 .balign 64 4319.L_OP_USHR_INT: /* 0x9a */ 4320/* File: armv5te/OP_USHR_INT.S */ 4321/* File: armv5te/binop.S */ 4322 /* 4323 * Generic 32-bit binary operation. Provide an "instr" line that 4324 * specifies an instruction that performs "result = r0 op r1". 4325 * This could be an ARM instruction or a function call. (If the result 4326 * comes back in a register other than r0, you can override "result".) 4327 * 4328 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4329 * vCC (r1). Useful for integer division and modulus. Note that we 4330 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4331 * handles it correctly. 4332 * 4333 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4334 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4335 * mul-float, div-float, rem-float 4336 */ 4337 /* binop vAA, vBB, vCC */ 4338 FETCH(r0, 1) @ r0<- CCBB 4339 mov r9, rINST, lsr #8 @ r9<- AA 4340 mov r3, r0, lsr #8 @ r3<- CC 4341 and r2, r0, #255 @ r2<- BB 4342 GET_VREG(r1, r3) @ r1<- vCC 4343 GET_VREG(r0, r2) @ r0<- vBB 4344 .if 0 4345 cmp r1, #0 @ is second operand zero? 4346 beq common_errDivideByZero 4347 .endif 4348 4349 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4350 and r1, r1, #31 @ optional op; may set condition codes 4351 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4352 GET_INST_OPCODE(ip) @ extract opcode from rINST 4353 SET_VREG(r0, r9) @ vAA<- r0 4354 GOTO_OPCODE(ip) @ jump to next instruction 4355 /* 11-14 instructions */ 4356 4357 4358 4359/* ------------------------------ */ 4360 .balign 64 4361.L_OP_ADD_LONG: /* 0x9b */ 4362/* File: armv5te/OP_ADD_LONG.S */ 4363/* File: armv5te/binopWide.S */ 4364 /* 4365 * Generic 64-bit binary operation. Provide an "instr" line that 4366 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4367 * This could be an ARM instruction or a function call. (If the result 4368 * comes back in a register other than r0, you can override "result".) 4369 * 4370 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4371 * vCC (r1). Useful for integer division and modulus. 4372 * 4373 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4374 * xor-long, add-double, sub-double, mul-double, div-double, 4375 * rem-double 4376 * 4377 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4378 */ 4379 /* binop vAA, vBB, vCC */ 4380 FETCH(r0, 1) @ r0<- CCBB 4381 mov r9, rINST, lsr #8 @ r9<- AA 4382 and r2, r0, #255 @ r2<- BB 4383 mov r3, r0, lsr #8 @ r3<- CC 4384 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4385 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4386 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4387 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4388 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4389 .if 0 4390 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4391 beq common_errDivideByZero 4392 .endif 4393 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4394 4395 adds r0, r0, r2 @ optional op; may set condition codes 4396 adc r1, r1, r3 @ result<- op, r0-r3 changed 4397 GET_INST_OPCODE(ip) @ extract opcode from rINST 4398 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4399 GOTO_OPCODE(ip) @ jump to next instruction 4400 /* 14-17 instructions */ 4401 4402 4403 4404/* ------------------------------ */ 4405 .balign 64 4406.L_OP_SUB_LONG: /* 0x9c */ 4407/* File: armv5te/OP_SUB_LONG.S */ 4408/* File: armv5te/binopWide.S */ 4409 /* 4410 * Generic 64-bit binary operation. Provide an "instr" line that 4411 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4412 * This could be an ARM instruction or a function call. (If the result 4413 * comes back in a register other than r0, you can override "result".) 4414 * 4415 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4416 * vCC (r1). Useful for integer division and modulus. 4417 * 4418 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4419 * xor-long, add-double, sub-double, mul-double, div-double, 4420 * rem-double 4421 * 4422 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4423 */ 4424 /* binop vAA, vBB, vCC */ 4425 FETCH(r0, 1) @ r0<- CCBB 4426 mov r9, rINST, lsr #8 @ r9<- AA 4427 and r2, r0, #255 @ r2<- BB 4428 mov r3, r0, lsr #8 @ r3<- CC 4429 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4430 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4431 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4432 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4433 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4434 .if 0 4435 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4436 beq common_errDivideByZero 4437 .endif 4438 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4439 4440 subs r0, r0, r2 @ optional op; may set condition codes 4441 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4442 GET_INST_OPCODE(ip) @ extract opcode from rINST 4443 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4444 GOTO_OPCODE(ip) @ jump to next instruction 4445 /* 14-17 instructions */ 4446 4447 4448 4449/* ------------------------------ */ 4450 .balign 64 4451.L_OP_MUL_LONG: /* 0x9d */ 4452/* File: armv5te/OP_MUL_LONG.S */ 4453 /* 4454 * Signed 64-bit integer multiply. 4455 * 4456 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4457 * WX 4458 * x YZ 4459 * -------- 4460 * ZW ZX 4461 * YW YX 4462 * 4463 * The low word of the result holds ZX, the high word holds 4464 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4465 * it doesn't fit in the low 64 bits. 4466 * 4467 * Unlike most ARM math operations, multiply instructions have 4468 * restrictions on using the same register more than once (Rd and Rm 4469 * cannot be the same). 4470 */ 4471 /* mul-long vAA, vBB, vCC */ 4472 FETCH(r0, 1) @ r0<- CCBB 4473 and r2, r0, #255 @ r2<- BB 4474 mov r3, r0, lsr #8 @ r3<- CC 4475 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4476 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4477 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4478 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4479 mul ip, r2, r1 @ ip<- ZxW 4480 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4481 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4482 mov r0, rINST, lsr #8 @ r0<- AA 4483 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4484 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4485 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4486 b .LOP_MUL_LONG_finish 4487 4488/* ------------------------------ */ 4489 .balign 64 4490.L_OP_DIV_LONG: /* 0x9e */ 4491/* File: armv5te/OP_DIV_LONG.S */ 4492/* File: armv5te/binopWide.S */ 4493 /* 4494 * Generic 64-bit binary operation. Provide an "instr" line that 4495 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4496 * This could be an ARM instruction or a function call. (If the result 4497 * comes back in a register other than r0, you can override "result".) 4498 * 4499 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4500 * vCC (r1). Useful for integer division and modulus. 4501 * 4502 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4503 * xor-long, add-double, sub-double, mul-double, div-double, 4504 * rem-double 4505 * 4506 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4507 */ 4508 /* binop vAA, vBB, vCC */ 4509 FETCH(r0, 1) @ r0<- CCBB 4510 mov r9, rINST, lsr #8 @ r9<- AA 4511 and r2, r0, #255 @ r2<- BB 4512 mov r3, r0, lsr #8 @ r3<- CC 4513 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4514 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4515 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4516 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4517 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4518 .if 1 4519 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4520 beq common_errDivideByZero 4521 .endif 4522 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4523 4524 @ optional op; may set condition codes 4525 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4526 GET_INST_OPCODE(ip) @ extract opcode from rINST 4527 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4528 GOTO_OPCODE(ip) @ jump to next instruction 4529 /* 14-17 instructions */ 4530 4531 4532 4533/* ------------------------------ */ 4534 .balign 64 4535.L_OP_REM_LONG: /* 0x9f */ 4536/* File: armv5te/OP_REM_LONG.S */ 4537/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 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 1 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 @ optional op; may set condition codes 4571 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4572 GET_INST_OPCODE(ip) @ extract opcode from rINST 4573 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4574 GOTO_OPCODE(ip) @ jump to next instruction 4575 /* 14-17 instructions */ 4576 4577 4578 4579/* ------------------------------ */ 4580 .balign 64 4581.L_OP_AND_LONG: /* 0xa0 */ 4582/* File: armv5te/OP_AND_LONG.S */ 4583/* File: armv5te/binopWide.S */ 4584 /* 4585 * Generic 64-bit binary operation. Provide an "instr" line that 4586 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4587 * This could be an ARM instruction or a function call. (If the result 4588 * comes back in a register other than r0, you can override "result".) 4589 * 4590 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4591 * vCC (r1). Useful for integer division and modulus. 4592 * 4593 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4594 * xor-long, add-double, sub-double, mul-double, div-double, 4595 * rem-double 4596 * 4597 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4598 */ 4599 /* binop vAA, vBB, vCC */ 4600 FETCH(r0, 1) @ r0<- CCBB 4601 mov r9, rINST, lsr #8 @ r9<- AA 4602 and r2, r0, #255 @ r2<- BB 4603 mov r3, r0, lsr #8 @ r3<- CC 4604 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 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 .if 0 4610 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4611 beq common_errDivideByZero 4612 .endif 4613 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4614 4615 and r0, r0, r2 @ optional op; may set condition codes 4616 and r1, r1, r3 @ result<- op, r0-r3 changed 4617 GET_INST_OPCODE(ip) @ extract opcode from rINST 4618 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4619 GOTO_OPCODE(ip) @ jump to next instruction 4620 /* 14-17 instructions */ 4621 4622 4623 4624/* ------------------------------ */ 4625 .balign 64 4626.L_OP_OR_LONG: /* 0xa1 */ 4627/* File: armv5te/OP_OR_LONG.S */ 4628/* File: armv5te/binopWide.S */ 4629 /* 4630 * Generic 64-bit binary operation. Provide an "instr" line that 4631 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4632 * This could be an ARM instruction or a function call. (If the result 4633 * comes back in a register other than r0, you can override "result".) 4634 * 4635 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4636 * vCC (r1). Useful for integer division and modulus. 4637 * 4638 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4639 * xor-long, add-double, sub-double, mul-double, div-double, 4640 * rem-double 4641 * 4642 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4643 */ 4644 /* binop vAA, vBB, vCC */ 4645 FETCH(r0, 1) @ r0<- CCBB 4646 mov r9, rINST, lsr #8 @ r9<- AA 4647 and r2, r0, #255 @ r2<- BB 4648 mov r3, r0, lsr #8 @ r3<- CC 4649 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4650 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4651 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4652 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4653 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4654 .if 0 4655 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4656 beq common_errDivideByZero 4657 .endif 4658 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4659 4660 orr r0, r0, r2 @ optional op; may set condition codes 4661 orr r1, r1, r3 @ result<- op, r0-r3 changed 4662 GET_INST_OPCODE(ip) @ extract opcode from rINST 4663 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4664 GOTO_OPCODE(ip) @ jump to next instruction 4665 /* 14-17 instructions */ 4666 4667 4668 4669/* ------------------------------ */ 4670 .balign 64 4671.L_OP_XOR_LONG: /* 0xa2 */ 4672/* File: armv5te/OP_XOR_LONG.S */ 4673/* File: armv5te/binopWide.S */ 4674 /* 4675 * Generic 64-bit binary operation. Provide an "instr" line that 4676 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4677 * This could be an ARM instruction or a function call. (If the result 4678 * comes back in a register other than r0, you can override "result".) 4679 * 4680 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4681 * vCC (r1). Useful for integer division and modulus. 4682 * 4683 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4684 * xor-long, add-double, sub-double, mul-double, div-double, 4685 * rem-double 4686 * 4687 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4688 */ 4689 /* binop vAA, vBB, vCC */ 4690 FETCH(r0, 1) @ r0<- CCBB 4691 mov r9, rINST, lsr #8 @ r9<- AA 4692 and r2, r0, #255 @ r2<- BB 4693 mov r3, r0, lsr #8 @ r3<- CC 4694 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4695 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4696 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4697 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4698 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4699 .if 0 4700 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4701 beq common_errDivideByZero 4702 .endif 4703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4704 4705 eor r0, r0, r2 @ optional op; may set condition codes 4706 eor r1, r1, r3 @ result<- op, r0-r3 changed 4707 GET_INST_OPCODE(ip) @ extract opcode from rINST 4708 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4709 GOTO_OPCODE(ip) @ jump to next instruction 4710 /* 14-17 instructions */ 4711 4712 4713 4714/* ------------------------------ */ 4715 .balign 64 4716.L_OP_SHL_LONG: /* 0xa3 */ 4717/* File: armv5te/OP_SHL_LONG.S */ 4718 /* 4719 * Long integer shift. This is different from the generic 32/64-bit 4720 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4721 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4722 * 6 bits of the shift distance. 4723 */ 4724 /* shl-long vAA, vBB, vCC */ 4725 FETCH(r0, 1) @ r0<- CCBB 4726 mov r9, rINST, lsr #8 @ r9<- AA 4727 and r3, r0, #255 @ r3<- BB 4728 mov r0, r0, lsr #8 @ r0<- CC 4729 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4730 GET_VREG(r2, r0) @ r2<- vCC 4731 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4732 and r2, r2, #63 @ r2<- r2 & 0x3f 4733 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4734 4735 mov r1, r1, asl r2 @ r1<- r1 << r2 4736 rsb r3, r2, #32 @ r3<- 32 - r2 4737 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4738 subs ip, r2, #32 @ ip<- r2 - 32 4739 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4740 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4741 b .LOP_SHL_LONG_finish 4742 4743/* ------------------------------ */ 4744 .balign 64 4745.L_OP_SHR_LONG: /* 0xa4 */ 4746/* File: armv5te/OP_SHR_LONG.S */ 4747 /* 4748 * Long integer shift. This is different from the generic 32/64-bit 4749 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4750 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4751 * 6 bits of the shift distance. 4752 */ 4753 /* shr-long vAA, vBB, vCC */ 4754 FETCH(r0, 1) @ r0<- CCBB 4755 mov r9, rINST, lsr #8 @ r9<- AA 4756 and r3, r0, #255 @ r3<- BB 4757 mov r0, r0, lsr #8 @ r0<- CC 4758 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4759 GET_VREG(r2, r0) @ r2<- vCC 4760 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4761 and r2, r2, #63 @ r0<- r0 & 0x3f 4762 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4763 4764 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4765 rsb r3, r2, #32 @ r3<- 32 - r2 4766 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4767 subs ip, r2, #32 @ ip<- r2 - 32 4768 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4769 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4770 b .LOP_SHR_LONG_finish 4771 4772/* ------------------------------ */ 4773 .balign 64 4774.L_OP_USHR_LONG: /* 0xa5 */ 4775/* File: armv5te/OP_USHR_LONG.S */ 4776 /* 4777 * Long integer shift. This is different from the generic 32/64-bit 4778 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4779 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4780 * 6 bits of the shift distance. 4781 */ 4782 /* ushr-long vAA, vBB, vCC */ 4783 FETCH(r0, 1) @ r0<- CCBB 4784 mov r9, rINST, lsr #8 @ r9<- AA 4785 and r3, r0, #255 @ r3<- BB 4786 mov r0, r0, lsr #8 @ r0<- CC 4787 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4788 GET_VREG(r2, r0) @ r2<- vCC 4789 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4790 and r2, r2, #63 @ r0<- r0 & 0x3f 4791 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4792 4793 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4794 rsb r3, r2, #32 @ r3<- 32 - r2 4795 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4796 subs ip, r2, #32 @ ip<- r2 - 32 4797 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4799 b .LOP_USHR_LONG_finish 4800 4801/* ------------------------------ */ 4802 .balign 64 4803.L_OP_ADD_FLOAT: /* 0xa6 */ 4804/* File: vfp/OP_ADD_FLOAT.S */ 4805/* File: vfp/fbinop.S */ 4806 /* 4807 * Generic 32-bit floating-point operation. Provide an "instr" line that 4808 * specifies an instruction that performs "s2 = s0 op s1". Because we 4809 * use the "softfp" ABI, this must be an instruction, not a function call. 4810 * 4811 * For: add-float, sub-float, mul-float, div-float 4812 */ 4813 /* floatop vAA, vBB, vCC */ 4814 FETCH(r0, 1) @ r0<- CCBB 4815 mov r9, rINST, lsr #8 @ r9<- AA 4816 mov r3, r0, lsr #8 @ r3<- CC 4817 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4818 flds s1, [r3] @ s1<- vCC 4819 and r2, r0, #255 @ r2<- BB 4820 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4821 flds s0, [r2] @ s0<- vBB 4822 4823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4824 fadds s2, s0, s1 @ s2<- op 4825 GET_INST_OPCODE(ip) @ extract opcode from rINST 4826 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4827 fsts s2, [r9] @ vAA<- s2 4828 GOTO_OPCODE(ip) @ jump to next instruction 4829 4830 4831/* ------------------------------ */ 4832 .balign 64 4833.L_OP_SUB_FLOAT: /* 0xa7 */ 4834/* File: vfp/OP_SUB_FLOAT.S */ 4835/* File: vfp/fbinop.S */ 4836 /* 4837 * Generic 32-bit floating-point operation. Provide an "instr" line that 4838 * specifies an instruction that performs "s2 = s0 op s1". Because we 4839 * use the "softfp" ABI, this must be an instruction, not a function call. 4840 * 4841 * For: add-float, sub-float, mul-float, div-float 4842 */ 4843 /* floatop vAA, vBB, vCC */ 4844 FETCH(r0, 1) @ r0<- CCBB 4845 mov r9, rINST, lsr #8 @ r9<- AA 4846 mov r3, r0, lsr #8 @ r3<- CC 4847 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4848 flds s1, [r3] @ s1<- vCC 4849 and r2, r0, #255 @ r2<- BB 4850 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4851 flds s0, [r2] @ s0<- vBB 4852 4853 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4854 fsubs s2, s0, s1 @ s2<- op 4855 GET_INST_OPCODE(ip) @ extract opcode from rINST 4856 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4857 fsts s2, [r9] @ vAA<- s2 4858 GOTO_OPCODE(ip) @ jump to next instruction 4859 4860 4861/* ------------------------------ */ 4862 .balign 64 4863.L_OP_MUL_FLOAT: /* 0xa8 */ 4864/* File: vfp/OP_MUL_FLOAT.S */ 4865/* File: vfp/fbinop.S */ 4866 /* 4867 * Generic 32-bit floating-point operation. Provide an "instr" line that 4868 * specifies an instruction that performs "s2 = s0 op s1". Because we 4869 * use the "softfp" ABI, this must be an instruction, not a function call. 4870 * 4871 * For: add-float, sub-float, mul-float, div-float 4872 */ 4873 /* floatop vAA, vBB, vCC */ 4874 FETCH(r0, 1) @ r0<- CCBB 4875 mov r9, rINST, lsr #8 @ r9<- AA 4876 mov r3, r0, lsr #8 @ r3<- CC 4877 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4878 flds s1, [r3] @ s1<- vCC 4879 and r2, r0, #255 @ r2<- BB 4880 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4881 flds s0, [r2] @ s0<- vBB 4882 4883 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4884 fmuls s2, s0, s1 @ s2<- op 4885 GET_INST_OPCODE(ip) @ extract opcode from rINST 4886 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4887 fsts s2, [r9] @ vAA<- s2 4888 GOTO_OPCODE(ip) @ jump to next instruction 4889 4890 4891/* ------------------------------ */ 4892 .balign 64 4893.L_OP_DIV_FLOAT: /* 0xa9 */ 4894/* File: vfp/OP_DIV_FLOAT.S */ 4895/* File: vfp/fbinop.S */ 4896 /* 4897 * Generic 32-bit floating-point operation. Provide an "instr" line that 4898 * specifies an instruction that performs "s2 = s0 op s1". Because we 4899 * use the "softfp" ABI, this must be an instruction, not a function call. 4900 * 4901 * For: add-float, sub-float, mul-float, div-float 4902 */ 4903 /* floatop vAA, vBB, vCC */ 4904 FETCH(r0, 1) @ r0<- CCBB 4905 mov r9, rINST, lsr #8 @ r9<- AA 4906 mov r3, r0, lsr #8 @ r3<- CC 4907 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4908 flds s1, [r3] @ s1<- vCC 4909 and r2, r0, #255 @ r2<- BB 4910 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4911 flds s0, [r2] @ s0<- vBB 4912 4913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4914 fdivs s2, s0, s1 @ s2<- op 4915 GET_INST_OPCODE(ip) @ extract opcode from rINST 4916 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4917 fsts s2, [r9] @ vAA<- s2 4918 GOTO_OPCODE(ip) @ jump to next instruction 4919 4920 4921/* ------------------------------ */ 4922 .balign 64 4923.L_OP_REM_FLOAT: /* 0xaa */ 4924/* File: armv5te/OP_REM_FLOAT.S */ 4925/* EABI doesn't define a float remainder function, but libm does */ 4926/* File: armv5te/binop.S */ 4927 /* 4928 * Generic 32-bit binary operation. Provide an "instr" line that 4929 * specifies an instruction that performs "result = r0 op r1". 4930 * This could be an ARM instruction or a function call. (If the result 4931 * comes back in a register other than r0, you can override "result".) 4932 * 4933 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4934 * vCC (r1). Useful for integer division and modulus. Note that we 4935 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4936 * handles it correctly. 4937 * 4938 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4939 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4940 * mul-float, div-float, rem-float 4941 */ 4942 /* binop vAA, vBB, vCC */ 4943 FETCH(r0, 1) @ r0<- CCBB 4944 mov r9, rINST, lsr #8 @ r9<- AA 4945 mov r3, r0, lsr #8 @ r3<- CC 4946 and r2, r0, #255 @ r2<- BB 4947 GET_VREG(r1, r3) @ r1<- vCC 4948 GET_VREG(r0, r2) @ r0<- vBB 4949 .if 0 4950 cmp r1, #0 @ is second operand zero? 4951 beq common_errDivideByZero 4952 .endif 4953 4954 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4955 @ optional op; may set condition codes 4956 bl fmodf @ r0<- op, r0-r3 changed 4957 GET_INST_OPCODE(ip) @ extract opcode from rINST 4958 SET_VREG(r0, r9) @ vAA<- r0 4959 GOTO_OPCODE(ip) @ jump to next instruction 4960 /* 11-14 instructions */ 4961 4962 4963 4964/* ------------------------------ */ 4965 .balign 64 4966.L_OP_ADD_DOUBLE: /* 0xab */ 4967/* File: vfp/OP_ADD_DOUBLE.S */ 4968/* File: vfp/fbinopWide.S */ 4969 /* 4970 * Generic 64-bit double-precision floating point binary operation. 4971 * Provide an "instr" line that specifies an instruction that performs 4972 * "d2 = d0 op d1". 4973 * 4974 * for: add-double, sub-double, mul-double, div-double 4975 */ 4976 /* doubleop vAA, vBB, vCC */ 4977 FETCH(r0, 1) @ r0<- CCBB 4978 mov r9, rINST, lsr #8 @ r9<- AA 4979 mov r3, r0, lsr #8 @ r3<- CC 4980 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4981 fldd d1, [r3] @ d1<- vCC 4982 and r2, r0, #255 @ r2<- BB 4983 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4984 fldd d0, [r2] @ d0<- vBB 4985 4986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4987 faddd d2, d0, d1 @ s2<- op 4988 GET_INST_OPCODE(ip) @ extract opcode from rINST 4989 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4990 fstd d2, [r9] @ vAA<- d2 4991 GOTO_OPCODE(ip) @ jump to next instruction 4992 4993 4994/* ------------------------------ */ 4995 .balign 64 4996.L_OP_SUB_DOUBLE: /* 0xac */ 4997/* File: vfp/OP_SUB_DOUBLE.S */ 4998/* File: vfp/fbinopWide.S */ 4999 /* 5000 * Generic 64-bit double-precision floating point binary operation. 5001 * Provide an "instr" line that specifies an instruction that performs 5002 * "d2 = d0 op d1". 5003 * 5004 * for: add-double, sub-double, mul-double, div-double 5005 */ 5006 /* doubleop vAA, vBB, vCC */ 5007 FETCH(r0, 1) @ r0<- CCBB 5008 mov r9, rINST, lsr #8 @ r9<- AA 5009 mov r3, r0, lsr #8 @ r3<- CC 5010 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5011 fldd d1, [r3] @ d1<- vCC 5012 and r2, r0, #255 @ r2<- BB 5013 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5014 fldd d0, [r2] @ d0<- vBB 5015 5016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5017 fsubd d2, d0, d1 @ s2<- op 5018 GET_INST_OPCODE(ip) @ extract opcode from rINST 5019 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5020 fstd d2, [r9] @ vAA<- d2 5021 GOTO_OPCODE(ip) @ jump to next instruction 5022 5023 5024/* ------------------------------ */ 5025 .balign 64 5026.L_OP_MUL_DOUBLE: /* 0xad */ 5027/* File: vfp/OP_MUL_DOUBLE.S */ 5028/* File: vfp/fbinopWide.S */ 5029 /* 5030 * Generic 64-bit double-precision floating point binary operation. 5031 * Provide an "instr" line that specifies an instruction that performs 5032 * "d2 = d0 op d1". 5033 * 5034 * for: add-double, sub-double, mul-double, div-double 5035 */ 5036 /* doubleop vAA, vBB, vCC */ 5037 FETCH(r0, 1) @ r0<- CCBB 5038 mov r9, rINST, lsr #8 @ r9<- AA 5039 mov r3, r0, lsr #8 @ r3<- CC 5040 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5041 fldd d1, [r3] @ d1<- vCC 5042 and r2, r0, #255 @ r2<- BB 5043 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5044 fldd d0, [r2] @ d0<- vBB 5045 5046 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5047 fmuld d2, d0, d1 @ s2<- op 5048 GET_INST_OPCODE(ip) @ extract opcode from rINST 5049 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5050 fstd d2, [r9] @ vAA<- d2 5051 GOTO_OPCODE(ip) @ jump to next instruction 5052 5053 5054/* ------------------------------ */ 5055 .balign 64 5056.L_OP_DIV_DOUBLE: /* 0xae */ 5057/* File: vfp/OP_DIV_DOUBLE.S */ 5058/* File: vfp/fbinopWide.S */ 5059 /* 5060 * Generic 64-bit double-precision floating point binary operation. 5061 * Provide an "instr" line that specifies an instruction that performs 5062 * "d2 = d0 op d1". 5063 * 5064 * for: add-double, sub-double, mul-double, div-double 5065 */ 5066 /* doubleop vAA, vBB, vCC */ 5067 FETCH(r0, 1) @ r0<- CCBB 5068 mov r9, rINST, lsr #8 @ r9<- AA 5069 mov r3, r0, lsr #8 @ r3<- CC 5070 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5071 fldd d1, [r3] @ d1<- vCC 5072 and r2, r0, #255 @ r2<- BB 5073 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5074 fldd d0, [r2] @ d0<- vBB 5075 5076 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5077 fdivd d2, d0, d1 @ s2<- op 5078 GET_INST_OPCODE(ip) @ extract opcode from rINST 5079 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5080 fstd d2, [r9] @ vAA<- d2 5081 GOTO_OPCODE(ip) @ jump to next instruction 5082 5083 5084/* ------------------------------ */ 5085 .balign 64 5086.L_OP_REM_DOUBLE: /* 0xaf */ 5087/* File: armv5te/OP_REM_DOUBLE.S */ 5088/* EABI doesn't define a double remainder function, but libm does */ 5089/* File: armv5te/binopWide.S */ 5090 /* 5091 * Generic 64-bit binary operation. Provide an "instr" line that 5092 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5093 * This could be an ARM instruction or a function call. (If the result 5094 * comes back in a register other than r0, you can override "result".) 5095 * 5096 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5097 * vCC (r1). Useful for integer division and modulus. 5098 * 5099 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5100 * xor-long, add-double, sub-double, mul-double, div-double, 5101 * rem-double 5102 * 5103 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5104 */ 5105 /* binop vAA, vBB, vCC */ 5106 FETCH(r0, 1) @ r0<- CCBB 5107 mov r9, rINST, lsr #8 @ r9<- AA 5108 and r2, r0, #255 @ r2<- BB 5109 mov r3, r0, lsr #8 @ r3<- CC 5110 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5111 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5112 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5113 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5114 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5115 .if 0 5116 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5117 beq common_errDivideByZero 5118 .endif 5119 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5120 5121 @ optional op; may set condition codes 5122 bl fmod @ result<- op, r0-r3 changed 5123 GET_INST_OPCODE(ip) @ extract opcode from rINST 5124 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5125 GOTO_OPCODE(ip) @ jump to next instruction 5126 /* 14-17 instructions */ 5127 5128 5129 5130/* ------------------------------ */ 5131 .balign 64 5132.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5133/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5134/* File: armv5te/binop2addr.S */ 5135 /* 5136 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5137 * that specifies an instruction that performs "result = r0 op r1". 5138 * This could be an ARM instruction or a function call. (If the result 5139 * comes back in a register other than r0, you can override "result".) 5140 * 5141 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5142 * vCC (r1). Useful for integer division and modulus. 5143 * 5144 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5145 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5146 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5147 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5148 */ 5149 /* binop/2addr vA, vB */ 5150 mov r9, rINST, lsr #8 @ r9<- A+ 5151 mov r3, rINST, lsr #12 @ r3<- B 5152 and r9, r9, #15 5153 GET_VREG(r0, r9) @ r0<- vA 5154 GET_VREG(r1, r3) @ r1<- vB 5155 .if 0 5156 cmp r1, #0 @ is second operand zero? 5157 beq common_errDivideByZero 5158 .endif 5159 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5160 5161 @ optional op; may set condition codes 5162 add r0, r0, r1 @ r0<- op, r0-r3 changed 5163 GET_INST_OPCODE(ip) @ extract opcode from rINST 5164 SET_VREG(r0, r9) @ vAA<- r0 5165 GOTO_OPCODE(ip) @ jump to next instruction 5166 /* 10-13 instructions */ 5167 5168 5169 5170/* ------------------------------ */ 5171 .balign 64 5172.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5173/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5174/* File: armv5te/binop2addr.S */ 5175 /* 5176 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5177 * that specifies an instruction that performs "result = r0 op r1". 5178 * This could be an ARM instruction or a function call. (If the result 5179 * comes back in a register other than r0, you can override "result".) 5180 * 5181 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5182 * vCC (r1). Useful for integer division and modulus. 5183 * 5184 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5185 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5186 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5187 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5188 */ 5189 /* binop/2addr vA, vB */ 5190 mov r9, rINST, lsr #8 @ r9<- A+ 5191 mov r3, rINST, lsr #12 @ r3<- B 5192 and r9, r9, #15 5193 GET_VREG(r0, r9) @ r0<- vA 5194 GET_VREG(r1, r3) @ r1<- vB 5195 .if 0 5196 cmp r1, #0 @ is second operand zero? 5197 beq common_errDivideByZero 5198 .endif 5199 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5200 5201 @ optional op; may set condition codes 5202 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5203 GET_INST_OPCODE(ip) @ extract opcode from rINST 5204 SET_VREG(r0, r9) @ vAA<- r0 5205 GOTO_OPCODE(ip) @ jump to next instruction 5206 /* 10-13 instructions */ 5207 5208 5209 5210/* ------------------------------ */ 5211 .balign 64 5212.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5213/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5214/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5215/* File: armv5te/binop2addr.S */ 5216 /* 5217 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5218 * that specifies an instruction that performs "result = r0 op r1". 5219 * This could be an ARM instruction or a function call. (If the result 5220 * comes back in a register other than r0, you can override "result".) 5221 * 5222 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5223 * vCC (r1). Useful for integer division and modulus. 5224 * 5225 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5226 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5227 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5228 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5229 */ 5230 /* binop/2addr vA, vB */ 5231 mov r9, rINST, lsr #8 @ r9<- A+ 5232 mov r3, rINST, lsr #12 @ r3<- B 5233 and r9, r9, #15 5234 GET_VREG(r0, r9) @ r0<- vA 5235 GET_VREG(r1, r3) @ r1<- vB 5236 .if 0 5237 cmp r1, #0 @ is second operand zero? 5238 beq common_errDivideByZero 5239 .endif 5240 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5241 5242 @ optional op; may set condition codes 5243 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5244 GET_INST_OPCODE(ip) @ extract opcode from rINST 5245 SET_VREG(r0, r9) @ vAA<- r0 5246 GOTO_OPCODE(ip) @ jump to next instruction 5247 /* 10-13 instructions */ 5248 5249 5250 5251/* ------------------------------ */ 5252 .balign 64 5253.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5254/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5255/* File: armv5te/binop2addr.S */ 5256 /* 5257 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5258 * that specifies an instruction that performs "result = r0 op r1". 5259 * This could be an ARM instruction or a function call. (If the result 5260 * comes back in a register other than r0, you can override "result".) 5261 * 5262 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5263 * vCC (r1). Useful for integer division and modulus. 5264 * 5265 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5266 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5267 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5268 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5269 */ 5270 /* binop/2addr vA, vB */ 5271 mov r9, rINST, lsr #8 @ r9<- A+ 5272 mov r3, rINST, lsr #12 @ r3<- B 5273 and r9, r9, #15 5274 GET_VREG(r0, r9) @ r0<- vA 5275 GET_VREG(r1, r3) @ r1<- vB 5276 .if 1 5277 cmp r1, #0 @ is second operand zero? 5278 beq common_errDivideByZero 5279 .endif 5280 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5281 5282 @ optional op; may set condition codes 5283 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5284 GET_INST_OPCODE(ip) @ extract opcode from rINST 5285 SET_VREG(r0, r9) @ vAA<- r0 5286 GOTO_OPCODE(ip) @ jump to next instruction 5287 /* 10-13 instructions */ 5288 5289 5290 5291/* ------------------------------ */ 5292 .balign 64 5293.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5294/* File: armv5te/OP_REM_INT_2ADDR.S */ 5295/* idivmod returns quotient in r0 and remainder in r1 */ 5296/* File: armv5te/binop2addr.S */ 5297 /* 5298 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5299 * that specifies an instruction that performs "result = r0 op r1". 5300 * This could be an ARM instruction or a function call. (If the result 5301 * comes back in a register other than r0, you can override "result".) 5302 * 5303 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5304 * vCC (r1). Useful for integer division and modulus. 5305 * 5306 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5307 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5308 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5309 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5310 */ 5311 /* binop/2addr vA, vB */ 5312 mov r9, rINST, lsr #8 @ r9<- A+ 5313 mov r3, rINST, lsr #12 @ r3<- B 5314 and r9, r9, #15 5315 GET_VREG(r0, r9) @ r0<- vA 5316 GET_VREG(r1, r3) @ r1<- vB 5317 .if 1 5318 cmp r1, #0 @ is second operand zero? 5319 beq common_errDivideByZero 5320 .endif 5321 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5322 5323 @ optional op; may set condition codes 5324 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5325 GET_INST_OPCODE(ip) @ extract opcode from rINST 5326 SET_VREG(r1, r9) @ vAA<- r1 5327 GOTO_OPCODE(ip) @ jump to next instruction 5328 /* 10-13 instructions */ 5329 5330 5331 5332/* ------------------------------ */ 5333 .balign 64 5334.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5335/* File: armv5te/OP_AND_INT_2ADDR.S */ 5336/* File: armv5te/binop2addr.S */ 5337 /* 5338 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5339 * that specifies an instruction that performs "result = r0 op r1". 5340 * This could be an ARM instruction or a function call. (If the result 5341 * comes back in a register other than r0, you can override "result".) 5342 * 5343 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5344 * vCC (r1). Useful for integer division and modulus. 5345 * 5346 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5347 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5348 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5349 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5350 */ 5351 /* binop/2addr vA, vB */ 5352 mov r9, rINST, lsr #8 @ r9<- A+ 5353 mov r3, rINST, lsr #12 @ r3<- B 5354 and r9, r9, #15 5355 GET_VREG(r0, r9) @ r0<- vA 5356 GET_VREG(r1, r3) @ r1<- vB 5357 .if 0 5358 cmp r1, #0 @ is second operand zero? 5359 beq common_errDivideByZero 5360 .endif 5361 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5362 5363 @ optional op; may set condition codes 5364 and r0, r0, r1 @ r0<- op, r0-r3 changed 5365 GET_INST_OPCODE(ip) @ extract opcode from rINST 5366 SET_VREG(r0, r9) @ vAA<- r0 5367 GOTO_OPCODE(ip) @ jump to next instruction 5368 /* 10-13 instructions */ 5369 5370 5371 5372/* ------------------------------ */ 5373 .balign 64 5374.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5375/* File: armv5te/OP_OR_INT_2ADDR.S */ 5376/* File: armv5te/binop2addr.S */ 5377 /* 5378 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5379 * that specifies an instruction that performs "result = r0 op r1". 5380 * This could be an ARM instruction or a function call. (If the result 5381 * comes back in a register other than r0, you can override "result".) 5382 * 5383 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5384 * vCC (r1). Useful for integer division and modulus. 5385 * 5386 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5387 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5388 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5389 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5390 */ 5391 /* binop/2addr vA, vB */ 5392 mov r9, rINST, lsr #8 @ r9<- A+ 5393 mov r3, rINST, lsr #12 @ r3<- B 5394 and r9, r9, #15 5395 GET_VREG(r0, r9) @ r0<- vA 5396 GET_VREG(r1, r3) @ r1<- vB 5397 .if 0 5398 cmp r1, #0 @ is second operand zero? 5399 beq common_errDivideByZero 5400 .endif 5401 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5402 5403 @ optional op; may set condition codes 5404 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5405 GET_INST_OPCODE(ip) @ extract opcode from rINST 5406 SET_VREG(r0, r9) @ vAA<- r0 5407 GOTO_OPCODE(ip) @ jump to next instruction 5408 /* 10-13 instructions */ 5409 5410 5411 5412/* ------------------------------ */ 5413 .balign 64 5414.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5415/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5416/* File: armv5te/binop2addr.S */ 5417 /* 5418 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5419 * that specifies an instruction that performs "result = r0 op r1". 5420 * This could be an ARM instruction or a function call. (If the result 5421 * comes back in a register other than r0, you can override "result".) 5422 * 5423 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5424 * vCC (r1). Useful for integer division and modulus. 5425 * 5426 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5427 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5428 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5429 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5430 */ 5431 /* binop/2addr vA, vB */ 5432 mov r9, rINST, lsr #8 @ r9<- A+ 5433 mov r3, rINST, lsr #12 @ r3<- B 5434 and r9, r9, #15 5435 GET_VREG(r0, r9) @ r0<- vA 5436 GET_VREG(r1, r3) @ r1<- vB 5437 .if 0 5438 cmp r1, #0 @ is second operand zero? 5439 beq common_errDivideByZero 5440 .endif 5441 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5442 5443 @ optional op; may set condition codes 5444 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5445 GET_INST_OPCODE(ip) @ extract opcode from rINST 5446 SET_VREG(r0, r9) @ vAA<- r0 5447 GOTO_OPCODE(ip) @ jump to next instruction 5448 /* 10-13 instructions */ 5449 5450 5451 5452/* ------------------------------ */ 5453 .balign 64 5454.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5455/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5456/* File: armv5te/binop2addr.S */ 5457 /* 5458 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5459 * that specifies an instruction that performs "result = r0 op r1". 5460 * This could be an ARM instruction or a function call. (If the result 5461 * comes back in a register other than r0, you can override "result".) 5462 * 5463 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5464 * vCC (r1). Useful for integer division and modulus. 5465 * 5466 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5467 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5468 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5469 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5470 */ 5471 /* binop/2addr vA, vB */ 5472 mov r9, rINST, lsr #8 @ r9<- A+ 5473 mov r3, rINST, lsr #12 @ r3<- B 5474 and r9, r9, #15 5475 GET_VREG(r0, r9) @ r0<- vA 5476 GET_VREG(r1, r3) @ r1<- vB 5477 .if 0 5478 cmp r1, #0 @ is second operand zero? 5479 beq common_errDivideByZero 5480 .endif 5481 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5482 5483 and r1, r1, #31 @ optional op; may set condition codes 5484 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5485 GET_INST_OPCODE(ip) @ extract opcode from rINST 5486 SET_VREG(r0, r9) @ vAA<- r0 5487 GOTO_OPCODE(ip) @ jump to next instruction 5488 /* 10-13 instructions */ 5489 5490 5491 5492/* ------------------------------ */ 5493 .balign 64 5494.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5495/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5496/* File: armv5te/binop2addr.S */ 5497 /* 5498 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5499 * that specifies an instruction that performs "result = r0 op r1". 5500 * This could be an ARM instruction or a function call. (If the result 5501 * comes back in a register other than r0, you can override "result".) 5502 * 5503 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5504 * vCC (r1). Useful for integer division and modulus. 5505 * 5506 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5507 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5508 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5509 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5510 */ 5511 /* binop/2addr vA, vB */ 5512 mov r9, rINST, lsr #8 @ r9<- A+ 5513 mov r3, rINST, lsr #12 @ r3<- B 5514 and r9, r9, #15 5515 GET_VREG(r0, r9) @ r0<- vA 5516 GET_VREG(r1, r3) @ r1<- vB 5517 .if 0 5518 cmp r1, #0 @ is second operand zero? 5519 beq common_errDivideByZero 5520 .endif 5521 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5522 5523 and r1, r1, #31 @ optional op; may set condition codes 5524 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5525 GET_INST_OPCODE(ip) @ extract opcode from rINST 5526 SET_VREG(r0, r9) @ vAA<- r0 5527 GOTO_OPCODE(ip) @ jump to next instruction 5528 /* 10-13 instructions */ 5529 5530 5531 5532/* ------------------------------ */ 5533 .balign 64 5534.L_OP_USHR_INT_2ADDR: /* 0xba */ 5535/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5536/* File: armv5te/binop2addr.S */ 5537 /* 5538 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5539 * that specifies an instruction that performs "result = r0 op r1". 5540 * This could be an ARM instruction or a function call. (If the result 5541 * comes back in a register other than r0, you can override "result".) 5542 * 5543 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5544 * vCC (r1). Useful for integer division and modulus. 5545 * 5546 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5547 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5548 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5549 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5550 */ 5551 /* binop/2addr vA, vB */ 5552 mov r9, rINST, lsr #8 @ r9<- A+ 5553 mov r3, rINST, lsr #12 @ r3<- B 5554 and r9, r9, #15 5555 GET_VREG(r0, r9) @ r0<- vA 5556 GET_VREG(r1, r3) @ r1<- vB 5557 .if 0 5558 cmp r1, #0 @ is second operand zero? 5559 beq common_errDivideByZero 5560 .endif 5561 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5562 5563 and r1, r1, #31 @ optional op; may set condition codes 5564 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5565 GET_INST_OPCODE(ip) @ extract opcode from rINST 5566 SET_VREG(r0, r9) @ vAA<- r0 5567 GOTO_OPCODE(ip) @ jump to next instruction 5568 /* 10-13 instructions */ 5569 5570 5571 5572/* ------------------------------ */ 5573 .balign 64 5574.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5575/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5576/* File: armv5te/binopWide2addr.S */ 5577 /* 5578 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5579 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5580 * This could be an ARM instruction or a function call. (If the result 5581 * comes back in a register other than r0, you can override "result".) 5582 * 5583 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5584 * vCC (r1). Useful for integer division and modulus. 5585 * 5586 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5587 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5588 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5589 * rem-double/2addr 5590 */ 5591 /* binop/2addr vA, vB */ 5592 mov r9, rINST, lsr #8 @ r9<- A+ 5593 mov r1, rINST, lsr #12 @ r1<- B 5594 and r9, r9, #15 5595 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5596 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5597 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5598 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5599 .if 0 5600 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5601 beq common_errDivideByZero 5602 .endif 5603 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5604 5605 adds r0, r0, r2 @ optional op; may set condition codes 5606 adc r1, r1, r3 @ result<- op, r0-r3 changed 5607 GET_INST_OPCODE(ip) @ extract opcode from rINST 5608 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5609 GOTO_OPCODE(ip) @ jump to next instruction 5610 /* 12-15 instructions */ 5611 5612 5613 5614/* ------------------------------ */ 5615 .balign 64 5616.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5617/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5618/* File: armv5te/binopWide2addr.S */ 5619 /* 5620 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5621 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5622 * This could be an ARM instruction or a function call. (If the result 5623 * comes back in a register other than r0, you can override "result".) 5624 * 5625 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5626 * vCC (r1). Useful for integer division and modulus. 5627 * 5628 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5629 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5630 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5631 * rem-double/2addr 5632 */ 5633 /* binop/2addr vA, vB */ 5634 mov r9, rINST, lsr #8 @ r9<- A+ 5635 mov r1, rINST, lsr #12 @ r1<- B 5636 and r9, r9, #15 5637 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5638 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5639 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5640 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5641 .if 0 5642 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5643 beq common_errDivideByZero 5644 .endif 5645 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5646 5647 subs r0, r0, r2 @ optional op; may set condition codes 5648 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5649 GET_INST_OPCODE(ip) @ extract opcode from rINST 5650 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5651 GOTO_OPCODE(ip) @ jump to next instruction 5652 /* 12-15 instructions */ 5653 5654 5655 5656/* ------------------------------ */ 5657 .balign 64 5658.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5659/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5660 /* 5661 * Signed 64-bit integer multiply, "/2addr" version. 5662 * 5663 * See OP_MUL_LONG for an explanation. 5664 * 5665 * We get a little tight on registers, so to avoid looking up &fp[A] 5666 * again we stuff it into rINST. 5667 */ 5668 /* mul-long/2addr vA, vB */ 5669 mov r9, rINST, lsr #8 @ r9<- A+ 5670 mov r1, rINST, lsr #12 @ r1<- B 5671 and r9, r9, #15 5672 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5673 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5674 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5675 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5676 mul ip, r2, r1 @ ip<- ZxW 5677 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5678 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5679 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5680 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5681 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5682 GET_INST_OPCODE(ip) @ extract opcode from rINST 5683 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5684 GOTO_OPCODE(ip) @ jump to next instruction 5685 5686 5687/* ------------------------------ */ 5688 .balign 64 5689.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5690/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5691/* File: armv5te/binopWide2addr.S */ 5692 /* 5693 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5694 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5695 * This could be an ARM instruction or a function call. (If the result 5696 * comes back in a register other than r0, you can override "result".) 5697 * 5698 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5699 * vCC (r1). Useful for integer division and modulus. 5700 * 5701 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5702 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5703 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5704 * rem-double/2addr 5705 */ 5706 /* binop/2addr vA, vB */ 5707 mov r9, rINST, lsr #8 @ r9<- A+ 5708 mov r1, rINST, lsr #12 @ r1<- B 5709 and r9, r9, #15 5710 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5711 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5712 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5713 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5714 .if 1 5715 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5716 beq common_errDivideByZero 5717 .endif 5718 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5719 5720 @ optional op; may set condition codes 5721 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5722 GET_INST_OPCODE(ip) @ extract opcode from rINST 5723 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5724 GOTO_OPCODE(ip) @ jump to next instruction 5725 /* 12-15 instructions */ 5726 5727 5728 5729/* ------------------------------ */ 5730 .balign 64 5731.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5732/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5733/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5734/* File: armv5te/binopWide2addr.S */ 5735 /* 5736 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5737 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5745 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5746 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5747 * rem-double/2addr 5748 */ 5749 /* binop/2addr vA, vB */ 5750 mov r9, rINST, lsr #8 @ r9<- A+ 5751 mov r1, rINST, lsr #12 @ r1<- B 5752 and r9, r9, #15 5753 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5754 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5755 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5756 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5757 .if 1 5758 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5759 beq common_errDivideByZero 5760 .endif 5761 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5762 5763 @ optional op; may set condition codes 5764 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5765 GET_INST_OPCODE(ip) @ extract opcode from rINST 5766 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5767 GOTO_OPCODE(ip) @ jump to next instruction 5768 /* 12-15 instructions */ 5769 5770 5771 5772/* ------------------------------ */ 5773 .balign 64 5774.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5775/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5776/* File: armv5te/binopWide2addr.S */ 5777 /* 5778 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5779 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5780 * This could be an ARM instruction or a function call. (If the result 5781 * comes back in a register other than r0, you can override "result".) 5782 * 5783 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5784 * vCC (r1). Useful for integer division and modulus. 5785 * 5786 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5787 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5788 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5789 * rem-double/2addr 5790 */ 5791 /* binop/2addr vA, vB */ 5792 mov r9, rINST, lsr #8 @ r9<- A+ 5793 mov r1, rINST, lsr #12 @ r1<- B 5794 and r9, r9, #15 5795 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5796 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5797 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5798 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5799 .if 0 5800 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5801 beq common_errDivideByZero 5802 .endif 5803 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5804 5805 and r0, r0, r2 @ optional op; may set condition codes 5806 and r1, r1, r3 @ result<- op, r0-r3 changed 5807 GET_INST_OPCODE(ip) @ extract opcode from rINST 5808 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5809 GOTO_OPCODE(ip) @ jump to next instruction 5810 /* 12-15 instructions */ 5811 5812 5813 5814/* ------------------------------ */ 5815 .balign 64 5816.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5817/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5818/* File: armv5te/binopWide2addr.S */ 5819 /* 5820 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5821 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5822 * This could be an ARM instruction or a function call. (If the result 5823 * comes back in a register other than r0, you can override "result".) 5824 * 5825 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5826 * vCC (r1). Useful for integer division and modulus. 5827 * 5828 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5829 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5830 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5831 * rem-double/2addr 5832 */ 5833 /* binop/2addr vA, vB */ 5834 mov r9, rINST, lsr #8 @ r9<- A+ 5835 mov r1, rINST, lsr #12 @ r1<- B 5836 and r9, r9, #15 5837 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5838 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5839 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5840 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5841 .if 0 5842 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5843 beq common_errDivideByZero 5844 .endif 5845 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5846 5847 orr r0, r0, r2 @ optional op; may set condition codes 5848 orr r1, r1, r3 @ result<- op, r0-r3 changed 5849 GET_INST_OPCODE(ip) @ extract opcode from rINST 5850 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5851 GOTO_OPCODE(ip) @ jump to next instruction 5852 /* 12-15 instructions */ 5853 5854 5855 5856/* ------------------------------ */ 5857 .balign 64 5858.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5859/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5860/* File: armv5te/binopWide2addr.S */ 5861 /* 5862 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5863 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5864 * This could be an ARM instruction or a function call. (If the result 5865 * comes back in a register other than r0, you can override "result".) 5866 * 5867 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5868 * vCC (r1). Useful for integer division and modulus. 5869 * 5870 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5871 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5872 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5873 * rem-double/2addr 5874 */ 5875 /* binop/2addr vA, vB */ 5876 mov r9, rINST, lsr #8 @ r9<- A+ 5877 mov r1, rINST, lsr #12 @ r1<- B 5878 and r9, r9, #15 5879 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5880 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5881 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5882 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5883 .if 0 5884 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5885 beq common_errDivideByZero 5886 .endif 5887 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5888 5889 eor r0, r0, r2 @ optional op; may set condition codes 5890 eor r1, r1, r3 @ result<- op, r0-r3 changed 5891 GET_INST_OPCODE(ip) @ extract opcode from rINST 5892 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5893 GOTO_OPCODE(ip) @ jump to next instruction 5894 /* 12-15 instructions */ 5895 5896 5897 5898/* ------------------------------ */ 5899 .balign 64 5900.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5901/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 5902 /* 5903 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5904 * 32-bit shift distance. 5905 */ 5906 /* shl-long/2addr vA, vB */ 5907 mov r9, rINST, lsr #8 @ r9<- A+ 5908 mov r3, rINST, lsr #12 @ r3<- B 5909 and r9, r9, #15 5910 GET_VREG(r2, r3) @ r2<- vB 5911 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5912 and r2, r2, #63 @ r2<- r2 & 0x3f 5913 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5914 5915 mov r1, r1, asl r2 @ r1<- r1 << r2 5916 rsb r3, r2, #32 @ r3<- 32 - r2 5917 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5918 subs ip, r2, #32 @ ip<- r2 - 32 5919 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5920 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5921 mov r0, r0, asl r2 @ r0<- r0 << r2 5922 b .LOP_SHL_LONG_2ADDR_finish 5923 5924/* ------------------------------ */ 5925 .balign 64 5926.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 5927/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 5928 /* 5929 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5930 * 32-bit shift distance. 5931 */ 5932 /* shr-long/2addr vA, vB */ 5933 mov r9, rINST, lsr #8 @ r9<- A+ 5934 mov r3, rINST, lsr #12 @ r3<- B 5935 and r9, r9, #15 5936 GET_VREG(r2, r3) @ r2<- vB 5937 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5938 and r2, r2, #63 @ r2<- r2 & 0x3f 5939 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5940 5941 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5942 rsb r3, r2, #32 @ r3<- 32 - r2 5943 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5944 subs ip, r2, #32 @ ip<- r2 - 32 5945 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5946 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 5947 mov r1, r1, asr r2 @ r1<- r1 >> r2 5948 b .LOP_SHR_LONG_2ADDR_finish 5949 5950/* ------------------------------ */ 5951 .balign 64 5952.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 5953/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 5954 /* 5955 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5956 * 32-bit shift distance. 5957 */ 5958 /* ushr-long/2addr vA, vB */ 5959 mov r9, rINST, lsr #8 @ r9<- A+ 5960 mov r3, rINST, lsr #12 @ r3<- B 5961 and r9, r9, #15 5962 GET_VREG(r2, r3) @ r2<- vB 5963 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5964 and r2, r2, #63 @ r2<- r2 & 0x3f 5965 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5966 5967 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5968 rsb r3, r2, #32 @ r3<- 32 - r2 5969 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 5970 subs ip, r2, #32 @ ip<- r2 - 32 5971 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5972 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 5973 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 5974 b .LOP_USHR_LONG_2ADDR_finish 5975 5976/* ------------------------------ */ 5977 .balign 64 5978.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 5979/* File: vfp/OP_ADD_FLOAT_2ADDR.S */ 5980/* File: vfp/fbinop2addr.S */ 5981 /* 5982 * Generic 32-bit floating point "/2addr" binary operation. Provide 5983 * an "instr" line that specifies an instruction that performs 5984 * "s2 = s0 op s1". 5985 * 5986 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 5987 */ 5988 /* binop/2addr vA, vB */ 5989 mov r3, rINST, lsr #12 @ r3<- B 5990 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 5991 flds s1, [r3] @ s1<- vB 5992 mov r9, rINST, lsr #8 @ r9<- A+ 5993 and r9, r9, #15 @ r9<- A 5994 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 5995 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5996 flds s0, [r9] @ s0<- vA 5997 5998 fadds s2, s0, s1 @ s2<- op 5999 GET_INST_OPCODE(ip) @ extract opcode from rINST 6000 fsts s2, [r9] @ vAA<- s2 6001 GOTO_OPCODE(ip) @ jump to next instruction 6002 6003 6004/* ------------------------------ */ 6005 .balign 64 6006.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6007/* File: vfp/OP_SUB_FLOAT_2ADDR.S */ 6008/* File: vfp/fbinop2addr.S */ 6009 /* 6010 * Generic 32-bit floating point "/2addr" binary operation. Provide 6011 * an "instr" line that specifies an instruction that performs 6012 * "s2 = s0 op s1". 6013 * 6014 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6015 */ 6016 /* binop/2addr vA, vB */ 6017 mov r3, rINST, lsr #12 @ r3<- B 6018 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6019 flds s1, [r3] @ s1<- vB 6020 mov r9, rINST, lsr #8 @ r9<- A+ 6021 and r9, r9, #15 @ r9<- A 6022 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6023 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6024 flds s0, [r9] @ s0<- vA 6025 6026 fsubs s2, s0, s1 @ s2<- op 6027 GET_INST_OPCODE(ip) @ extract opcode from rINST 6028 fsts s2, [r9] @ vAA<- s2 6029 GOTO_OPCODE(ip) @ jump to next instruction 6030 6031 6032/* ------------------------------ */ 6033 .balign 64 6034.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6035/* File: vfp/OP_MUL_FLOAT_2ADDR.S */ 6036/* File: vfp/fbinop2addr.S */ 6037 /* 6038 * Generic 32-bit floating point "/2addr" binary operation. Provide 6039 * an "instr" line that specifies an instruction that performs 6040 * "s2 = s0 op s1". 6041 * 6042 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6043 */ 6044 /* binop/2addr vA, vB */ 6045 mov r3, rINST, lsr #12 @ r3<- B 6046 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6047 flds s1, [r3] @ s1<- vB 6048 mov r9, rINST, lsr #8 @ r9<- A+ 6049 and r9, r9, #15 @ r9<- A 6050 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6051 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6052 flds s0, [r9] @ s0<- vA 6053 6054 fmuls s2, s0, s1 @ s2<- op 6055 GET_INST_OPCODE(ip) @ extract opcode from rINST 6056 fsts s2, [r9] @ vAA<- s2 6057 GOTO_OPCODE(ip) @ jump to next instruction 6058 6059 6060/* ------------------------------ */ 6061 .balign 64 6062.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6063/* File: vfp/OP_DIV_FLOAT_2ADDR.S */ 6064/* File: vfp/fbinop2addr.S */ 6065 /* 6066 * Generic 32-bit floating point "/2addr" binary operation. Provide 6067 * an "instr" line that specifies an instruction that performs 6068 * "s2 = s0 op s1". 6069 * 6070 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6071 */ 6072 /* binop/2addr vA, vB */ 6073 mov r3, rINST, lsr #12 @ r3<- B 6074 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6075 flds s1, [r3] @ s1<- vB 6076 mov r9, rINST, lsr #8 @ r9<- A+ 6077 and r9, r9, #15 @ r9<- A 6078 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6079 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6080 flds s0, [r9] @ s0<- vA 6081 6082 fdivs s2, s0, s1 @ s2<- op 6083 GET_INST_OPCODE(ip) @ extract opcode from rINST 6084 fsts s2, [r9] @ vAA<- s2 6085 GOTO_OPCODE(ip) @ jump to next instruction 6086 6087 6088/* ------------------------------ */ 6089 .balign 64 6090.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6091/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6092/* EABI doesn't define a float remainder function, but libm does */ 6093/* File: armv5te/binop2addr.S */ 6094 /* 6095 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6096 * that specifies an instruction that performs "result = r0 op r1". 6097 * This could be an ARM instruction or a function call. (If the result 6098 * comes back in a register other than r0, you can override "result".) 6099 * 6100 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6101 * vCC (r1). Useful for integer division and modulus. 6102 * 6103 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6104 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6105 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6106 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6107 */ 6108 /* binop/2addr vA, vB */ 6109 mov r9, rINST, lsr #8 @ r9<- A+ 6110 mov r3, rINST, lsr #12 @ r3<- B 6111 and r9, r9, #15 6112 GET_VREG(r0, r9) @ r0<- vA 6113 GET_VREG(r1, r3) @ r1<- vB 6114 .if 0 6115 cmp r1, #0 @ is second operand zero? 6116 beq common_errDivideByZero 6117 .endif 6118 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6119 6120 @ optional op; may set condition codes 6121 bl fmodf @ r0<- op, r0-r3 changed 6122 GET_INST_OPCODE(ip) @ extract opcode from rINST 6123 SET_VREG(r0, r9) @ vAA<- r0 6124 GOTO_OPCODE(ip) @ jump to next instruction 6125 /* 10-13 instructions */ 6126 6127 6128 6129/* ------------------------------ */ 6130 .balign 64 6131.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6132/* File: vfp/OP_ADD_DOUBLE_2ADDR.S */ 6133/* File: vfp/fbinopWide2addr.S */ 6134 /* 6135 * Generic 64-bit floating point "/2addr" binary operation. Provide 6136 * an "instr" line that specifies an instruction that performs 6137 * "d2 = d0 op d1". 6138 * 6139 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6140 * div-double/2addr 6141 */ 6142 /* binop/2addr vA, vB */ 6143 mov r3, rINST, lsr #12 @ r3<- B 6144 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6145 fldd d1, [r3] @ d1<- vB 6146 mov r9, rINST, lsr #8 @ r9<- A+ 6147 and r9, r9, #15 @ r9<- A 6148 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6149 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6150 fldd d0, [r9] @ d0<- vA 6151 6152 faddd d2, d0, d1 @ d2<- op 6153 GET_INST_OPCODE(ip) @ extract opcode from rINST 6154 fstd d2, [r9] @ vAA<- d2 6155 GOTO_OPCODE(ip) @ jump to next instruction 6156 6157 6158/* ------------------------------ */ 6159 .balign 64 6160.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6161/* File: vfp/OP_SUB_DOUBLE_2ADDR.S */ 6162/* File: vfp/fbinopWide2addr.S */ 6163 /* 6164 * Generic 64-bit floating point "/2addr" binary operation. Provide 6165 * an "instr" line that specifies an instruction that performs 6166 * "d2 = d0 op d1". 6167 * 6168 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6169 * div-double/2addr 6170 */ 6171 /* binop/2addr vA, vB */ 6172 mov r3, rINST, lsr #12 @ r3<- B 6173 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6174 fldd d1, [r3] @ d1<- vB 6175 mov r9, rINST, lsr #8 @ r9<- A+ 6176 and r9, r9, #15 @ r9<- A 6177 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6178 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6179 fldd d0, [r9] @ d0<- vA 6180 6181 fsubd d2, d0, d1 @ d2<- op 6182 GET_INST_OPCODE(ip) @ extract opcode from rINST 6183 fstd d2, [r9] @ vAA<- d2 6184 GOTO_OPCODE(ip) @ jump to next instruction 6185 6186 6187/* ------------------------------ */ 6188 .balign 64 6189.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6190/* File: vfp/OP_MUL_DOUBLE_2ADDR.S */ 6191/* File: vfp/fbinopWide2addr.S */ 6192 /* 6193 * Generic 64-bit floating point "/2addr" binary operation. Provide 6194 * an "instr" line that specifies an instruction that performs 6195 * "d2 = d0 op d1". 6196 * 6197 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6198 * div-double/2addr 6199 */ 6200 /* binop/2addr vA, vB */ 6201 mov r3, rINST, lsr #12 @ r3<- B 6202 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6203 fldd d1, [r3] @ d1<- vB 6204 mov r9, rINST, lsr #8 @ r9<- A+ 6205 and r9, r9, #15 @ r9<- A 6206 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6207 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6208 fldd d0, [r9] @ d0<- vA 6209 6210 fmuld d2, d0, d1 @ d2<- op 6211 GET_INST_OPCODE(ip) @ extract opcode from rINST 6212 fstd d2, [r9] @ vAA<- d2 6213 GOTO_OPCODE(ip) @ jump to next instruction 6214 6215 6216/* ------------------------------ */ 6217 .balign 64 6218.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6219/* File: vfp/OP_DIV_DOUBLE_2ADDR.S */ 6220/* File: vfp/fbinopWide2addr.S */ 6221 /* 6222 * Generic 64-bit floating point "/2addr" binary operation. Provide 6223 * an "instr" line that specifies an instruction that performs 6224 * "d2 = d0 op d1". 6225 * 6226 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6227 * div-double/2addr 6228 */ 6229 /* binop/2addr vA, vB */ 6230 mov r3, rINST, lsr #12 @ r3<- B 6231 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6232 fldd d1, [r3] @ d1<- vB 6233 mov r9, rINST, lsr #8 @ r9<- A+ 6234 and r9, r9, #15 @ r9<- A 6235 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6236 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6237 fldd d0, [r9] @ d0<- vA 6238 6239 fdivd d2, d0, d1 @ d2<- op 6240 GET_INST_OPCODE(ip) @ extract opcode from rINST 6241 fstd d2, [r9] @ vAA<- d2 6242 GOTO_OPCODE(ip) @ jump to next instruction 6243 6244 6245/* ------------------------------ */ 6246 .balign 64 6247.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6248/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6249/* EABI doesn't define a double remainder function, but libm does */ 6250/* File: armv5te/binopWide2addr.S */ 6251 /* 6252 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6253 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6254 * This could be an ARM instruction or a function call. (If the result 6255 * comes back in a register other than r0, you can override "result".) 6256 * 6257 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6258 * vCC (r1). Useful for integer division and modulus. 6259 * 6260 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6261 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6262 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6263 * rem-double/2addr 6264 */ 6265 /* binop/2addr vA, vB */ 6266 mov r9, rINST, lsr #8 @ r9<- A+ 6267 mov r1, rINST, lsr #12 @ r1<- B 6268 and r9, r9, #15 6269 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6270 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6271 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6272 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6273 .if 0 6274 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6275 beq common_errDivideByZero 6276 .endif 6277 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6278 6279 @ optional op; may set condition codes 6280 bl fmod @ result<- op, r0-r3 changed 6281 GET_INST_OPCODE(ip) @ extract opcode from rINST 6282 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6283 GOTO_OPCODE(ip) @ jump to next instruction 6284 /* 12-15 instructions */ 6285 6286 6287 6288/* ------------------------------ */ 6289 .balign 64 6290.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6291/* File: armv5te/OP_ADD_INT_LIT16.S */ 6292/* File: armv5te/binopLit16.S */ 6293 /* 6294 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6295 * that specifies an instruction that performs "result = r0 op r1". 6296 * This could be an ARM instruction or a function call. (If the result 6297 * comes back in a register other than r0, you can override "result".) 6298 * 6299 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6300 * vCC (r1). Useful for integer division and modulus. 6301 * 6302 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6303 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6304 */ 6305 /* binop/lit16 vA, vB, #+CCCC */ 6306 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6307 mov r2, rINST, lsr #12 @ r2<- B 6308 mov r9, rINST, lsr #8 @ r9<- A+ 6309 GET_VREG(r0, r2) @ r0<- vB 6310 and r9, r9, #15 6311 .if 0 6312 cmp r1, #0 @ is second operand zero? 6313 beq common_errDivideByZero 6314 .endif 6315 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6316 6317 add r0, r0, r1 @ r0<- op, r0-r3 changed 6318 GET_INST_OPCODE(ip) @ extract opcode from rINST 6319 SET_VREG(r0, r9) @ vAA<- r0 6320 GOTO_OPCODE(ip) @ jump to next instruction 6321 /* 10-13 instructions */ 6322 6323 6324 6325/* ------------------------------ */ 6326 .balign 64 6327.L_OP_RSUB_INT: /* 0xd1 */ 6328/* File: armv5te/OP_RSUB_INT.S */ 6329/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6330/* File: armv5te/binopLit16.S */ 6331 /* 6332 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6333 * that specifies an instruction that performs "result = r0 op r1". 6334 * This could be an ARM instruction or a function call. (If the result 6335 * comes back in a register other than r0, you can override "result".) 6336 * 6337 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6338 * vCC (r1). Useful for integer division and modulus. 6339 * 6340 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6341 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6342 */ 6343 /* binop/lit16 vA, vB, #+CCCC */ 6344 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6345 mov r2, rINST, lsr #12 @ r2<- B 6346 mov r9, rINST, lsr #8 @ r9<- A+ 6347 GET_VREG(r0, r2) @ r0<- vB 6348 and r9, r9, #15 6349 .if 0 6350 cmp r1, #0 @ is second operand zero? 6351 beq common_errDivideByZero 6352 .endif 6353 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6354 6355 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6356 GET_INST_OPCODE(ip) @ extract opcode from rINST 6357 SET_VREG(r0, r9) @ vAA<- r0 6358 GOTO_OPCODE(ip) @ jump to next instruction 6359 /* 10-13 instructions */ 6360 6361 6362 6363/* ------------------------------ */ 6364 .balign 64 6365.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6366/* File: armv5te/OP_MUL_INT_LIT16.S */ 6367/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6368/* File: armv5te/binopLit16.S */ 6369 /* 6370 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6371 * that specifies an instruction that performs "result = r0 op r1". 6372 * This could be an ARM instruction or a function call. (If the result 6373 * comes back in a register other than r0, you can override "result".) 6374 * 6375 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6376 * vCC (r1). Useful for integer division and modulus. 6377 * 6378 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6379 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6380 */ 6381 /* binop/lit16 vA, vB, #+CCCC */ 6382 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6383 mov r2, rINST, lsr #12 @ r2<- B 6384 mov r9, rINST, lsr #8 @ r9<- A+ 6385 GET_VREG(r0, r2) @ r0<- vB 6386 and r9, r9, #15 6387 .if 0 6388 cmp r1, #0 @ is second operand zero? 6389 beq common_errDivideByZero 6390 .endif 6391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6392 6393 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6394 GET_INST_OPCODE(ip) @ extract opcode from rINST 6395 SET_VREG(r0, r9) @ vAA<- r0 6396 GOTO_OPCODE(ip) @ jump to next instruction 6397 /* 10-13 instructions */ 6398 6399 6400 6401/* ------------------------------ */ 6402 .balign 64 6403.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6404/* File: armv5te/OP_DIV_INT_LIT16.S */ 6405/* File: armv5te/binopLit16.S */ 6406 /* 6407 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6408 * that specifies an instruction that performs "result = r0 op r1". 6409 * This could be an ARM instruction or a function call. (If the result 6410 * comes back in a register other than r0, you can override "result".) 6411 * 6412 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6413 * vCC (r1). Useful for integer division and modulus. 6414 * 6415 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6416 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6417 */ 6418 /* binop/lit16 vA, vB, #+CCCC */ 6419 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6420 mov r2, rINST, lsr #12 @ r2<- B 6421 mov r9, rINST, lsr #8 @ r9<- A+ 6422 GET_VREG(r0, r2) @ r0<- vB 6423 and r9, r9, #15 6424 .if 1 6425 cmp r1, #0 @ is second operand zero? 6426 beq common_errDivideByZero 6427 .endif 6428 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6429 6430 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6431 GET_INST_OPCODE(ip) @ extract opcode from rINST 6432 SET_VREG(r0, r9) @ vAA<- r0 6433 GOTO_OPCODE(ip) @ jump to next instruction 6434 /* 10-13 instructions */ 6435 6436 6437 6438/* ------------------------------ */ 6439 .balign 64 6440.L_OP_REM_INT_LIT16: /* 0xd4 */ 6441/* File: armv5te/OP_REM_INT_LIT16.S */ 6442/* idivmod returns quotient in r0 and remainder in r1 */ 6443/* File: armv5te/binopLit16.S */ 6444 /* 6445 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6446 * that specifies an instruction that performs "result = r0 op r1". 6447 * This could be an ARM instruction or a function call. (If the result 6448 * comes back in a register other than r0, you can override "result".) 6449 * 6450 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6451 * vCC (r1). Useful for integer division and modulus. 6452 * 6453 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6454 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6455 */ 6456 /* binop/lit16 vA, vB, #+CCCC */ 6457 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6458 mov r2, rINST, lsr #12 @ r2<- B 6459 mov r9, rINST, lsr #8 @ r9<- A+ 6460 GET_VREG(r0, r2) @ r0<- vB 6461 and r9, r9, #15 6462 .if 1 6463 cmp r1, #0 @ is second operand zero? 6464 beq common_errDivideByZero 6465 .endif 6466 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6467 6468 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6469 GET_INST_OPCODE(ip) @ extract opcode from rINST 6470 SET_VREG(r1, r9) @ vAA<- r1 6471 GOTO_OPCODE(ip) @ jump to next instruction 6472 /* 10-13 instructions */ 6473 6474 6475 6476/* ------------------------------ */ 6477 .balign 64 6478.L_OP_AND_INT_LIT16: /* 0xd5 */ 6479/* File: armv5te/OP_AND_INT_LIT16.S */ 6480/* File: armv5te/binopLit16.S */ 6481 /* 6482 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6483 * that specifies an instruction that performs "result = r0 op r1". 6484 * This could be an ARM instruction or a function call. (If the result 6485 * comes back in a register other than r0, you can override "result".) 6486 * 6487 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6488 * vCC (r1). Useful for integer division and modulus. 6489 * 6490 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6491 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6492 */ 6493 /* binop/lit16 vA, vB, #+CCCC */ 6494 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6495 mov r2, rINST, lsr #12 @ r2<- B 6496 mov r9, rINST, lsr #8 @ r9<- A+ 6497 GET_VREG(r0, r2) @ r0<- vB 6498 and r9, r9, #15 6499 .if 0 6500 cmp r1, #0 @ is second operand zero? 6501 beq common_errDivideByZero 6502 .endif 6503 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6504 6505 and r0, r0, r1 @ r0<- op, r0-r3 changed 6506 GET_INST_OPCODE(ip) @ extract opcode from rINST 6507 SET_VREG(r0, r9) @ vAA<- r0 6508 GOTO_OPCODE(ip) @ jump to next instruction 6509 /* 10-13 instructions */ 6510 6511 6512 6513/* ------------------------------ */ 6514 .balign 64 6515.L_OP_OR_INT_LIT16: /* 0xd6 */ 6516/* File: armv5te/OP_OR_INT_LIT16.S */ 6517/* File: armv5te/binopLit16.S */ 6518 /* 6519 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6520 * that specifies an instruction that performs "result = r0 op r1". 6521 * This could be an ARM instruction or a function call. (If the result 6522 * comes back in a register other than r0, you can override "result".) 6523 * 6524 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6525 * vCC (r1). Useful for integer division and modulus. 6526 * 6527 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6528 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6529 */ 6530 /* binop/lit16 vA, vB, #+CCCC */ 6531 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6532 mov r2, rINST, lsr #12 @ r2<- B 6533 mov r9, rINST, lsr #8 @ r9<- A+ 6534 GET_VREG(r0, r2) @ r0<- vB 6535 and r9, r9, #15 6536 .if 0 6537 cmp r1, #0 @ is second operand zero? 6538 beq common_errDivideByZero 6539 .endif 6540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6541 6542 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6543 GET_INST_OPCODE(ip) @ extract opcode from rINST 6544 SET_VREG(r0, r9) @ vAA<- r0 6545 GOTO_OPCODE(ip) @ jump to next instruction 6546 /* 10-13 instructions */ 6547 6548 6549 6550/* ------------------------------ */ 6551 .balign 64 6552.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6553/* File: armv5te/OP_XOR_INT_LIT16.S */ 6554/* File: armv5te/binopLit16.S */ 6555 /* 6556 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6557 * that specifies an instruction that performs "result = r0 op r1". 6558 * This could be an ARM instruction or a function call. (If the result 6559 * comes back in a register other than r0, you can override "result".) 6560 * 6561 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6562 * vCC (r1). Useful for integer division and modulus. 6563 * 6564 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6565 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6566 */ 6567 /* binop/lit16 vA, vB, #+CCCC */ 6568 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6569 mov r2, rINST, lsr #12 @ r2<- B 6570 mov r9, rINST, lsr #8 @ r9<- A+ 6571 GET_VREG(r0, r2) @ r0<- vB 6572 and r9, r9, #15 6573 .if 0 6574 cmp r1, #0 @ is second operand zero? 6575 beq common_errDivideByZero 6576 .endif 6577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6578 6579 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6580 GET_INST_OPCODE(ip) @ extract opcode from rINST 6581 SET_VREG(r0, r9) @ vAA<- r0 6582 GOTO_OPCODE(ip) @ jump to next instruction 6583 /* 10-13 instructions */ 6584 6585 6586 6587/* ------------------------------ */ 6588 .balign 64 6589.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6590/* File: armv5te/OP_ADD_INT_LIT8.S */ 6591/* File: armv5te/binopLit8.S */ 6592 /* 6593 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6594 * that specifies an instruction that performs "result = r0 op r1". 6595 * This could be an ARM instruction or a function call. (If the result 6596 * comes back in a register other than r0, you can override "result".) 6597 * 6598 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6599 * vCC (r1). Useful for integer division and modulus. 6600 * 6601 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6602 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6603 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6604 */ 6605 /* binop/lit8 vAA, vBB, #+CC */ 6606 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6607 mov r9, rINST, lsr #8 @ r9<- AA 6608 and r2, r3, #255 @ r2<- BB 6609 GET_VREG(r0, r2) @ r0<- vBB 6610 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6611 .if 0 6612 @cmp r1, #0 @ is second operand zero? 6613 beq common_errDivideByZero 6614 .endif 6615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6616 6617 @ optional op; may set condition codes 6618 add r0, r0, r1 @ r0<- op, r0-r3 changed 6619 GET_INST_OPCODE(ip) @ extract opcode from rINST 6620 SET_VREG(r0, r9) @ vAA<- r0 6621 GOTO_OPCODE(ip) @ jump to next instruction 6622 /* 10-12 instructions */ 6623 6624 6625 6626/* ------------------------------ */ 6627 .balign 64 6628.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6629/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6630/* File: armv5te/binopLit8.S */ 6631 /* 6632 * Generic 32-bit "lit8" 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/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6641 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6642 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6643 */ 6644 /* binop/lit8 vAA, vBB, #+CC */ 6645 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6646 mov r9, rINST, lsr #8 @ r9<- AA 6647 and r2, r3, #255 @ r2<- BB 6648 GET_VREG(r0, r2) @ r0<- vBB 6649 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6650 .if 0 6651 @cmp r1, #0 @ is second operand zero? 6652 beq common_errDivideByZero 6653 .endif 6654 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6655 6656 @ optional op; may set condition codes 6657 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6658 GET_INST_OPCODE(ip) @ extract opcode from rINST 6659 SET_VREG(r0, r9) @ vAA<- r0 6660 GOTO_OPCODE(ip) @ jump to next instruction 6661 /* 10-12 instructions */ 6662 6663 6664 6665/* ------------------------------ */ 6666 .balign 64 6667.L_OP_MUL_INT_LIT8: /* 0xda */ 6668/* File: armv5te/OP_MUL_INT_LIT8.S */ 6669/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6670/* File: armv5te/binopLit8.S */ 6671 /* 6672 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6673 * that specifies an instruction that performs "result = r0 op r1". 6674 * This could be an ARM instruction or a function call. (If the result 6675 * comes back in a register other than r0, you can override "result".) 6676 * 6677 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6678 * vCC (r1). Useful for integer division and modulus. 6679 * 6680 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6681 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6682 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6683 */ 6684 /* binop/lit8 vAA, vBB, #+CC */ 6685 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6686 mov r9, rINST, lsr #8 @ r9<- AA 6687 and r2, r3, #255 @ r2<- BB 6688 GET_VREG(r0, r2) @ r0<- vBB 6689 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6690 .if 0 6691 @cmp r1, #0 @ is second operand zero? 6692 beq common_errDivideByZero 6693 .endif 6694 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6695 6696 @ optional op; may set condition codes 6697 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6698 GET_INST_OPCODE(ip) @ extract opcode from rINST 6699 SET_VREG(r0, r9) @ vAA<- r0 6700 GOTO_OPCODE(ip) @ jump to next instruction 6701 /* 10-12 instructions */ 6702 6703 6704 6705/* ------------------------------ */ 6706 .balign 64 6707.L_OP_DIV_INT_LIT8: /* 0xdb */ 6708/* File: armv5te/OP_DIV_INT_LIT8.S */ 6709/* File: armv5te/binopLit8.S */ 6710 /* 6711 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6712 * that specifies an instruction that performs "result = r0 op r1". 6713 * This could be an ARM instruction or a function call. (If the result 6714 * comes back in a register other than r0, you can override "result".) 6715 * 6716 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6717 * vCC (r1). Useful for integer division and modulus. 6718 * 6719 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6720 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6721 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6722 */ 6723 /* binop/lit8 vAA, vBB, #+CC */ 6724 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6725 mov r9, rINST, lsr #8 @ r9<- AA 6726 and r2, r3, #255 @ r2<- BB 6727 GET_VREG(r0, r2) @ r0<- vBB 6728 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6729 .if 1 6730 @cmp r1, #0 @ is second operand zero? 6731 beq common_errDivideByZero 6732 .endif 6733 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6734 6735 @ optional op; may set condition codes 6736 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6737 GET_INST_OPCODE(ip) @ extract opcode from rINST 6738 SET_VREG(r0, r9) @ vAA<- r0 6739 GOTO_OPCODE(ip) @ jump to next instruction 6740 /* 10-12 instructions */ 6741 6742 6743 6744/* ------------------------------ */ 6745 .balign 64 6746.L_OP_REM_INT_LIT8: /* 0xdc */ 6747/* File: armv5te/OP_REM_INT_LIT8.S */ 6748/* idivmod returns quotient in r0 and remainder in r1 */ 6749/* File: armv5te/binopLit8.S */ 6750 /* 6751 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6752 * that specifies an instruction that performs "result = r0 op r1". 6753 * This could be an ARM instruction or a function call. (If the result 6754 * comes back in a register other than r0, you can override "result".) 6755 * 6756 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6757 * vCC (r1). Useful for integer division and modulus. 6758 * 6759 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6760 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6761 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6762 */ 6763 /* binop/lit8 vAA, vBB, #+CC */ 6764 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6765 mov r9, rINST, lsr #8 @ r9<- AA 6766 and r2, r3, #255 @ r2<- BB 6767 GET_VREG(r0, r2) @ r0<- vBB 6768 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6769 .if 1 6770 @cmp r1, #0 @ is second operand zero? 6771 beq common_errDivideByZero 6772 .endif 6773 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6774 6775 @ optional op; may set condition codes 6776 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6777 GET_INST_OPCODE(ip) @ extract opcode from rINST 6778 SET_VREG(r1, r9) @ vAA<- r1 6779 GOTO_OPCODE(ip) @ jump to next instruction 6780 /* 10-12 instructions */ 6781 6782 6783 6784/* ------------------------------ */ 6785 .balign 64 6786.L_OP_AND_INT_LIT8: /* 0xdd */ 6787/* File: armv5te/OP_AND_INT_LIT8.S */ 6788/* File: armv5te/binopLit8.S */ 6789 /* 6790 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6791 * that specifies an instruction that performs "result = r0 op r1". 6792 * This could be an ARM instruction or a function call. (If the result 6793 * comes back in a register other than r0, you can override "result".) 6794 * 6795 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6796 * vCC (r1). Useful for integer division and modulus. 6797 * 6798 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6799 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6800 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6801 */ 6802 /* binop/lit8 vAA, vBB, #+CC */ 6803 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6804 mov r9, rINST, lsr #8 @ r9<- AA 6805 and r2, r3, #255 @ r2<- BB 6806 GET_VREG(r0, r2) @ r0<- vBB 6807 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6808 .if 0 6809 @cmp r1, #0 @ is second operand zero? 6810 beq common_errDivideByZero 6811 .endif 6812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6813 6814 @ optional op; may set condition codes 6815 and r0, r0, r1 @ r0<- op, r0-r3 changed 6816 GET_INST_OPCODE(ip) @ extract opcode from rINST 6817 SET_VREG(r0, r9) @ vAA<- r0 6818 GOTO_OPCODE(ip) @ jump to next instruction 6819 /* 10-12 instructions */ 6820 6821 6822 6823/* ------------------------------ */ 6824 .balign 64 6825.L_OP_OR_INT_LIT8: /* 0xde */ 6826/* File: armv5te/OP_OR_INT_LIT8.S */ 6827/* File: armv5te/binopLit8.S */ 6828 /* 6829 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6830 * that specifies an instruction that performs "result = r0 op r1". 6831 * This could be an ARM instruction or a function call. (If the result 6832 * comes back in a register other than r0, you can override "result".) 6833 * 6834 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6835 * vCC (r1). Useful for integer division and modulus. 6836 * 6837 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6838 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6839 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6840 */ 6841 /* binop/lit8 vAA, vBB, #+CC */ 6842 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6843 mov r9, rINST, lsr #8 @ r9<- AA 6844 and r2, r3, #255 @ r2<- BB 6845 GET_VREG(r0, r2) @ r0<- vBB 6846 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6847 .if 0 6848 @cmp r1, #0 @ is second operand zero? 6849 beq common_errDivideByZero 6850 .endif 6851 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6852 6853 @ optional op; may set condition codes 6854 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6855 GET_INST_OPCODE(ip) @ extract opcode from rINST 6856 SET_VREG(r0, r9) @ vAA<- r0 6857 GOTO_OPCODE(ip) @ jump to next instruction 6858 /* 10-12 instructions */ 6859 6860 6861 6862/* ------------------------------ */ 6863 .balign 64 6864.L_OP_XOR_INT_LIT8: /* 0xdf */ 6865/* File: armv5te/OP_XOR_INT_LIT8.S */ 6866/* File: armv5te/binopLit8.S */ 6867 /* 6868 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6869 * that specifies an instruction that performs "result = r0 op r1". 6870 * This could be an ARM instruction or a function call. (If the result 6871 * comes back in a register other than r0, you can override "result".) 6872 * 6873 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6874 * vCC (r1). Useful for integer division and modulus. 6875 * 6876 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6877 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6878 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6879 */ 6880 /* binop/lit8 vAA, vBB, #+CC */ 6881 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6882 mov r9, rINST, lsr #8 @ r9<- AA 6883 and r2, r3, #255 @ r2<- BB 6884 GET_VREG(r0, r2) @ r0<- vBB 6885 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6886 .if 0 6887 @cmp r1, #0 @ is second operand zero? 6888 beq common_errDivideByZero 6889 .endif 6890 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6891 6892 @ optional op; may set condition codes 6893 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6894 GET_INST_OPCODE(ip) @ extract opcode from rINST 6895 SET_VREG(r0, r9) @ vAA<- r0 6896 GOTO_OPCODE(ip) @ jump to next instruction 6897 /* 10-12 instructions */ 6898 6899 6900 6901/* ------------------------------ */ 6902 .balign 64 6903.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6904/* File: armv5te/OP_SHL_INT_LIT8.S */ 6905/* File: armv5te/binopLit8.S */ 6906 /* 6907 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6908 * that specifies an instruction that performs "result = r0 op r1". 6909 * This could be an ARM instruction or a function call. (If the result 6910 * comes back in a register other than r0, you can override "result".) 6911 * 6912 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6913 * vCC (r1). Useful for integer division and modulus. 6914 * 6915 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6916 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6917 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6918 */ 6919 /* binop/lit8 vAA, vBB, #+CC */ 6920 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6921 mov r9, rINST, lsr #8 @ r9<- AA 6922 and r2, r3, #255 @ r2<- BB 6923 GET_VREG(r0, r2) @ r0<- vBB 6924 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6925 .if 0 6926 @cmp r1, #0 @ is second operand zero? 6927 beq common_errDivideByZero 6928 .endif 6929 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6930 6931 and r1, r1, #31 @ optional op; may set condition codes 6932 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6933 GET_INST_OPCODE(ip) @ extract opcode from rINST 6934 SET_VREG(r0, r9) @ vAA<- r0 6935 GOTO_OPCODE(ip) @ jump to next instruction 6936 /* 10-12 instructions */ 6937 6938 6939 6940/* ------------------------------ */ 6941 .balign 64 6942.L_OP_SHR_INT_LIT8: /* 0xe1 */ 6943/* File: armv5te/OP_SHR_INT_LIT8.S */ 6944/* File: armv5te/binopLit8.S */ 6945 /* 6946 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6947 * that specifies an instruction that performs "result = r0 op r1". 6948 * This could be an ARM instruction or a function call. (If the result 6949 * comes back in a register other than r0, you can override "result".) 6950 * 6951 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6952 * vCC (r1). Useful for integer division and modulus. 6953 * 6954 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6955 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6956 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6957 */ 6958 /* binop/lit8 vAA, vBB, #+CC */ 6959 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6960 mov r9, rINST, lsr #8 @ r9<- AA 6961 and r2, r3, #255 @ r2<- BB 6962 GET_VREG(r0, r2) @ r0<- vBB 6963 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6964 .if 0 6965 @cmp r1, #0 @ is second operand zero? 6966 beq common_errDivideByZero 6967 .endif 6968 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6969 6970 and r1, r1, #31 @ optional op; may set condition codes 6971 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 6972 GET_INST_OPCODE(ip) @ extract opcode from rINST 6973 SET_VREG(r0, r9) @ vAA<- r0 6974 GOTO_OPCODE(ip) @ jump to next instruction 6975 /* 10-12 instructions */ 6976 6977 6978 6979/* ------------------------------ */ 6980 .balign 64 6981.L_OP_USHR_INT_LIT8: /* 0xe2 */ 6982/* File: armv5te/OP_USHR_INT_LIT8.S */ 6983/* File: armv5te/binopLit8.S */ 6984 /* 6985 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6986 * that specifies an instruction that performs "result = r0 op r1". 6987 * This could be an ARM instruction or a function call. (If the result 6988 * comes back in a register other than r0, you can override "result".) 6989 * 6990 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6991 * vCC (r1). Useful for integer division and modulus. 6992 * 6993 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6994 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6995 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6996 */ 6997 /* binop/lit8 vAA, vBB, #+CC */ 6998 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6999 mov r9, rINST, lsr #8 @ r9<- AA 7000 and r2, r3, #255 @ r2<- BB 7001 GET_VREG(r0, r2) @ r0<- vBB 7002 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7003 .if 0 7004 @cmp r1, #0 @ is second operand zero? 7005 beq common_errDivideByZero 7006 .endif 7007 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7008 7009 and r1, r1, #31 @ optional op; may set condition codes 7010 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7011 GET_INST_OPCODE(ip) @ extract opcode from rINST 7012 SET_VREG(r0, r9) @ vAA<- r0 7013 GOTO_OPCODE(ip) @ jump to next instruction 7014 /* 10-12 instructions */ 7015 7016 7017 7018/* ------------------------------ */ 7019 .balign 64 7020.L_OP_UNUSED_E3: /* 0xe3 */ 7021/* File: armv5te/OP_UNUSED_E3.S */ 7022/* File: armv5te/unused.S */ 7023 bl common_abort 7024 7025 7026 7027/* ------------------------------ */ 7028 .balign 64 7029.L_OP_UNUSED_E4: /* 0xe4 */ 7030/* File: armv5te/OP_UNUSED_E4.S */ 7031/* File: armv5te/unused.S */ 7032 bl common_abort 7033 7034 7035 7036/* ------------------------------ */ 7037 .balign 64 7038.L_OP_UNUSED_E5: /* 0xe5 */ 7039/* File: armv5te/OP_UNUSED_E5.S */ 7040/* File: armv5te/unused.S */ 7041 bl common_abort 7042 7043 7044 7045/* ------------------------------ */ 7046 .balign 64 7047.L_OP_UNUSED_E6: /* 0xe6 */ 7048/* File: armv5te/OP_UNUSED_E6.S */ 7049/* File: armv5te/unused.S */ 7050 bl common_abort 7051 7052 7053 7054/* ------------------------------ */ 7055 .balign 64 7056.L_OP_UNUSED_E7: /* 0xe7 */ 7057/* File: armv5te/OP_UNUSED_E7.S */ 7058/* File: armv5te/unused.S */ 7059 bl common_abort 7060 7061 7062 7063/* ------------------------------ */ 7064 .balign 64 7065.L_OP_UNUSED_E8: /* 0xe8 */ 7066/* File: armv5te/OP_UNUSED_E8.S */ 7067/* File: armv5te/unused.S */ 7068 bl common_abort 7069 7070 7071 7072/* ------------------------------ */ 7073 .balign 64 7074.L_OP_UNUSED_E9: /* 0xe9 */ 7075/* File: armv5te/OP_UNUSED_E9.S */ 7076/* File: armv5te/unused.S */ 7077 bl common_abort 7078 7079 7080 7081/* ------------------------------ */ 7082 .balign 64 7083.L_OP_UNUSED_EA: /* 0xea */ 7084/* File: armv5te/OP_UNUSED_EA.S */ 7085/* File: armv5te/unused.S */ 7086 bl common_abort 7087 7088 7089 7090/* ------------------------------ */ 7091 .balign 64 7092.L_OP_UNUSED_EB: /* 0xeb */ 7093/* File: armv5te/OP_UNUSED_EB.S */ 7094/* File: armv5te/unused.S */ 7095 bl common_abort 7096 7097 7098 7099/* ------------------------------ */ 7100 .balign 64 7101.L_OP_UNUSED_EC: /* 0xec */ 7102/* File: armv5te/OP_UNUSED_EC.S */ 7103/* File: armv5te/unused.S */ 7104 bl common_abort 7105 7106 7107 7108/* ------------------------------ */ 7109 .balign 64 7110.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7111/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7112 /* 7113 * Handle a throw-verification-error instruction. This throws an 7114 * exception for an error discovered during verification. The 7115 * exception is indicated by AA, with some detail provided by BBBB. 7116 */ 7117 /* op AA, ref@BBBB */ 7118 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7119 FETCH(r2, 1) @ r2<- BBBB 7120 EXPORT_PC() @ export the PC 7121 mov r1, rINST, lsr #8 @ r1<- AA 7122 bl dvmThrowVerificationError @ always throws 7123 b common_exceptionThrown @ handle exception 7124 7125 7126/* ------------------------------ */ 7127 .balign 64 7128.L_OP_EXECUTE_INLINE: /* 0xee */ 7129/* File: armv5te/OP_EXECUTE_INLINE.S */ 7130 /* 7131 * Execute a "native inline" instruction. 7132 * 7133 * We need to call: 7134 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7135 * 7136 * The first four args are in r0-r3, but the last two must be pushed 7137 * onto the stack. 7138 */ 7139 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7140 FETCH(r10, 1) @ r10<- BBBB 7141 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7142 EXPORT_PC() @ can throw 7143 sub sp, sp, #8 @ make room for arg(s) 7144 mov r0, rINST, lsr #12 @ r0<- B 7145 str r1, [sp] @ push &glue->retval 7146 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7147 add sp, sp, #8 @ pop stack 7148 cmp r0, #0 @ test boolean result of inline 7149 beq common_exceptionThrown @ returned false, handle exception 7150 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7151 GET_INST_OPCODE(ip) @ extract opcode from rINST 7152 GOTO_OPCODE(ip) @ jump to next instruction 7153 7154/* ------------------------------ */ 7155 .balign 64 7156.L_OP_UNUSED_EF: /* 0xef */ 7157/* File: armv5te/OP_UNUSED_EF.S */ 7158/* File: armv5te/unused.S */ 7159 bl common_abort 7160 7161 7162 7163/* ------------------------------ */ 7164 .balign 64 7165.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7166/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7167 /* 7168 * invoke-direct-empty is a no-op in a "standard" interpreter. 7169 */ 7170 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7171 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7172 GOTO_OPCODE(ip) @ execute it 7173 7174/* ------------------------------ */ 7175 .balign 64 7176.L_OP_UNUSED_F1: /* 0xf1 */ 7177/* File: armv5te/OP_UNUSED_F1.S */ 7178/* File: armv5te/unused.S */ 7179 bl common_abort 7180 7181 7182 7183/* ------------------------------ */ 7184 .balign 64 7185.L_OP_IGET_QUICK: /* 0xf2 */ 7186/* File: armv5te/OP_IGET_QUICK.S */ 7187 /* For: iget-quick, iget-object-quick */ 7188 /* op vA, vB, offset@CCCC */ 7189 mov r2, rINST, lsr #12 @ r2<- B 7190 GET_VREG(r3, r2) @ r3<- object we're operating on 7191 FETCH(r1, 1) @ r1<- field byte offset 7192 cmp r3, #0 @ check object for null 7193 mov r2, rINST, lsr #8 @ r2<- A(+) 7194 beq common_errNullObject @ object was null 7195 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7197 and r2, r2, #15 7198 GET_INST_OPCODE(ip) @ extract opcode from rINST 7199 SET_VREG(r0, r2) @ fp[A]<- r0 7200 GOTO_OPCODE(ip) @ jump to next instruction 7201 7202 7203/* ------------------------------ */ 7204 .balign 64 7205.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7206/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7207 /* iget-wide-quick vA, vB, offset@CCCC */ 7208 mov r2, rINST, lsr #12 @ r2<- B 7209 GET_VREG(r3, r2) @ r3<- object we're operating on 7210 FETCH(r1, 1) @ r1<- field byte offset 7211 cmp r3, #0 @ check object for null 7212 mov r2, rINST, lsr #8 @ r2<- A(+) 7213 beq common_errNullObject @ object was null 7214 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7215 and r2, r2, #15 7216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7217 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7218 GET_INST_OPCODE(ip) @ extract opcode from rINST 7219 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7220 GOTO_OPCODE(ip) @ jump to next instruction 7221 7222 7223/* ------------------------------ */ 7224 .balign 64 7225.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7226/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7227/* File: armv5te/OP_IGET_QUICK.S */ 7228 /* For: iget-quick, iget-object-quick */ 7229 /* op vA, vB, offset@CCCC */ 7230 mov r2, rINST, lsr #12 @ r2<- B 7231 GET_VREG(r3, r2) @ r3<- object we're operating on 7232 FETCH(r1, 1) @ r1<- field byte offset 7233 cmp r3, #0 @ check object for null 7234 mov r2, rINST, lsr #8 @ r2<- A(+) 7235 beq common_errNullObject @ object was null 7236 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7237 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7238 and r2, r2, #15 7239 GET_INST_OPCODE(ip) @ extract opcode from rINST 7240 SET_VREG(r0, r2) @ fp[A]<- r0 7241 GOTO_OPCODE(ip) @ jump to next instruction 7242 7243 7244 7245/* ------------------------------ */ 7246 .balign 64 7247.L_OP_IPUT_QUICK: /* 0xf5 */ 7248/* File: armv5te/OP_IPUT_QUICK.S */ 7249 /* For: iput-quick, iput-object-quick */ 7250 /* op vA, vB, offset@CCCC */ 7251 mov r2, rINST, lsr #12 @ r2<- B 7252 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7253 FETCH(r1, 1) @ r1<- field byte offset 7254 cmp r3, #0 @ check object for null 7255 mov r2, rINST, lsr #8 @ r2<- A(+) 7256 beq common_errNullObject @ object was null 7257 and r2, r2, #15 7258 GET_VREG(r0, r2) @ r0<- fp[A] 7259 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7260 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7261 GET_INST_OPCODE(ip) @ extract opcode from rINST 7262 GOTO_OPCODE(ip) @ jump to next instruction 7263 7264 7265/* ------------------------------ */ 7266 .balign 64 7267.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7268/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7269 /* iput-wide-quick vA, vB, offset@CCCC */ 7270 mov r0, rINST, lsr #8 @ r0<- A(+) 7271 mov r1, rINST, lsr #12 @ r1<- B 7272 and r0, r0, #15 7273 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7274 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7275 cmp r2, #0 @ check object for null 7276 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7277 beq common_errNullObject @ object was null 7278 FETCH(r3, 1) @ r3<- field byte offset 7279 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7280 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7281 GET_INST_OPCODE(ip) @ extract opcode from rINST 7282 GOTO_OPCODE(ip) @ jump to next instruction 7283 7284 7285/* ------------------------------ */ 7286 .balign 64 7287.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7288/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7289/* File: armv5te/OP_IPUT_QUICK.S */ 7290 /* For: iput-quick, iput-object-quick */ 7291 /* op vA, vB, offset@CCCC */ 7292 mov r2, rINST, lsr #12 @ r2<- B 7293 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7294 FETCH(r1, 1) @ r1<- field byte offset 7295 cmp r3, #0 @ check object for null 7296 mov r2, rINST, lsr #8 @ r2<- A(+) 7297 beq common_errNullObject @ object was null 7298 and r2, r2, #15 7299 GET_VREG(r0, r2) @ r0<- fp[A] 7300 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7301 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7302 GET_INST_OPCODE(ip) @ extract opcode from rINST 7303 GOTO_OPCODE(ip) @ jump to next instruction 7304 7305 7306 7307/* ------------------------------ */ 7308 .balign 64 7309.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7310/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7311 /* 7312 * Handle an optimized virtual method call. 7313 * 7314 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7315 */ 7316 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7317 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7318 FETCH(r3, 2) @ r3<- FEDC or CCCC 7319 FETCH(r1, 1) @ r1<- BBBB 7320 .if (!0) 7321 and r3, r3, #15 @ r3<- C (or stays CCCC) 7322 .endif 7323 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7324 cmp r2, #0 @ is "this" null? 7325 beq common_errNullObject @ null "this", throw exception 7326 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7327 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7328 EXPORT_PC() @ invoke must export 7329 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7330 bl common_invokeMethodNoRange @ continue on 7331 7332/* ------------------------------ */ 7333 .balign 64 7334.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7335/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7336/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7337 /* 7338 * Handle an optimized virtual method call. 7339 * 7340 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7341 */ 7342 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7343 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7344 FETCH(r3, 2) @ r3<- FEDC or CCCC 7345 FETCH(r1, 1) @ r1<- BBBB 7346 .if (!1) 7347 and r3, r3, #15 @ r3<- C (or stays CCCC) 7348 .endif 7349 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7350 cmp r2, #0 @ is "this" null? 7351 beq common_errNullObject @ null "this", throw exception 7352 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7353 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7354 EXPORT_PC() @ invoke must export 7355 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7356 bl common_invokeMethodRange @ continue on 7357 7358 7359/* ------------------------------ */ 7360 .balign 64 7361.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7362/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7363 /* 7364 * Handle an optimized "super" method call. 7365 * 7366 * for: [opt] invoke-super-quick, invoke-super-quick/range 7367 */ 7368 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7369 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7370 FETCH(r10, 2) @ r10<- GFED or CCCC 7371 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7372 .if (!0) 7373 and r10, r10, #15 @ r10<- D (or stays CCCC) 7374 .endif 7375 FETCH(r1, 1) @ r1<- BBBB 7376 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7377 EXPORT_PC() @ must export for invoke 7378 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7379 GET_VREG(r3, r10) @ r3<- "this" 7380 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7381 cmp r3, #0 @ null "this" ref? 7382 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7383 beq common_errNullObject @ "this" is null, throw exception 7384 bl common_invokeMethodNoRange @ continue on 7385 7386 7387/* ------------------------------ */ 7388 .balign 64 7389.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7390/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7391/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7392 /* 7393 * Handle an optimized "super" method call. 7394 * 7395 * for: [opt] invoke-super-quick, invoke-super-quick/range 7396 */ 7397 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7398 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7399 FETCH(r10, 2) @ r10<- GFED or CCCC 7400 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7401 .if (!1) 7402 and r10, r10, #15 @ r10<- D (or stays CCCC) 7403 .endif 7404 FETCH(r1, 1) @ r1<- BBBB 7405 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7406 EXPORT_PC() @ must export for invoke 7407 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7408 GET_VREG(r3, r10) @ r3<- "this" 7409 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7410 cmp r3, #0 @ null "this" ref? 7411 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7412 beq common_errNullObject @ "this" is null, throw exception 7413 bl common_invokeMethodRange @ continue on 7414 7415 7416 7417/* ------------------------------ */ 7418 .balign 64 7419.L_OP_UNUSED_FC: /* 0xfc */ 7420/* File: armv5te/OP_UNUSED_FC.S */ 7421/* File: armv5te/unused.S */ 7422 bl common_abort 7423 7424 7425 7426/* ------------------------------ */ 7427 .balign 64 7428.L_OP_UNUSED_FD: /* 0xfd */ 7429/* File: armv5te/OP_UNUSED_FD.S */ 7430/* File: armv5te/unused.S */ 7431 bl common_abort 7432 7433 7434 7435/* ------------------------------ */ 7436 .balign 64 7437.L_OP_UNUSED_FE: /* 0xfe */ 7438/* File: armv5te/OP_UNUSED_FE.S */ 7439/* File: armv5te/unused.S */ 7440 bl common_abort 7441 7442 7443 7444/* ------------------------------ */ 7445 .balign 64 7446.L_OP_UNUSED_FF: /* 0xff */ 7447/* File: armv5te/OP_UNUSED_FF.S */ 7448/* File: armv5te/unused.S */ 7449 bl common_abort 7450 7451 7452 7453 7454 .balign 64 7455 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7456 .global dvmAsmInstructionEnd 7457dvmAsmInstructionEnd: 7458 7459/* 7460 * =========================================================================== 7461 * Sister implementations 7462 * =========================================================================== 7463 */ 7464 .global dvmAsmSisterStart 7465 .type dvmAsmSisterStart, %function 7466 .text 7467 .balign 4 7468dvmAsmSisterStart: 7469 7470/* continuation for OP_CONST_STRING */ 7471 7472 /* 7473 * Continuation if the String has not yet been resolved. 7474 * r1: BBBB (String ref) 7475 * r9: target register 7476 */ 7477.LOP_CONST_STRING_resolve: 7478 EXPORT_PC() 7479 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7480 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7481 bl dvmResolveString @ r0<- String reference 7482 cmp r0, #0 @ failed? 7483 beq common_exceptionThrown @ yup, handle the exception 7484 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7485 GET_INST_OPCODE(ip) @ extract opcode from rINST 7486 SET_VREG(r0, r9) @ vAA<- r0 7487 GOTO_OPCODE(ip) @ jump to next instruction 7488 7489 7490/* continuation for OP_CONST_STRING_JUMBO */ 7491 7492 /* 7493 * Continuation if the String has not yet been resolved. 7494 * r1: BBBBBBBB (String ref) 7495 * r9: target register 7496 */ 7497.LOP_CONST_STRING_JUMBO_resolve: 7498 EXPORT_PC() 7499 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7500 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7501 bl dvmResolveString @ r0<- String reference 7502 cmp r0, #0 @ failed? 7503 beq common_exceptionThrown @ yup, handle the exception 7504 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7505 GET_INST_OPCODE(ip) @ extract opcode from rINST 7506 SET_VREG(r0, r9) @ vAA<- r0 7507 GOTO_OPCODE(ip) @ jump to next instruction 7508 7509 7510/* continuation for OP_CONST_CLASS */ 7511 7512 /* 7513 * Continuation if the Class has not yet been resolved. 7514 * r1: BBBB (Class ref) 7515 * r9: target register 7516 */ 7517.LOP_CONST_CLASS_resolve: 7518 EXPORT_PC() 7519 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7520 mov r2, #1 @ r2<- true 7521 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7522 bl dvmResolveClass @ r0<- Class reference 7523 cmp r0, #0 @ failed? 7524 beq common_exceptionThrown @ yup, handle the exception 7525 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7526 GET_INST_OPCODE(ip) @ extract opcode from rINST 7527 SET_VREG(r0, r9) @ vAA<- r0 7528 GOTO_OPCODE(ip) @ jump to next instruction 7529 7530 7531/* continuation for OP_CHECK_CAST */ 7532 7533 /* 7534 * Trivial test failed, need to perform full check. This is common. 7535 * r0 holds obj->clazz 7536 * r1 holds class resolved from BBBB 7537 * r9 holds object 7538 */ 7539.LOP_CHECK_CAST_fullcheck: 7540 bl dvmInstanceofNonTrivial @ r0<- boolean result 7541 cmp r0, #0 @ failed? 7542 bne .LOP_CHECK_CAST_okay @ no, success 7543 7544 @ A cast has failed. We need to throw a ClassCastException with the 7545 @ class of the object that failed to be cast. 7546 EXPORT_PC() @ about to throw 7547 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7548 ldr r0, .LstrClassCastExceptionPtr 7549 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7550 bl dvmThrowExceptionWithClassMessage 7551 b common_exceptionThrown 7552 7553 /* 7554 * Resolution required. This is the least-likely path. 7555 * 7556 * r2 holds BBBB 7557 * r9 holds object 7558 */ 7559.LOP_CHECK_CAST_resolve: 7560 EXPORT_PC() @ resolve() could throw 7561 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7562 mov r1, r2 @ r1<- BBBB 7563 mov r2, #0 @ r2<- false 7564 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7565 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7566 cmp r0, #0 @ got null? 7567 beq common_exceptionThrown @ yes, handle exception 7568 mov r1, r0 @ r1<- class resolved from BBB 7569 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7570 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7571 7572.LstrClassCastExceptionPtr: 7573 .word .LstrClassCastException 7574 7575 7576/* continuation for OP_INSTANCE_OF */ 7577 7578 /* 7579 * Trivial test failed, need to perform full check. This is common. 7580 * r0 holds obj->clazz 7581 * r1 holds class resolved from BBBB 7582 * r9 holds A 7583 */ 7584.LOP_INSTANCE_OF_fullcheck: 7585 bl dvmInstanceofNonTrivial @ r0<- boolean result 7586 @ fall through to OP_INSTANCE_OF_store 7587 7588 /* 7589 * r0 holds boolean result 7590 * r9 holds A 7591 */ 7592.LOP_INSTANCE_OF_store: 7593 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7594 SET_VREG(r0, r9) @ vA<- r0 7595 GET_INST_OPCODE(ip) @ extract opcode from rINST 7596 GOTO_OPCODE(ip) @ jump to next instruction 7597 7598 /* 7599 * Trivial test succeeded, save and bail. 7600 * r9 holds A 7601 */ 7602.LOP_INSTANCE_OF_trivial: 7603 mov r0, #1 @ indicate success 7604 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7605 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7606 SET_VREG(r0, r9) @ vA<- r0 7607 GET_INST_OPCODE(ip) @ extract opcode from rINST 7608 GOTO_OPCODE(ip) @ jump to next instruction 7609 7610 /* 7611 * Resolution required. This is the least-likely path. 7612 * 7613 * r3 holds BBBB 7614 * r9 holds A 7615 */ 7616.LOP_INSTANCE_OF_resolve: 7617 EXPORT_PC() @ resolve() could throw 7618 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7619 mov r1, r3 @ r1<- BBBB 7620 mov r2, #1 @ r2<- true 7621 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7622 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7623 cmp r0, #0 @ got null? 7624 beq common_exceptionThrown @ yes, handle exception 7625 mov r1, r0 @ r1<- class resolved from BBB 7626 mov r3, rINST, lsr #12 @ r3<- B 7627 GET_VREG(r0, r3) @ r0<- vB (object) 7628 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7629 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7630 7631 7632/* continuation for OP_NEW_INSTANCE */ 7633 7634 .balign 32 @ minimize cache lines 7635.LOP_NEW_INSTANCE_finish: @ r0=new object 7636 mov r3, rINST, lsr #8 @ r3<- AA 7637 cmp r0, #0 @ failed? 7638 beq common_exceptionThrown @ yes, handle the exception 7639 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7640 GET_INST_OPCODE(ip) @ extract opcode from rINST 7641 SET_VREG(r0, r3) @ vAA<- r0 7642 GOTO_OPCODE(ip) @ jump to next instruction 7643 7644 /* 7645 * Class initialization required. 7646 * 7647 * r0 holds class object 7648 */ 7649.LOP_NEW_INSTANCE_needinit: 7650 mov r9, r0 @ save r0 7651 bl dvmInitClass @ initialize class 7652 cmp r0, #0 @ check boolean result 7653 mov r0, r9 @ restore r0 7654 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7655 b common_exceptionThrown @ failed, deal with init exception 7656 7657 /* 7658 * Resolution required. This is the least-likely path. 7659 * 7660 * r1 holds BBBB 7661 */ 7662.LOP_NEW_INSTANCE_resolve: 7663 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7664 mov r2, #0 @ r2<- false 7665 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7666 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7667 cmp r0, #0 @ got null? 7668 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7669 b common_exceptionThrown @ yes, handle exception 7670 7671.LstrInstantiationErrorPtr: 7672 .word .LstrInstantiationError 7673 7674 7675/* continuation for OP_NEW_ARRAY */ 7676 7677 7678 /* 7679 * Resolve class. (This is an uncommon case.) 7680 * 7681 * r1 holds array length 7682 * r2 holds class ref CCCC 7683 */ 7684.LOP_NEW_ARRAY_resolve: 7685 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7686 mov r9, r1 @ r9<- length (save) 7687 mov r1, r2 @ r1<- CCCC 7688 mov r2, #0 @ r2<- false 7689 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7690 bl dvmResolveClass @ r0<- call(clazz, ref) 7691 cmp r0, #0 @ got null? 7692 mov r1, r9 @ r1<- length (restore) 7693 beq common_exceptionThrown @ yes, handle exception 7694 @ fall through to OP_NEW_ARRAY_finish 7695 7696 /* 7697 * Finish allocation. 7698 * 7699 * r0 holds class 7700 * r1 holds array length 7701 */ 7702.LOP_NEW_ARRAY_finish: 7703 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7704 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7705 cmp r0, #0 @ failed? 7706 mov r2, rINST, lsr #8 @ r2<- A+ 7707 beq common_exceptionThrown @ yes, handle the exception 7708 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7709 and r2, r2, #15 @ r2<- A 7710 GET_INST_OPCODE(ip) @ extract opcode from rINST 7711 SET_VREG(r0, r2) @ vA<- r0 7712 GOTO_OPCODE(ip) @ jump to next instruction 7713 7714 7715/* continuation for OP_FILLED_NEW_ARRAY */ 7716 7717 /* 7718 * On entry: 7719 * r0 holds array class 7720 * r10 holds AA or BA 7721 */ 7722.LOP_FILLED_NEW_ARRAY_continue: 7723 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7724 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7725 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7726 .if 0 7727 mov r1, r10 @ r1<- AA (length) 7728 .else 7729 mov r1, r10, lsr #4 @ r1<- B (length) 7730 .endif 7731 cmp r3, #'I' @ array of ints? 7732 cmpne r3, #'L' @ array of objects? 7733 cmpne r3, #'[' @ array of arrays? 7734 mov r9, r1 @ save length in r9 7735 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7736 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7737 cmp r0, #0 @ null return? 7738 beq common_exceptionThrown @ alloc failed, handle exception 7739 7740 FETCH(r1, 2) @ r1<- FEDC or CCCC 7741 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7742 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7743 subs r9, r9, #1 @ length--, check for neg 7744 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7745 bmi 2f @ was zero, bail 7746 7747 @ copy values from registers into the array 7748 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7749 .if 0 7750 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 77511: ldr r3, [r2], #4 @ r3<- *r2++ 7752 subs r9, r9, #1 @ count-- 7753 str r3, [r0], #4 @ *contents++ = vX 7754 bpl 1b 7755 @ continue at 2 7756 .else 7757 cmp r9, #4 @ length was initially 5? 7758 and r2, r10, #15 @ r2<- A 7759 bne 1f @ <= 4 args, branch 7760 GET_VREG(r3, r2) @ r3<- vA 7761 sub r9, r9, #1 @ count-- 7762 str r3, [r0, #16] @ contents[4] = vA 77631: and r2, r1, #15 @ r2<- F/E/D/C 7764 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7765 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7766 subs r9, r9, #1 @ count-- 7767 str r3, [r0], #4 @ *contents++ = vX 7768 bpl 1b 7769 @ continue at 2 7770 .endif 7771 77722: 7773 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7774 GOTO_OPCODE(ip) @ execute it 7775 7776 /* 7777 * Throw an exception indicating that we have not implemented this 7778 * mode of filled-new-array. 7779 */ 7780.LOP_FILLED_NEW_ARRAY_notimpl: 7781 ldr r0, .L_strInternalError 7782 ldr r1, .L_strFilledNewArrayNotImpl 7783 bl dvmThrowException 7784 b common_exceptionThrown 7785 7786 .if (!0) @ define in one or the other, not both 7787.L_strFilledNewArrayNotImpl: 7788 .word .LstrFilledNewArrayNotImpl 7789.L_strInternalError: 7790 .word .LstrInternalError 7791 .endif 7792 7793 7794/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 7795 7796 /* 7797 * On entry: 7798 * r0 holds array class 7799 * r10 holds AA or BA 7800 */ 7801.LOP_FILLED_NEW_ARRAY_RANGE_continue: 7802 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7803 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7804 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7805 .if 1 7806 mov r1, r10 @ r1<- AA (length) 7807 .else 7808 mov r1, r10, lsr #4 @ r1<- B (length) 7809 .endif 7810 cmp r3, #'I' @ array of ints? 7811 cmpne r3, #'L' @ array of objects? 7812 cmpne r3, #'[' @ array of arrays? 7813 mov r9, r1 @ save length in r9 7814 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 7815 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7816 cmp r0, #0 @ null return? 7817 beq common_exceptionThrown @ alloc failed, handle exception 7818 7819 FETCH(r1, 2) @ r1<- FEDC or CCCC 7820 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7821 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7822 subs r9, r9, #1 @ length--, check for neg 7823 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7824 bmi 2f @ was zero, bail 7825 7826 @ copy values from registers into the array 7827 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7828 .if 1 7829 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 78301: ldr r3, [r2], #4 @ r3<- *r2++ 7831 subs r9, r9, #1 @ count-- 7832 str r3, [r0], #4 @ *contents++ = vX 7833 bpl 1b 7834 @ continue at 2 7835 .else 7836 cmp r9, #4 @ length was initially 5? 7837 and r2, r10, #15 @ r2<- A 7838 bne 1f @ <= 4 args, branch 7839 GET_VREG(r3, r2) @ r3<- vA 7840 sub r9, r9, #1 @ count-- 7841 str r3, [r0, #16] @ contents[4] = vA 78421: and r2, r1, #15 @ r2<- F/E/D/C 7843 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 7844 mov r1, r1, lsr #4 @ r1<- next reg in low 4 7845 subs r9, r9, #1 @ count-- 7846 str r3, [r0], #4 @ *contents++ = vX 7847 bpl 1b 7848 @ continue at 2 7849 .endif 7850 78512: 7852 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7853 GOTO_OPCODE(ip) @ execute it 7854 7855 /* 7856 * Throw an exception indicating that we have not implemented this 7857 * mode of filled-new-array. 7858 */ 7859.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 7860 ldr r0, .L_strInternalError 7861 ldr r1, .L_strFilledNewArrayNotImpl 7862 bl dvmThrowException 7863 b common_exceptionThrown 7864 7865 .if (!1) @ define in one or the other, not both 7866.L_strFilledNewArrayNotImpl: 7867 .word .LstrFilledNewArrayNotImpl 7868.L_strInternalError: 7869 .word .LstrInternalError 7870 .endif 7871 7872 7873/* continuation for OP_CMPL_FLOAT */ 7874.LOP_CMPL_FLOAT_finish: 7875 SET_VREG(r0, r9) @ vAA<- r0 7876 GOTO_OPCODE(ip) @ jump to next instruction 7877 7878 7879/* continuation for OP_CMPG_FLOAT */ 7880.LOP_CMPG_FLOAT_finish: 7881 SET_VREG(r0, r9) @ vAA<- r0 7882 GOTO_OPCODE(ip) @ jump to next instruction 7883 7884 7885/* continuation for OP_CMPL_DOUBLE */ 7886.LOP_CMPL_DOUBLE_finish: 7887 SET_VREG(r0, r9) @ vAA<- r0 7888 GOTO_OPCODE(ip) @ jump to next instruction 7889 7890 7891/* continuation for OP_CMPG_DOUBLE */ 7892.LOP_CMPG_DOUBLE_finish: 7893 SET_VREG(r0, r9) @ vAA<- r0 7894 GOTO_OPCODE(ip) @ jump to next instruction 7895 7896 7897/* continuation for OP_CMP_LONG */ 7898 7899.LOP_CMP_LONG_less: 7900 mvn r1, #0 @ r1<- -1 7901 @ Want to cond code the next mov so we can avoid branch, but don't see it; 7902 @ instead, we just replicate the tail end. 7903 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7904 SET_VREG(r1, r9) @ vAA<- r1 7905 GET_INST_OPCODE(ip) @ extract opcode from rINST 7906 GOTO_OPCODE(ip) @ jump to next instruction 7907 7908.LOP_CMP_LONG_greater: 7909 mov r1, #1 @ r1<- 1 7910 @ fall through to _finish 7911 7912.LOP_CMP_LONG_finish: 7913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7914 SET_VREG(r1, r9) @ vAA<- r1 7915 GET_INST_OPCODE(ip) @ extract opcode from rINST 7916 GOTO_OPCODE(ip) @ jump to next instruction 7917 7918 7919/* continuation for OP_AGET_WIDE */ 7920 7921.LOP_AGET_WIDE_finish: 7922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7923 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 7924 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7925 GET_INST_OPCODE(ip) @ extract opcode from rINST 7926 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 7927 GOTO_OPCODE(ip) @ jump to next instruction 7928 7929 7930/* continuation for OP_APUT_WIDE */ 7931 7932.LOP_APUT_WIDE_finish: 7933 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7934 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 7935 GET_INST_OPCODE(ip) @ extract opcode from rINST 7936 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 7937 GOTO_OPCODE(ip) @ jump to next instruction 7938 7939 7940/* continuation for OP_APUT_OBJECT */ 7941 /* 7942 * On entry: 7943 * r1 = vBB (arrayObj) 7944 * r9 = vAA (obj) 7945 * r10 = offset into array (vBB + vCC * width) 7946 */ 7947.LOP_APUT_OBJECT_finish: 7948 cmp r9, #0 @ storing null reference? 7949 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 7950 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7951 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 7952 bl dvmCanPutArrayElement @ test object type vs. array type 7953 cmp r0, #0 @ okay? 7954 beq common_errArrayStore @ no 7955.LOP_APUT_OBJECT_skip_check: 7956 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7957 GET_INST_OPCODE(ip) @ extract opcode from rINST 7958 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 7959 GOTO_OPCODE(ip) @ jump to next instruction 7960 7961 7962/* continuation for OP_IGET */ 7963 7964 /* 7965 * Currently: 7966 * r0 holds resolved field 7967 * r9 holds object 7968 */ 7969.LOP_IGET_finish: 7970 @bl common_squeak0 7971 cmp r9, #0 @ check object for null 7972 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 7973 beq common_errNullObject @ object was null 7974 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 7975 mov r2, rINST, lsr #8 @ r2<- A+ 7976 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7977 and r2, r2, #15 @ r2<- A 7978 GET_INST_OPCODE(ip) @ extract opcode from rINST 7979 SET_VREG(r0, r2) @ fp[A]<- r0 7980 GOTO_OPCODE(ip) @ jump to next instruction 7981 7982 7983/* continuation for OP_IGET_WIDE */ 7984 7985 /* 7986 * Currently: 7987 * r0 holds resolved field 7988 * r9 holds object 7989 */ 7990.LOP_IGET_WIDE_finish: 7991 cmp r9, #0 @ check object for null 7992 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 7993 beq common_errNullObject @ object was null 7994 mov r2, rINST, lsr #8 @ r2<- A+ 7995 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 7996 and r2, r2, #15 @ r2<- A 7997 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7998 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7999 GET_INST_OPCODE(ip) @ extract opcode from rINST 8000 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8001 GOTO_OPCODE(ip) @ jump to next instruction 8002 8003 8004/* continuation for OP_IGET_OBJECT */ 8005 8006 /* 8007 * Currently: 8008 * r0 holds resolved field 8009 * r9 holds object 8010 */ 8011.LOP_IGET_OBJECT_finish: 8012 @bl common_squeak0 8013 cmp r9, #0 @ check object for null 8014 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8015 beq common_errNullObject @ object was null 8016 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8017 mov r2, rINST, lsr #8 @ r2<- A+ 8018 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8019 and r2, r2, #15 @ r2<- A 8020 GET_INST_OPCODE(ip) @ extract opcode from rINST 8021 SET_VREG(r0, r2) @ fp[A]<- r0 8022 GOTO_OPCODE(ip) @ jump to next instruction 8023 8024 8025/* continuation for OP_IGET_BOOLEAN */ 8026 8027 /* 8028 * Currently: 8029 * r0 holds resolved field 8030 * r9 holds object 8031 */ 8032.LOP_IGET_BOOLEAN_finish: 8033 @bl common_squeak1 8034 cmp r9, #0 @ check object for null 8035 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8036 beq common_errNullObject @ object was null 8037 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8038 mov r2, rINST, lsr #8 @ r2<- A+ 8039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8040 and r2, r2, #15 @ r2<- A 8041 GET_INST_OPCODE(ip) @ extract opcode from rINST 8042 SET_VREG(r0, r2) @ fp[A]<- r0 8043 GOTO_OPCODE(ip) @ jump to next instruction 8044 8045 8046/* continuation for OP_IGET_BYTE */ 8047 8048 /* 8049 * Currently: 8050 * r0 holds resolved field 8051 * r9 holds object 8052 */ 8053.LOP_IGET_BYTE_finish: 8054 @bl common_squeak2 8055 cmp r9, #0 @ check object for null 8056 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8057 beq common_errNullObject @ object was null 8058 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8059 mov r2, rINST, lsr #8 @ r2<- A+ 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) @ fp[A]<- r0 8064 GOTO_OPCODE(ip) @ jump to next instruction 8065 8066 8067/* continuation for OP_IGET_CHAR */ 8068 8069 /* 8070 * Currently: 8071 * r0 holds resolved field 8072 * r9 holds object 8073 */ 8074.LOP_IGET_CHAR_finish: 8075 @bl common_squeak3 8076 cmp r9, #0 @ check object for null 8077 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8078 beq common_errNullObject @ object was null 8079 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8080 mov r2, rINST, lsr #8 @ r2<- A+ 8081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8082 and r2, r2, #15 @ r2<- A 8083 GET_INST_OPCODE(ip) @ extract opcode from rINST 8084 SET_VREG(r0, r2) @ fp[A]<- r0 8085 GOTO_OPCODE(ip) @ jump to next instruction 8086 8087 8088/* continuation for OP_IGET_SHORT */ 8089 8090 /* 8091 * Currently: 8092 * r0 holds resolved field 8093 * r9 holds object 8094 */ 8095.LOP_IGET_SHORT_finish: 8096 @bl common_squeak4 8097 cmp r9, #0 @ check object for null 8098 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8099 beq common_errNullObject @ object was null 8100 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8101 mov r2, rINST, lsr #8 @ r2<- A+ 8102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8103 and r2, r2, #15 @ r2<- A 8104 GET_INST_OPCODE(ip) @ extract opcode from rINST 8105 SET_VREG(r0, r2) @ fp[A]<- r0 8106 GOTO_OPCODE(ip) @ jump to next instruction 8107 8108 8109/* continuation for OP_IPUT */ 8110 8111 /* 8112 * Currently: 8113 * r0 holds resolved field 8114 * r9 holds object 8115 */ 8116.LOP_IPUT_finish: 8117 @bl common_squeak0 8118 mov r1, rINST, lsr #8 @ r1<- A+ 8119 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8120 and r1, r1, #15 @ r1<- A 8121 cmp r9, #0 @ check object for null 8122 GET_VREG(r0, r1) @ r0<- fp[A] 8123 beq common_errNullObject @ object was null 8124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8125 GET_INST_OPCODE(ip) @ extract opcode from rINST 8126 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8127 GOTO_OPCODE(ip) @ jump to next instruction 8128 8129 8130/* continuation for OP_IPUT_WIDE */ 8131 8132 /* 8133 * Currently: 8134 * r0 holds resolved field 8135 * r9 holds object 8136 */ 8137.LOP_IPUT_WIDE_finish: 8138 mov r2, rINST, lsr #8 @ r2<- A+ 8139 cmp r9, #0 @ check object for null 8140 and r2, r2, #15 @ r2<- A 8141 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8142 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8143 beq common_errNullObject @ object was null 8144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8145 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8146 GET_INST_OPCODE(ip) @ extract opcode from rINST 8147 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8148 GOTO_OPCODE(ip) @ jump to next instruction 8149 8150 8151/* continuation for OP_IPUT_OBJECT */ 8152 8153 /* 8154 * Currently: 8155 * r0 holds resolved field 8156 * r9 holds object 8157 */ 8158.LOP_IPUT_OBJECT_finish: 8159 @bl common_squeak0 8160 mov r1, rINST, lsr #8 @ r1<- A+ 8161 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8162 and r1, r1, #15 @ r1<- A 8163 cmp r9, #0 @ check object for null 8164 GET_VREG(r0, r1) @ r0<- fp[A] 8165 beq common_errNullObject @ object was null 8166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8167 GET_INST_OPCODE(ip) @ extract opcode from rINST 8168 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8169 GOTO_OPCODE(ip) @ jump to next instruction 8170 8171 8172/* continuation for OP_IPUT_BOOLEAN */ 8173 8174 /* 8175 * Currently: 8176 * r0 holds resolved field 8177 * r9 holds object 8178 */ 8179.LOP_IPUT_BOOLEAN_finish: 8180 @bl common_squeak1 8181 mov r1, rINST, lsr #8 @ r1<- A+ 8182 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8183 and r1, r1, #15 @ r1<- A 8184 cmp r9, #0 @ check object for null 8185 GET_VREG(r0, r1) @ r0<- fp[A] 8186 beq common_errNullObject @ object was null 8187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8188 GET_INST_OPCODE(ip) @ extract opcode from rINST 8189 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8190 GOTO_OPCODE(ip) @ jump to next instruction 8191 8192 8193/* continuation for OP_IPUT_BYTE */ 8194 8195 /* 8196 * Currently: 8197 * r0 holds resolved field 8198 * r9 holds object 8199 */ 8200.LOP_IPUT_BYTE_finish: 8201 @bl common_squeak2 8202 mov r1, rINST, lsr #8 @ r1<- A+ 8203 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8204 and r1, r1, #15 @ r1<- A 8205 cmp r9, #0 @ check object for null 8206 GET_VREG(r0, r1) @ r0<- fp[A] 8207 beq common_errNullObject @ object was null 8208 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8209 GET_INST_OPCODE(ip) @ extract opcode from rINST 8210 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8211 GOTO_OPCODE(ip) @ jump to next instruction 8212 8213 8214/* continuation for OP_IPUT_CHAR */ 8215 8216 /* 8217 * Currently: 8218 * r0 holds resolved field 8219 * r9 holds object 8220 */ 8221.LOP_IPUT_CHAR_finish: 8222 @bl common_squeak3 8223 mov r1, rINST, lsr #8 @ r1<- A+ 8224 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8225 and r1, r1, #15 @ r1<- A 8226 cmp r9, #0 @ check object for null 8227 GET_VREG(r0, r1) @ r0<- fp[A] 8228 beq common_errNullObject @ object was null 8229 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8230 GET_INST_OPCODE(ip) @ extract opcode from rINST 8231 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8232 GOTO_OPCODE(ip) @ jump to next instruction 8233 8234 8235/* continuation for OP_IPUT_SHORT */ 8236 8237 /* 8238 * Currently: 8239 * r0 holds resolved field 8240 * r9 holds object 8241 */ 8242.LOP_IPUT_SHORT_finish: 8243 @bl common_squeak4 8244 mov r1, rINST, lsr #8 @ r1<- A+ 8245 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8246 and r1, r1, #15 @ r1<- A 8247 cmp r9, #0 @ check object for null 8248 GET_VREG(r0, r1) @ r0<- fp[A] 8249 beq common_errNullObject @ object was null 8250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8251 GET_INST_OPCODE(ip) @ extract opcode from rINST 8252 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8253 GOTO_OPCODE(ip) @ jump to next instruction 8254 8255 8256/* continuation for OP_SGET */ 8257 8258 /* 8259 * Continuation if the field has not yet been resolved. 8260 * r1: BBBB field ref 8261 */ 8262.LOP_SGET_resolve: 8263 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8264 EXPORT_PC() @ resolve() could throw, so export now 8265 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8266 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8267 cmp r0, #0 @ success? 8268 bne .LOP_SGET_finish @ yes, finish 8269 b common_exceptionThrown @ no, handle exception 8270 8271 8272/* continuation for OP_SGET_WIDE */ 8273 8274 /* 8275 * Continuation if the field has not yet been resolved. 8276 * r1: BBBB field ref 8277 */ 8278.LOP_SGET_WIDE_resolve: 8279 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8280 EXPORT_PC() @ resolve() could throw, so export now 8281 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8282 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8283 cmp r0, #0 @ success? 8284 bne .LOP_SGET_WIDE_finish @ yes, finish 8285 b common_exceptionThrown @ no, handle exception 8286 8287 8288/* continuation for OP_SGET_OBJECT */ 8289 8290 /* 8291 * Continuation if the field has not yet been resolved. 8292 * r1: BBBB field ref 8293 */ 8294.LOP_SGET_OBJECT_resolve: 8295 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8296 EXPORT_PC() @ resolve() could throw, so export now 8297 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8298 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8299 cmp r0, #0 @ success? 8300 bne .LOP_SGET_OBJECT_finish @ yes, finish 8301 b common_exceptionThrown @ no, handle exception 8302 8303 8304/* continuation for OP_SGET_BOOLEAN */ 8305 8306 /* 8307 * Continuation if the field has not yet been resolved. 8308 * r1: BBBB field ref 8309 */ 8310.LOP_SGET_BOOLEAN_resolve: 8311 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8312 EXPORT_PC() @ resolve() could throw, so export now 8313 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8314 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8315 cmp r0, #0 @ success? 8316 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8317 b common_exceptionThrown @ no, handle exception 8318 8319 8320/* continuation for OP_SGET_BYTE */ 8321 8322 /* 8323 * Continuation if the field has not yet been resolved. 8324 * r1: BBBB field ref 8325 */ 8326.LOP_SGET_BYTE_resolve: 8327 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8328 EXPORT_PC() @ resolve() could throw, so export now 8329 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8330 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8331 cmp r0, #0 @ success? 8332 bne .LOP_SGET_BYTE_finish @ yes, finish 8333 b common_exceptionThrown @ no, handle exception 8334 8335 8336/* continuation for OP_SGET_CHAR */ 8337 8338 /* 8339 * Continuation if the field has not yet been resolved. 8340 * r1: BBBB field ref 8341 */ 8342.LOP_SGET_CHAR_resolve: 8343 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8344 EXPORT_PC() @ resolve() could throw, so export now 8345 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8346 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8347 cmp r0, #0 @ success? 8348 bne .LOP_SGET_CHAR_finish @ yes, finish 8349 b common_exceptionThrown @ no, handle exception 8350 8351 8352/* continuation for OP_SGET_SHORT */ 8353 8354 /* 8355 * Continuation if the field has not yet been resolved. 8356 * r1: BBBB field ref 8357 */ 8358.LOP_SGET_SHORT_resolve: 8359 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8360 EXPORT_PC() @ resolve() could throw, so export now 8361 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8362 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8363 cmp r0, #0 @ success? 8364 bne .LOP_SGET_SHORT_finish @ yes, finish 8365 b common_exceptionThrown @ no, handle exception 8366 8367 8368/* continuation for OP_SPUT */ 8369 8370 /* 8371 * Continuation if the field has not yet been resolved. 8372 * r1: BBBB field ref 8373 */ 8374.LOP_SPUT_resolve: 8375 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8376 EXPORT_PC() @ resolve() could throw, so export now 8377 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8378 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8379 cmp r0, #0 @ success? 8380 bne .LOP_SPUT_finish @ yes, finish 8381 b common_exceptionThrown @ no, handle exception 8382 8383 8384/* continuation for OP_SPUT_WIDE */ 8385 8386 /* 8387 * Continuation if the field has not yet been resolved. 8388 * r1: BBBB field ref 8389 * r9: &fp[AA] 8390 */ 8391.LOP_SPUT_WIDE_resolve: 8392 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8393 EXPORT_PC() @ resolve() could throw, so export now 8394 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8395 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8396 cmp r0, #0 @ success? 8397 bne .LOP_SPUT_WIDE_finish @ yes, finish 8398 b common_exceptionThrown @ no, handle exception 8399 8400 8401/* continuation for OP_SPUT_OBJECT */ 8402 8403 /* 8404 * Continuation if the field has not yet been resolved. 8405 * r1: BBBB field ref 8406 */ 8407.LOP_SPUT_OBJECT_resolve: 8408 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8409 EXPORT_PC() @ resolve() could throw, so export now 8410 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8411 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8412 cmp r0, #0 @ success? 8413 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8414 b common_exceptionThrown @ no, handle exception 8415 8416 8417/* continuation for OP_SPUT_BOOLEAN */ 8418 8419 /* 8420 * Continuation if the field has not yet been resolved. 8421 * r1: BBBB field ref 8422 */ 8423.LOP_SPUT_BOOLEAN_resolve: 8424 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8425 EXPORT_PC() @ resolve() could throw, so export now 8426 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8427 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8428 cmp r0, #0 @ success? 8429 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8430 b common_exceptionThrown @ no, handle exception 8431 8432 8433/* continuation for OP_SPUT_BYTE */ 8434 8435 /* 8436 * Continuation if the field has not yet been resolved. 8437 * r1: BBBB field ref 8438 */ 8439.LOP_SPUT_BYTE_resolve: 8440 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8441 EXPORT_PC() @ resolve() could throw, so export now 8442 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8443 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8444 cmp r0, #0 @ success? 8445 bne .LOP_SPUT_BYTE_finish @ yes, finish 8446 b common_exceptionThrown @ no, handle exception 8447 8448 8449/* continuation for OP_SPUT_CHAR */ 8450 8451 /* 8452 * Continuation if the field has not yet been resolved. 8453 * r1: BBBB field ref 8454 */ 8455.LOP_SPUT_CHAR_resolve: 8456 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8457 EXPORT_PC() @ resolve() could throw, so export now 8458 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8459 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8460 cmp r0, #0 @ success? 8461 bne .LOP_SPUT_CHAR_finish @ yes, finish 8462 b common_exceptionThrown @ no, handle exception 8463 8464 8465/* continuation for OP_SPUT_SHORT */ 8466 8467 /* 8468 * Continuation if the field has not yet been resolved. 8469 * r1: BBBB field ref 8470 */ 8471.LOP_SPUT_SHORT_resolve: 8472 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8473 EXPORT_PC() @ resolve() could throw, so export now 8474 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8475 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8476 cmp r0, #0 @ success? 8477 bne .LOP_SPUT_SHORT_finish @ yes, finish 8478 b common_exceptionThrown @ no, handle exception 8479 8480 8481/* continuation for OP_INVOKE_VIRTUAL */ 8482 8483 /* 8484 * At this point: 8485 * r0 = resolved base method 8486 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8487 */ 8488.LOP_INVOKE_VIRTUAL_continue: 8489 GET_VREG(r1, r10) @ r1<- "this" ptr 8490 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8491 cmp r1, #0 @ is "this" null? 8492 beq common_errNullObject @ null "this", throw exception 8493 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8494 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8495 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8496 bl common_invokeMethodNoRange @ continue on 8497 8498 8499/* continuation for OP_INVOKE_SUPER */ 8500 8501 /* 8502 * At this point: 8503 * r0 = resolved base method 8504 * r9 = method->clazz 8505 */ 8506.LOP_INVOKE_SUPER_continue: 8507 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8508 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8509 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8510 EXPORT_PC() @ must export for invoke 8511 cmp r2, r3 @ compare (methodIndex, vtableCount) 8512 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8513 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8514 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8515 bl common_invokeMethodNoRange @ continue on 8516 8517.LOP_INVOKE_SUPER_resolve: 8518 mov r0, r9 @ r0<- method->clazz 8519 mov r2, #METHOD_VIRTUAL @ resolver method type 8520 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8521 cmp r0, #0 @ got null? 8522 bne .LOP_INVOKE_SUPER_continue @ no, continue 8523 b common_exceptionThrown @ yes, handle exception 8524 8525 /* 8526 * Throw a NoSuchMethodError with the method name as the message. 8527 * r0 = resolved base method 8528 */ 8529.LOP_INVOKE_SUPER_nsm: 8530 ldr r1, [r0, #offMethod_name] @ r1<- method name 8531 b common_errNoSuchMethod 8532 8533 8534/* continuation for OP_INVOKE_DIRECT */ 8535 8536 /* 8537 * On entry: 8538 * r1 = reference (BBBB or CCCC) 8539 * r10 = "this" register 8540 */ 8541.LOP_INVOKE_DIRECT_resolve: 8542 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8543 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8544 mov r2, #METHOD_DIRECT @ resolver method type 8545 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8546 cmp r0, #0 @ got null? 8547 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8548 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8549 b common_exceptionThrown @ yes, handle exception 8550 8551 8552/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8553 8554 /* 8555 * At this point: 8556 * r0 = resolved base method 8557 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8558 */ 8559.LOP_INVOKE_VIRTUAL_RANGE_continue: 8560 GET_VREG(r1, r10) @ r1<- "this" ptr 8561 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8562 cmp r1, #0 @ is "this" null? 8563 beq common_errNullObject @ null "this", throw exception 8564 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8565 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8566 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8567 bl common_invokeMethodRange @ continue on 8568 8569 8570/* continuation for OP_INVOKE_SUPER_RANGE */ 8571 8572 /* 8573 * At this point: 8574 * r0 = resolved base method 8575 * r9 = method->clazz 8576 */ 8577.LOP_INVOKE_SUPER_RANGE_continue: 8578 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8579 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8580 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8581 EXPORT_PC() @ must export for invoke 8582 cmp r2, r3 @ compare (methodIndex, vtableCount) 8583 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8584 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8585 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8586 bl common_invokeMethodRange @ continue on 8587 8588.LOP_INVOKE_SUPER_RANGE_resolve: 8589 mov r0, r9 @ r0<- method->clazz 8590 mov r2, #METHOD_VIRTUAL @ resolver method type 8591 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8592 cmp r0, #0 @ got null? 8593 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8594 b common_exceptionThrown @ yes, handle exception 8595 8596 /* 8597 * Throw a NoSuchMethodError with the method name as the message. 8598 * r0 = resolved base method 8599 */ 8600.LOP_INVOKE_SUPER_RANGE_nsm: 8601 ldr r1, [r0, #offMethod_name] @ r1<- method name 8602 b common_errNoSuchMethod 8603 8604 8605/* continuation for OP_INVOKE_DIRECT_RANGE */ 8606 8607 /* 8608 * On entry: 8609 * r1 = reference (BBBB or CCCC) 8610 * r10 = "this" register 8611 */ 8612.LOP_INVOKE_DIRECT_RANGE_resolve: 8613 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8614 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8615 mov r2, #METHOD_DIRECT @ resolver method type 8616 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8617 cmp r0, #0 @ got null? 8618 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8619 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8620 b common_exceptionThrown @ yes, handle exception 8621 8622 8623/* continuation for OP_FLOAT_TO_LONG */ 8624/* 8625 * Convert the float in r0 to a long in r0/r1. 8626 * 8627 * We have to clip values to long min/max per the specification. The 8628 * expected common case is a "reasonable" value that converts directly 8629 * to modest integer. The EABI convert function isn't doing this for us. 8630 */ 8631f2l_doconv: 8632 stmfd sp!, {r4, lr} 8633 mov r1, #0x5f000000 @ (float)maxlong 8634 mov r4, r0 8635 bl __aeabi_fcmpge @ is arg >= maxlong? 8636 cmp r0, #0 @ nonzero == yes 8637 mvnne r0, #0 @ return maxlong (7fffffff) 8638 mvnne r1, #0x80000000 8639 ldmnefd sp!, {r4, pc} 8640 8641 mov r0, r4 @ recover arg 8642 mov r1, #0xdf000000 @ (float)minlong 8643 bl __aeabi_fcmple @ is arg <= minlong? 8644 cmp r0, #0 @ nonzero == yes 8645 movne r0, #0 @ return minlong (80000000) 8646 movne r1, #0x80000000 8647 ldmnefd sp!, {r4, pc} 8648 8649 mov r0, r4 @ recover arg 8650 mov r1, r4 8651 bl __aeabi_fcmpeq @ is arg == self? 8652 cmp r0, #0 @ zero == no 8653 moveq r1, #0 @ return zero for NaN 8654 ldmeqfd sp!, {r4, pc} 8655 8656 mov r0, r4 @ recover arg 8657 bl __aeabi_f2lz @ convert float to long 8658 ldmfd sp!, {r4, pc} 8659 8660 8661/* continuation for OP_DOUBLE_TO_LONG */ 8662/* 8663 * Convert the double in r0/r1 to a long in r0/r1. 8664 * 8665 * We have to clip values to long min/max per the specification. The 8666 * expected common case is a "reasonable" value that converts directly 8667 * to modest integer. The EABI convert function isn't doing this for us. 8668 */ 8669d2l_doconv: 8670 stmfd sp!, {r4, r5, lr} @ save regs 8671 ldr r3, .LOP_DOUBLE_TO_LONG_max @ (double)maxlong, hi 8672 sub sp, sp, #4 @ align for EABI 8673 mov r2, #0 @ (double)maxlong, lo 8674 mov r4, r0 @ save r0 8675 mov r5, r1 @ and r1 8676 bl __aeabi_dcmpge @ is arg >= maxlong? 8677 cmp r0, #0 @ nonzero == yes 8678 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8679 mvnne r1, #0x80000000 8680 bne 1f 8681 8682 mov r0, r4 @ recover arg 8683 mov r1, r5 8684 ldr r3, .LOP_DOUBLE_TO_LONG_min @ (double)minlong, hi 8685 mov r2, #0 @ (double)minlong, lo 8686 bl __aeabi_dcmple @ is arg <= minlong? 8687 cmp r0, #0 @ nonzero == yes 8688 movne r0, #0 @ return minlong (8000000000000000) 8689 movne r1, #0x80000000 8690 bne 1f 8691 8692 mov r0, r4 @ recover arg 8693 mov r1, r5 8694 mov r2, r4 @ compare against self 8695 mov r3, r5 8696 bl __aeabi_dcmpeq @ is arg == self? 8697 cmp r0, #0 @ zero == no 8698 moveq r1, #0 @ return zero for NaN 8699 beq 1f 8700 8701 mov r0, r4 @ recover arg 8702 mov r1, r5 8703 bl __aeabi_d2lz @ convert double to long 8704 87051: 8706 add sp, sp, #4 8707 ldmfd sp!, {r4, r5, pc} 8708 8709.LOP_DOUBLE_TO_LONG_max: 8710 .word 0x43e00000 @ maxlong, as a double (high word) 8711.LOP_DOUBLE_TO_LONG_min: 8712 .word 0xc3e00000 @ minlong, as a double (high word) 8713 8714 8715/* continuation for OP_MUL_LONG */ 8716 8717.LOP_MUL_LONG_finish: 8718 GET_INST_OPCODE(ip) @ extract opcode from rINST 8719 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8720 GOTO_OPCODE(ip) @ jump to next instruction 8721 8722 8723/* continuation for OP_SHL_LONG */ 8724 8725.LOP_SHL_LONG_finish: 8726 mov r0, r0, asl r2 @ r0<- r0 << r2 8727 GET_INST_OPCODE(ip) @ extract opcode from rINST 8728 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8729 GOTO_OPCODE(ip) @ jump to next instruction 8730 8731 8732/* continuation for OP_SHR_LONG */ 8733 8734.LOP_SHR_LONG_finish: 8735 mov r1, r1, asr r2 @ r1<- r1 >> r2 8736 GET_INST_OPCODE(ip) @ extract opcode from rINST 8737 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8738 GOTO_OPCODE(ip) @ jump to next instruction 8739 8740 8741/* continuation for OP_USHR_LONG */ 8742 8743.LOP_USHR_LONG_finish: 8744 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8745 GET_INST_OPCODE(ip) @ extract opcode from rINST 8746 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8747 GOTO_OPCODE(ip) @ jump to next instruction 8748 8749 8750/* continuation for OP_SHL_LONG_2ADDR */ 8751 8752.LOP_SHL_LONG_2ADDR_finish: 8753 GET_INST_OPCODE(ip) @ extract opcode from rINST 8754 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8755 GOTO_OPCODE(ip) @ jump to next instruction 8756 8757 8758/* continuation for OP_SHR_LONG_2ADDR */ 8759 8760.LOP_SHR_LONG_2ADDR_finish: 8761 GET_INST_OPCODE(ip) @ extract opcode from rINST 8762 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8763 GOTO_OPCODE(ip) @ jump to next instruction 8764 8765 8766/* continuation for OP_USHR_LONG_2ADDR */ 8767 8768.LOP_USHR_LONG_2ADDR_finish: 8769 GET_INST_OPCODE(ip) @ extract opcode from rINST 8770 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8771 GOTO_OPCODE(ip) @ jump to next instruction 8772 8773 8774/* continuation for OP_EXECUTE_INLINE */ 8775 8776 /* 8777 * Extract args, call function. 8778 * r0 = #of args (0-4) 8779 * r10 = call index 8780 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 8781 * 8782 * Other ideas: 8783 * - Use a jump table from the main piece to jump directly into the 8784 * AND/LDR pairs. Costs a data load, saves a branch. 8785 * - Have five separate pieces that do the loading, so we can work the 8786 * interleave a little better. Increases code size. 8787 */ 8788.LOP_EXECUTE_INLINE_continue: 8789 rsb r0, r0, #4 @ r0<- 4-r0 8790 FETCH(r9, 2) @ r9<- FEDC 8791 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 8792 bl common_abort @ (skipped due to ARM prefetch) 87934: and ip, r9, #0xf000 @ isolate F 8794 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 87953: and ip, r9, #0x0f00 @ isolate E 8796 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 87972: and ip, r9, #0x00f0 @ isolate D 8798 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 87991: and ip, r9, #0x000f @ isolate C 8800 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 88010: 8802 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 8803 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 8804 @ (not reached) 8805 8806.LOP_EXECUTE_INLINE_table: 8807 .word gDvmInlineOpsTable 8808 8809 8810 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8811 .global dvmAsmSisterEnd 8812dvmAsmSisterEnd: 8813 8814/* File: armv5te/footer.S */ 8815/* 8816 * =========================================================================== 8817 * Common subroutines and data 8818 * =========================================================================== 8819 */ 8820 8821 .text 8822 .align 2 8823 8824/* 8825 * Common code when a backward branch is taken. 8826 * 8827 * On entry: 8828 * r9 is PC adjustment *in bytes* 8829 */ 8830common_backwardBranch: 8831 mov r0, #kInterpEntryInstr 8832 bl common_periodicChecks 8833 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 8834 GET_INST_OPCODE(ip) @ extract opcode from rINST 8835 GOTO_OPCODE(ip) @ jump to next instruction 8836 8837 8838/* 8839 * Need to see if the thread needs to be suspended or debugger/profiler 8840 * activity has begun. 8841 * 8842 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 8843 * have to do the second ldr. 8844 * 8845 * TODO: reduce this so we're just checking a single location. 8846 * 8847 * On entry: 8848 * r0 is reentry type, e.g. kInterpEntryInstr 8849 * r9 is trampoline PC adjustment *in bytes* 8850 */ 8851common_periodicChecks: 8852 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 8853 8854#if defined(WITH_DEBUGGER) 8855 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 8856#endif 8857#if defined(WITH_PROFILER) 8858 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 8859#endif 8860 8861 ldr r3, [r3] @ r3<- suspendCount (int) 8862 8863#if defined(WITH_DEBUGGER) 8864 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 8865#endif 8866#if defined (WITH_PROFILER) 8867 ldr r2, [r2] @ r2<- activeProfilers (int) 8868#endif 8869 8870 cmp r3, #0 @ suspend pending? 8871 bne 2f @ yes, do full suspension check 8872 8873#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 8874# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 8875 orrs r1, r1, r2 @ r1<- r1 | r2 8876 cmp r1, #0 @ debugger attached or profiler started? 8877# elif defined(WITH_DEBUGGER) 8878 cmp r1, #0 @ debugger attached? 8879# elif defined(WITH_PROFILER) 8880 cmp r2, #0 @ profiler started? 8881# endif 8882 bne 3f @ debugger/profiler, switch interp 8883#endif 8884 8885 bx lr @ nothing to do, return 8886 88872: @ check suspend 8888 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 8889 EXPORT_PC() @ need for precise GC 8890 b dvmCheckSuspendPending @ suspend if necessary, then return 8891 88923: @ debugger/profiler enabled, bail out 8893 add rPC, rPC, r9 @ update rPC 8894 str r0, [rGLUE, #offGlue_entryPoint] 8895 mov r1, #1 @ "want switch" = true 8896 b common_gotoBail 8897 8898 8899/* 8900 * The equivalent of "goto bail", this calls through the "bail handler". 8901 * 8902 * State registers will be saved to the "glue" area before bailing. 8903 * 8904 * On entry: 8905 * r1 is "bool changeInterp", indicating if we want to switch to the 8906 * other interpreter or just bail all the way out 8907 */ 8908common_gotoBail: 8909 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 8910 mov r0, rGLUE @ r0<- glue ptr 8911 b dvmMterpStdBail @ call(glue, changeInterp) 8912 8913 @add r1, r1, #1 @ using (boolean+1) 8914 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 8915 @bl _longjmp @ does not return 8916 @bl common_abort 8917 8918 8919/* 8920 * Common code for method invocation with range. 8921 * 8922 * On entry: 8923 * r0 is "Method* methodToCall", the method we're trying to call 8924 */ 8925common_invokeMethodRange: 8926.LinvokeNewRange: 8927 @ prepare to copy args to "outs" area of current frame 8928 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 8929 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 8930 beq .LinvokeArgsDone @ if no args, skip the rest 8931 FETCH(r1, 2) @ r1<- CCCC 8932 8933 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 8934 @ (very few methods have > 10 args; could unroll for common cases) 8935 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 8936 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 8937 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 89381: ldr r1, [r3], #4 @ val = *fp++ 8939 subs r2, r2, #1 @ count-- 8940 str r1, [r10], #4 @ *outs++ = val 8941 bne 1b @ ...while count != 0 8942 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 8943 b .LinvokeArgsDone 8944 8945/* 8946 * Common code for method invocation without range. 8947 * 8948 * On entry: 8949 * r0 is "Method* methodToCall", the method we're trying to call 8950 */ 8951common_invokeMethodNoRange: 8952.LinvokeNewNoRange: 8953 @ prepare to copy args to "outs" area of current frame 8954 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 8955 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 8956 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 8957 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 8958 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 8959 beq .LinvokeArgsDone 8960 8961 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 8962.LinvokeNonRange: 8963 rsb r2, r2, #5 @ r2<- 5-r2 8964 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 8965 bl common_abort @ (skipped due to ARM prefetch) 89665: and ip, rINST, #0x0f00 @ isolate A 8967 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 8968 mov r0, r0 @ nop 8969 str r2, [r10, #-4]! @ *--outs = vA 89704: and ip, r1, #0xf000 @ isolate G 8971 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 8972 mov r0, r0 @ nop 8973 str r2, [r10, #-4]! @ *--outs = vG 89743: and ip, r1, #0x0f00 @ isolate F 8975 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 8976 mov r0, r0 @ nop 8977 str r2, [r10, #-4]! @ *--outs = vF 89782: and ip, r1, #0x00f0 @ isolate E 8979 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 8980 mov r0, r0 @ nop 8981 str r2, [r10, #-4]! @ *--outs = vE 89821: and ip, r1, #0x000f @ isolate D 8983 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 8984 mov r0, r0 @ nop 8985 str r2, [r10, #-4]! @ *--outs = vD 89860: @ fall through to .LinvokeArgsDone 8987 8988.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 8989 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 8990 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 8991 @ find space for the new stack frame, check for overflow 8992 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 8993 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 8994 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 8995@ bl common_dumpRegs 8996 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 8997 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 8998 cmp r3, r9 @ bottom < interpStackEnd? 8999 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9000 blt .LstackOverflow @ yes, this frame will overflow stack 9001 9002 @ set up newSaveArea 9003#ifdef EASY_GDB 9004 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9005 str ip, [r10, #offStackSaveArea_prevSave] 9006#endif 9007 str rFP, [r10, #offStackSaveArea_prevFrame] 9008 str rPC, [r10, #offStackSaveArea_savedPc] 9009 str r0, [r10, #offStackSaveArea_method] 9010 tst r3, #ACC_NATIVE 9011 bne .LinvokeNative 9012 9013 /* 9014 stmfd sp!, {r0-r3} 9015 bl common_printNewline 9016 mov r0, rFP 9017 mov r1, #0 9018 bl dvmDumpFp 9019 ldmfd sp!, {r0-r3} 9020 stmfd sp!, {r0-r3} 9021 mov r0, r1 9022 mov r1, r10 9023 bl dvmDumpFp 9024 bl common_printNewline 9025 ldmfd sp!, {r0-r3} 9026 */ 9027 9028 ldrh r9, [r2] @ r9 <- load INST from new PC 9029 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9030 mov rPC, r2 @ publish new rPC 9031 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9032 9033 @ Update "glue" values for the new method 9034 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9035 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9036 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9037 mov rFP, r1 @ fp = newFp 9038 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9039 mov rINST, r9 @ publish new rINST 9040 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9041 GOTO_OPCODE(ip) @ jump to next instruction 9042 9043.LinvokeNative: 9044 @ Prep for the native call 9045 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9046 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9047 ldr r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext 9048 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9049 str r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext 9050 mov r9, r3 @ r9<- glue->self (preserve) 9051 9052 mov r2, r0 @ r2<- methodToCall 9053 mov r0, r1 @ r0<- newFp (points to args) 9054 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9055 9056#ifdef ASSIST_DEBUGGER 9057 /* insert fake function header to help gdb find the stack frame */ 9058 b .Lskip 9059 .type dalvik_mterp, %function 9060dalvik_mterp: 9061 .fnstart 9062 MTERP_ENTRY1 9063 MTERP_ENTRY2 9064.Lskip: 9065#endif 9066 9067 @mov lr, pc @ set return addr 9068 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9069 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9070 9071 @ native return; r9=self, r10=newSaveArea 9072 @ equivalent to dvmPopJniLocals 9073 ldr r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop 9074 ldr r1, [r9, #offThread_exception] @ check for exception 9075 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9076 cmp r1, #0 @ null? 9077 str r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0 9078 bne common_exceptionThrown @ no, handle exception 9079 9080 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9081 GET_INST_OPCODE(ip) @ extract opcode from rINST 9082 GOTO_OPCODE(ip) @ jump to next instruction 9083 9084.LstackOverflow: 9085 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9086 bl dvmHandleStackOverflow 9087 b common_exceptionThrown 9088#ifdef ASSIST_DEBUGGER 9089 .fnend 9090#endif 9091 9092 9093 /* 9094 * Common code for method invocation, calling through "glue code". 9095 * 9096 * TODO: now that we have range and non-range invoke handlers, this 9097 * needs to be split into two. Maybe just create entry points 9098 * that set r9 and jump here? 9099 * 9100 * On entry: 9101 * r0 is "Method* methodToCall", the method we're trying to call 9102 * r9 is "bool methodCallRange", indicating if this is a /range variant 9103 */ 9104 .if 0 9105.LinvokeOld: 9106 sub sp, sp, #8 @ space for args + pad 9107 FETCH(ip, 2) @ ip<- FEDC or CCCC 9108 mov r2, r0 @ A2<- methodToCall 9109 mov r0, rGLUE @ A0<- glue 9110 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9111 mov r1, r9 @ A1<- methodCallRange 9112 mov r3, rINST, lsr #8 @ A3<- AA 9113 str ip, [sp, #0] @ A4<- ip 9114 bl dvmMterp_invokeMethod @ call the C invokeMethod 9115 add sp, sp, #8 @ remove arg area 9116 b common_resumeAfterGlueCall @ continue to next instruction 9117 .endif 9118 9119 9120 9121/* 9122 * Common code for handling a return instruction. 9123 * 9124 * This does not return. 9125 */ 9126common_returnFromMethod: 9127.LreturnNew: 9128 mov r0, #kInterpEntryReturn 9129 mov r9, #0 9130 bl common_periodicChecks 9131 9132 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9133 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9134 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9135 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9136 @ r2<- method we're returning to 9137 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9138 cmp r2, #0 @ is this a break frame? 9139 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9140 mov r1, #0 @ "want switch" = false 9141 beq common_gotoBail @ break frame, bail out completely 9142 9143 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9144 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9145 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9146 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9147 GET_INST_OPCODE(ip) @ extract opcode from rINST 9148 mov rPC, r9 @ publish new rPC 9149 str r1, [rGLUE, #offGlue_methodClassDex] 9150 GOTO_OPCODE(ip) @ jump to next instruction 9151 9152 /* 9153 * Return handling, calls through "glue code". 9154 */ 9155 .if 0 9156.LreturnOld: 9157 SAVE_PC_FP_TO_GLUE() @ export state 9158 mov r0, rGLUE @ arg to function 9159 bl dvmMterp_returnFromMethod 9160 b common_resumeAfterGlueCall 9161 .endif 9162 9163 9164/* 9165 * Somebody has thrown an exception. Handle it. 9166 * 9167 * If the exception processing code returns to us (instead of falling 9168 * out of the interpreter), continue with whatever the next instruction 9169 * now happens to be. 9170 * 9171 * This does not return. 9172 */ 9173common_exceptionThrown: 9174.LexceptionNew: 9175 mov r0, #kInterpEntryThrow 9176 mov r9, #0 9177 bl common_periodicChecks 9178 9179 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9180 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9181 mov r1, r10 @ r1<- self 9182 mov r0, r9 @ r0<- exception 9183 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9184 mov r3, #0 @ r3<- NULL 9185 str r3, [r10, #offThread_exception] @ self->exception = NULL 9186 9187 /* set up args and a local for "&fp" */ 9188 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9189 str rFP, [sp, #-4]! @ *--sp = fp 9190 mov ip, sp @ ip<- &fp 9191 mov r3, #0 @ r3<- false 9192 str ip, [sp, #-4]! @ *--sp = &fp 9193 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9194 mov r0, r10 @ r0<- self 9195 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9196 mov r2, r9 @ r2<- exception 9197 sub r1, rPC, r1 @ r1<- pc - method->insns 9198 mov r1, r1, asr #1 @ r1<- offset in code units 9199 9200 /* call, r0 gets catchRelPc (a code-unit offset) */ 9201 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9202 9203 /* fix earlier stack overflow if necessary; may trash rFP */ 9204 ldrb r1, [r10, #offThread_stackOverflowed] 9205 cmp r1, #0 @ did we overflow earlier? 9206 beq 1f @ no, skip ahead 9207 mov rFP, r0 @ save relPc result in rFP 9208 mov r0, r10 @ r0<- self 9209 bl dvmCleanupStackOverflow @ call(self) 9210 mov r0, rFP @ restore result 92111: 9212 9213 /* update frame pointer and check result from dvmFindCatchBlock */ 9214 ldr rFP, [sp, #4] @ retrieve the updated rFP 9215 cmp r0, #0 @ is catchRelPc < 0? 9216 add sp, sp, #8 @ restore stack 9217 bmi .LnotCaughtLocally 9218 9219 /* adjust locals to match self->curFrame and updated PC */ 9220 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9221 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9222 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9223 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9224 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9225 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9226 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9227 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9228 9229 /* release the tracked alloc on the exception */ 9230 mov r0, r9 @ r0<- exception 9231 mov r1, r10 @ r1<- self 9232 bl dvmReleaseTrackedAlloc @ release the exception 9233 9234 /* restore the exception if the handler wants it */ 9235 FETCH_INST() @ load rINST from rPC 9236 GET_INST_OPCODE(ip) @ extract opcode from rINST 9237 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9238 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9239 GOTO_OPCODE(ip) @ jump to next instruction 9240 9241.LnotCaughtLocally: @ r9=exception, r10=self 9242 /* fix stack overflow if necessary */ 9243 ldrb r1, [r10, #offThread_stackOverflowed] 9244 cmp r1, #0 @ did we overflow earlier? 9245 movne r0, r10 @ if yes: r0<- self 9246 blne dvmCleanupStackOverflow @ if yes: call(self) 9247 9248 @ may want to show "not caught locally" debug messages here 9249#if DVM_SHOW_EXCEPTION >= 2 9250 /* call __android_log_print(prio, tag, format, ...) */ 9251 /* "Exception %s from %s:%d not caught locally" */ 9252 @ dvmLineNumFromPC(method, pc - method->insns) 9253 ldr r0, [rGLUE, #offGlue_method] 9254 ldr r1, [r0, #offMethod_insns] 9255 sub r1, rPC, r1 9256 asr r1, r1, #1 9257 bl dvmLineNumFromPC 9258 str r0, [sp, #-4]! 9259 @ dvmGetMethodSourceFile(method) 9260 ldr r0, [rGLUE, #offGlue_method] 9261 bl dvmGetMethodSourceFile 9262 str r0, [sp, #-4]! 9263 @ exception->clazz->descriptor 9264 ldr r3, [r9, #offObject_clazz] 9265 ldr r3, [r3, #offClassObject_descriptor] 9266 @ 9267 ldr r2, strExceptionNotCaughtLocally 9268 ldr r1, strLogTag 9269 mov r0, #3 @ LOG_DEBUG 9270 bl __android_log_print 9271#endif 9272 str r9, [r10, #offThread_exception] @ restore exception 9273 mov r0, r9 @ r0<- exception 9274 mov r1, r10 @ r1<- self 9275 bl dvmReleaseTrackedAlloc @ release the exception 9276 mov r1, #0 @ "want switch" = false 9277 b common_gotoBail @ bail out 9278 9279 9280 /* 9281 * Exception handling, calls through "glue code". 9282 */ 9283 .if 0 9284.LexceptionOld: 9285 SAVE_PC_FP_TO_GLUE() @ export state 9286 mov r0, rGLUE @ arg to function 9287 bl dvmMterp_exceptionThrown 9288 b common_resumeAfterGlueCall 9289 .endif 9290 9291 9292/* 9293 * After returning from a "glued" function, pull out the updated 9294 * values and start executing at the next instruction. 9295 */ 9296common_resumeAfterGlueCall: 9297 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9298 FETCH_INST() @ load rINST from rPC 9299 GET_INST_OPCODE(ip) @ extract opcode from rINST 9300 GOTO_OPCODE(ip) @ jump to next instruction 9301 9302/* 9303 * Invalid array index. 9304 */ 9305common_errArrayIndex: 9306 EXPORT_PC() 9307 ldr r0, strArrayIndexException 9308 mov r1, #0 9309 bl dvmThrowException 9310 b common_exceptionThrown 9311 9312/* 9313 * Invalid array value. 9314 */ 9315common_errArrayStore: 9316 EXPORT_PC() 9317 ldr r0, strArrayStoreException 9318 mov r1, #0 9319 bl dvmThrowException 9320 b common_exceptionThrown 9321 9322/* 9323 * Integer divide or mod by zero. 9324 */ 9325common_errDivideByZero: 9326 EXPORT_PC() 9327 ldr r0, strArithmeticException 9328 ldr r1, strDivideByZero 9329 bl dvmThrowException 9330 b common_exceptionThrown 9331 9332/* 9333 * Attempt to allocate an array with a negative size. 9334 */ 9335common_errNegativeArraySize: 9336 EXPORT_PC() 9337 ldr r0, strNegativeArraySizeException 9338 mov r1, #0 9339 bl dvmThrowException 9340 b common_exceptionThrown 9341 9342/* 9343 * Invocation of a non-existent method. 9344 */ 9345common_errNoSuchMethod: 9346 EXPORT_PC() 9347 ldr r0, strNoSuchMethodError 9348 mov r1, #0 9349 bl dvmThrowException 9350 b common_exceptionThrown 9351 9352/* 9353 * We encountered a null object when we weren't expecting one. We 9354 * export the PC, throw a NullPointerException, and goto the exception 9355 * processing code. 9356 */ 9357common_errNullObject: 9358 EXPORT_PC() 9359 ldr r0, strNullPointerException 9360 mov r1, #0 9361 bl dvmThrowException 9362 b common_exceptionThrown 9363 9364/* 9365 * For debugging, cause an immediate fault. The source address will 9366 * be in lr (use a bl instruction to jump here). 9367 */ 9368common_abort: 9369 ldr pc, .LdeadFood 9370.LdeadFood: 9371 .word 0xdeadf00d 9372 9373/* 9374 * Spit out a "we were here", preserving all registers. (The attempt 9375 * to save ip won't work, but we need to save an even number of 9376 * registers for EABI 64-bit stack alignment.) 9377 */ 9378 .macro SQUEAK num 9379common_squeak\num: 9380 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9381 ldr r0, strSqueak 9382 mov r1, #\num 9383 bl printf 9384 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9385 bx lr 9386 .endm 9387 9388 SQUEAK 0 9389 SQUEAK 1 9390 SQUEAK 2 9391 SQUEAK 3 9392 SQUEAK 4 9393 SQUEAK 5 9394 9395/* 9396 * Spit out the number in r0, preserving registers. 9397 */ 9398common_printNum: 9399 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9400 mov r1, r0 9401 ldr r0, strSqueak 9402 bl printf 9403 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9404 bx lr 9405 9406/* 9407 * Print a newline, preserving registers. 9408 */ 9409common_printNewline: 9410 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9411 ldr r0, strNewline 9412 bl printf 9413 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9414 bx lr 9415 9416 /* 9417 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9418 */ 9419common_printHex: 9420 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9421 mov r1, r0 9422 ldr r0, strPrintHex 9423 bl printf 9424 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9425 bx lr 9426 9427/* 9428 * Print the 64-bit quantity in r0-r1, preserving registers. 9429 */ 9430common_printLong: 9431 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9432 mov r3, r1 9433 mov r2, r0 9434 ldr r0, strPrintLong 9435 bl printf 9436 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9437 bx lr 9438 9439/* 9440 * Print full method info. Pass the Method* in r0. Preserves regs. 9441 */ 9442common_printMethod: 9443 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9444 bl dvmMterpPrintMethod 9445 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9446 bx lr 9447 9448/* 9449 * Call a C helper function that dumps regs and possibly some 9450 * additional info. Requires the C function to be compiled in. 9451 */ 9452 .if 0 9453common_dumpRegs: 9454 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9455 bl dvmMterpDumpArmRegs 9456 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9457 bx lr 9458 .endif 9459 9460 9461/* 9462 * String references, must be close to the code that uses them. 9463 */ 9464 .align 2 9465strArithmeticException: 9466 .word .LstrArithmeticException 9467strArrayIndexException: 9468 .word .LstrArrayIndexException 9469strArrayStoreException: 9470 .word .LstrArrayStoreException 9471strDivideByZero: 9472 .word .LstrDivideByZero 9473strNegativeArraySizeException: 9474 .word .LstrNegativeArraySizeException 9475strNoSuchMethodError: 9476 .word .LstrNoSuchMethodError 9477strNullPointerException: 9478 .word .LstrNullPointerException 9479 9480strLogTag: 9481 .word .LstrLogTag 9482strExceptionNotCaughtLocally: 9483 .word .LstrExceptionNotCaughtLocally 9484 9485strNewline: 9486 .word .LstrNewline 9487strSqueak: 9488 .word .LstrSqueak 9489strPrintHex: 9490 .word .LstrPrintHex 9491strPrintLong: 9492 .word .LstrPrintLong 9493 9494/* 9495 * Zero-terminated ASCII string data. 9496 * 9497 * On ARM we have two choices: do like gcc does, and LDR from a .word 9498 * with the address, or use an ADR pseudo-op to get the address 9499 * directly. ADR saves 4 bytes and an indirection, but it's using a 9500 * PC-relative addressing mode and hence has a limited range, which 9501 * makes it not work well with mergeable string sections. 9502 */ 9503 .section .rodata.str1.4,"aMS",%progbits,1 9504 9505.LstrBadEntryPoint: 9506 .asciz "Bad entry point %d\n" 9507.LstrArithmeticException: 9508 .asciz "Ljava/lang/ArithmeticException;" 9509.LstrArrayIndexException: 9510 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9511.LstrArrayStoreException: 9512 .asciz "Ljava/lang/ArrayStoreException;" 9513.LstrClassCastException: 9514 .asciz "Ljava/lang/ClassCastException;" 9515.LstrDivideByZero: 9516 .asciz "divide by zero" 9517.LstrFilledNewArrayNotImpl: 9518 .asciz "filled-new-array only implemented for objects and 'int'" 9519.LstrInternalError: 9520 .asciz "Ljava/lang/InternalError;" 9521.LstrInstantiationError: 9522 .asciz "Ljava/lang/InstantiationError;" 9523.LstrNegativeArraySizeException: 9524 .asciz "Ljava/lang/NegativeArraySizeException;" 9525.LstrNoSuchMethodError: 9526 .asciz "Ljava/lang/NoSuchMethodError;" 9527.LstrNullPointerException: 9528 .asciz "Ljava/lang/NullPointerException;" 9529 9530.LstrLogTag: 9531 .asciz "mterp" 9532.LstrExceptionNotCaughtLocally: 9533 .asciz "Exception %s from %s:%d not caught locally\n" 9534 9535.LstrNewline: 9536 .asciz "\n" 9537.LstrSqueak: 9538 .asciz "<%d>" 9539.LstrPrintHex: 9540 .asciz "<0x%x>" 9541.LstrPrintLong: 9542 .asciz "<%lld>" 9543 9544 9545