InterpAsm-armv5te.S revision 99409883d9c4c0ffb49b070ce307bb33a9dfe9f1
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. 44 45Stack is "full descending". Only the arguments that don't fit in the first 4 46registers are placed on the stack. "sp" points at the first stacked argument 47(i.e. the 5th arg). 48 49VFP: single-precision results in s0, double-precision results in d0. 50 51In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5264-bit quantities (long long, double) must be 64-bit aligned. 53*/ 54 55/* 56Mterp and ARM notes: 57 58The following registers have fixed assignments: 59 60 reg nick purpose 61 r4 rPC interpreted program counter, used for fetching instructions 62 r5 rFP interpreted frame pointer, used for accessing locals and args 63 r6 rGLUE MterpGlue pointer 64 r7 rIBASE interpreted instruction base pointer, used for computed goto 65 r8 rINST first 16-bit code unit of current instruction 66 67Macros are provided for common operations. Each macro MUST emit only 68one instruction to make instruction-counting easier. They MUST NOT alter 69unspecified registers or condition codes. 70*/ 71 72/* single-purpose registers, given names for clarity */ 73#define rPC r4 74#define rFP r5 75#define rGLUE r6 76#define rIBASE r7 77#define rINST r8 78 79/* save/restore the PC and/or FP from the glue struct */ 80#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 81#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 82#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 83#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 84#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 85#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 86 87/* 88 * "export" the PC to the stack frame, f/b/o future exception objects. Must 89 * be done *before* something calls dvmThrowException. 90 * 91 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 92 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 93 * 94 * It's okay to do this more than once. 95 */ 96#define EXPORT_PC() \ 97 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 98 99/* 100 * Given a frame pointer, find the stack save area. 101 * 102 * In C this is "((StackSaveArea*)(_fp) -1)". 103 */ 104#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 105 sub _reg, _fpreg, #sizeofStackSaveArea 106 107/* 108 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 109 */ 110#define FETCH_INST() ldrh rINST, [rPC] 111 112/* 113 * Fetch the next instruction from the specified offset. Advances rPC 114 * to point to the next instruction. "_count" is in 16-bit code units. 115 * 116 * Because of the limited size of immediate constants on ARM, this is only 117 * suitable for small forward movements (i.e. don't try to implement "goto" 118 * with this). 119 * 120 * This must come AFTER anything that can throw an exception, or the 121 * exception catch may miss. (This also implies that it must come after 122 * EXPORT_PC().) 123 */ 124#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 125 126/* 127 * Fetch the next instruction from an offset specified by _reg. Updates 128 * rPC to point to the next instruction. "_reg" must specify the distance 129 * in bytes, *not* 16-bit code units, and may be a signed value. 130 * 131 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 132 * bits that hold the shift distance are used for the half/byte/sign flags. 133 * In some cases we can pre-double _reg for free, so we require a byte offset 134 * here. 135 */ 136#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 137 138/* 139 * Fetch a half-word code unit from an offset past the current PC. The 140 * "_count" value is in 16-bit code units. Does not advance rPC. 141 * 142 * The "_S" variant works the same but treats the value as signed. 143 */ 144#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 145#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 146 147/* 148 * Fetch one byte from an offset past the current PC. Pass in the same 149 * "_count" as you would for FETCH, and an additional 0/1 indicating which 150 * byte of the halfword you want (lo/hi). 151 */ 152#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 153 154/* 155 * Put the instruction's opcode field into the specified register. 156 */ 157#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 158 159/* 160 * Begin executing the opcode in _reg. Because this only jumps within the 161 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 162 */ 163#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 164 165/* 166 * Get/set the 32-bit value from a Dalvik register. 167 */ 168#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 169#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 170 171/* 172 * This is a #include, not a %include, because we want the C pre-processor 173 * to expand the macros into assembler assignment statements. 174 */ 175#include "../common/asm-constants.h" 176 177 178/* File: armv5te/platform.S */ 179/* 180 * =========================================================================== 181 * CPU-version-specific defines 182 * =========================================================================== 183 */ 184 185/* 186 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 187 * one-way branch. 188 * 189 * May modify IP. Does not modify LR. 190 */ 191.macro LDR_PC source 192 ldr pc, \source 193.endm 194 195/* 196 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 197 * Jump to subroutine. 198 * 199 * May modify IP and LR. 200 */ 201.macro LDR_PC_LR source 202 mov lr, pc 203 ldr pc, \source 204.endm 205 206/* 207 * Macro for "LDMFD SP!, {...regs...,PC}". 208 * 209 * May modify IP and LR. 210 */ 211.macro LDMFD_PC regs 212 ldmfd sp!, {\regs,pc} 213.endm 214 215 216/* File: armv5te/entry.S */ 217/* 218 * Copyright (C) 2008 The Android Open Source Project 219 * 220 * Licensed under the Apache License, Version 2.0 (the "License"); 221 * you may not use this file except in compliance with the License. 222 * You may obtain a copy of the License at 223 * 224 * http://www.apache.org/licenses/LICENSE-2.0 225 * 226 * Unless required by applicable law or agreed to in writing, software 227 * distributed under the License is distributed on an "AS IS" BASIS, 228 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 229 * See the License for the specific language governing permissions and 230 * limitations under the License. 231 */ 232/* 233 * Interpreter entry point. 234 */ 235 236/* 237 * We don't have formal stack frames, so gdb scans upward in the code 238 * to find the start of the function (a label with the %function type), 239 * and then looks at the next few instructions to figure out what 240 * got pushed onto the stack. From this it figures out how to restore 241 * the registers, including PC, for the previous stack frame. If gdb 242 * sees a non-function label, it stops scanning, so either we need to 243 * have nothing but assembler-local labels between the entry point and 244 * the break, or we need to fake it out. 245 * 246 * When this is defined, we add some stuff to make gdb less confused. 247 */ 248#define ASSIST_DEBUGGER 1 249 250 .text 251 .align 2 252 .global dvmMterpStdRun 253 .type dvmMterpStdRun, %function 254 255/* 256 * On entry: 257 * r0 MterpGlue* glue 258 * 259 * This function returns a boolean "changeInterp" value. The return comes 260 * via a call to dvmMterpStdBail(). 261 */ 262dvmMterpStdRun: 263#define MTERP_ENTRY1 \ 264 .save {r4-r10,fp,lr}; \ 265 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 266#define MTERP_ENTRY2 \ 267 .pad #4; \ 268 sub sp, sp, #4 @ align 64 269 270 .fnstart 271 MTERP_ENTRY1 272 MTERP_ENTRY2 273 274 /* save stack pointer, add magic word for debuggerd */ 275 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 276 277 /* set up "named" registers, figure out entry point */ 278 mov rGLUE, r0 @ set rGLUE 279 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char 280 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 281 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 282 cmp r1, #kInterpEntryInstr @ usual case? 283 bne .Lnot_instr @ no, handle it 284 285 /* start executing the instruction at rPC */ 286 FETCH_INST() @ load rINST from rPC 287 GET_INST_OPCODE(ip) @ extract opcode from rINST 288 GOTO_OPCODE(ip) @ jump to next instruction 289 290.Lnot_instr: 291 cmp r1, #kInterpEntryReturn @ were we returning from a method? 292 beq common_returnFromMethod 293 294.Lnot_return: 295 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 296 beq common_exceptionThrown 297 298.Lbad_arg: 299 ldr r0, strBadEntryPoint 300 @ r1 holds value of entryPoint 301 bl printf 302 bl dvmAbort 303 .fnend 304 305 306 .global dvmMterpStdBail 307 .type dvmMterpStdBail, %function 308 309/* 310 * Restore the stack pointer and PC from the save point established on entry. 311 * This is essentially the same as a longjmp, but should be cheaper. The 312 * last instruction causes us to return to whoever called dvmMterpStdRun. 313 * 314 * We pushed some registers on the stack in dvmMterpStdRun, then saved 315 * SP and LR. Here we restore SP, restore the registers, and then restore 316 * LR to PC. 317 * 318 * On entry: 319 * r0 MterpGlue* glue 320 * r1 bool changeInterp 321 */ 322dvmMterpStdBail: 323 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 324 mov r0, r1 @ return the changeInterp value 325 add sp, sp, #4 @ un-align 64 326 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 327 328 329/* 330 * String references. 331 */ 332strBadEntryPoint: 333 .word .LstrBadEntryPoint 334 335 336 337 .global dvmAsmInstructionStart 338 .type dvmAsmInstructionStart, %function 339dvmAsmInstructionStart = .L_OP_NOP 340 .text 341 342/* ------------------------------ */ 343 .balign 64 344.L_OP_NOP: /* 0x00 */ 345/* File: armv5te/OP_NOP.S */ 346 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 347 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 348 GOTO_OPCODE(ip) @ execute it 349 350#ifdef ASSIST_DEBUGGER 351 /* insert fake function header to help gdb find the stack frame */ 352 .type dalvik_inst, %function 353dalvik_inst: 354 .fnstart 355 MTERP_ENTRY1 356 MTERP_ENTRY2 357 .fnend 358#endif 359 360 361/* ------------------------------ */ 362 .balign 64 363.L_OP_MOVE: /* 0x01 */ 364/* File: armv5te/OP_MOVE.S */ 365 /* for move, move-object, long-to-int */ 366 /* op vA, vB */ 367 mov r1, rINST, lsr #12 @ r1<- B from 15:12 368 mov r0, rINST, lsr #8 @ r0<- A from 11:8 369 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 370 GET_VREG(r2, r1) @ r2<- fp[B] 371 and r0, r0, #15 372 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 373 SET_VREG(r2, r0) @ fp[A]<- r2 374 GOTO_OPCODE(ip) @ execute next instruction 375 376 377/* ------------------------------ */ 378 .balign 64 379.L_OP_MOVE_FROM16: /* 0x02 */ 380/* File: armv5te/OP_MOVE_FROM16.S */ 381 /* for: move/from16, move-object/from16 */ 382 /* op vAA, vBBBB */ 383 FETCH(r1, 1) @ r1<- BBBB 384 mov r0, rINST, lsr #8 @ r0<- AA 385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 386 GET_VREG(r2, r1) @ r2<- fp[BBBB] 387 GET_INST_OPCODE(ip) @ extract opcode from rINST 388 SET_VREG(r2, r0) @ fp[AA]<- r2 389 GOTO_OPCODE(ip) @ jump to next instruction 390 391 392/* ------------------------------ */ 393 .balign 64 394.L_OP_MOVE_16: /* 0x03 */ 395/* File: armv5te/OP_MOVE_16.S */ 396 /* for: move/16, move-object/16 */ 397 /* op vAAAA, vBBBB */ 398 FETCH(r1, 2) @ r1<- BBBB 399 FETCH(r0, 1) @ r0<- AAAA 400 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 401 GET_VREG(r2, r1) @ r2<- fp[BBBB] 402 GET_INST_OPCODE(ip) @ extract opcode from rINST 403 SET_VREG(r2, r0) @ fp[AAAA]<- r2 404 GOTO_OPCODE(ip) @ jump to next instruction 405 406 407/* ------------------------------ */ 408 .balign 64 409.L_OP_MOVE_WIDE: /* 0x04 */ 410/* File: armv5te/OP_MOVE_WIDE.S */ 411 /* move-wide vA, vB */ 412 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 413 mov r2, rINST, lsr #8 @ r2<- A(+) 414 mov r3, rINST, lsr #12 @ r3<- B 415 and r2, r2, #15 416 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 417 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 418 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 419 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 420 GET_INST_OPCODE(ip) @ extract opcode from rINST 421 stmia r2, {r0-r1} @ fp[A]<- r0/r1 422 GOTO_OPCODE(ip) @ jump to next instruction 423 424 425/* ------------------------------ */ 426 .balign 64 427.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 428/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 429 /* move-wide/from16 vAA, vBBBB */ 430 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 431 FETCH(r3, 1) @ r3<- BBBB 432 mov r2, rINST, lsr #8 @ r2<- AA 433 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 434 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 435 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 437 GET_INST_OPCODE(ip) @ extract opcode from rINST 438 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 439 GOTO_OPCODE(ip) @ jump to next instruction 440 441 442/* ------------------------------ */ 443 .balign 64 444.L_OP_MOVE_WIDE_16: /* 0x06 */ 445/* File: armv5te/OP_MOVE_WIDE_16.S */ 446 /* move-wide/16 vAAAA, vBBBB */ 447 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 448 FETCH(r3, 2) @ r3<- BBBB 449 FETCH(r2, 1) @ r2<- AAAA 450 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 451 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 452 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 454 GET_INST_OPCODE(ip) @ extract opcode from rINST 455 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 456 GOTO_OPCODE(ip) @ jump to next instruction 457 458 459/* ------------------------------ */ 460 .balign 64 461.L_OP_MOVE_OBJECT: /* 0x07 */ 462/* File: armv5te/OP_MOVE_OBJECT.S */ 463/* File: armv5te/OP_MOVE.S */ 464 /* for move, move-object, long-to-int */ 465 /* op vA, vB */ 466 mov r1, rINST, lsr #12 @ r1<- B from 15:12 467 mov r0, rINST, lsr #8 @ r0<- A from 11:8 468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 469 GET_VREG(r2, r1) @ r2<- fp[B] 470 and r0, r0, #15 471 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 472 SET_VREG(r2, r0) @ fp[A]<- r2 473 GOTO_OPCODE(ip) @ execute next instruction 474 475 476 477/* ------------------------------ */ 478 .balign 64 479.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 480/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 481/* File: armv5te/OP_MOVE_FROM16.S */ 482 /* for: move/from16, move-object/from16 */ 483 /* op vAA, vBBBB */ 484 FETCH(r1, 1) @ r1<- BBBB 485 mov r0, rINST, lsr #8 @ r0<- AA 486 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 487 GET_VREG(r2, r1) @ r2<- fp[BBBB] 488 GET_INST_OPCODE(ip) @ extract opcode from rINST 489 SET_VREG(r2, r0) @ fp[AA]<- r2 490 GOTO_OPCODE(ip) @ jump to next instruction 491 492 493 494/* ------------------------------ */ 495 .balign 64 496.L_OP_MOVE_OBJECT_16: /* 0x09 */ 497/* File: armv5te/OP_MOVE_OBJECT_16.S */ 498/* File: armv5te/OP_MOVE_16.S */ 499 /* for: move/16, move-object/16 */ 500 /* op vAAAA, vBBBB */ 501 FETCH(r1, 2) @ r1<- BBBB 502 FETCH(r0, 1) @ r0<- AAAA 503 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 504 GET_VREG(r2, r1) @ r2<- fp[BBBB] 505 GET_INST_OPCODE(ip) @ extract opcode from rINST 506 SET_VREG(r2, r0) @ fp[AAAA]<- r2 507 GOTO_OPCODE(ip) @ jump to next instruction 508 509 510 511/* ------------------------------ */ 512 .balign 64 513.L_OP_MOVE_RESULT: /* 0x0a */ 514/* File: armv5te/OP_MOVE_RESULT.S */ 515 /* for: move-result, move-result-object */ 516 /* op vAA */ 517 mov r2, rINST, lsr #8 @ r2<- AA 518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 519 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 520 GET_INST_OPCODE(ip) @ extract opcode from rINST 521 SET_VREG(r0, r2) @ fp[AA]<- r0 522 GOTO_OPCODE(ip) @ jump to next instruction 523 524 525/* ------------------------------ */ 526 .balign 64 527.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 528/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 529 /* move-result-wide vAA */ 530 mov r2, rINST, lsr #8 @ r2<- AA 531 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 532 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 533 ldmia r3, {r0-r1} @ r0/r1<- retval.j 534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 535 GET_INST_OPCODE(ip) @ extract opcode from rINST 536 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 537 GOTO_OPCODE(ip) @ jump to next instruction 538 539 540/* ------------------------------ */ 541 .balign 64 542.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 543/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 544/* File: armv5te/OP_MOVE_RESULT.S */ 545 /* for: move-result, move-result-object */ 546 /* op vAA */ 547 mov r2, rINST, lsr #8 @ r2<- AA 548 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 549 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 550 GET_INST_OPCODE(ip) @ extract opcode from rINST 551 SET_VREG(r0, r2) @ fp[AA]<- r0 552 GOTO_OPCODE(ip) @ jump to next instruction 553 554 555 556/* ------------------------------ */ 557 .balign 64 558.L_OP_MOVE_EXCEPTION: /* 0x0d */ 559/* File: armv5te/OP_MOVE_EXCEPTION.S */ 560 /* move-exception vAA */ 561 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 562 mov r2, rINST, lsr #8 @ r2<- AA 563 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 564 mov r1, #0 @ r1<- 0 565 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 566 SET_VREG(r3, r2) @ fp[AA]<- exception obj 567 GET_INST_OPCODE(ip) @ extract opcode from rINST 568 str r1, [r0, #offThread_exception] @ dvmClearException bypass 569 GOTO_OPCODE(ip) @ jump to next instruction 570 571 572/* ------------------------------ */ 573 .balign 64 574.L_OP_RETURN_VOID: /* 0x0e */ 575/* File: armv5te/OP_RETURN_VOID.S */ 576 b common_returnFromMethod 577 578 579/* ------------------------------ */ 580 .balign 64 581.L_OP_RETURN: /* 0x0f */ 582/* File: armv5te/OP_RETURN.S */ 583 /* 584 * Return a 32-bit value. Copies the return value into the "glue" 585 * structure, then jumps to the return handler. 586 * 587 * for: return, return-object 588 */ 589 /* op vAA */ 590 mov r2, rINST, lsr #8 @ r2<- AA 591 GET_VREG(r0, r2) @ r0<- vAA 592 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 593 b common_returnFromMethod 594 595 596/* ------------------------------ */ 597 .balign 64 598.L_OP_RETURN_WIDE: /* 0x10 */ 599/* File: armv5te/OP_RETURN_WIDE.S */ 600 /* 601 * Return a 64-bit value. Copies the return value into the "glue" 602 * structure, then jumps to the return handler. 603 */ 604 /* return-wide vAA */ 605 mov r2, rINST, lsr #8 @ r2<- AA 606 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 607 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 608 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 609 stmia r3, {r0-r1} @ retval<- r0/r1 610 b common_returnFromMethod 611 612 613/* ------------------------------ */ 614 .balign 64 615.L_OP_RETURN_OBJECT: /* 0x11 */ 616/* File: armv5te/OP_RETURN_OBJECT.S */ 617/* File: armv5te/OP_RETURN.S */ 618 /* 619 * Return a 32-bit value. Copies the return value into the "glue" 620 * structure, then jumps to the return handler. 621 * 622 * for: return, return-object 623 */ 624 /* op vAA */ 625 mov r2, rINST, lsr #8 @ r2<- AA 626 GET_VREG(r0, r2) @ r0<- vAA 627 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 628 b common_returnFromMethod 629 630 631 632/* ------------------------------ */ 633 .balign 64 634.L_OP_CONST_4: /* 0x12 */ 635/* File: armv5te/OP_CONST_4.S */ 636 /* const/4 vA, #+B */ 637 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 638 mov r0, rINST, lsr #8 @ r0<- A+ 639 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 640 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 641 and r0, r0, #15 642 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 643 SET_VREG(r1, r0) @ fp[A]<- r1 644 GOTO_OPCODE(ip) @ execute next instruction 645 646 647/* ------------------------------ */ 648 .balign 64 649.L_OP_CONST_16: /* 0x13 */ 650/* File: armv5te/OP_CONST_16.S */ 651 /* const/16 vAA, #+BBBB */ 652 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 653 mov r3, rINST, lsr #8 @ r3<- AA 654 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 655 SET_VREG(r0, r3) @ vAA<- r0 656 GET_INST_OPCODE(ip) @ extract opcode from rINST 657 GOTO_OPCODE(ip) @ jump to next instruction 658 659 660/* ------------------------------ */ 661 .balign 64 662.L_OP_CONST: /* 0x14 */ 663/* File: armv5te/OP_CONST.S */ 664 /* const vAA, #+BBBBbbbb */ 665 mov r3, rINST, lsr #8 @ r3<- AA 666 FETCH(r0, 1) @ r0<- bbbb (low) 667 FETCH(r1, 2) @ r1<- BBBB (high) 668 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 669 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 670 GET_INST_OPCODE(ip) @ extract opcode from rINST 671 SET_VREG(r0, r3) @ vAA<- r0 672 GOTO_OPCODE(ip) @ jump to next instruction 673 674 675/* ------------------------------ */ 676 .balign 64 677.L_OP_CONST_HIGH16: /* 0x15 */ 678/* File: armv5te/OP_CONST_HIGH16.S */ 679 /* const/high16 vAA, #+BBBB0000 */ 680 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 681 mov r3, rINST, lsr #8 @ r3<- AA 682 mov r0, r0, lsl #16 @ r0<- BBBB0000 683 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 684 SET_VREG(r0, r3) @ vAA<- r0 685 GET_INST_OPCODE(ip) @ extract opcode from rINST 686 GOTO_OPCODE(ip) @ jump to next instruction 687 688 689/* ------------------------------ */ 690 .balign 64 691.L_OP_CONST_WIDE_16: /* 0x16 */ 692/* File: armv5te/OP_CONST_WIDE_16.S */ 693 /* const-wide/16 vAA, #+BBBB */ 694 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 695 mov r3, rINST, lsr #8 @ r3<- AA 696 mov r1, r0, asr #31 @ r1<- ssssssss 697 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 698 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 699 GET_INST_OPCODE(ip) @ extract opcode from rINST 700 stmia r3, {r0-r1} @ vAA<- r0/r1 701 GOTO_OPCODE(ip) @ jump to next instruction 702 703 704/* ------------------------------ */ 705 .balign 64 706.L_OP_CONST_WIDE_32: /* 0x17 */ 707/* File: armv5te/OP_CONST_WIDE_32.S */ 708 /* const-wide/32 vAA, #+BBBBbbbb */ 709 FETCH(r0, 1) @ r0<- 0000bbbb (low) 710 mov r3, rINST, lsr #8 @ r3<- AA 711 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 712 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 713 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 714 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 715 mov r1, r0, asr #31 @ r1<- ssssssss 716 GET_INST_OPCODE(ip) @ extract opcode from rINST 717 stmia r3, {r0-r1} @ vAA<- r0/r1 718 GOTO_OPCODE(ip) @ jump to next instruction 719 720 721/* ------------------------------ */ 722 .balign 64 723.L_OP_CONST_WIDE: /* 0x18 */ 724/* File: armv5te/OP_CONST_WIDE.S */ 725 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 726 FETCH(r0, 1) @ r0<- bbbb (low) 727 FETCH(r1, 2) @ r1<- BBBB (low middle) 728 FETCH(r2, 3) @ r2<- hhhh (high middle) 729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 730 FETCH(r3, 4) @ r3<- HHHH (high) 731 mov r9, rINST, lsr #8 @ r9<- AA 732 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 733 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 734 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 735 GET_INST_OPCODE(ip) @ extract opcode from rINST 736 stmia r9, {r0-r1} @ vAA<- r0/r1 737 GOTO_OPCODE(ip) @ jump to next instruction 738 739 740/* ------------------------------ */ 741 .balign 64 742.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 743/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 744 /* const-wide/high16 vAA, #+BBBB000000000000 */ 745 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 746 mov r3, rINST, lsr #8 @ r3<- AA 747 mov r0, #0 @ r0<- 00000000 748 mov r1, r1, lsl #16 @ r1<- BBBB0000 749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 750 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 751 GET_INST_OPCODE(ip) @ extract opcode from rINST 752 stmia r3, {r0-r1} @ vAA<- r0/r1 753 GOTO_OPCODE(ip) @ jump to next instruction 754 755 756/* ------------------------------ */ 757 .balign 64 758.L_OP_CONST_STRING: /* 0x1a */ 759/* File: armv5te/OP_CONST_STRING.S */ 760 /* const/string vAA, String@BBBB */ 761 FETCH(r1, 1) @ r1<- BBBB 762 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 763 mov r9, rINST, lsr #8 @ r9<- AA 764 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 765 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 766 cmp r0, #0 @ not yet resolved? 767 beq .LOP_CONST_STRING_resolve 768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 769 GET_INST_OPCODE(ip) @ extract opcode from rINST 770 SET_VREG(r0, r9) @ vAA<- r0 771 GOTO_OPCODE(ip) @ jump to next instruction 772 773/* ------------------------------ */ 774 .balign 64 775.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 776/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 777 /* const/string vAA, String@BBBBBBBB */ 778 FETCH(r0, 1) @ r0<- bbbb (low) 779 FETCH(r1, 2) @ r1<- BBBB (high) 780 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 781 mov r9, rINST, lsr #8 @ r9<- AA 782 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 783 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 784 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 785 cmp r0, #0 786 beq .LOP_CONST_STRING_JUMBO_resolve 787 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 788 GET_INST_OPCODE(ip) @ extract opcode from rINST 789 SET_VREG(r0, r9) @ vAA<- r0 790 GOTO_OPCODE(ip) @ jump to next instruction 791 792/* ------------------------------ */ 793 .balign 64 794.L_OP_CONST_CLASS: /* 0x1c */ 795/* File: armv5te/OP_CONST_CLASS.S */ 796 /* const/class vAA, Class@BBBB */ 797 FETCH(r1, 1) @ r1<- BBBB 798 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 799 mov r9, rINST, lsr #8 @ r9<- AA 800 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 801 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 802 cmp r0, #0 @ not yet resolved? 803 beq .LOP_CONST_CLASS_resolve 804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 805 GET_INST_OPCODE(ip) @ extract opcode from rINST 806 SET_VREG(r0, r9) @ vAA<- r0 807 GOTO_OPCODE(ip) @ jump to next instruction 808 809/* ------------------------------ */ 810 .balign 64 811.L_OP_MONITOR_ENTER: /* 0x1d */ 812/* File: armv5te/OP_MONITOR_ENTER.S */ 813 /* 814 * Synchronize on an object. 815 */ 816 /* monitor-enter vAA */ 817 mov r2, rINST, lsr #8 @ r2<- AA 818 GET_VREG(r1, r2) @ r1<- vAA (object) 819 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 820 cmp r1, #0 @ null object? 821 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 822 beq common_errNullObject @ null object, throw an exception 823 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 824 bl dvmLockObject @ call(self, obj) 825#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 826 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 827 ldr r1, [r0, #offThread_exception] @ check for exception 828 cmp r1, #0 829 bne common_exceptionThrown @ exception raised, bail out 830#endif 831 GET_INST_OPCODE(ip) @ extract opcode from rINST 832 GOTO_OPCODE(ip) @ jump to next instruction 833 834 835/* ------------------------------ */ 836 .balign 64 837.L_OP_MONITOR_EXIT: /* 0x1e */ 838/* File: armv5te/OP_MONITOR_EXIT.S */ 839 /* 840 * Unlock an object. 841 * 842 * Exceptions that occur when unlocking a monitor need to appear as 843 * if they happened at the following instruction. See the Dalvik 844 * instruction spec. 845 */ 846 /* monitor-exit vAA */ 847 mov r2, rINST, lsr #8 @ r2<- AA 848 EXPORT_PC() @ before fetch: export the PC 849 GET_VREG(r1, r2) @ r1<- vAA (object) 850 cmp r1, #0 @ null object? 851 beq common_errNullObject @ yes 852 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 853 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 854 cmp r0, #0 @ failed? 855 beq common_exceptionThrown @ yes, exception is pending 856 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 857 GET_INST_OPCODE(ip) @ extract opcode from rINST 858 GOTO_OPCODE(ip) @ jump to next instruction 859 860 861/* ------------------------------ */ 862 .balign 64 863.L_OP_CHECK_CAST: /* 0x1f */ 864/* File: armv5te/OP_CHECK_CAST.S */ 865 /* 866 * Check to see if a cast from one class to another is allowed. 867 */ 868 /* check-cast vAA, class@BBBB */ 869 mov r3, rINST, lsr #8 @ r3<- AA 870 FETCH(r2, 1) @ r2<- BBBB 871 GET_VREG(r9, r3) @ r9<- object 872 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 873 cmp r9, #0 @ is object null? 874 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 875 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 876 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 877 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 878 cmp r1, #0 @ have we resolved this before? 879 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 880.LOP_CHECK_CAST_resolved: 881 cmp r0, r1 @ same class (trivial success)? 882 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 883.LOP_CHECK_CAST_okay: 884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 885 GET_INST_OPCODE(ip) @ extract opcode from rINST 886 GOTO_OPCODE(ip) @ jump to next instruction 887 888/* ------------------------------ */ 889 .balign 64 890.L_OP_INSTANCE_OF: /* 0x20 */ 891/* File: armv5te/OP_INSTANCE_OF.S */ 892 /* 893 * Check to see if an object reference is an instance of a class. 894 * 895 * Most common situation is a non-null object, being compared against 896 * an already-resolved class. 897 */ 898 /* instance-of vA, vB, class@CCCC */ 899 mov r3, rINST, lsr #12 @ r3<- B 900 mov r9, rINST, lsr #8 @ r9<- A+ 901 GET_VREG(r0, r3) @ r0<- vB (object) 902 and r9, r9, #15 @ r9<- A 903 cmp r0, #0 @ is object null? 904 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 905 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 906 FETCH(r3, 1) @ r3<- CCCC 907 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 908 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 909 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 910 cmp r1, #0 @ have we resolved this before? 911 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 912.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 913 cmp r0, r1 @ same class (trivial success)? 914 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 915 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 916 917/* ------------------------------ */ 918 .balign 64 919.L_OP_ARRAY_LENGTH: /* 0x21 */ 920/* File: armv5te/OP_ARRAY_LENGTH.S */ 921 /* 922 * Return the length of an array. 923 */ 924 mov r1, rINST, lsr #12 @ r1<- B 925 mov r2, rINST, lsr #8 @ r2<- A+ 926 GET_VREG(r0, r1) @ r0<- vB (object ref) 927 and r2, r2, #15 @ r2<- A 928 cmp r0, #0 @ is object null? 929 beq common_errNullObject @ yup, fail 930 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 931 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 932 GET_INST_OPCODE(ip) @ extract opcode from rINST 933 SET_VREG(r3, r2) @ vB<- length 934 GOTO_OPCODE(ip) @ jump to next instruction 935 936 937/* ------------------------------ */ 938 .balign 64 939.L_OP_NEW_INSTANCE: /* 0x22 */ 940/* File: armv5te/OP_NEW_INSTANCE.S */ 941 /* 942 * Create a new instance of a class. 943 */ 944 /* new-instance vAA, class@BBBB */ 945 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 946 FETCH(r1, 1) @ r1<- BBBB 947 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 948 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 949 EXPORT_PC() @ req'd for init, resolve, alloc 950 cmp r0, #0 @ already resolved? 951 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 952.LOP_NEW_INSTANCE_resolved: @ r0=class 953 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 954 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 955 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 956.LOP_NEW_INSTANCE_initialized: @ r0=class 957 ldr r3, [r0, #offClassObject_accessFlags] @ r3<- clazz->accessFlags 958 tst r3, #(ACC_INTERFACE|ACC_ABSTRACT) @ abstract or interface? 959 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 960 beq .LOP_NEW_INSTANCE_finish @ concrete class, continue 961 b .LOP_NEW_INSTANCE_abstract @ fail 962 963/* ------------------------------ */ 964 .balign 64 965.L_OP_NEW_ARRAY: /* 0x23 */ 966/* File: armv5te/OP_NEW_ARRAY.S */ 967 /* 968 * Allocate an array of objects, specified with the array class 969 * and a count. 970 * 971 * The verifier guarantees that this is an array class, so we don't 972 * check for it here. 973 */ 974 /* new-array vA, vB, class@CCCC */ 975 mov r0, rINST, lsr #12 @ r0<- B 976 FETCH(r2, 1) @ r2<- CCCC 977 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 978 GET_VREG(r1, r0) @ r1<- vB (array length) 979 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 980 cmp r1, #0 @ check length 981 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 982 bmi common_errNegativeArraySize @ negative length, bail 983 cmp r0, #0 @ already resolved? 984 EXPORT_PC() @ req'd for resolve, alloc 985 bne .LOP_NEW_ARRAY_finish @ resolved, continue 986 b .LOP_NEW_ARRAY_resolve @ do resolve now 987 988/* ------------------------------ */ 989 .balign 64 990.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 991/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 992 /* 993 * Create a new array with elements filled from registers. 994 * 995 * for: filled-new-array, filled-new-array/range 996 */ 997 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 998 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 999 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1000 FETCH(r1, 1) @ r1<- BBBB 1001 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1002 EXPORT_PC() @ need for resolve and alloc 1003 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1004 mov r10, rINST, lsr #8 @ r10<- AA or BA 1005 cmp r0, #0 @ already resolved? 1006 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10078: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1008 mov r2, #0 @ r2<- false 1009 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1010 bl dvmResolveClass @ r0<- call(clazz, ref) 1011 cmp r0, #0 @ got null? 1012 beq common_exceptionThrown @ yes, handle exception 1013 b .LOP_FILLED_NEW_ARRAY_continue 1014 1015/* ------------------------------ */ 1016 .balign 64 1017.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1018/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1019/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1020 /* 1021 * Create a new array with elements filled from registers. 1022 * 1023 * for: filled-new-array, filled-new-array/range 1024 */ 1025 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1026 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1027 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1028 FETCH(r1, 1) @ r1<- BBBB 1029 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1030 EXPORT_PC() @ need for resolve and alloc 1031 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1032 mov r10, rINST, lsr #8 @ r10<- AA or BA 1033 cmp r0, #0 @ already resolved? 1034 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10358: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1036 mov r2, #0 @ r2<- false 1037 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1038 bl dvmResolveClass @ r0<- call(clazz, ref) 1039 cmp r0, #0 @ got null? 1040 beq common_exceptionThrown @ yes, handle exception 1041 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1042 1043 1044/* ------------------------------ */ 1045 .balign 64 1046.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1047/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1048 /* fill-array-data vAA, +BBBBBBBB */ 1049 FETCH(r0, 1) @ r0<- bbbb (lo) 1050 FETCH(r1, 2) @ r1<- BBBB (hi) 1051 mov r3, rINST, lsr #8 @ r3<- AA 1052 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1053 GET_VREG(r0, r3) @ r0<- vAA (array object) 1054 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1055 EXPORT_PC(); 1056 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1057 cmp r0, #0 @ 0 means an exception is thrown 1058 beq common_exceptionThrown @ has exception 1059 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1060 GET_INST_OPCODE(ip) @ extract opcode from rINST 1061 GOTO_OPCODE(ip) @ jump to next instruction 1062 1063/* ------------------------------ */ 1064 .balign 64 1065.L_OP_THROW: /* 0x27 */ 1066/* File: armv5te/OP_THROW.S */ 1067 /* 1068 * Throw an exception object in the current thread. 1069 */ 1070 /* throw vAA */ 1071 mov r2, rINST, lsr #8 @ r2<- AA 1072 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1073 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1074 cmp r1, #0 @ null object? 1075 beq common_errNullObject @ yes, throw an NPE instead 1076 @ bypass dvmSetException, just store it 1077 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1078 b common_exceptionThrown 1079 1080 1081/* ------------------------------ */ 1082 .balign 64 1083.L_OP_GOTO: /* 0x28 */ 1084/* File: armv5te/OP_GOTO.S */ 1085 /* 1086 * Unconditional branch, 8-bit offset. 1087 * 1088 * The branch distance is a signed code-unit offset, which we need to 1089 * double to get a byte offset. 1090 */ 1091 /* goto +AA */ 1092 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1093 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1094 mov r9, r9, lsl #1 @ r9<- byte offset 1095 bmi common_backwardBranch @ backward branch, do periodic checks 1096 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1097 GET_INST_OPCODE(ip) @ extract opcode from rINST 1098 GOTO_OPCODE(ip) @ jump to next instruction 1099 1100 1101/* ------------------------------ */ 1102 .balign 64 1103.L_OP_GOTO_16: /* 0x29 */ 1104/* File: armv5te/OP_GOTO_16.S */ 1105 /* 1106 * Unconditional branch, 16-bit offset. 1107 * 1108 * The branch distance is a signed code-unit offset, which we need to 1109 * double to get a byte offset. 1110 */ 1111 /* goto/16 +AAAA */ 1112 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1113 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1114 bmi common_backwardBranch @ backward branch, do periodic checks 1115 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1116 GET_INST_OPCODE(ip) @ extract opcode from rINST 1117 GOTO_OPCODE(ip) @ jump to next instruction 1118 1119 1120/* ------------------------------ */ 1121 .balign 64 1122.L_OP_GOTO_32: /* 0x2a */ 1123/* File: armv5te/OP_GOTO_32.S */ 1124 /* 1125 * Unconditional branch, 32-bit offset. 1126 * 1127 * The branch distance is a signed code-unit offset, which we need to 1128 * double to get a byte offset. 1129 * 1130 * Unlike most opcodes, this one is allowed to branch to itself, so 1131 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1132 * instruction doesn't affect the V flag, so we need to clear it 1133 * explicitly. 1134 */ 1135 /* goto/32 +AAAAAAAA */ 1136 FETCH(r0, 1) @ r0<- aaaa (lo) 1137 FETCH(r1, 2) @ r1<- AAAA (hi) 1138 cmp ip, ip @ (clear V flag during stall) 1139 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1140 mov r9, r0, asl #1 @ r9<- byte offset 1141 ble common_backwardBranch @ backward branch, do periodic checks 1142 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1143 GET_INST_OPCODE(ip) @ extract opcode from rINST 1144 GOTO_OPCODE(ip) @ jump to next instruction 1145 1146 1147/* ------------------------------ */ 1148 .balign 64 1149.L_OP_PACKED_SWITCH: /* 0x2b */ 1150/* File: armv5te/OP_PACKED_SWITCH.S */ 1151 /* 1152 * Handle a packed-switch or sparse-switch instruction. In both cases 1153 * we decode it and hand it off to a helper function. 1154 * 1155 * We don't really expect backward branches in a switch statement, but 1156 * they're perfectly legal, so we check for them here. 1157 * 1158 * for: packed-switch, sparse-switch 1159 */ 1160 /* op vAA, +BBBB */ 1161 FETCH(r0, 1) @ r0<- bbbb (lo) 1162 FETCH(r1, 2) @ r1<- BBBB (hi) 1163 mov r3, rINST, lsr #8 @ r3<- AA 1164 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1165 GET_VREG(r1, r3) @ r1<- vAA 1166 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1167 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1168 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1169 bmi common_backwardBranch @ backward branch, do periodic checks 1170 beq common_backwardBranch @ (want to use BLE but V is unknown) 1171 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1172 GET_INST_OPCODE(ip) @ extract opcode from rINST 1173 GOTO_OPCODE(ip) @ jump to next instruction 1174 1175 1176/* ------------------------------ */ 1177 .balign 64 1178.L_OP_SPARSE_SWITCH: /* 0x2c */ 1179/* File: armv5te/OP_SPARSE_SWITCH.S */ 1180/* File: armv5te/OP_PACKED_SWITCH.S */ 1181 /* 1182 * Handle a packed-switch or sparse-switch instruction. In both cases 1183 * we decode it and hand it off to a helper function. 1184 * 1185 * We don't really expect backward branches in a switch statement, but 1186 * they're perfectly legal, so we check for them here. 1187 * 1188 * for: packed-switch, sparse-switch 1189 */ 1190 /* op vAA, +BBBB */ 1191 FETCH(r0, 1) @ r0<- bbbb (lo) 1192 FETCH(r1, 2) @ r1<- BBBB (hi) 1193 mov r3, rINST, lsr #8 @ r3<- AA 1194 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1195 GET_VREG(r1, r3) @ r1<- vAA 1196 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1197 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1198 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1199 bmi common_backwardBranch @ backward branch, do periodic checks 1200 beq common_backwardBranch @ (want to use BLE but V is unknown) 1201 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1202 GET_INST_OPCODE(ip) @ extract opcode from rINST 1203 GOTO_OPCODE(ip) @ jump to next instruction 1204 1205 1206 1207/* ------------------------------ */ 1208 .balign 64 1209.L_OP_CMPL_FLOAT: /* 0x2d */ 1210/* File: armv5te/OP_CMPL_FLOAT.S */ 1211 /* 1212 * Compare two floating-point values. Puts 0, 1, or -1 into the 1213 * destination register based on the results of the comparison. 1214 * 1215 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1216 * on what value we'd like to return when one of the operands is NaN. 1217 * 1218 * The operation we're implementing is: 1219 * if (x == y) 1220 * return 0; 1221 * else if (x < y) 1222 * return -1; 1223 * else if (x > y) 1224 * return 1; 1225 * else 1226 * return {-1,1}; // one or both operands was NaN 1227 * 1228 * The straightforward implementation requires 3 calls to functions 1229 * that return a result in r0. We can do it with two calls if our 1230 * EABI library supports __aeabi_cfcmple (only one if we want to check 1231 * for NaN directly): 1232 * check x <= y 1233 * if <, return -1 1234 * if ==, return 0 1235 * check y <= x 1236 * if <, return 1 1237 * return {-1,1} 1238 * 1239 * for: cmpl-float, cmpg-float 1240 */ 1241 /* op vAA, vBB, vCC */ 1242 FETCH(r0, 1) @ r0<- CCBB 1243 and r2, r0, #255 @ r2<- BB 1244 mov r3, r0, lsr #8 @ r3<- CC 1245 GET_VREG(r9, r2) @ r9<- vBB 1246 GET_VREG(r10, r3) @ r10<- vCC 1247 mov r0, r9 @ copy to arg registers 1248 mov r1, r10 1249 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1250 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1251 mvncc r1, #0 @ (less than) r1<- -1 1252 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1253.LOP_CMPL_FLOAT_finish: 1254 mov r3, rINST, lsr #8 @ r3<- AA 1255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1256 SET_VREG(r1, r3) @ vAA<- r1 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 GOTO_OPCODE(ip) @ jump to next instruction 1259 1260/* ------------------------------ */ 1261 .balign 64 1262.L_OP_CMPG_FLOAT: /* 0x2e */ 1263/* File: armv5te/OP_CMPG_FLOAT.S */ 1264/* File: armv5te/OP_CMPL_FLOAT.S */ 1265 /* 1266 * Compare two floating-point values. Puts 0, 1, or -1 into the 1267 * destination register based on the results of the comparison. 1268 * 1269 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1270 * on what value we'd like to return when one of the operands is NaN. 1271 * 1272 * The operation we're implementing is: 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,1}; // one or both operands was NaN 1281 * 1282 * The straightforward implementation requires 3 calls to functions 1283 * that return a result in r0. We can do it with two calls if our 1284 * EABI library supports __aeabi_cfcmple (only one if we want to check 1285 * for NaN directly): 1286 * check x <= y 1287 * if <, return -1 1288 * if ==, return 0 1289 * check y <= x 1290 * if <, return 1 1291 * return {-1,1} 1292 * 1293 * for: cmpl-float, cmpg-float 1294 */ 1295 /* op vAA, vBB, vCC */ 1296 FETCH(r0, 1) @ r0<- CCBB 1297 and r2, r0, #255 @ r2<- BB 1298 mov r3, r0, lsr #8 @ r3<- CC 1299 GET_VREG(r9, r2) @ r9<- vBB 1300 GET_VREG(r10, r3) @ r10<- vCC 1301 mov r0, r9 @ copy to arg registers 1302 mov r1, r10 1303 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 1304 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 1305 mvncc r1, #0 @ (less than) r1<- -1 1306 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1307.LOP_CMPG_FLOAT_finish: 1308 mov r3, rINST, lsr #8 @ r3<- AA 1309 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1310 SET_VREG(r1, r3) @ vAA<- r1 1311 GET_INST_OPCODE(ip) @ extract opcode from rINST 1312 GOTO_OPCODE(ip) @ jump to next instruction 1313 1314 1315/* ------------------------------ */ 1316 .balign 64 1317.L_OP_CMPL_DOUBLE: /* 0x2f */ 1318/* File: armv5te/OP_CMPL_DOUBLE.S */ 1319 /* 1320 * Compare two floating-point values. Puts 0, 1, or -1 into the 1321 * destination register based on the results of the comparison. 1322 * 1323 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1324 * on what value we'd like to return when one of the operands is NaN. 1325 * 1326 * See OP_CMPL_FLOAT for an explanation. 1327 * 1328 * For: cmpl-double, cmpg-double 1329 */ 1330 /* op vAA, vBB, vCC */ 1331 FETCH(r0, 1) @ r0<- CCBB 1332 and r9, r0, #255 @ r9<- BB 1333 mov r10, r0, lsr #8 @ r10<- CC 1334 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1335 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1336 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1337 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1338 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1339 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1340 mvncc r1, #0 @ (less than) r1<- -1 1341 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1342.LOP_CMPL_DOUBLE_finish: 1343 mov r3, rINST, lsr #8 @ r3<- AA 1344 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1345 SET_VREG(r1, r3) @ vAA<- r1 1346 GET_INST_OPCODE(ip) @ extract opcode from rINST 1347 GOTO_OPCODE(ip) @ jump to next instruction 1348 1349/* ------------------------------ */ 1350 .balign 64 1351.L_OP_CMPG_DOUBLE: /* 0x30 */ 1352/* File: armv5te/OP_CMPG_DOUBLE.S */ 1353/* File: armv5te/OP_CMPL_DOUBLE.S */ 1354 /* 1355 * Compare two floating-point values. Puts 0, 1, or -1 into the 1356 * destination register based on the results of the comparison. 1357 * 1358 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 1359 * on what value we'd like to return when one of the operands is NaN. 1360 * 1361 * See OP_CMPL_FLOAT for an explanation. 1362 * 1363 * For: cmpl-double, cmpg-double 1364 */ 1365 /* op vAA, vBB, vCC */ 1366 FETCH(r0, 1) @ r0<- CCBB 1367 and r9, r0, #255 @ r9<- BB 1368 mov r10, r0, lsr #8 @ r10<- CC 1369 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB] 1370 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC] 1371 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1 1372 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1 1373 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq 1374 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 1375 mvncc r1, #0 @ (less than) r1<- -1 1376 moveq r1, #0 @ (equal) r1<- 0, trumps less than 1377.LOP_CMPG_DOUBLE_finish: 1378 mov r3, rINST, lsr #8 @ r3<- AA 1379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1380 SET_VREG(r1, r3) @ vAA<- r1 1381 GET_INST_OPCODE(ip) @ extract opcode from rINST 1382 GOTO_OPCODE(ip) @ jump to next instruction 1383 1384 1385/* ------------------------------ */ 1386 .balign 64 1387.L_OP_CMP_LONG: /* 0x31 */ 1388/* File: armv5te/OP_CMP_LONG.S */ 1389 /* 1390 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1391 * register based on the results of the comparison. 1392 * 1393 * We load the full values with LDM, but in practice many values could 1394 * be resolved by only looking at the high word. This could be made 1395 * faster or slower by splitting the LDM into a pair of LDRs. 1396 * 1397 * If we just wanted to set condition flags, we could do this: 1398 * subs ip, r0, r2 1399 * sbcs ip, r1, r3 1400 * subeqs ip, r0, r2 1401 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1402 * integer value, which we can do with 2 conditional mov/mvn instructions 1403 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1404 * us a constant 5-cycle path plus a branch at the end to the 1405 * instruction epilogue code. The multi-compare approach below needs 1406 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1407 * in the worst case (the 64-bit values are equal). 1408 */ 1409 /* cmp-long vAA, vBB, vCC */ 1410 FETCH(r0, 1) @ r0<- CCBB 1411 mov r9, rINST, lsr #8 @ r9<- AA 1412 and r2, r0, #255 @ r2<- BB 1413 mov r3, r0, lsr #8 @ r3<- CC 1414 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1415 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1416 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1417 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1418 cmp r1, r3 @ compare (vBB+1, vCC+1) 1419 blt .LOP_CMP_LONG_less @ signed compare on high part 1420 bgt .LOP_CMP_LONG_greater 1421 subs r1, r0, r2 @ r1<- r0 - r2 1422 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1423 bne .LOP_CMP_LONG_less 1424 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1425 1426/* ------------------------------ */ 1427 .balign 64 1428.L_OP_IF_EQ: /* 0x32 */ 1429/* File: armv5te/OP_IF_EQ.S */ 1430/* File: armv5te/bincmp.S */ 1431 /* 1432 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1433 * fragment that specifies the *reverse* comparison to perform, e.g. 1434 * for "if-le" you would use "gt". 1435 * 1436 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1437 */ 1438 /* if-cmp vA, vB, +CCCC */ 1439 mov r0, rINST, lsr #8 @ r0<- A+ 1440 mov r1, rINST, lsr #12 @ r1<- B 1441 and r0, r0, #15 1442 GET_VREG(r3, r1) @ r3<- vB 1443 GET_VREG(r2, r0) @ r2<- vA 1444 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1445 cmp r2, r3 @ compare (vA, vB) 1446 bne 1f @ branch to 1 if comparison failed 1447 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1448 movs r9, r9, asl #1 @ convert to bytes, check sign 1449 bmi common_backwardBranch @ yes, do periodic checks 14501: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1451 GET_INST_OPCODE(ip) @ extract opcode from rINST 1452 GOTO_OPCODE(ip) @ jump to next instruction 1453 1454 1455 1456/* ------------------------------ */ 1457 .balign 64 1458.L_OP_IF_NE: /* 0x33 */ 1459/* File: armv5te/OP_IF_NE.S */ 1460/* File: armv5te/bincmp.S */ 1461 /* 1462 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1463 * fragment that specifies the *reverse* comparison to perform, e.g. 1464 * for "if-le" you would use "gt". 1465 * 1466 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1467 */ 1468 /* if-cmp vA, vB, +CCCC */ 1469 mov r0, rINST, lsr #8 @ r0<- A+ 1470 mov r1, rINST, lsr #12 @ r1<- B 1471 and r0, r0, #15 1472 GET_VREG(r3, r1) @ r3<- vB 1473 GET_VREG(r2, r0) @ r2<- vA 1474 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1475 cmp r2, r3 @ compare (vA, vB) 1476 beq 1f @ branch to 1 if comparison failed 1477 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1478 movs r9, r9, asl #1 @ convert to bytes, check sign 1479 bmi common_backwardBranch @ yes, do periodic checks 14801: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1481 GET_INST_OPCODE(ip) @ extract opcode from rINST 1482 GOTO_OPCODE(ip) @ jump to next instruction 1483 1484 1485 1486/* ------------------------------ */ 1487 .balign 64 1488.L_OP_IF_LT: /* 0x34 */ 1489/* File: armv5te/OP_IF_LT.S */ 1490/* File: armv5te/bincmp.S */ 1491 /* 1492 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1493 * fragment that specifies the *reverse* comparison to perform, e.g. 1494 * for "if-le" you would use "gt". 1495 * 1496 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1497 */ 1498 /* if-cmp vA, vB, +CCCC */ 1499 mov r0, rINST, lsr #8 @ r0<- A+ 1500 mov r1, rINST, lsr #12 @ r1<- B 1501 and r0, r0, #15 1502 GET_VREG(r3, r1) @ r3<- vB 1503 GET_VREG(r2, r0) @ r2<- vA 1504 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1505 cmp r2, r3 @ compare (vA, vB) 1506 bge 1f @ branch to 1 if comparison failed 1507 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1508 movs r9, r9, asl #1 @ convert to bytes, check sign 1509 bmi common_backwardBranch @ yes, do periodic checks 15101: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1511 GET_INST_OPCODE(ip) @ extract opcode from rINST 1512 GOTO_OPCODE(ip) @ jump to next instruction 1513 1514 1515 1516/* ------------------------------ */ 1517 .balign 64 1518.L_OP_IF_GE: /* 0x35 */ 1519/* File: armv5te/OP_IF_GE.S */ 1520/* File: armv5te/bincmp.S */ 1521 /* 1522 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1523 * fragment that specifies the *reverse* comparison to perform, e.g. 1524 * for "if-le" you would use "gt". 1525 * 1526 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1527 */ 1528 /* if-cmp vA, vB, +CCCC */ 1529 mov r0, rINST, lsr #8 @ r0<- A+ 1530 mov r1, rINST, lsr #12 @ r1<- B 1531 and r0, r0, #15 1532 GET_VREG(r3, r1) @ r3<- vB 1533 GET_VREG(r2, r0) @ r2<- vA 1534 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1535 cmp r2, r3 @ compare (vA, vB) 1536 blt 1f @ branch to 1 if comparison failed 1537 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1538 movs r9, r9, asl #1 @ convert to bytes, check sign 1539 bmi common_backwardBranch @ yes, do periodic checks 15401: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1541 GET_INST_OPCODE(ip) @ extract opcode from rINST 1542 GOTO_OPCODE(ip) @ jump to next instruction 1543 1544 1545 1546/* ------------------------------ */ 1547 .balign 64 1548.L_OP_IF_GT: /* 0x36 */ 1549/* File: armv5te/OP_IF_GT.S */ 1550/* File: armv5te/bincmp.S */ 1551 /* 1552 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1553 * fragment that specifies the *reverse* comparison to perform, e.g. 1554 * for "if-le" you would use "gt". 1555 * 1556 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1557 */ 1558 /* if-cmp vA, vB, +CCCC */ 1559 mov r0, rINST, lsr #8 @ r0<- A+ 1560 mov r1, rINST, lsr #12 @ r1<- B 1561 and r0, r0, #15 1562 GET_VREG(r3, r1) @ r3<- vB 1563 GET_VREG(r2, r0) @ r2<- vA 1564 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1565 cmp r2, r3 @ compare (vA, vB) 1566 ble 1f @ branch to 1 if comparison failed 1567 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1568 movs r9, r9, asl #1 @ convert to bytes, check sign 1569 bmi common_backwardBranch @ yes, do periodic checks 15701: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1571 GET_INST_OPCODE(ip) @ extract opcode from rINST 1572 GOTO_OPCODE(ip) @ jump to next instruction 1573 1574 1575 1576/* ------------------------------ */ 1577 .balign 64 1578.L_OP_IF_LE: /* 0x37 */ 1579/* File: armv5te/OP_IF_LE.S */ 1580/* File: armv5te/bincmp.S */ 1581 /* 1582 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1583 * fragment that specifies the *reverse* comparison to perform, e.g. 1584 * for "if-le" you would use "gt". 1585 * 1586 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1587 */ 1588 /* if-cmp vA, vB, +CCCC */ 1589 mov r0, rINST, lsr #8 @ r0<- A+ 1590 mov r1, rINST, lsr #12 @ r1<- B 1591 and r0, r0, #15 1592 GET_VREG(r3, r1) @ r3<- vB 1593 GET_VREG(r2, r0) @ r2<- vA 1594 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1595 cmp r2, r3 @ compare (vA, vB) 1596 bgt 1f @ branch to 1 if comparison failed 1597 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1598 movs r9, r9, asl #1 @ convert to bytes, check sign 1599 bmi common_backwardBranch @ yes, do periodic checks 16001: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1601 GET_INST_OPCODE(ip) @ extract opcode from rINST 1602 GOTO_OPCODE(ip) @ jump to next instruction 1603 1604 1605 1606/* ------------------------------ */ 1607 .balign 64 1608.L_OP_IF_EQZ: /* 0x38 */ 1609/* File: armv5te/OP_IF_EQZ.S */ 1610/* File: armv5te/zcmp.S */ 1611 /* 1612 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1613 * fragment that specifies the *reverse* comparison to perform, e.g. 1614 * for "if-le" you would use "gt". 1615 * 1616 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1617 */ 1618 /* if-cmp vAA, +BBBB */ 1619 mov r0, rINST, lsr #8 @ r0<- AA 1620 GET_VREG(r2, r0) @ r2<- vAA 1621 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1622 cmp r2, #0 @ compare (vA, 0) 1623 bne 1f @ branch to 1 if comparison failed 1624 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1625 movs r9, r9, asl #1 @ convert to bytes, check sign 1626 bmi common_backwardBranch @ backward branch, do periodic checks 16271: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1628 GET_INST_OPCODE(ip) @ extract opcode from rINST 1629 GOTO_OPCODE(ip) @ jump to next instruction 1630 1631 1632 1633/* ------------------------------ */ 1634 .balign 64 1635.L_OP_IF_NEZ: /* 0x39 */ 1636/* File: armv5te/OP_IF_NEZ.S */ 1637/* File: armv5te/zcmp.S */ 1638 /* 1639 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1640 * fragment that specifies the *reverse* comparison to perform, e.g. 1641 * for "if-le" you would use "gt". 1642 * 1643 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1644 */ 1645 /* if-cmp vAA, +BBBB */ 1646 mov r0, rINST, lsr #8 @ r0<- AA 1647 GET_VREG(r2, r0) @ r2<- vAA 1648 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1649 cmp r2, #0 @ compare (vA, 0) 1650 beq 1f @ branch to 1 if comparison failed 1651 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1652 movs r9, r9, asl #1 @ convert to bytes, check sign 1653 bmi common_backwardBranch @ backward branch, do periodic checks 16541: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1655 GET_INST_OPCODE(ip) @ extract opcode from rINST 1656 GOTO_OPCODE(ip) @ jump to next instruction 1657 1658 1659 1660/* ------------------------------ */ 1661 .balign 64 1662.L_OP_IF_LTZ: /* 0x3a */ 1663/* File: armv5te/OP_IF_LTZ.S */ 1664/* File: armv5te/zcmp.S */ 1665 /* 1666 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1667 * fragment that specifies the *reverse* comparison to perform, e.g. 1668 * for "if-le" you would use "gt". 1669 * 1670 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1671 */ 1672 /* if-cmp vAA, +BBBB */ 1673 mov r0, rINST, lsr #8 @ r0<- AA 1674 GET_VREG(r2, r0) @ r2<- vAA 1675 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1676 cmp r2, #0 @ compare (vA, 0) 1677 bge 1f @ branch to 1 if comparison failed 1678 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1679 movs r9, r9, asl #1 @ convert to bytes, check sign 1680 bmi common_backwardBranch @ backward branch, do periodic checks 16811: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1682 GET_INST_OPCODE(ip) @ extract opcode from rINST 1683 GOTO_OPCODE(ip) @ jump to next instruction 1684 1685 1686 1687/* ------------------------------ */ 1688 .balign 64 1689.L_OP_IF_GEZ: /* 0x3b */ 1690/* File: armv5te/OP_IF_GEZ.S */ 1691/* File: armv5te/zcmp.S */ 1692 /* 1693 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1694 * fragment that specifies the *reverse* comparison to perform, e.g. 1695 * for "if-le" you would use "gt". 1696 * 1697 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1698 */ 1699 /* if-cmp vAA, +BBBB */ 1700 mov r0, rINST, lsr #8 @ r0<- AA 1701 GET_VREG(r2, r0) @ r2<- vAA 1702 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1703 cmp r2, #0 @ compare (vA, 0) 1704 blt 1f @ branch to 1 if comparison failed 1705 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1706 movs r9, r9, asl #1 @ convert to bytes, check sign 1707 bmi common_backwardBranch @ backward branch, do periodic checks 17081: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1709 GET_INST_OPCODE(ip) @ extract opcode from rINST 1710 GOTO_OPCODE(ip) @ jump to next instruction 1711 1712 1713 1714/* ------------------------------ */ 1715 .balign 64 1716.L_OP_IF_GTZ: /* 0x3c */ 1717/* File: armv5te/OP_IF_GTZ.S */ 1718/* File: armv5te/zcmp.S */ 1719 /* 1720 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1721 * fragment that specifies the *reverse* comparison to perform, e.g. 1722 * for "if-le" you would use "gt". 1723 * 1724 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1725 */ 1726 /* if-cmp vAA, +BBBB */ 1727 mov r0, rINST, lsr #8 @ r0<- AA 1728 GET_VREG(r2, r0) @ r2<- vAA 1729 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1730 cmp r2, #0 @ compare (vA, 0) 1731 ble 1f @ branch to 1 if comparison failed 1732 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1733 movs r9, r9, asl #1 @ convert to bytes, check sign 1734 bmi common_backwardBranch @ backward branch, do periodic checks 17351: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1736 GET_INST_OPCODE(ip) @ extract opcode from rINST 1737 GOTO_OPCODE(ip) @ jump to next instruction 1738 1739 1740 1741/* ------------------------------ */ 1742 .balign 64 1743.L_OP_IF_LEZ: /* 0x3d */ 1744/* File: armv5te/OP_IF_LEZ.S */ 1745/* File: armv5te/zcmp.S */ 1746 /* 1747 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1748 * fragment that specifies the *reverse* comparison to perform, e.g. 1749 * for "if-le" you would use "gt". 1750 * 1751 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1752 */ 1753 /* if-cmp vAA, +BBBB */ 1754 mov r0, rINST, lsr #8 @ r0<- AA 1755 GET_VREG(r2, r0) @ r2<- vAA 1756 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1757 cmp r2, #0 @ compare (vA, 0) 1758 bgt 1f @ branch to 1 if comparison failed 1759 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1760 movs r9, r9, asl #1 @ convert to bytes, check sign 1761 bmi common_backwardBranch @ backward branch, do periodic checks 17621: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1763 GET_INST_OPCODE(ip) @ extract opcode from rINST 1764 GOTO_OPCODE(ip) @ jump to next instruction 1765 1766 1767 1768/* ------------------------------ */ 1769 .balign 64 1770.L_OP_UNUSED_3E: /* 0x3e */ 1771/* File: armv5te/OP_UNUSED_3E.S */ 1772/* File: armv5te/unused.S */ 1773 bl common_abort 1774 1775 1776 1777/* ------------------------------ */ 1778 .balign 64 1779.L_OP_UNUSED_3F: /* 0x3f */ 1780/* File: armv5te/OP_UNUSED_3F.S */ 1781/* File: armv5te/unused.S */ 1782 bl common_abort 1783 1784 1785 1786/* ------------------------------ */ 1787 .balign 64 1788.L_OP_UNUSED_40: /* 0x40 */ 1789/* File: armv5te/OP_UNUSED_40.S */ 1790/* File: armv5te/unused.S */ 1791 bl common_abort 1792 1793 1794 1795/* ------------------------------ */ 1796 .balign 64 1797.L_OP_UNUSED_41: /* 0x41 */ 1798/* File: armv5te/OP_UNUSED_41.S */ 1799/* File: armv5te/unused.S */ 1800 bl common_abort 1801 1802 1803 1804/* ------------------------------ */ 1805 .balign 64 1806.L_OP_UNUSED_42: /* 0x42 */ 1807/* File: armv5te/OP_UNUSED_42.S */ 1808/* File: armv5te/unused.S */ 1809 bl common_abort 1810 1811 1812 1813/* ------------------------------ */ 1814 .balign 64 1815.L_OP_UNUSED_43: /* 0x43 */ 1816/* File: armv5te/OP_UNUSED_43.S */ 1817/* File: armv5te/unused.S */ 1818 bl common_abort 1819 1820 1821 1822/* ------------------------------ */ 1823 .balign 64 1824.L_OP_AGET: /* 0x44 */ 1825/* File: armv5te/OP_AGET.S */ 1826 /* 1827 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1828 * 1829 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1830 * instructions. We use a pair of FETCH_Bs instead. 1831 * 1832 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1833 */ 1834 /* op vAA, vBB, vCC */ 1835 FETCH_B(r2, 1, 0) @ r2<- BB 1836 mov r9, rINST, lsr #8 @ r9<- AA 1837 FETCH_B(r3, 1, 1) @ r3<- CC 1838 GET_VREG(r0, r2) @ r0<- vBB (array object) 1839 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1840 cmp r0, #0 @ null array object? 1841 beq common_errNullObject @ yes, bail 1842 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1843 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1844 cmp r1, r3 @ compare unsigned index, length 1845 bcs common_errArrayIndex @ index >= length, bail 1846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1847 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1848 GET_INST_OPCODE(ip) @ extract opcode from rINST 1849 SET_VREG(r2, r9) @ vAA<- r2 1850 GOTO_OPCODE(ip) @ jump to next instruction 1851 1852 1853/* ------------------------------ */ 1854 .balign 64 1855.L_OP_AGET_WIDE: /* 0x45 */ 1856/* File: armv5te/OP_AGET_WIDE.S */ 1857 /* 1858 * Array get, 64 bits. vAA <- vBB[vCC]. 1859 * 1860 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1861 */ 1862 /* aget-wide vAA, vBB, vCC */ 1863 FETCH(r0, 1) @ r0<- CCBB 1864 mov r9, rINST, lsr #8 @ r9<- AA 1865 and r2, r0, #255 @ r2<- BB 1866 mov r3, r0, lsr #8 @ r3<- CC 1867 GET_VREG(r0, r2) @ r0<- vBB (array object) 1868 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1869 cmp r0, #0 @ null array object? 1870 beq common_errNullObject @ yes, bail 1871 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1872 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 1873 cmp r1, r3 @ compare unsigned index, length 1874 bcc .LOP_AGET_WIDE_finish @ okay, continue below 1875 b common_errArrayIndex @ index >= length, bail 1876 @ May want to swap the order of these two branches depending on how the 1877 @ branch prediction (if any) handles conditional forward branches vs. 1878 @ unconditional forward branches. 1879 1880/* ------------------------------ */ 1881 .balign 64 1882.L_OP_AGET_OBJECT: /* 0x46 */ 1883/* File: armv5te/OP_AGET_OBJECT.S */ 1884/* File: armv5te/OP_AGET.S */ 1885 /* 1886 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1887 * 1888 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1889 * instructions. We use a pair of FETCH_Bs instead. 1890 * 1891 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1892 */ 1893 /* op vAA, vBB, vCC */ 1894 FETCH_B(r2, 1, 0) @ r2<- BB 1895 mov r9, rINST, lsr #8 @ r9<- AA 1896 FETCH_B(r3, 1, 1) @ r3<- CC 1897 GET_VREG(r0, r2) @ r0<- vBB (array object) 1898 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1899 cmp r0, #0 @ null array object? 1900 beq common_errNullObject @ yes, bail 1901 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1902 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1903 cmp r1, r3 @ compare unsigned index, length 1904 bcs common_errArrayIndex @ index >= length, bail 1905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1906 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1907 GET_INST_OPCODE(ip) @ extract opcode from rINST 1908 SET_VREG(r2, r9) @ vAA<- r2 1909 GOTO_OPCODE(ip) @ jump to next instruction 1910 1911 1912 1913/* ------------------------------ */ 1914 .balign 64 1915.L_OP_AGET_BOOLEAN: /* 0x47 */ 1916/* File: armv5te/OP_AGET_BOOLEAN.S */ 1917/* File: armv5te/OP_AGET.S */ 1918 /* 1919 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1920 * 1921 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1922 * instructions. We use a pair of FETCH_Bs instead. 1923 * 1924 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1925 */ 1926 /* op vAA, vBB, vCC */ 1927 FETCH_B(r2, 1, 0) @ r2<- BB 1928 mov r9, rINST, lsr #8 @ r9<- AA 1929 FETCH_B(r3, 1, 1) @ r3<- CC 1930 GET_VREG(r0, r2) @ r0<- vBB (array object) 1931 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1932 cmp r0, #0 @ null array object? 1933 beq common_errNullObject @ yes, bail 1934 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1935 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1936 cmp r1, r3 @ compare unsigned index, length 1937 bcs common_errArrayIndex @ index >= length, bail 1938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1939 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1940 GET_INST_OPCODE(ip) @ extract opcode from rINST 1941 SET_VREG(r2, r9) @ vAA<- r2 1942 GOTO_OPCODE(ip) @ jump to next instruction 1943 1944 1945 1946/* ------------------------------ */ 1947 .balign 64 1948.L_OP_AGET_BYTE: /* 0x48 */ 1949/* File: armv5te/OP_AGET_BYTE.S */ 1950/* File: armv5te/OP_AGET.S */ 1951 /* 1952 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1953 * 1954 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1955 * instructions. We use a pair of FETCH_Bs instead. 1956 * 1957 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1958 */ 1959 /* op vAA, vBB, vCC */ 1960 FETCH_B(r2, 1, 0) @ r2<- BB 1961 mov r9, rINST, lsr #8 @ r9<- AA 1962 FETCH_B(r3, 1, 1) @ r3<- CC 1963 GET_VREG(r0, r2) @ r0<- vBB (array object) 1964 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1965 cmp r0, #0 @ null array object? 1966 beq common_errNullObject @ yes, bail 1967 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1968 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 1969 cmp r1, r3 @ compare unsigned index, length 1970 bcs common_errArrayIndex @ index >= length, bail 1971 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1972 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1973 GET_INST_OPCODE(ip) @ extract opcode from rINST 1974 SET_VREG(r2, r9) @ vAA<- r2 1975 GOTO_OPCODE(ip) @ jump to next instruction 1976 1977 1978 1979/* ------------------------------ */ 1980 .balign 64 1981.L_OP_AGET_CHAR: /* 0x49 */ 1982/* File: armv5te/OP_AGET_CHAR.S */ 1983/* File: armv5te/OP_AGET.S */ 1984 /* 1985 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1986 * 1987 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1988 * instructions. We use a pair of FETCH_Bs instead. 1989 * 1990 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1991 */ 1992 /* op vAA, vBB, vCC */ 1993 FETCH_B(r2, 1, 0) @ r2<- BB 1994 mov r9, rINST, lsr #8 @ r9<- AA 1995 FETCH_B(r3, 1, 1) @ r3<- CC 1996 GET_VREG(r0, r2) @ r0<- vBB (array object) 1997 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1998 cmp r0, #0 @ null array object? 1999 beq common_errNullObject @ yes, bail 2000 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2001 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2002 cmp r1, r3 @ compare unsigned index, length 2003 bcs common_errArrayIndex @ index >= length, bail 2004 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2005 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2006 GET_INST_OPCODE(ip) @ extract opcode from rINST 2007 SET_VREG(r2, r9) @ vAA<- r2 2008 GOTO_OPCODE(ip) @ jump to next instruction 2009 2010 2011 2012/* ------------------------------ */ 2013 .balign 64 2014.L_OP_AGET_SHORT: /* 0x4a */ 2015/* File: armv5te/OP_AGET_SHORT.S */ 2016/* File: armv5te/OP_AGET.S */ 2017 /* 2018 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2019 * 2020 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2021 * instructions. We use a pair of FETCH_Bs instead. 2022 * 2023 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2024 */ 2025 /* op vAA, vBB, vCC */ 2026 FETCH_B(r2, 1, 0) @ r2<- BB 2027 mov r9, rINST, lsr #8 @ r9<- AA 2028 FETCH_B(r3, 1, 1) @ r3<- CC 2029 GET_VREG(r0, r2) @ r0<- vBB (array object) 2030 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2031 cmp r0, #0 @ null array object? 2032 beq common_errNullObject @ yes, bail 2033 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2034 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2035 cmp r1, r3 @ compare unsigned index, length 2036 bcs common_errArrayIndex @ index >= length, bail 2037 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2038 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2039 GET_INST_OPCODE(ip) @ extract opcode from rINST 2040 SET_VREG(r2, r9) @ vAA<- r2 2041 GOTO_OPCODE(ip) @ jump to next instruction 2042 2043 2044 2045/* ------------------------------ */ 2046 .balign 64 2047.L_OP_APUT: /* 0x4b */ 2048/* File: armv5te/OP_APUT.S */ 2049 /* 2050 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2051 * 2052 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2053 * instructions. We use a pair of FETCH_Bs instead. 2054 * 2055 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2056 */ 2057 /* op vAA, vBB, vCC */ 2058 FETCH_B(r2, 1, 0) @ r2<- BB 2059 mov r9, rINST, lsr #8 @ r9<- AA 2060 FETCH_B(r3, 1, 1) @ r3<- CC 2061 GET_VREG(r0, r2) @ r0<- vBB (array object) 2062 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2063 cmp r0, #0 @ null array object? 2064 beq common_errNullObject @ yes, bail 2065 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2066 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2067 cmp r1, r3 @ compare unsigned index, length 2068 bcs common_errArrayIndex @ index >= length, bail 2069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2070 GET_VREG(r2, r9) @ r2<- vAA 2071 GET_INST_OPCODE(ip) @ extract opcode from rINST 2072 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2073 GOTO_OPCODE(ip) @ jump to next instruction 2074 2075 2076/* ------------------------------ */ 2077 .balign 64 2078.L_OP_APUT_WIDE: /* 0x4c */ 2079/* File: armv5te/OP_APUT_WIDE.S */ 2080 /* 2081 * Array put, 64 bits. vBB[vCC] <- vAA. 2082 * 2083 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2084 */ 2085 /* aput-wide vAA, vBB, vCC */ 2086 FETCH(r0, 1) @ r0<- CCBB 2087 mov r9, rINST, lsr #8 @ r9<- AA 2088 and r2, r0, #255 @ r2<- BB 2089 mov r3, r0, lsr #8 @ r3<- CC 2090 GET_VREG(r0, r2) @ r0<- vBB (array object) 2091 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2092 cmp r0, #0 @ null array object? 2093 beq common_errNullObject @ yes, bail 2094 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2095 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2096 cmp r1, r3 @ compare unsigned index, length 2097 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2098 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2099 b common_errArrayIndex @ index >= length, bail 2100 @ May want to swap the order of these two branches depending on how the 2101 @ branch prediction (if any) handles conditional forward branches vs. 2102 @ unconditional forward branches. 2103 2104/* ------------------------------ */ 2105 .balign 64 2106.L_OP_APUT_OBJECT: /* 0x4d */ 2107/* File: armv5te/OP_APUT_OBJECT.S */ 2108 /* 2109 * Store an object into an array. vBB[vCC] <- vAA. 2110 * 2111 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2112 * instructions. We use a pair of FETCH_Bs instead. 2113 */ 2114 /* op vAA, vBB, vCC */ 2115 FETCH(r0, 1) @ r0<- CCBB 2116 mov r9, rINST, lsr #8 @ r9<- AA 2117 and r2, r0, #255 @ r2<- BB 2118 mov r3, r0, lsr #8 @ r3<- CC 2119 GET_VREG(r1, r2) @ r1<- vBB (array object) 2120 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2121 cmp r1, #0 @ null array object? 2122 GET_VREG(r9, r9) @ r9<- vAA 2123 beq common_errNullObject @ yes, bail 2124 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2125 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2126 cmp r0, r3 @ compare unsigned index, length 2127 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2128 b common_errArrayIndex @ index >= length, bail 2129 2130 2131/* ------------------------------ */ 2132 .balign 64 2133.L_OP_APUT_BOOLEAN: /* 0x4e */ 2134/* File: armv5te/OP_APUT_BOOLEAN.S */ 2135/* File: armv5te/OP_APUT.S */ 2136 /* 2137 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2138 * 2139 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2140 * instructions. We use a pair of FETCH_Bs instead. 2141 * 2142 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2143 */ 2144 /* op vAA, vBB, vCC */ 2145 FETCH_B(r2, 1, 0) @ r2<- BB 2146 mov r9, rINST, lsr #8 @ r9<- AA 2147 FETCH_B(r3, 1, 1) @ r3<- CC 2148 GET_VREG(r0, r2) @ r0<- vBB (array object) 2149 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2150 cmp r0, #0 @ null array object? 2151 beq common_errNullObject @ yes, bail 2152 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2153 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2154 cmp r1, r3 @ compare unsigned index, length 2155 bcs common_errArrayIndex @ index >= length, bail 2156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2157 GET_VREG(r2, r9) @ r2<- vAA 2158 GET_INST_OPCODE(ip) @ extract opcode from rINST 2159 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2160 GOTO_OPCODE(ip) @ jump to next instruction 2161 2162 2163 2164/* ------------------------------ */ 2165 .balign 64 2166.L_OP_APUT_BYTE: /* 0x4f */ 2167/* File: armv5te/OP_APUT_BYTE.S */ 2168/* File: armv5te/OP_APUT.S */ 2169 /* 2170 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2171 * 2172 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2173 * instructions. We use a pair of FETCH_Bs instead. 2174 * 2175 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2176 */ 2177 /* op vAA, vBB, vCC */ 2178 FETCH_B(r2, 1, 0) @ r2<- BB 2179 mov r9, rINST, lsr #8 @ r9<- AA 2180 FETCH_B(r3, 1, 1) @ r3<- CC 2181 GET_VREG(r0, r2) @ r0<- vBB (array object) 2182 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2183 cmp r0, #0 @ null array object? 2184 beq common_errNullObject @ yes, bail 2185 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2186 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2187 cmp r1, r3 @ compare unsigned index, length 2188 bcs common_errArrayIndex @ index >= length, bail 2189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2190 GET_VREG(r2, r9) @ r2<- vAA 2191 GET_INST_OPCODE(ip) @ extract opcode from rINST 2192 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2193 GOTO_OPCODE(ip) @ jump to next instruction 2194 2195 2196 2197/* ------------------------------ */ 2198 .balign 64 2199.L_OP_APUT_CHAR: /* 0x50 */ 2200/* File: armv5te/OP_APUT_CHAR.S */ 2201/* File: armv5te/OP_APUT.S */ 2202 /* 2203 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2204 * 2205 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2206 * instructions. We use a pair of FETCH_Bs instead. 2207 * 2208 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2209 */ 2210 /* op vAA, vBB, vCC */ 2211 FETCH_B(r2, 1, 0) @ r2<- BB 2212 mov r9, rINST, lsr #8 @ r9<- AA 2213 FETCH_B(r3, 1, 1) @ r3<- CC 2214 GET_VREG(r0, r2) @ r0<- vBB (array object) 2215 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2216 cmp r0, #0 @ null array object? 2217 beq common_errNullObject @ yes, bail 2218 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2219 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2220 cmp r1, r3 @ compare unsigned index, length 2221 bcs common_errArrayIndex @ index >= length, bail 2222 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2223 GET_VREG(r2, r9) @ r2<- vAA 2224 GET_INST_OPCODE(ip) @ extract opcode from rINST 2225 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2226 GOTO_OPCODE(ip) @ jump to next instruction 2227 2228 2229 2230/* ------------------------------ */ 2231 .balign 64 2232.L_OP_APUT_SHORT: /* 0x51 */ 2233/* File: armv5te/OP_APUT_SHORT.S */ 2234/* File: armv5te/OP_APUT.S */ 2235 /* 2236 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2237 * 2238 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2239 * instructions. We use a pair of FETCH_Bs instead. 2240 * 2241 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2242 */ 2243 /* op vAA, vBB, vCC */ 2244 FETCH_B(r2, 1, 0) @ r2<- BB 2245 mov r9, rINST, lsr #8 @ r9<- AA 2246 FETCH_B(r3, 1, 1) @ r3<- CC 2247 GET_VREG(r0, r2) @ r0<- vBB (array object) 2248 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2249 cmp r0, #0 @ null array object? 2250 beq common_errNullObject @ yes, bail 2251 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2252 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2253 cmp r1, r3 @ compare unsigned index, length 2254 bcs common_errArrayIndex @ index >= length, bail 2255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2256 GET_VREG(r2, r9) @ r2<- vAA 2257 GET_INST_OPCODE(ip) @ extract opcode from rINST 2258 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2259 GOTO_OPCODE(ip) @ jump to next instruction 2260 2261 2262 2263/* ------------------------------ */ 2264 .balign 64 2265.L_OP_IGET: /* 0x52 */ 2266/* File: armv5te/OP_IGET.S */ 2267 /* 2268 * General 32-bit instance field get. 2269 * 2270 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2271 */ 2272 /* op vA, vB, field@CCCC */ 2273 mov r0, rINST, lsr #12 @ r0<- B 2274 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2275 FETCH(r1, 1) @ r1<- field ref CCCC 2276 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2277 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2278 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2279 cmp r0, #0 @ is resolved entry null? 2280 bne .LOP_IGET_finish @ no, already resolved 22818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2282 EXPORT_PC() @ resolve() could throw 2283 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2284 bl dvmResolveInstField @ r0<- resolved InstField ptr 2285 cmp r0, #0 2286 bne .LOP_IGET_finish 2287 b common_exceptionThrown 2288 2289/* ------------------------------ */ 2290 .balign 64 2291.L_OP_IGET_WIDE: /* 0x53 */ 2292/* File: armv5te/OP_IGET_WIDE.S */ 2293 /* 2294 * Wide 32-bit instance field get. 2295 */ 2296 /* iget-wide vA, vB, field@CCCC */ 2297 mov r0, rINST, lsr #12 @ r0<- B 2298 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2299 FETCH(r1, 1) @ r1<- field ref CCCC 2300 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2301 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2302 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2303 cmp r0, #0 @ is resolved entry null? 2304 bne .LOP_IGET_WIDE_finish @ no, already resolved 23058: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2306 EXPORT_PC() @ resolve() could throw 2307 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2308 bl dvmResolveInstField @ r0<- resolved InstField ptr 2309 cmp r0, #0 2310 bne .LOP_IGET_WIDE_finish 2311 b common_exceptionThrown 2312 2313/* ------------------------------ */ 2314 .balign 64 2315.L_OP_IGET_OBJECT: /* 0x54 */ 2316/* File: armv5te/OP_IGET_OBJECT.S */ 2317/* File: armv5te/OP_IGET.S */ 2318 /* 2319 * General 32-bit instance field get. 2320 * 2321 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2322 */ 2323 /* op vA, vB, field@CCCC */ 2324 mov r0, rINST, lsr #12 @ r0<- B 2325 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2326 FETCH(r1, 1) @ r1<- field ref CCCC 2327 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2328 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2329 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2330 cmp r0, #0 @ is resolved entry null? 2331 bne .LOP_IGET_OBJECT_finish @ no, already resolved 23328: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2333 EXPORT_PC() @ resolve() could throw 2334 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2335 bl dvmResolveInstField @ r0<- resolved InstField ptr 2336 cmp r0, #0 2337 bne .LOP_IGET_OBJECT_finish 2338 b common_exceptionThrown 2339 2340 2341/* ------------------------------ */ 2342 .balign 64 2343.L_OP_IGET_BOOLEAN: /* 0x55 */ 2344/* File: armv5te/OP_IGET_BOOLEAN.S */ 2345@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2346/* File: armv5te/OP_IGET.S */ 2347 /* 2348 * General 32-bit instance field get. 2349 * 2350 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2351 */ 2352 /* op vA, vB, field@CCCC */ 2353 mov r0, rINST, lsr #12 @ r0<- B 2354 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2355 FETCH(r1, 1) @ r1<- field ref CCCC 2356 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2357 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2358 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2359 cmp r0, #0 @ is resolved entry null? 2360 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 23618: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2362 EXPORT_PC() @ resolve() could throw 2363 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2364 bl dvmResolveInstField @ r0<- resolved InstField ptr 2365 cmp r0, #0 2366 bne .LOP_IGET_BOOLEAN_finish 2367 b common_exceptionThrown 2368 2369 2370/* ------------------------------ */ 2371 .balign 64 2372.L_OP_IGET_BYTE: /* 0x56 */ 2373/* File: armv5te/OP_IGET_BYTE.S */ 2374@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2375/* File: armv5te/OP_IGET.S */ 2376 /* 2377 * General 32-bit instance field get. 2378 * 2379 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2380 */ 2381 /* op vA, vB, field@CCCC */ 2382 mov r0, rINST, lsr #12 @ r0<- B 2383 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2384 FETCH(r1, 1) @ r1<- field ref CCCC 2385 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2386 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2387 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2388 cmp r0, #0 @ is resolved entry null? 2389 bne .LOP_IGET_BYTE_finish @ no, already resolved 23908: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2391 EXPORT_PC() @ resolve() could throw 2392 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2393 bl dvmResolveInstField @ r0<- resolved InstField ptr 2394 cmp r0, #0 2395 bne .LOP_IGET_BYTE_finish 2396 b common_exceptionThrown 2397 2398 2399/* ------------------------------ */ 2400 .balign 64 2401.L_OP_IGET_CHAR: /* 0x57 */ 2402/* File: armv5te/OP_IGET_CHAR.S */ 2403@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2404/* File: armv5te/OP_IGET.S */ 2405 /* 2406 * General 32-bit instance field get. 2407 * 2408 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2409 */ 2410 /* op vA, vB, field@CCCC */ 2411 mov r0, rINST, lsr #12 @ r0<- B 2412 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2413 FETCH(r1, 1) @ r1<- field ref CCCC 2414 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2415 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2416 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2417 cmp r0, #0 @ is resolved entry null? 2418 bne .LOP_IGET_CHAR_finish @ no, already resolved 24198: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2420 EXPORT_PC() @ resolve() could throw 2421 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2422 bl dvmResolveInstField @ r0<- resolved InstField ptr 2423 cmp r0, #0 2424 bne .LOP_IGET_CHAR_finish 2425 b common_exceptionThrown 2426 2427 2428/* ------------------------------ */ 2429 .balign 64 2430.L_OP_IGET_SHORT: /* 0x58 */ 2431/* File: armv5te/OP_IGET_SHORT.S */ 2432@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2433/* File: armv5te/OP_IGET.S */ 2434 /* 2435 * General 32-bit instance field get. 2436 * 2437 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2438 */ 2439 /* op vA, vB, field@CCCC */ 2440 mov r0, rINST, lsr #12 @ r0<- B 2441 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2442 FETCH(r1, 1) @ r1<- field ref CCCC 2443 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2444 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2445 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2446 cmp r0, #0 @ is resolved entry null? 2447 bne .LOP_IGET_SHORT_finish @ no, already resolved 24488: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2449 EXPORT_PC() @ resolve() could throw 2450 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2451 bl dvmResolveInstField @ r0<- resolved InstField ptr 2452 cmp r0, #0 2453 bne .LOP_IGET_SHORT_finish 2454 b common_exceptionThrown 2455 2456 2457/* ------------------------------ */ 2458 .balign 64 2459.L_OP_IPUT: /* 0x59 */ 2460/* File: armv5te/OP_IPUT.S */ 2461 /* 2462 * General 32-bit instance field put. 2463 * 2464 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2465 */ 2466 /* op vA, vB, field@CCCC */ 2467 mov r0, rINST, lsr #12 @ r0<- B 2468 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2469 FETCH(r1, 1) @ r1<- field ref CCCC 2470 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2471 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2472 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2473 cmp r0, #0 @ is resolved entry null? 2474 bne .LOP_IPUT_finish @ no, already resolved 24758: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2476 EXPORT_PC() @ resolve() could throw 2477 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2478 bl dvmResolveInstField @ r0<- resolved InstField ptr 2479 cmp r0, #0 @ success? 2480 bne .LOP_IPUT_finish @ yes, finish up 2481 b common_exceptionThrown 2482 2483/* ------------------------------ */ 2484 .balign 64 2485.L_OP_IPUT_WIDE: /* 0x5a */ 2486/* File: armv5te/OP_IPUT_WIDE.S */ 2487 /* iput-wide vA, vB, field@CCCC */ 2488 mov r0, rINST, lsr #12 @ r0<- B 2489 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2490 FETCH(r1, 1) @ r1<- field ref CCCC 2491 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2492 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2493 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2494 cmp r0, #0 @ is resolved entry null? 2495 bne .LOP_IPUT_WIDE_finish @ no, already resolved 24968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2497 EXPORT_PC() @ resolve() could throw 2498 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2499 bl dvmResolveInstField @ r0<- resolved InstField ptr 2500 cmp r0, #0 @ success? 2501 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2502 b common_exceptionThrown 2503 2504/* ------------------------------ */ 2505 .balign 64 2506.L_OP_IPUT_OBJECT: /* 0x5b */ 2507/* File: armv5te/OP_IPUT_OBJECT.S */ 2508/* File: armv5te/OP_IPUT.S */ 2509 /* 2510 * General 32-bit instance field put. 2511 * 2512 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2513 */ 2514 /* op vA, vB, field@CCCC */ 2515 mov r0, rINST, lsr #12 @ r0<- B 2516 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2517 FETCH(r1, 1) @ r1<- field ref CCCC 2518 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2519 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2520 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2521 cmp r0, #0 @ is resolved entry null? 2522 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 25238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2524 EXPORT_PC() @ resolve() could throw 2525 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2526 bl dvmResolveInstField @ r0<- resolved InstField ptr 2527 cmp r0, #0 @ success? 2528 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2529 b common_exceptionThrown 2530 2531 2532/* ------------------------------ */ 2533 .balign 64 2534.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2535/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2536@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2537/* File: armv5te/OP_IPUT.S */ 2538 /* 2539 * General 32-bit instance field put. 2540 * 2541 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2542 */ 2543 /* op vA, vB, field@CCCC */ 2544 mov r0, rINST, lsr #12 @ r0<- B 2545 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2546 FETCH(r1, 1) @ r1<- field ref CCCC 2547 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2548 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2549 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2550 cmp r0, #0 @ is resolved entry null? 2551 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 25528: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2553 EXPORT_PC() @ resolve() could throw 2554 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2555 bl dvmResolveInstField @ r0<- resolved InstField ptr 2556 cmp r0, #0 @ success? 2557 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2558 b common_exceptionThrown 2559 2560 2561/* ------------------------------ */ 2562 .balign 64 2563.L_OP_IPUT_BYTE: /* 0x5d */ 2564/* File: armv5te/OP_IPUT_BYTE.S */ 2565@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2566/* File: armv5te/OP_IPUT.S */ 2567 /* 2568 * General 32-bit instance field put. 2569 * 2570 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2571 */ 2572 /* op vA, vB, field@CCCC */ 2573 mov r0, rINST, lsr #12 @ r0<- B 2574 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2575 FETCH(r1, 1) @ r1<- field ref CCCC 2576 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2577 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2578 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2579 cmp r0, #0 @ is resolved entry null? 2580 bne .LOP_IPUT_BYTE_finish @ no, already resolved 25818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2582 EXPORT_PC() @ resolve() could throw 2583 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2584 bl dvmResolveInstField @ r0<- resolved InstField ptr 2585 cmp r0, #0 @ success? 2586 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2587 b common_exceptionThrown 2588 2589 2590/* ------------------------------ */ 2591 .balign 64 2592.L_OP_IPUT_CHAR: /* 0x5e */ 2593/* File: armv5te/OP_IPUT_CHAR.S */ 2594@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2595/* File: armv5te/OP_IPUT.S */ 2596 /* 2597 * General 32-bit instance field put. 2598 * 2599 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2600 */ 2601 /* op vA, vB, field@CCCC */ 2602 mov r0, rINST, lsr #12 @ r0<- B 2603 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2604 FETCH(r1, 1) @ r1<- field ref CCCC 2605 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2606 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2607 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2608 cmp r0, #0 @ is resolved entry null? 2609 bne .LOP_IPUT_CHAR_finish @ no, already resolved 26108: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2611 EXPORT_PC() @ resolve() could throw 2612 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2613 bl dvmResolveInstField @ r0<- resolved InstField ptr 2614 cmp r0, #0 @ success? 2615 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2616 b common_exceptionThrown 2617 2618 2619/* ------------------------------ */ 2620 .balign 64 2621.L_OP_IPUT_SHORT: /* 0x5f */ 2622/* File: armv5te/OP_IPUT_SHORT.S */ 2623@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2624/* File: armv5te/OP_IPUT.S */ 2625 /* 2626 * General 32-bit instance field put. 2627 * 2628 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2629 */ 2630 /* op vA, vB, field@CCCC */ 2631 mov r0, rINST, lsr #12 @ r0<- B 2632 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2633 FETCH(r1, 1) @ r1<- field ref CCCC 2634 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2635 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2636 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2637 cmp r0, #0 @ is resolved entry null? 2638 bne .LOP_IPUT_SHORT_finish @ no, already resolved 26398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2640 EXPORT_PC() @ resolve() could throw 2641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2642 bl dvmResolveInstField @ r0<- resolved InstField ptr 2643 cmp r0, #0 @ success? 2644 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2645 b common_exceptionThrown 2646 2647 2648/* ------------------------------ */ 2649 .balign 64 2650.L_OP_SGET: /* 0x60 */ 2651/* File: armv5te/OP_SGET.S */ 2652 /* 2653 * General 32-bit SGET handler. 2654 * 2655 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2656 */ 2657 /* op vAA, field@BBBB */ 2658 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2659 FETCH(r1, 1) @ r1<- field ref BBBB 2660 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2661 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2662 cmp r0, #0 @ is resolved entry null? 2663 beq .LOP_SGET_resolve @ yes, do resolve 2664.LOP_SGET_finish: @ field ptr in r0 2665 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2666 mov r2, rINST, lsr #8 @ r2<- AA 2667 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2668 SET_VREG(r1, r2) @ fp[AA]<- r1 2669 GET_INST_OPCODE(ip) @ extract opcode from rINST 2670 GOTO_OPCODE(ip) @ jump to next instruction 2671 2672/* ------------------------------ */ 2673 .balign 64 2674.L_OP_SGET_WIDE: /* 0x61 */ 2675/* File: armv5te/OP_SGET_WIDE.S */ 2676 /* 2677 * 64-bit SGET handler. 2678 */ 2679 /* sget-wide vAA, field@BBBB */ 2680 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2681 FETCH(r1, 1) @ r1<- field ref BBBB 2682 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2683 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2684 cmp r0, #0 @ is resolved entry null? 2685 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2686.LOP_SGET_WIDE_finish: 2687 mov r1, rINST, lsr #8 @ r1<- AA 2688 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned) 2689 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA] 2690 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2691 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3 2692 GET_INST_OPCODE(ip) @ extract opcode from rINST 2693 GOTO_OPCODE(ip) @ jump to next instruction 2694 2695/* ------------------------------ */ 2696 .balign 64 2697.L_OP_SGET_OBJECT: /* 0x62 */ 2698/* File: armv5te/OP_SGET_OBJECT.S */ 2699/* File: armv5te/OP_SGET.S */ 2700 /* 2701 * General 32-bit SGET handler. 2702 * 2703 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2704 */ 2705 /* op vAA, field@BBBB */ 2706 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2707 FETCH(r1, 1) @ r1<- field ref BBBB 2708 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2709 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2710 cmp r0, #0 @ is resolved entry null? 2711 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2712.LOP_SGET_OBJECT_finish: @ field ptr in r0 2713 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2714 mov r2, rINST, lsr #8 @ r2<- AA 2715 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2716 SET_VREG(r1, r2) @ fp[AA]<- r1 2717 GET_INST_OPCODE(ip) @ extract opcode from rINST 2718 GOTO_OPCODE(ip) @ jump to next instruction 2719 2720 2721/* ------------------------------ */ 2722 .balign 64 2723.L_OP_SGET_BOOLEAN: /* 0x63 */ 2724/* File: armv5te/OP_SGET_BOOLEAN.S */ 2725/* File: armv5te/OP_SGET.S */ 2726 /* 2727 * General 32-bit SGET handler. 2728 * 2729 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2730 */ 2731 /* op vAA, field@BBBB */ 2732 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2733 FETCH(r1, 1) @ r1<- field ref BBBB 2734 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2735 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2736 cmp r0, #0 @ is resolved entry null? 2737 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2738.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2739 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2740 mov r2, rINST, lsr #8 @ r2<- AA 2741 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2742 SET_VREG(r1, r2) @ fp[AA]<- r1 2743 GET_INST_OPCODE(ip) @ extract opcode from rINST 2744 GOTO_OPCODE(ip) @ jump to next instruction 2745 2746 2747/* ------------------------------ */ 2748 .balign 64 2749.L_OP_SGET_BYTE: /* 0x64 */ 2750/* File: armv5te/OP_SGET_BYTE.S */ 2751/* File: armv5te/OP_SGET.S */ 2752 /* 2753 * General 32-bit SGET handler. 2754 * 2755 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2756 */ 2757 /* op vAA, field@BBBB */ 2758 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2759 FETCH(r1, 1) @ r1<- field ref BBBB 2760 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2761 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2762 cmp r0, #0 @ is resolved entry null? 2763 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2764.LOP_SGET_BYTE_finish: @ field ptr in r0 2765 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2766 mov r2, rINST, lsr #8 @ r2<- AA 2767 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2768 SET_VREG(r1, r2) @ fp[AA]<- r1 2769 GET_INST_OPCODE(ip) @ extract opcode from rINST 2770 GOTO_OPCODE(ip) @ jump to next instruction 2771 2772 2773/* ------------------------------ */ 2774 .balign 64 2775.L_OP_SGET_CHAR: /* 0x65 */ 2776/* File: armv5te/OP_SGET_CHAR.S */ 2777/* File: armv5te/OP_SGET.S */ 2778 /* 2779 * General 32-bit SGET handler. 2780 * 2781 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2782 */ 2783 /* op vAA, field@BBBB */ 2784 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2785 FETCH(r1, 1) @ r1<- field ref BBBB 2786 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2787 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2788 cmp r0, #0 @ is resolved entry null? 2789 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2790.LOP_SGET_CHAR_finish: @ field ptr in r0 2791 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2792 mov r2, rINST, lsr #8 @ r2<- AA 2793 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2794 SET_VREG(r1, r2) @ fp[AA]<- r1 2795 GET_INST_OPCODE(ip) @ extract opcode from rINST 2796 GOTO_OPCODE(ip) @ jump to next instruction 2797 2798 2799/* ------------------------------ */ 2800 .balign 64 2801.L_OP_SGET_SHORT: /* 0x66 */ 2802/* File: armv5te/OP_SGET_SHORT.S */ 2803/* File: armv5te/OP_SGET.S */ 2804 /* 2805 * General 32-bit SGET handler. 2806 * 2807 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2808 */ 2809 /* op vAA, field@BBBB */ 2810 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2811 FETCH(r1, 1) @ r1<- field ref BBBB 2812 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2813 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2814 cmp r0, #0 @ is resolved entry null? 2815 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2816.LOP_SGET_SHORT_finish: @ field ptr in r0 2817 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2818 mov r2, rINST, lsr #8 @ r2<- AA 2819 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2820 SET_VREG(r1, r2) @ fp[AA]<- r1 2821 GET_INST_OPCODE(ip) @ extract opcode from rINST 2822 GOTO_OPCODE(ip) @ jump to next instruction 2823 2824 2825/* ------------------------------ */ 2826 .balign 64 2827.L_OP_SPUT: /* 0x67 */ 2828/* File: armv5te/OP_SPUT.S */ 2829 /* 2830 * General 32-bit SPUT handler. 2831 * 2832 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2833 */ 2834 /* op vAA, field@BBBB */ 2835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2836 FETCH(r1, 1) @ r1<- field ref BBBB 2837 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2838 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2839 cmp r0, #0 @ is resolved entry null? 2840 beq .LOP_SPUT_resolve @ yes, do resolve 2841.LOP_SPUT_finish: @ field ptr in r0 2842 mov r2, rINST, lsr #8 @ r2<- AA 2843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2844 GET_VREG(r1, r2) @ r1<- fp[AA] 2845 GET_INST_OPCODE(ip) @ extract opcode from rINST 2846 str r1, [r0, #offStaticField_value] @ field<- vAA 2847 GOTO_OPCODE(ip) @ jump to next instruction 2848 2849/* ------------------------------ */ 2850 .balign 64 2851.L_OP_SPUT_WIDE: /* 0x68 */ 2852/* File: armv5te/OP_SPUT_WIDE.S */ 2853 /* 2854 * 64-bit SPUT handler. 2855 */ 2856 /* sput-wide vAA, field@BBBB */ 2857 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2858 FETCH(r1, 1) @ r1<- field ref BBBB 2859 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2860 mov r9, rINST, lsr #8 @ r9<- AA 2861 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2862 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2863 cmp r0, #0 @ is resolved entry null? 2864 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2865.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9 2866 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2867 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 2868 GET_INST_OPCODE(ip) @ extract opcode from rINST 2869 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1 2870 GOTO_OPCODE(ip) @ jump to next instruction 2871 2872/* ------------------------------ */ 2873 .balign 64 2874.L_OP_SPUT_OBJECT: /* 0x69 */ 2875/* File: armv5te/OP_SPUT_OBJECT.S */ 2876/* File: armv5te/OP_SPUT.S */ 2877 /* 2878 * General 32-bit SPUT handler. 2879 * 2880 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2881 */ 2882 /* op vAA, field@BBBB */ 2883 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2884 FETCH(r1, 1) @ r1<- field ref BBBB 2885 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2886 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2887 cmp r0, #0 @ is resolved entry null? 2888 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 2889.LOP_SPUT_OBJECT_finish: @ field ptr in r0 2890 mov r2, rINST, lsr #8 @ r2<- AA 2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2892 GET_VREG(r1, r2) @ r1<- fp[AA] 2893 GET_INST_OPCODE(ip) @ extract opcode from rINST 2894 str r1, [r0, #offStaticField_value] @ field<- vAA 2895 GOTO_OPCODE(ip) @ jump to next instruction 2896 2897 2898/* ------------------------------ */ 2899 .balign 64 2900.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2901/* File: armv5te/OP_SPUT_BOOLEAN.S */ 2902/* File: armv5te/OP_SPUT.S */ 2903 /* 2904 * General 32-bit SPUT handler. 2905 * 2906 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2907 */ 2908 /* op vAA, field@BBBB */ 2909 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2910 FETCH(r1, 1) @ r1<- field ref BBBB 2911 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2912 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2913 cmp r0, #0 @ is resolved entry null? 2914 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 2915.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 2916 mov r2, rINST, lsr #8 @ r2<- AA 2917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2918 GET_VREG(r1, r2) @ r1<- fp[AA] 2919 GET_INST_OPCODE(ip) @ extract opcode from rINST 2920 str r1, [r0, #offStaticField_value] @ field<- vAA 2921 GOTO_OPCODE(ip) @ jump to next instruction 2922 2923 2924/* ------------------------------ */ 2925 .balign 64 2926.L_OP_SPUT_BYTE: /* 0x6b */ 2927/* File: armv5te/OP_SPUT_BYTE.S */ 2928/* File: armv5te/OP_SPUT.S */ 2929 /* 2930 * General 32-bit SPUT handler. 2931 * 2932 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2933 */ 2934 /* op vAA, field@BBBB */ 2935 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2936 FETCH(r1, 1) @ r1<- field ref BBBB 2937 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2938 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2939 cmp r0, #0 @ is resolved entry null? 2940 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 2941.LOP_SPUT_BYTE_finish: @ field ptr in r0 2942 mov r2, rINST, lsr #8 @ r2<- AA 2943 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2944 GET_VREG(r1, r2) @ r1<- fp[AA] 2945 GET_INST_OPCODE(ip) @ extract opcode from rINST 2946 str r1, [r0, #offStaticField_value] @ field<- vAA 2947 GOTO_OPCODE(ip) @ jump to next instruction 2948 2949 2950/* ------------------------------ */ 2951 .balign 64 2952.L_OP_SPUT_CHAR: /* 0x6c */ 2953/* File: armv5te/OP_SPUT_CHAR.S */ 2954/* File: armv5te/OP_SPUT.S */ 2955 /* 2956 * General 32-bit SPUT handler. 2957 * 2958 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2959 */ 2960 /* op vAA, field@BBBB */ 2961 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2962 FETCH(r1, 1) @ r1<- field ref BBBB 2963 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2964 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2965 cmp r0, #0 @ is resolved entry null? 2966 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 2967.LOP_SPUT_CHAR_finish: @ field ptr in r0 2968 mov r2, rINST, lsr #8 @ r2<- AA 2969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2970 GET_VREG(r1, r2) @ r1<- fp[AA] 2971 GET_INST_OPCODE(ip) @ extract opcode from rINST 2972 str r1, [r0, #offStaticField_value] @ field<- vAA 2973 GOTO_OPCODE(ip) @ jump to next instruction 2974 2975 2976/* ------------------------------ */ 2977 .balign 64 2978.L_OP_SPUT_SHORT: /* 0x6d */ 2979/* File: armv5te/OP_SPUT_SHORT.S */ 2980/* File: armv5te/OP_SPUT.S */ 2981 /* 2982 * General 32-bit SPUT handler. 2983 * 2984 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2985 */ 2986 /* op vAA, field@BBBB */ 2987 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2988 FETCH(r1, 1) @ r1<- field ref BBBB 2989 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2990 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2991 cmp r0, #0 @ is resolved entry null? 2992 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 2993.LOP_SPUT_SHORT_finish: @ field ptr in r0 2994 mov r2, rINST, lsr #8 @ r2<- AA 2995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2996 GET_VREG(r1, r2) @ r1<- fp[AA] 2997 GET_INST_OPCODE(ip) @ extract opcode from rINST 2998 str r1, [r0, #offStaticField_value] @ field<- vAA 2999 GOTO_OPCODE(ip) @ jump to next instruction 3000 3001 3002/* ------------------------------ */ 3003 .balign 64 3004.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3005/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3006 /* 3007 * Handle a virtual method call. 3008 * 3009 * for: invoke-virtual, invoke-virtual/range 3010 */ 3011 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3012 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3013 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3014 FETCH(r1, 1) @ r1<- BBBB 3015 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3016 FETCH(r10, 2) @ r10<- GFED or CCCC 3017 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3018 .if (!0) 3019 and r10, r10, #15 @ r10<- D (or stays CCCC) 3020 .endif 3021 cmp r0, #0 @ already resolved? 3022 EXPORT_PC() @ must export for invoke 3023 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3024 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3025 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3026 mov r2, #METHOD_VIRTUAL @ resolver method type 3027 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3028 cmp r0, #0 @ got null? 3029 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3030 b common_exceptionThrown @ yes, handle exception 3031 3032/* ------------------------------ */ 3033 .balign 64 3034.L_OP_INVOKE_SUPER: /* 0x6f */ 3035/* File: armv5te/OP_INVOKE_SUPER.S */ 3036 /* 3037 * Handle a "super" method call. 3038 * 3039 * for: invoke-super, invoke-super/range 3040 */ 3041 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3042 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3043 FETCH(r10, 2) @ r10<- GFED or CCCC 3044 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3045 .if (!0) 3046 and r10, r10, #15 @ r10<- D (or stays CCCC) 3047 .endif 3048 FETCH(r1, 1) @ r1<- BBBB 3049 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3050 GET_VREG(r2, r10) @ r2<- "this" ptr 3051 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3052 cmp r2, #0 @ null "this"? 3053 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3054 beq common_errNullObject @ null "this", throw exception 3055 cmp r0, #0 @ already resolved? 3056 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3057 EXPORT_PC() @ must export for invoke 3058 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3059 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3060 3061/* ------------------------------ */ 3062 .balign 64 3063.L_OP_INVOKE_DIRECT: /* 0x70 */ 3064/* File: armv5te/OP_INVOKE_DIRECT.S */ 3065 /* 3066 * Handle a direct method call. 3067 * 3068 * (We could defer the "is 'this' pointer null" test to the common 3069 * method invocation code, and use a flag to indicate that static 3070 * calls don't count. If we do this as part of copying the arguments 3071 * out we could avoiding loading the first arg twice.) 3072 * 3073 * for: invoke-direct, invoke-direct/range 3074 */ 3075 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3076 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3077 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3078 FETCH(r1, 1) @ r1<- BBBB 3079 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3080 FETCH(r10, 2) @ r10<- GFED or CCCC 3081 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3082 .if (!0) 3083 and r10, r10, #15 @ r10<- D (or stays CCCC) 3084 .endif 3085 cmp r0, #0 @ already resolved? 3086 EXPORT_PC() @ must export for invoke 3087 GET_VREG(r2, r10) @ r2<- "this" ptr 3088 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3089.LOP_INVOKE_DIRECT_finish: 3090 cmp r2, #0 @ null "this" ref? 3091 bne common_invokeMethodNoRange @ no, continue on 3092 b common_errNullObject @ yes, throw exception 3093 3094/* ------------------------------ */ 3095 .balign 64 3096.L_OP_INVOKE_STATIC: /* 0x71 */ 3097/* File: armv5te/OP_INVOKE_STATIC.S */ 3098 /* 3099 * Handle a static method call. 3100 * 3101 * for: invoke-static, invoke-static/range 3102 */ 3103 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3104 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3105 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3106 FETCH(r1, 1) @ r1<- BBBB 3107 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3108 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3109 cmp r0, #0 @ already resolved? 3110 EXPORT_PC() @ must export for invoke 3111 bne common_invokeMethodNoRange @ yes, continue on 31120: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3113 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3114 mov r2, #METHOD_STATIC @ resolver method type 3115 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3116 cmp r0, #0 @ got null? 3117 bne common_invokeMethodNoRange @ no, continue 3118 b common_exceptionThrown @ yes, handle exception 3119 3120 3121/* ------------------------------ */ 3122 .balign 64 3123.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3124/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3125 /* 3126 * Handle an interface method call. 3127 * 3128 * for: invoke-interface, invoke-interface/range 3129 */ 3130 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3131 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3132 FETCH(r2, 2) @ r2<- FEDC or CCCC 3133 FETCH(r1, 1) @ r1<- BBBB 3134 .if (!0) 3135 and r2, r2, #15 @ r2<- C (or stays CCCC) 3136 .endif 3137 EXPORT_PC() @ must export for invoke 3138 GET_VREG(r0, r2) @ r0<- first arg ("this") 3139 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3140 cmp r0, #0 @ null obj? 3141 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3142 beq common_errNullObject @ yes, fail 3143 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3144 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3145 cmp r0, #0 @ failed? 3146 beq common_exceptionThrown @ yes, handle exception 3147 b common_invokeMethodNoRange @ jump to common handler 3148 3149 3150/* ------------------------------ */ 3151 .balign 64 3152.L_OP_UNUSED_73: /* 0x73 */ 3153/* File: armv5te/OP_UNUSED_73.S */ 3154/* File: armv5te/unused.S */ 3155 bl common_abort 3156 3157 3158 3159/* ------------------------------ */ 3160 .balign 64 3161.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3162/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3163/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3164 /* 3165 * Handle a virtual method call. 3166 * 3167 * for: invoke-virtual, invoke-virtual/range 3168 */ 3169 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3170 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3171 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3172 FETCH(r1, 1) @ r1<- BBBB 3173 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3174 FETCH(r10, 2) @ r10<- GFED or CCCC 3175 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3176 .if (!1) 3177 and r10, r10, #15 @ r10<- D (or stays CCCC) 3178 .endif 3179 cmp r0, #0 @ already resolved? 3180 EXPORT_PC() @ must export for invoke 3181 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3182 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3183 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3184 mov r2, #METHOD_VIRTUAL @ resolver method type 3185 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3186 cmp r0, #0 @ got null? 3187 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3188 b common_exceptionThrown @ yes, handle exception 3189 3190 3191/* ------------------------------ */ 3192 .balign 64 3193.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3194/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3195/* File: armv5te/OP_INVOKE_SUPER.S */ 3196 /* 3197 * Handle a "super" method call. 3198 * 3199 * for: invoke-super, invoke-super/range 3200 */ 3201 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3202 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3203 FETCH(r10, 2) @ r10<- GFED or CCCC 3204 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3205 .if (!1) 3206 and r10, r10, #15 @ r10<- D (or stays CCCC) 3207 .endif 3208 FETCH(r1, 1) @ r1<- BBBB 3209 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3210 GET_VREG(r2, r10) @ r2<- "this" ptr 3211 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3212 cmp r2, #0 @ null "this"? 3213 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3214 beq common_errNullObject @ null "this", throw exception 3215 cmp r0, #0 @ already resolved? 3216 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3217 EXPORT_PC() @ must export for invoke 3218 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3219 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3220 3221 3222/* ------------------------------ */ 3223 .balign 64 3224.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3225/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3226/* File: armv5te/OP_INVOKE_DIRECT.S */ 3227 /* 3228 * Handle a direct method call. 3229 * 3230 * (We could defer the "is 'this' pointer null" test to the common 3231 * method invocation code, and use a flag to indicate that static 3232 * calls don't count. If we do this as part of copying the arguments 3233 * out we could avoiding loading the first arg twice.) 3234 * 3235 * for: invoke-direct, invoke-direct/range 3236 */ 3237 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3238 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3239 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3240 FETCH(r1, 1) @ r1<- BBBB 3241 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3242 FETCH(r10, 2) @ r10<- GFED or CCCC 3243 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3244 .if (!1) 3245 and r10, r10, #15 @ r10<- D (or stays CCCC) 3246 .endif 3247 cmp r0, #0 @ already resolved? 3248 EXPORT_PC() @ must export for invoke 3249 GET_VREG(r2, r10) @ r2<- "this" ptr 3250 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3251.LOP_INVOKE_DIRECT_RANGE_finish: 3252 cmp r2, #0 @ null "this" ref? 3253 bne common_invokeMethodRange @ no, continue on 3254 b common_errNullObject @ yes, throw exception 3255 3256 3257/* ------------------------------ */ 3258 .balign 64 3259.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3260/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3261/* File: armv5te/OP_INVOKE_STATIC.S */ 3262 /* 3263 * Handle a static method call. 3264 * 3265 * for: invoke-static, invoke-static/range 3266 */ 3267 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3268 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3269 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3270 FETCH(r1, 1) @ r1<- BBBB 3271 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3272 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3273 cmp r0, #0 @ already resolved? 3274 EXPORT_PC() @ must export for invoke 3275 bne common_invokeMethodRange @ yes, continue on 32760: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3277 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3278 mov r2, #METHOD_STATIC @ resolver method type 3279 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3280 cmp r0, #0 @ got null? 3281 bne common_invokeMethodRange @ no, continue 3282 b common_exceptionThrown @ yes, handle exception 3283 3284 3285 3286/* ------------------------------ */ 3287 .balign 64 3288.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3289/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3290/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3291 /* 3292 * Handle an interface method call. 3293 * 3294 * for: invoke-interface, invoke-interface/range 3295 */ 3296 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3297 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3298 FETCH(r2, 2) @ r2<- FEDC or CCCC 3299 FETCH(r1, 1) @ r1<- BBBB 3300 .if (!1) 3301 and r2, r2, #15 @ r2<- C (or stays CCCC) 3302 .endif 3303 EXPORT_PC() @ must export for invoke 3304 GET_VREG(r0, r2) @ r0<- first arg ("this") 3305 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3306 cmp r0, #0 @ null obj? 3307 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3308 beq common_errNullObject @ yes, fail 3309 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3310 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3311 cmp r0, #0 @ failed? 3312 beq common_exceptionThrown @ yes, handle exception 3313 b common_invokeMethodRange @ jump to common handler 3314 3315 3316 3317/* ------------------------------ */ 3318 .balign 64 3319.L_OP_UNUSED_79: /* 0x79 */ 3320/* File: armv5te/OP_UNUSED_79.S */ 3321/* File: armv5te/unused.S */ 3322 bl common_abort 3323 3324 3325 3326/* ------------------------------ */ 3327 .balign 64 3328.L_OP_UNUSED_7A: /* 0x7a */ 3329/* File: armv5te/OP_UNUSED_7A.S */ 3330/* File: armv5te/unused.S */ 3331 bl common_abort 3332 3333 3334 3335/* ------------------------------ */ 3336 .balign 64 3337.L_OP_NEG_INT: /* 0x7b */ 3338/* File: armv5te/OP_NEG_INT.S */ 3339/* File: armv5te/unop.S */ 3340 /* 3341 * Generic 32-bit unary operation. Provide an "instr" line that 3342 * specifies an instruction that performs "result = op r0". 3343 * This could be an ARM instruction or a function call. 3344 * 3345 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3346 * int-to-byte, int-to-char, int-to-short 3347 */ 3348 /* unop vA, vB */ 3349 mov r3, rINST, lsr #12 @ r3<- B 3350 mov r9, rINST, lsr #8 @ r9<- A+ 3351 GET_VREG(r0, r3) @ r0<- vB 3352 and r9, r9, #15 3353 @ optional op; may set condition codes 3354 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3355 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3356 GET_INST_OPCODE(ip) @ extract opcode from rINST 3357 SET_VREG(r0, r9) @ vAA<- r0 3358 GOTO_OPCODE(ip) @ jump to next instruction 3359 /* 9-10 instructions */ 3360 3361 3362/* ------------------------------ */ 3363 .balign 64 3364.L_OP_NOT_INT: /* 0x7c */ 3365/* File: armv5te/OP_NOT_INT.S */ 3366/* File: armv5te/unop.S */ 3367 /* 3368 * Generic 32-bit unary operation. Provide an "instr" line that 3369 * specifies an instruction that performs "result = op r0". 3370 * This could be an ARM instruction or a function call. 3371 * 3372 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3373 * int-to-byte, int-to-char, int-to-short 3374 */ 3375 /* unop vA, vB */ 3376 mov r3, rINST, lsr #12 @ r3<- B 3377 mov r9, rINST, lsr #8 @ r9<- A+ 3378 GET_VREG(r0, r3) @ r0<- vB 3379 and r9, r9, #15 3380 @ optional op; may set condition codes 3381 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3382 mvn r0, r0 @ r0<- op, r0-r3 changed 3383 GET_INST_OPCODE(ip) @ extract opcode from rINST 3384 SET_VREG(r0, r9) @ vAA<- r0 3385 GOTO_OPCODE(ip) @ jump to next instruction 3386 /* 9-10 instructions */ 3387 3388 3389/* ------------------------------ */ 3390 .balign 64 3391.L_OP_NEG_LONG: /* 0x7d */ 3392/* File: armv5te/OP_NEG_LONG.S */ 3393/* File: armv5te/unopWide.S */ 3394 /* 3395 * Generic 64-bit unary operation. Provide an "instr" line that 3396 * specifies an instruction that performs "result = op r0/r1". 3397 * This could be an ARM instruction or a function call. 3398 * 3399 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3400 */ 3401 /* unop vA, vB */ 3402 mov r9, rINST, lsr #8 @ r9<- A+ 3403 mov r3, rINST, lsr #12 @ r3<- B 3404 and r9, r9, #15 3405 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3406 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3407 ldmia r3, {r0-r1} @ r0/r1<- vAA 3408 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3409 rsbs r0, r0, #0 @ optional op; may set condition codes 3410 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3411 GET_INST_OPCODE(ip) @ extract opcode from rINST 3412 stmia r9, {r0-r1} @ vAA<- r0/r1 3413 GOTO_OPCODE(ip) @ jump to next instruction 3414 /* 12-13 instructions */ 3415 3416 3417 3418/* ------------------------------ */ 3419 .balign 64 3420.L_OP_NOT_LONG: /* 0x7e */ 3421/* File: armv5te/OP_NOT_LONG.S */ 3422/* File: armv5te/unopWide.S */ 3423 /* 3424 * Generic 64-bit unary operation. Provide an "instr" line that 3425 * specifies an instruction that performs "result = op r0/r1". 3426 * This could be an ARM instruction or a function call. 3427 * 3428 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3429 */ 3430 /* unop vA, vB */ 3431 mov r9, rINST, lsr #8 @ r9<- A+ 3432 mov r3, rINST, lsr #12 @ r3<- B 3433 and r9, r9, #15 3434 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3435 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3436 ldmia r3, {r0-r1} @ r0/r1<- vAA 3437 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3438 mvn r0, r0 @ optional op; may set condition codes 3439 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3440 GET_INST_OPCODE(ip) @ extract opcode from rINST 3441 stmia r9, {r0-r1} @ vAA<- r0/r1 3442 GOTO_OPCODE(ip) @ jump to next instruction 3443 /* 12-13 instructions */ 3444 3445 3446 3447/* ------------------------------ */ 3448 .balign 64 3449.L_OP_NEG_FLOAT: /* 0x7f */ 3450/* File: armv5te/OP_NEG_FLOAT.S */ 3451/* File: armv5te/unop.S */ 3452 /* 3453 * Generic 32-bit unary operation. Provide an "instr" line that 3454 * specifies an instruction that performs "result = op r0". 3455 * This could be an ARM instruction or a function call. 3456 * 3457 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3458 * int-to-byte, int-to-char, int-to-short 3459 */ 3460 /* unop vA, vB */ 3461 mov r3, rINST, lsr #12 @ r3<- B 3462 mov r9, rINST, lsr #8 @ r9<- A+ 3463 GET_VREG(r0, r3) @ r0<- vB 3464 and r9, r9, #15 3465 @ optional op; may set condition codes 3466 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3467 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3468 GET_INST_OPCODE(ip) @ extract opcode from rINST 3469 SET_VREG(r0, r9) @ vAA<- r0 3470 GOTO_OPCODE(ip) @ jump to next instruction 3471 /* 9-10 instructions */ 3472 3473 3474/* ------------------------------ */ 3475 .balign 64 3476.L_OP_NEG_DOUBLE: /* 0x80 */ 3477/* File: armv5te/OP_NEG_DOUBLE.S */ 3478/* File: armv5te/unopWide.S */ 3479 /* 3480 * Generic 64-bit unary operation. Provide an "instr" line that 3481 * specifies an instruction that performs "result = op r0/r1". 3482 * This could be an ARM instruction or a function call. 3483 * 3484 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3485 */ 3486 /* unop vA, vB */ 3487 mov r9, rINST, lsr #8 @ r9<- A+ 3488 mov r3, rINST, lsr #12 @ r3<- B 3489 and r9, r9, #15 3490 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3491 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3492 ldmia r3, {r0-r1} @ r0/r1<- vAA 3493 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3494 @ optional op; may set condition codes 3495 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3496 GET_INST_OPCODE(ip) @ extract opcode from rINST 3497 stmia r9, {r0-r1} @ vAA<- r0/r1 3498 GOTO_OPCODE(ip) @ jump to next instruction 3499 /* 12-13 instructions */ 3500 3501 3502 3503/* ------------------------------ */ 3504 .balign 64 3505.L_OP_INT_TO_LONG: /* 0x81 */ 3506/* File: armv5te/OP_INT_TO_LONG.S */ 3507/* File: armv5te/unopWider.S */ 3508 /* 3509 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3510 * that specifies an instruction that performs "result = op r0", where 3511 * "result" is a 64-bit quantity in r0/r1. 3512 * 3513 * For: int-to-long, int-to-double, float-to-long, float-to-double 3514 */ 3515 /* unop vA, vB */ 3516 mov r9, rINST, lsr #8 @ r9<- A+ 3517 mov r3, rINST, lsr #12 @ r3<- B 3518 and r9, r9, #15 3519 GET_VREG(r0, r3) @ r0<- vB 3520 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3521 @ optional op; may set condition codes 3522 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3523 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3524 GET_INST_OPCODE(ip) @ extract opcode from rINST 3525 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3526 GOTO_OPCODE(ip) @ jump to next instruction 3527 /* 10-11 instructions */ 3528 3529 3530/* ------------------------------ */ 3531 .balign 64 3532.L_OP_INT_TO_FLOAT: /* 0x82 */ 3533/* File: armv5te/OP_INT_TO_FLOAT.S */ 3534/* File: armv5te/unop.S */ 3535 /* 3536 * Generic 32-bit unary operation. Provide an "instr" line that 3537 * specifies an instruction that performs "result = op r0". 3538 * This could be an ARM instruction or a function call. 3539 * 3540 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3541 * int-to-byte, int-to-char, int-to-short 3542 */ 3543 /* unop vA, vB */ 3544 mov r3, rINST, lsr #12 @ r3<- B 3545 mov r9, rINST, lsr #8 @ r9<- A+ 3546 GET_VREG(r0, r3) @ r0<- vB 3547 and r9, r9, #15 3548 @ optional op; may set condition codes 3549 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3550 bl __aeabi_i2f @ r0<- op, r0-r3 changed 3551 GET_INST_OPCODE(ip) @ extract opcode from rINST 3552 SET_VREG(r0, r9) @ vAA<- r0 3553 GOTO_OPCODE(ip) @ jump to next instruction 3554 /* 9-10 instructions */ 3555 3556 3557/* ------------------------------ */ 3558 .balign 64 3559.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3560/* File: armv5te/OP_INT_TO_DOUBLE.S */ 3561/* File: armv5te/unopWider.S */ 3562 /* 3563 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3564 * that specifies an instruction that performs "result = op r0", where 3565 * "result" is a 64-bit quantity in r0/r1. 3566 * 3567 * For: int-to-long, int-to-double, float-to-long, float-to-double 3568 */ 3569 /* unop vA, vB */ 3570 mov r9, rINST, lsr #8 @ r9<- A+ 3571 mov r3, rINST, lsr #12 @ r3<- B 3572 and r9, r9, #15 3573 GET_VREG(r0, r3) @ r0<- vB 3574 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3575 @ optional op; may set condition codes 3576 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3577 bl __aeabi_i2d @ r0<- op, r0-r3 changed 3578 GET_INST_OPCODE(ip) @ extract opcode from rINST 3579 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3580 GOTO_OPCODE(ip) @ jump to next instruction 3581 /* 10-11 instructions */ 3582 3583 3584/* ------------------------------ */ 3585 .balign 64 3586.L_OP_LONG_TO_INT: /* 0x84 */ 3587/* File: armv5te/OP_LONG_TO_INT.S */ 3588/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3589/* File: armv5te/OP_MOVE.S */ 3590 /* for move, move-object, long-to-int */ 3591 /* op vA, vB */ 3592 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3593 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3594 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3595 GET_VREG(r2, r1) @ r2<- fp[B] 3596 and r0, r0, #15 3597 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3598 SET_VREG(r2, r0) @ fp[A]<- r2 3599 GOTO_OPCODE(ip) @ execute next instruction 3600 3601 3602 3603/* ------------------------------ */ 3604 .balign 64 3605.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3606/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3607/* File: armv5te/unopNarrower.S */ 3608 /* 3609 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3610 * that specifies an instruction that performs "result = op r0/r1", where 3611 * "result" is a 32-bit quantity in r0. 3612 * 3613 * For: long-to-float, double-to-int, double-to-float 3614 * 3615 * (This would work for long-to-int, but that instruction is actually 3616 * an exact match for OP_MOVE.) 3617 */ 3618 /* unop vA, vB */ 3619 mov r3, rINST, lsr #12 @ r3<- B 3620 mov r9, rINST, lsr #8 @ r9<- A+ 3621 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3622 and r9, r9, #15 3623 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3624 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3625 @ optional op; may set condition codes 3626 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3627 GET_INST_OPCODE(ip) @ extract opcode from rINST 3628 SET_VREG(r0, r9) @ vA<- r0 3629 GOTO_OPCODE(ip) @ jump to next instruction 3630 /* 10-11 instructions */ 3631 3632 3633/* ------------------------------ */ 3634 .balign 64 3635.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3636/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3637/* File: armv5te/unopWide.S */ 3638 /* 3639 * Generic 64-bit unary operation. Provide an "instr" line that 3640 * specifies an instruction that performs "result = op r0/r1". 3641 * This could be an ARM instruction or a function call. 3642 * 3643 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3644 */ 3645 /* unop vA, vB */ 3646 mov r9, rINST, lsr #8 @ r9<- A+ 3647 mov r3, rINST, lsr #12 @ r3<- B 3648 and r9, r9, #15 3649 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3650 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3651 ldmia r3, {r0-r1} @ r0/r1<- vAA 3652 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3653 @ optional op; may set condition codes 3654 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3655 GET_INST_OPCODE(ip) @ extract opcode from rINST 3656 stmia r9, {r0-r1} @ vAA<- r0/r1 3657 GOTO_OPCODE(ip) @ jump to next instruction 3658 /* 12-13 instructions */ 3659 3660 3661 3662/* ------------------------------ */ 3663 .balign 64 3664.L_OP_FLOAT_TO_INT: /* 0x87 */ 3665/* File: armv5te/OP_FLOAT_TO_INT.S */ 3666/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3667/* File: armv5te/unop.S */ 3668 /* 3669 * Generic 32-bit unary operation. Provide an "instr" line that 3670 * specifies an instruction that performs "result = op r0". 3671 * This could be an ARM instruction or a function call. 3672 * 3673 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3674 * int-to-byte, int-to-char, int-to-short 3675 */ 3676 /* unop vA, vB */ 3677 mov r3, rINST, lsr #12 @ r3<- B 3678 mov r9, rINST, lsr #8 @ r9<- A+ 3679 GET_VREG(r0, r3) @ r0<- vB 3680 and r9, r9, #15 3681 @ optional op; may set condition codes 3682 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3683 bl __aeabi_f2iz @ r0<- op, r0-r3 changed 3684 GET_INST_OPCODE(ip) @ extract opcode from rINST 3685 SET_VREG(r0, r9) @ vAA<- r0 3686 GOTO_OPCODE(ip) @ jump to next instruction 3687 /* 9-10 instructions */ 3688 3689 3690#if 0 3691@include "armv5te/unop.S" {"instr":"bl f2i_doconv"} 3692@break 3693/* 3694 * Convert the float in r0 to an int in r0. 3695 * 3696 * We have to clip values to int min/max per the specification. The 3697 * expected common case is a "reasonable" value that converts directly 3698 * to modest integer. The EABI convert function isn't doing this for us. 3699 */ 3700f2i_doconv: 3701 stmfd sp!, {r4, lr} 3702 mov r1, #0x4f000000 @ (float)maxint 3703 mov r4, r0 3704 bl __aeabi_fcmpge @ is arg >= maxint? 3705 cmp r0, #0 @ nonzero == yes 3706 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3707 ldmnefd sp!, {r4, pc} 3708 3709 mov r0, r4 @ recover arg 3710 mov r1, #0xcf000000 @ (float)minint 3711 bl __aeabi_fcmple @ is arg <= minint? 3712 cmp r0, #0 @ nonzero == yes 3713 movne r0, #0x80000000 @ return minint (80000000) 3714 ldmnefd sp!, {r4, pc} 3715 3716 mov r0, r4 @ recover arg 3717 mov r1, r4 3718 bl __aeabi_fcmpeq @ is arg == self? 3719 cmp r0, #0 @ zero == no 3720 ldmeqfd sp!, {r4, pc} @ return zero for NaN 3721 3722 mov r0, r4 @ recover arg 3723 bl __aeabi_f2iz @ convert float to int 3724 ldmfd sp!, {r4, pc} 3725#endif 3726 3727 3728/* ------------------------------ */ 3729 .balign 64 3730.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3731/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3732@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3733/* File: armv5te/unopWider.S */ 3734 /* 3735 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3736 * that specifies an instruction that performs "result = op r0", where 3737 * "result" is a 64-bit quantity in r0/r1. 3738 * 3739 * For: int-to-long, int-to-double, float-to-long, float-to-double 3740 */ 3741 /* unop vA, vB */ 3742 mov r9, rINST, lsr #8 @ r9<- A+ 3743 mov r3, rINST, lsr #12 @ r3<- B 3744 and r9, r9, #15 3745 GET_VREG(r0, r3) @ r0<- vB 3746 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3747 @ optional op; may set condition codes 3748 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3749 bl f2l_doconv @ r0<- op, r0-r3 changed 3750 GET_INST_OPCODE(ip) @ extract opcode from rINST 3751 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3752 GOTO_OPCODE(ip) @ jump to next instruction 3753 /* 10-11 instructions */ 3754 3755 3756 3757/* ------------------------------ */ 3758 .balign 64 3759.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3760/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */ 3761/* File: armv5te/unopWider.S */ 3762 /* 3763 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3764 * that specifies an instruction that performs "result = op r0", where 3765 * "result" is a 64-bit quantity in r0/r1. 3766 * 3767 * For: int-to-long, int-to-double, float-to-long, float-to-double 3768 */ 3769 /* unop vA, vB */ 3770 mov r9, rINST, lsr #8 @ r9<- A+ 3771 mov r3, rINST, lsr #12 @ r3<- B 3772 and r9, r9, #15 3773 GET_VREG(r0, r3) @ r0<- vB 3774 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3775 @ optional op; may set condition codes 3776 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3777 bl __aeabi_f2d @ r0<- op, r0-r3 changed 3778 GET_INST_OPCODE(ip) @ extract opcode from rINST 3779 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3780 GOTO_OPCODE(ip) @ jump to next instruction 3781 /* 10-11 instructions */ 3782 3783 3784/* ------------------------------ */ 3785 .balign 64 3786.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3787/* File: armv5te/OP_DOUBLE_TO_INT.S */ 3788/* EABI appears to have Java-style conversions of +inf/-inf/NaN */ 3789/* File: armv5te/unopNarrower.S */ 3790 /* 3791 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3792 * that specifies an instruction that performs "result = op r0/r1", where 3793 * "result" is a 32-bit quantity in r0. 3794 * 3795 * For: long-to-float, double-to-int, double-to-float 3796 * 3797 * (This would work for long-to-int, but that instruction is actually 3798 * an exact match for OP_MOVE.) 3799 */ 3800 /* unop vA, vB */ 3801 mov r3, rINST, lsr #12 @ r3<- B 3802 mov r9, rINST, lsr #8 @ r9<- A+ 3803 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3804 and r9, r9, #15 3805 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3806 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3807 @ optional op; may set condition codes 3808 bl __aeabi_d2iz @ r0<- op, r0-r3 changed 3809 GET_INST_OPCODE(ip) @ extract opcode from rINST 3810 SET_VREG(r0, r9) @ vA<- r0 3811 GOTO_OPCODE(ip) @ jump to next instruction 3812 /* 10-11 instructions */ 3813 3814 3815#if 0 3816@include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"} 3817@break 3818/* 3819 * Convert the double in r0/r1 to an int in r0. 3820 * 3821 * We have to clip values to int min/max per the specification. The 3822 * expected common case is a "reasonable" value that converts directly 3823 * to modest integer. The EABI convert function isn't doing this for us. 3824 */ 3825d2i_doconv: 3826 stmfd sp!, {r4, r5, lr} @ save regs 3827 ldr r2, .LOP_DOUBLE_TO_INT_maxlo @ (double)maxint, lo 3828 ldr r3, .LOP_DOUBLE_TO_INT_maxhi @ (double)maxint, hi 3829 sub sp, sp, #4 @ align for EABI 3830 mov r4, r0 @ save r0 3831 mov r5, r1 @ and r1 3832 bl __aeabi_dcmpge @ is arg >= maxint? 3833 cmp r0, #0 @ nonzero == yes 3834 mvnne r0, #0x80000000 @ return maxint (7fffffff) 3835 bne 1f 3836 3837 mov r0, r4 @ recover arg 3838 mov r1, r5 3839 ldr r3, .LOP_DOUBLE_TO_INT_min @ (double)minint, hi 3840 mov r2, #0 @ (double)minint, lo 3841 bl __aeabi_dcmple @ is arg <= minint? 3842 cmp r0, #0 @ nonzero == yes 3843 movne r0, #0x80000000 @ return minint (80000000) 3844 bne 1f 3845 3846 mov r0, r4 @ recover arg 3847 mov r1, r5 3848 mov r2, r4 @ compare against self 3849 mov r3, r5 3850 bl __aeabi_dcmpeq @ is arg == self? 3851 cmp r0, #0 @ zero == no 3852 beq 1f @ return zero for NaN 3853 3854 mov r0, r4 @ recover arg 3855 mov r1, r5 3856 bl __aeabi_d2iz @ convert double to int 3857 38581: 3859 add sp, sp, #4 3860 ldmfd sp!, {r4, r5, pc} 3861 3862.LOP_DOUBLE_TO_INT_maxlo: 3863 .word 0xffc00000 @ maxint, as a double (low word) 3864.LOP_DOUBLE_TO_INT_maxhi: 3865 .word 0x41dfffff @ maxint, as a double (high word) 3866.LOP_DOUBLE_TO_INT_min: 3867 .word 0xc1e00000 @ minint, as a double (high word) 3868#endif 3869 3870 3871/* ------------------------------ */ 3872 .balign 64 3873.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3874/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3875@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3876/* File: armv5te/unopWide.S */ 3877 /* 3878 * Generic 64-bit unary operation. Provide an "instr" line that 3879 * specifies an instruction that performs "result = op r0/r1". 3880 * This could be an ARM instruction or a function call. 3881 * 3882 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3883 */ 3884 /* unop vA, vB */ 3885 mov r9, rINST, lsr #8 @ r9<- A+ 3886 mov r3, rINST, lsr #12 @ r3<- B 3887 and r9, r9, #15 3888 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3889 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3890 ldmia r3, {r0-r1} @ r0/r1<- vAA 3891 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3892 @ optional op; may set condition codes 3893 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3894 GET_INST_OPCODE(ip) @ extract opcode from rINST 3895 stmia r9, {r0-r1} @ vAA<- r0/r1 3896 GOTO_OPCODE(ip) @ jump to next instruction 3897 /* 12-13 instructions */ 3898 3899 3900 3901 3902/* ------------------------------ */ 3903 .balign 64 3904.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3905/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */ 3906/* File: armv5te/unopNarrower.S */ 3907 /* 3908 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3909 * that specifies an instruction that performs "result = op r0/r1", where 3910 * "result" is a 32-bit quantity in r0. 3911 * 3912 * For: long-to-float, double-to-int, double-to-float 3913 * 3914 * (This would work for long-to-int, but that instruction is actually 3915 * an exact match for OP_MOVE.) 3916 */ 3917 /* unop vA, vB */ 3918 mov r3, rINST, lsr #12 @ r3<- B 3919 mov r9, rINST, lsr #8 @ r9<- A+ 3920 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3921 and r9, r9, #15 3922 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3923 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3924 @ optional op; may set condition codes 3925 bl __aeabi_d2f @ r0<- op, r0-r3 changed 3926 GET_INST_OPCODE(ip) @ extract opcode from rINST 3927 SET_VREG(r0, r9) @ vA<- r0 3928 GOTO_OPCODE(ip) @ jump to next instruction 3929 /* 10-11 instructions */ 3930 3931 3932/* ------------------------------ */ 3933 .balign 64 3934.L_OP_INT_TO_BYTE: /* 0x8d */ 3935/* File: armv5te/OP_INT_TO_BYTE.S */ 3936/* File: armv5te/unop.S */ 3937 /* 3938 * Generic 32-bit unary operation. Provide an "instr" line that 3939 * specifies an instruction that performs "result = op r0". 3940 * This could be an ARM instruction or a function call. 3941 * 3942 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3943 * int-to-byte, int-to-char, int-to-short 3944 */ 3945 /* unop vA, vB */ 3946 mov r3, rINST, lsr #12 @ r3<- B 3947 mov r9, rINST, lsr #8 @ r9<- A+ 3948 GET_VREG(r0, r3) @ r0<- vB 3949 and r9, r9, #15 3950 mov r0, r0, asl #24 @ optional op; may set condition codes 3951 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3952 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3953 GET_INST_OPCODE(ip) @ extract opcode from rINST 3954 SET_VREG(r0, r9) @ vAA<- r0 3955 GOTO_OPCODE(ip) @ jump to next instruction 3956 /* 9-10 instructions */ 3957 3958 3959/* ------------------------------ */ 3960 .balign 64 3961.L_OP_INT_TO_CHAR: /* 0x8e */ 3962/* File: armv5te/OP_INT_TO_CHAR.S */ 3963/* File: armv5te/unop.S */ 3964 /* 3965 * Generic 32-bit unary operation. Provide an "instr" line that 3966 * specifies an instruction that performs "result = op r0". 3967 * This could be an ARM instruction or a function call. 3968 * 3969 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3970 * int-to-byte, int-to-char, int-to-short 3971 */ 3972 /* unop vA, vB */ 3973 mov r3, rINST, lsr #12 @ r3<- B 3974 mov r9, rINST, lsr #8 @ r9<- A+ 3975 GET_VREG(r0, r3) @ r0<- vB 3976 and r9, r9, #15 3977 mov r0, r0, asl #16 @ optional op; may set condition codes 3978 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3979 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3980 GET_INST_OPCODE(ip) @ extract opcode from rINST 3981 SET_VREG(r0, r9) @ vAA<- r0 3982 GOTO_OPCODE(ip) @ jump to next instruction 3983 /* 9-10 instructions */ 3984 3985 3986/* ------------------------------ */ 3987 .balign 64 3988.L_OP_INT_TO_SHORT: /* 0x8f */ 3989/* File: armv5te/OP_INT_TO_SHORT.S */ 3990/* File: armv5te/unop.S */ 3991 /* 3992 * Generic 32-bit unary operation. Provide an "instr" line that 3993 * specifies an instruction that performs "result = op r0". 3994 * This could be an ARM instruction or a function call. 3995 * 3996 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3997 * int-to-byte, int-to-char, int-to-short 3998 */ 3999 /* unop vA, vB */ 4000 mov r3, rINST, lsr #12 @ r3<- B 4001 mov r9, rINST, lsr #8 @ r9<- A+ 4002 GET_VREG(r0, r3) @ r0<- vB 4003 and r9, r9, #15 4004 mov r0, r0, asl #16 @ optional op; may set condition codes 4005 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4006 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4007 GET_INST_OPCODE(ip) @ extract opcode from rINST 4008 SET_VREG(r0, r9) @ vAA<- r0 4009 GOTO_OPCODE(ip) @ jump to next instruction 4010 /* 9-10 instructions */ 4011 4012 4013/* ------------------------------ */ 4014 .balign 64 4015.L_OP_ADD_INT: /* 0x90 */ 4016/* File: armv5te/OP_ADD_INT.S */ 4017/* File: armv5te/binop.S */ 4018 /* 4019 * Generic 32-bit binary operation. Provide an "instr" line that 4020 * specifies an instruction that performs "result = r0 op r1". 4021 * This could be an ARM instruction or a function call. (If the result 4022 * comes back in a register other than r0, you can override "result".) 4023 * 4024 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4025 * vCC (r1). Useful for integer division and modulus. Note that we 4026 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4027 * handles it correctly. 4028 * 4029 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4030 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4031 * mul-float, div-float, rem-float 4032 */ 4033 /* binop vAA, vBB, vCC */ 4034 FETCH(r0, 1) @ r0<- CCBB 4035 mov r9, rINST, lsr #8 @ r9<- AA 4036 mov r3, r0, lsr #8 @ r3<- CC 4037 and r2, r0, #255 @ r2<- BB 4038 GET_VREG(r1, r3) @ r1<- vCC 4039 GET_VREG(r0, r2) @ r0<- vBB 4040 .if 0 4041 cmp r1, #0 @ is second operand zero? 4042 beq common_errDivideByZero 4043 .endif 4044 4045 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4046 @ optional op; may set condition codes 4047 add r0, r0, r1 @ r0<- op, r0-r3 changed 4048 GET_INST_OPCODE(ip) @ extract opcode from rINST 4049 SET_VREG(r0, r9) @ vAA<- r0 4050 GOTO_OPCODE(ip) @ jump to next instruction 4051 /* 11-14 instructions */ 4052 4053 4054 4055/* ------------------------------ */ 4056 .balign 64 4057.L_OP_SUB_INT: /* 0x91 */ 4058/* File: armv5te/OP_SUB_INT.S */ 4059/* File: armv5te/binop.S */ 4060 /* 4061 * Generic 32-bit binary operation. Provide an "instr" line that 4062 * specifies an instruction that performs "result = r0 op r1". 4063 * This could be an ARM instruction or a function call. (If the result 4064 * comes back in a register other than r0, you can override "result".) 4065 * 4066 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4067 * vCC (r1). Useful for integer division and modulus. Note that we 4068 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4069 * handles it correctly. 4070 * 4071 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4072 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4073 * mul-float, div-float, rem-float 4074 */ 4075 /* binop vAA, vBB, vCC */ 4076 FETCH(r0, 1) @ r0<- CCBB 4077 mov r9, rINST, lsr #8 @ r9<- AA 4078 mov r3, r0, lsr #8 @ r3<- CC 4079 and r2, r0, #255 @ r2<- BB 4080 GET_VREG(r1, r3) @ r1<- vCC 4081 GET_VREG(r0, r2) @ r0<- vBB 4082 .if 0 4083 cmp r1, #0 @ is second operand zero? 4084 beq common_errDivideByZero 4085 .endif 4086 4087 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4088 @ optional op; may set condition codes 4089 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4090 GET_INST_OPCODE(ip) @ extract opcode from rINST 4091 SET_VREG(r0, r9) @ vAA<- r0 4092 GOTO_OPCODE(ip) @ jump to next instruction 4093 /* 11-14 instructions */ 4094 4095 4096 4097/* ------------------------------ */ 4098 .balign 64 4099.L_OP_MUL_INT: /* 0x92 */ 4100/* File: armv5te/OP_MUL_INT.S */ 4101/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4102/* File: armv5te/binop.S */ 4103 /* 4104 * Generic 32-bit binary operation. Provide an "instr" line that 4105 * specifies an instruction that performs "result = r0 op r1". 4106 * This could be an ARM instruction or a function call. (If the result 4107 * comes back in a register other than r0, you can override "result".) 4108 * 4109 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4110 * vCC (r1). Useful for integer division and modulus. Note that we 4111 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4112 * handles it correctly. 4113 * 4114 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4115 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4116 * mul-float, div-float, rem-float 4117 */ 4118 /* binop vAA, vBB, vCC */ 4119 FETCH(r0, 1) @ r0<- CCBB 4120 mov r9, rINST, lsr #8 @ r9<- AA 4121 mov r3, r0, lsr #8 @ r3<- CC 4122 and r2, r0, #255 @ r2<- BB 4123 GET_VREG(r1, r3) @ r1<- vCC 4124 GET_VREG(r0, r2) @ r0<- vBB 4125 .if 0 4126 cmp r1, #0 @ is second operand zero? 4127 beq common_errDivideByZero 4128 .endif 4129 4130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4131 @ optional op; may set condition codes 4132 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4133 GET_INST_OPCODE(ip) @ extract opcode from rINST 4134 SET_VREG(r0, r9) @ vAA<- r0 4135 GOTO_OPCODE(ip) @ jump to next instruction 4136 /* 11-14 instructions */ 4137 4138 4139 4140/* ------------------------------ */ 4141 .balign 64 4142.L_OP_DIV_INT: /* 0x93 */ 4143/* File: armv5te/OP_DIV_INT.S */ 4144/* File: armv5te/binop.S */ 4145 /* 4146 * Generic 32-bit binary operation. Provide an "instr" line that 4147 * specifies an instruction that performs "result = r0 op r1". 4148 * This could be an ARM instruction or a function call. (If the result 4149 * comes back in a register other than r0, you can override "result".) 4150 * 4151 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4152 * vCC (r1). Useful for integer division and modulus. Note that we 4153 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4154 * handles it correctly. 4155 * 4156 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4157 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4158 * mul-float, div-float, rem-float 4159 */ 4160 /* binop vAA, vBB, vCC */ 4161 FETCH(r0, 1) @ r0<- CCBB 4162 mov r9, rINST, lsr #8 @ r9<- AA 4163 mov r3, r0, lsr #8 @ r3<- CC 4164 and r2, r0, #255 @ r2<- BB 4165 GET_VREG(r1, r3) @ r1<- vCC 4166 GET_VREG(r0, r2) @ r0<- vBB 4167 .if 1 4168 cmp r1, #0 @ is second operand zero? 4169 beq common_errDivideByZero 4170 .endif 4171 4172 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4173 @ optional op; may set condition codes 4174 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4175 GET_INST_OPCODE(ip) @ extract opcode from rINST 4176 SET_VREG(r0, r9) @ vAA<- r0 4177 GOTO_OPCODE(ip) @ jump to next instruction 4178 /* 11-14 instructions */ 4179 4180 4181 4182/* ------------------------------ */ 4183 .balign 64 4184.L_OP_REM_INT: /* 0x94 */ 4185/* File: armv5te/OP_REM_INT.S */ 4186/* idivmod returns quotient in r0 and remainder in r1 */ 4187/* File: armv5te/binop.S */ 4188 /* 4189 * Generic 32-bit binary operation. Provide an "instr" line that 4190 * specifies an instruction that performs "result = r0 op r1". 4191 * This could be an ARM instruction or a function call. (If the result 4192 * comes back in a register other than r0, you can override "result".) 4193 * 4194 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4195 * vCC (r1). Useful for integer division and modulus. Note that we 4196 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4197 * handles it correctly. 4198 * 4199 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4200 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4201 * mul-float, div-float, rem-float 4202 */ 4203 /* binop vAA, vBB, vCC */ 4204 FETCH(r0, 1) @ r0<- CCBB 4205 mov r9, rINST, lsr #8 @ r9<- AA 4206 mov r3, r0, lsr #8 @ r3<- CC 4207 and r2, r0, #255 @ r2<- BB 4208 GET_VREG(r1, r3) @ r1<- vCC 4209 GET_VREG(r0, r2) @ r0<- vBB 4210 .if 1 4211 cmp r1, #0 @ is second operand zero? 4212 beq common_errDivideByZero 4213 .endif 4214 4215 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4216 @ optional op; may set condition codes 4217 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4218 GET_INST_OPCODE(ip) @ extract opcode from rINST 4219 SET_VREG(r1, r9) @ vAA<- r1 4220 GOTO_OPCODE(ip) @ jump to next instruction 4221 /* 11-14 instructions */ 4222 4223 4224 4225/* ------------------------------ */ 4226 .balign 64 4227.L_OP_AND_INT: /* 0x95 */ 4228/* File: armv5te/OP_AND_INT.S */ 4229/* File: armv5te/binop.S */ 4230 /* 4231 * Generic 32-bit binary operation. Provide an "instr" line that 4232 * specifies an instruction that performs "result = r0 op r1". 4233 * This could be an ARM instruction or a function call. (If the result 4234 * comes back in a register other than r0, you can override "result".) 4235 * 4236 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4237 * vCC (r1). Useful for integer division and modulus. Note that we 4238 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4239 * handles it correctly. 4240 * 4241 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4242 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4243 * mul-float, div-float, rem-float 4244 */ 4245 /* binop vAA, vBB, vCC */ 4246 FETCH(r0, 1) @ r0<- CCBB 4247 mov r9, rINST, lsr #8 @ r9<- AA 4248 mov r3, r0, lsr #8 @ r3<- CC 4249 and r2, r0, #255 @ r2<- BB 4250 GET_VREG(r1, r3) @ r1<- vCC 4251 GET_VREG(r0, r2) @ r0<- vBB 4252 .if 0 4253 cmp r1, #0 @ is second operand zero? 4254 beq common_errDivideByZero 4255 .endif 4256 4257 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4258 @ optional op; may set condition codes 4259 and r0, r0, r1 @ r0<- op, r0-r3 changed 4260 GET_INST_OPCODE(ip) @ extract opcode from rINST 4261 SET_VREG(r0, r9) @ vAA<- r0 4262 GOTO_OPCODE(ip) @ jump to next instruction 4263 /* 11-14 instructions */ 4264 4265 4266 4267/* ------------------------------ */ 4268 .balign 64 4269.L_OP_OR_INT: /* 0x96 */ 4270/* File: armv5te/OP_OR_INT.S */ 4271/* File: armv5te/binop.S */ 4272 /* 4273 * Generic 32-bit binary operation. Provide an "instr" line that 4274 * specifies an instruction that performs "result = r0 op r1". 4275 * This could be an ARM instruction or a function call. (If the result 4276 * comes back in a register other than r0, you can override "result".) 4277 * 4278 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4279 * vCC (r1). Useful for integer division and modulus. Note that we 4280 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4281 * handles it correctly. 4282 * 4283 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4284 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4285 * mul-float, div-float, rem-float 4286 */ 4287 /* binop vAA, vBB, vCC */ 4288 FETCH(r0, 1) @ r0<- CCBB 4289 mov r9, rINST, lsr #8 @ r9<- AA 4290 mov r3, r0, lsr #8 @ r3<- CC 4291 and r2, r0, #255 @ r2<- BB 4292 GET_VREG(r1, r3) @ r1<- vCC 4293 GET_VREG(r0, r2) @ r0<- vBB 4294 .if 0 4295 cmp r1, #0 @ is second operand zero? 4296 beq common_errDivideByZero 4297 .endif 4298 4299 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4300 @ optional op; may set condition codes 4301 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4302 GET_INST_OPCODE(ip) @ extract opcode from rINST 4303 SET_VREG(r0, r9) @ vAA<- r0 4304 GOTO_OPCODE(ip) @ jump to next instruction 4305 /* 11-14 instructions */ 4306 4307 4308 4309/* ------------------------------ */ 4310 .balign 64 4311.L_OP_XOR_INT: /* 0x97 */ 4312/* File: armv5te/OP_XOR_INT.S */ 4313/* File: armv5te/binop.S */ 4314 /* 4315 * Generic 32-bit binary operation. Provide an "instr" line that 4316 * specifies an instruction that performs "result = r0 op r1". 4317 * This could be an ARM instruction or a function call. (If the result 4318 * comes back in a register other than r0, you can override "result".) 4319 * 4320 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4321 * vCC (r1). Useful for integer division and modulus. Note that we 4322 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4323 * handles it correctly. 4324 * 4325 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4326 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4327 * mul-float, div-float, rem-float 4328 */ 4329 /* binop vAA, vBB, vCC */ 4330 FETCH(r0, 1) @ r0<- CCBB 4331 mov r9, rINST, lsr #8 @ r9<- AA 4332 mov r3, r0, lsr #8 @ r3<- CC 4333 and r2, r0, #255 @ r2<- BB 4334 GET_VREG(r1, r3) @ r1<- vCC 4335 GET_VREG(r0, r2) @ r0<- vBB 4336 .if 0 4337 cmp r1, #0 @ is second operand zero? 4338 beq common_errDivideByZero 4339 .endif 4340 4341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4342 @ optional op; may set condition codes 4343 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4344 GET_INST_OPCODE(ip) @ extract opcode from rINST 4345 SET_VREG(r0, r9) @ vAA<- r0 4346 GOTO_OPCODE(ip) @ jump to next instruction 4347 /* 11-14 instructions */ 4348 4349 4350 4351/* ------------------------------ */ 4352 .balign 64 4353.L_OP_SHL_INT: /* 0x98 */ 4354/* File: armv5te/OP_SHL_INT.S */ 4355/* File: armv5te/binop.S */ 4356 /* 4357 * Generic 32-bit binary operation. Provide an "instr" line that 4358 * specifies an instruction that performs "result = r0 op r1". 4359 * This could be an ARM instruction or a function call. (If the result 4360 * comes back in a register other than r0, you can override "result".) 4361 * 4362 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4363 * vCC (r1). Useful for integer division and modulus. Note that we 4364 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4365 * handles it correctly. 4366 * 4367 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4368 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4369 * mul-float, div-float, rem-float 4370 */ 4371 /* binop vAA, vBB, vCC */ 4372 FETCH(r0, 1) @ r0<- CCBB 4373 mov r9, rINST, lsr #8 @ r9<- AA 4374 mov r3, r0, lsr #8 @ r3<- CC 4375 and r2, r0, #255 @ r2<- BB 4376 GET_VREG(r1, r3) @ r1<- vCC 4377 GET_VREG(r0, r2) @ r0<- vBB 4378 .if 0 4379 cmp r1, #0 @ is second operand zero? 4380 beq common_errDivideByZero 4381 .endif 4382 4383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4384 and r1, r1, #31 @ optional op; may set condition codes 4385 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4386 GET_INST_OPCODE(ip) @ extract opcode from rINST 4387 SET_VREG(r0, r9) @ vAA<- r0 4388 GOTO_OPCODE(ip) @ jump to next instruction 4389 /* 11-14 instructions */ 4390 4391 4392 4393/* ------------------------------ */ 4394 .balign 64 4395.L_OP_SHR_INT: /* 0x99 */ 4396/* File: armv5te/OP_SHR_INT.S */ 4397/* File: armv5te/binop.S */ 4398 /* 4399 * Generic 32-bit binary operation. Provide an "instr" line that 4400 * specifies an instruction that performs "result = r0 op r1". 4401 * This could be an ARM instruction or a function call. (If the result 4402 * comes back in a register other than r0, you can override "result".) 4403 * 4404 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4405 * vCC (r1). Useful for integer division and modulus. Note that we 4406 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4407 * handles it correctly. 4408 * 4409 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4410 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4411 * mul-float, div-float, rem-float 4412 */ 4413 /* binop vAA, vBB, vCC */ 4414 FETCH(r0, 1) @ r0<- CCBB 4415 mov r9, rINST, lsr #8 @ r9<- AA 4416 mov r3, r0, lsr #8 @ r3<- CC 4417 and r2, r0, #255 @ r2<- BB 4418 GET_VREG(r1, r3) @ r1<- vCC 4419 GET_VREG(r0, r2) @ r0<- vBB 4420 .if 0 4421 cmp r1, #0 @ is second operand zero? 4422 beq common_errDivideByZero 4423 .endif 4424 4425 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4426 and r1, r1, #31 @ optional op; may set condition codes 4427 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4428 GET_INST_OPCODE(ip) @ extract opcode from rINST 4429 SET_VREG(r0, r9) @ vAA<- r0 4430 GOTO_OPCODE(ip) @ jump to next instruction 4431 /* 11-14 instructions */ 4432 4433 4434 4435/* ------------------------------ */ 4436 .balign 64 4437.L_OP_USHR_INT: /* 0x9a */ 4438/* File: armv5te/OP_USHR_INT.S */ 4439/* File: armv5te/binop.S */ 4440 /* 4441 * Generic 32-bit binary operation. Provide an "instr" line that 4442 * specifies an instruction that performs "result = r0 op r1". 4443 * This could be an ARM instruction or a function call. (If the result 4444 * comes back in a register other than r0, you can override "result".) 4445 * 4446 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4447 * vCC (r1). Useful for integer division and modulus. Note that we 4448 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4449 * handles it correctly. 4450 * 4451 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4452 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4453 * mul-float, div-float, rem-float 4454 */ 4455 /* binop vAA, vBB, vCC */ 4456 FETCH(r0, 1) @ r0<- CCBB 4457 mov r9, rINST, lsr #8 @ r9<- AA 4458 mov r3, r0, lsr #8 @ r3<- CC 4459 and r2, r0, #255 @ r2<- BB 4460 GET_VREG(r1, r3) @ r1<- vCC 4461 GET_VREG(r0, r2) @ r0<- vBB 4462 .if 0 4463 cmp r1, #0 @ is second operand zero? 4464 beq common_errDivideByZero 4465 .endif 4466 4467 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4468 and r1, r1, #31 @ optional op; may set condition codes 4469 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4470 GET_INST_OPCODE(ip) @ extract opcode from rINST 4471 SET_VREG(r0, r9) @ vAA<- r0 4472 GOTO_OPCODE(ip) @ jump to next instruction 4473 /* 11-14 instructions */ 4474 4475 4476 4477/* ------------------------------ */ 4478 .balign 64 4479.L_OP_ADD_LONG: /* 0x9b */ 4480/* File: armv5te/OP_ADD_LONG.S */ 4481/* File: armv5te/binopWide.S */ 4482 /* 4483 * Generic 64-bit binary operation. Provide an "instr" line that 4484 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4485 * This could be an ARM instruction or a function call. (If the result 4486 * comes back in a register other than r0, you can override "result".) 4487 * 4488 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4489 * vCC (r1). Useful for integer division and modulus. 4490 * 4491 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4492 * xor-long, add-double, sub-double, mul-double, div-double, 4493 * rem-double 4494 * 4495 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4496 */ 4497 /* binop vAA, vBB, vCC */ 4498 FETCH(r0, 1) @ r0<- CCBB 4499 mov r9, rINST, lsr #8 @ r9<- AA 4500 and r2, r0, #255 @ r2<- BB 4501 mov r3, r0, lsr #8 @ r3<- CC 4502 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4503 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4504 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4505 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4506 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4507 .if 0 4508 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4509 beq common_errDivideByZero 4510 .endif 4511 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4512 4513 adds r0, r0, r2 @ optional op; may set condition codes 4514 adc r1, r1, r3 @ result<- op, r0-r3 changed 4515 GET_INST_OPCODE(ip) @ extract opcode from rINST 4516 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4517 GOTO_OPCODE(ip) @ jump to next instruction 4518 /* 14-17 instructions */ 4519 4520 4521 4522/* ------------------------------ */ 4523 .balign 64 4524.L_OP_SUB_LONG: /* 0x9c */ 4525/* File: armv5te/OP_SUB_LONG.S */ 4526/* File: armv5te/binopWide.S */ 4527 /* 4528 * Generic 64-bit binary operation. Provide an "instr" line that 4529 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4530 * This could be an ARM instruction or a function call. (If the result 4531 * comes back in a register other than r0, you can override "result".) 4532 * 4533 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4534 * vCC (r1). Useful for integer division and modulus. 4535 * 4536 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4537 * xor-long, add-double, sub-double, mul-double, div-double, 4538 * rem-double 4539 * 4540 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4541 */ 4542 /* binop vAA, vBB, vCC */ 4543 FETCH(r0, 1) @ r0<- CCBB 4544 mov r9, rINST, lsr #8 @ r9<- AA 4545 and r2, r0, #255 @ r2<- BB 4546 mov r3, r0, lsr #8 @ r3<- CC 4547 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4548 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4549 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4550 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4551 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4552 .if 0 4553 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4554 beq common_errDivideByZero 4555 .endif 4556 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4557 4558 subs r0, r0, r2 @ optional op; may set condition codes 4559 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4560 GET_INST_OPCODE(ip) @ extract opcode from rINST 4561 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4562 GOTO_OPCODE(ip) @ jump to next instruction 4563 /* 14-17 instructions */ 4564 4565 4566 4567/* ------------------------------ */ 4568 .balign 64 4569.L_OP_MUL_LONG: /* 0x9d */ 4570/* File: armv5te/OP_MUL_LONG.S */ 4571 /* 4572 * Signed 64-bit integer multiply. 4573 * 4574 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4575 * WX 4576 * x YZ 4577 * -------- 4578 * ZW ZX 4579 * YW YX 4580 * 4581 * The low word of the result holds ZX, the high word holds 4582 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4583 * it doesn't fit in the low 64 bits. 4584 * 4585 * Unlike most ARM math operations, multiply instructions have 4586 * restrictions on using the same register more than once (Rd and Rm 4587 * cannot be the same). 4588 */ 4589 /* mul-long vAA, vBB, vCC */ 4590 FETCH(r0, 1) @ r0<- CCBB 4591 and r2, r0, #255 @ r2<- BB 4592 mov r3, r0, lsr #8 @ r3<- CC 4593 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4594 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4595 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4596 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4597 mul ip, r2, r1 @ ip<- ZxW 4598 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4599 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4600 mov r0, rINST, lsr #8 @ r0<- AA 4601 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4602 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4603 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4604 b .LOP_MUL_LONG_finish 4605 4606/* ------------------------------ */ 4607 .balign 64 4608.L_OP_DIV_LONG: /* 0x9e */ 4609/* File: armv5te/OP_DIV_LONG.S */ 4610/* File: armv5te/binopWide.S */ 4611 /* 4612 * Generic 64-bit binary operation. Provide an "instr" line that 4613 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4614 * This could be an ARM instruction or a function call. (If the result 4615 * comes back in a register other than r0, you can override "result".) 4616 * 4617 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4618 * vCC (r1). Useful for integer division and modulus. 4619 * 4620 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4621 * xor-long, add-double, sub-double, mul-double, div-double, 4622 * rem-double 4623 * 4624 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4625 */ 4626 /* binop vAA, vBB, vCC */ 4627 FETCH(r0, 1) @ r0<- CCBB 4628 mov r9, rINST, lsr #8 @ r9<- AA 4629 and r2, r0, #255 @ r2<- BB 4630 mov r3, r0, lsr #8 @ r3<- CC 4631 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4632 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4633 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4634 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4635 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4636 .if 1 4637 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4638 beq common_errDivideByZero 4639 .endif 4640 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4641 4642 @ optional op; may set condition codes 4643 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4644 GET_INST_OPCODE(ip) @ extract opcode from rINST 4645 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4646 GOTO_OPCODE(ip) @ jump to next instruction 4647 /* 14-17 instructions */ 4648 4649 4650 4651/* ------------------------------ */ 4652 .balign 64 4653.L_OP_REM_LONG: /* 0x9f */ 4654/* File: armv5te/OP_REM_LONG.S */ 4655/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4656/* File: armv5te/binopWide.S */ 4657 /* 4658 * Generic 64-bit binary operation. Provide an "instr" line that 4659 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4660 * This could be an ARM instruction or a function call. (If the result 4661 * comes back in a register other than r0, you can override "result".) 4662 * 4663 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4664 * vCC (r1). Useful for integer division and modulus. 4665 * 4666 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4667 * xor-long, add-double, sub-double, mul-double, div-double, 4668 * rem-double 4669 * 4670 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4671 */ 4672 /* binop vAA, vBB, vCC */ 4673 FETCH(r0, 1) @ r0<- CCBB 4674 mov r9, rINST, lsr #8 @ r9<- AA 4675 and r2, r0, #255 @ r2<- BB 4676 mov r3, r0, lsr #8 @ r3<- CC 4677 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4678 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4679 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4680 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4681 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4682 .if 1 4683 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4684 beq common_errDivideByZero 4685 .endif 4686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4687 4688 @ optional op; may set condition codes 4689 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4690 GET_INST_OPCODE(ip) @ extract opcode from rINST 4691 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4692 GOTO_OPCODE(ip) @ jump to next instruction 4693 /* 14-17 instructions */ 4694 4695 4696 4697/* ------------------------------ */ 4698 .balign 64 4699.L_OP_AND_LONG: /* 0xa0 */ 4700/* File: armv5te/OP_AND_LONG.S */ 4701/* File: armv5te/binopWide.S */ 4702 /* 4703 * Generic 64-bit binary operation. Provide an "instr" line that 4704 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4705 * This could be an ARM instruction or a function call. (If the result 4706 * comes back in a register other than r0, you can override "result".) 4707 * 4708 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4709 * vCC (r1). Useful for integer division and modulus. 4710 * 4711 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4712 * xor-long, add-double, sub-double, mul-double, div-double, 4713 * rem-double 4714 * 4715 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4716 */ 4717 /* binop vAA, vBB, vCC */ 4718 FETCH(r0, 1) @ r0<- CCBB 4719 mov r9, rINST, lsr #8 @ r9<- AA 4720 and r2, r0, #255 @ r2<- BB 4721 mov r3, r0, lsr #8 @ r3<- CC 4722 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4723 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4724 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4725 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4726 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4727 .if 0 4728 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4729 beq common_errDivideByZero 4730 .endif 4731 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4732 4733 and r0, r0, r2 @ optional op; may set condition codes 4734 and r1, r1, r3 @ result<- op, r0-r3 changed 4735 GET_INST_OPCODE(ip) @ extract opcode from rINST 4736 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4737 GOTO_OPCODE(ip) @ jump to next instruction 4738 /* 14-17 instructions */ 4739 4740 4741 4742/* ------------------------------ */ 4743 .balign 64 4744.L_OP_OR_LONG: /* 0xa1 */ 4745/* File: armv5te/OP_OR_LONG.S */ 4746/* File: armv5te/binopWide.S */ 4747 /* 4748 * Generic 64-bit binary operation. Provide an "instr" line that 4749 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4750 * This could be an ARM instruction or a function call. (If the result 4751 * comes back in a register other than r0, you can override "result".) 4752 * 4753 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4754 * vCC (r1). Useful for integer division and modulus. 4755 * 4756 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4757 * xor-long, add-double, sub-double, mul-double, div-double, 4758 * rem-double 4759 * 4760 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4761 */ 4762 /* binop vAA, vBB, vCC */ 4763 FETCH(r0, 1) @ r0<- CCBB 4764 mov r9, rINST, lsr #8 @ r9<- AA 4765 and r2, r0, #255 @ r2<- BB 4766 mov r3, r0, lsr #8 @ r3<- CC 4767 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4768 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4769 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4770 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4771 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4772 .if 0 4773 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4774 beq common_errDivideByZero 4775 .endif 4776 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4777 4778 orr r0, r0, r2 @ optional op; may set condition codes 4779 orr r1, r1, r3 @ result<- op, r0-r3 changed 4780 GET_INST_OPCODE(ip) @ extract opcode from rINST 4781 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4782 GOTO_OPCODE(ip) @ jump to next instruction 4783 /* 14-17 instructions */ 4784 4785 4786 4787/* ------------------------------ */ 4788 .balign 64 4789.L_OP_XOR_LONG: /* 0xa2 */ 4790/* File: armv5te/OP_XOR_LONG.S */ 4791/* File: armv5te/binopWide.S */ 4792 /* 4793 * Generic 64-bit binary operation. Provide an "instr" line that 4794 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4795 * This could be an ARM instruction or a function call. (If the result 4796 * comes back in a register other than r0, you can override "result".) 4797 * 4798 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4799 * vCC (r1). Useful for integer division and modulus. 4800 * 4801 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4802 * xor-long, add-double, sub-double, mul-double, div-double, 4803 * rem-double 4804 * 4805 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4806 */ 4807 /* binop vAA, vBB, vCC */ 4808 FETCH(r0, 1) @ r0<- CCBB 4809 mov r9, rINST, lsr #8 @ r9<- AA 4810 and r2, r0, #255 @ r2<- BB 4811 mov r3, r0, lsr #8 @ r3<- CC 4812 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4813 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4814 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4815 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4816 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4817 .if 0 4818 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4819 beq common_errDivideByZero 4820 .endif 4821 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4822 4823 eor r0, r0, r2 @ optional op; may set condition codes 4824 eor r1, r1, r3 @ result<- op, r0-r3 changed 4825 GET_INST_OPCODE(ip) @ extract opcode from rINST 4826 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4827 GOTO_OPCODE(ip) @ jump to next instruction 4828 /* 14-17 instructions */ 4829 4830 4831 4832/* ------------------------------ */ 4833 .balign 64 4834.L_OP_SHL_LONG: /* 0xa3 */ 4835/* File: armv5te/OP_SHL_LONG.S */ 4836 /* 4837 * Long integer shift. This is different from the generic 32/64-bit 4838 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4839 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4840 * 6 bits of the shift distance. 4841 */ 4842 /* shl-long vAA, vBB, vCC */ 4843 FETCH(r0, 1) @ r0<- CCBB 4844 mov r9, rINST, lsr #8 @ r9<- AA 4845 and r3, r0, #255 @ r3<- BB 4846 mov r0, r0, lsr #8 @ r0<- CC 4847 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4848 GET_VREG(r2, r0) @ r2<- vCC 4849 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4850 and r2, r2, #63 @ r2<- r2 & 0x3f 4851 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4852 4853 mov r1, r1, asl r2 @ r1<- r1 << r2 4854 rsb r3, r2, #32 @ r3<- 32 - r2 4855 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4856 subs ip, r2, #32 @ ip<- r2 - 32 4857 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4859 b .LOP_SHL_LONG_finish 4860 4861/* ------------------------------ */ 4862 .balign 64 4863.L_OP_SHR_LONG: /* 0xa4 */ 4864/* File: armv5te/OP_SHR_LONG.S */ 4865 /* 4866 * Long integer shift. This is different from the generic 32/64-bit 4867 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4868 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4869 * 6 bits of the shift distance. 4870 */ 4871 /* shr-long vAA, vBB, vCC */ 4872 FETCH(r0, 1) @ r0<- CCBB 4873 mov r9, rINST, lsr #8 @ r9<- AA 4874 and r3, r0, #255 @ r3<- BB 4875 mov r0, r0, lsr #8 @ r0<- CC 4876 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4877 GET_VREG(r2, r0) @ r2<- vCC 4878 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4879 and r2, r2, #63 @ r0<- r0 & 0x3f 4880 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4881 4882 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4883 rsb r3, r2, #32 @ r3<- 32 - r2 4884 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4885 subs ip, r2, #32 @ ip<- r2 - 32 4886 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4887 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4888 b .LOP_SHR_LONG_finish 4889 4890/* ------------------------------ */ 4891 .balign 64 4892.L_OP_USHR_LONG: /* 0xa5 */ 4893/* File: armv5te/OP_USHR_LONG.S */ 4894 /* 4895 * Long integer shift. This is different from the generic 32/64-bit 4896 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4897 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4898 * 6 bits of the shift distance. 4899 */ 4900 /* ushr-long vAA, vBB, vCC */ 4901 FETCH(r0, 1) @ r0<- CCBB 4902 mov r9, rINST, lsr #8 @ r9<- AA 4903 and r3, r0, #255 @ r3<- BB 4904 mov r0, r0, lsr #8 @ r0<- CC 4905 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4906 GET_VREG(r2, r0) @ r2<- vCC 4907 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4908 and r2, r2, #63 @ r0<- r0 & 0x3f 4909 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4910 4911 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4912 rsb r3, r2, #32 @ r3<- 32 - r2 4913 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4914 subs ip, r2, #32 @ ip<- r2 - 32 4915 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4917 b .LOP_USHR_LONG_finish 4918 4919/* ------------------------------ */ 4920 .balign 64 4921.L_OP_ADD_FLOAT: /* 0xa6 */ 4922/* File: armv5te/OP_ADD_FLOAT.S */ 4923/* File: armv5te/binop.S */ 4924 /* 4925 * Generic 32-bit binary operation. Provide an "instr" line that 4926 * specifies an instruction that performs "result = r0 op r1". 4927 * This could be an ARM instruction or a function call. (If the result 4928 * comes back in a register other than r0, you can override "result".) 4929 * 4930 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4931 * vCC (r1). Useful for integer division and modulus. Note that we 4932 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4933 * handles it correctly. 4934 * 4935 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4936 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4937 * mul-float, div-float, rem-float 4938 */ 4939 /* binop vAA, vBB, vCC */ 4940 FETCH(r0, 1) @ r0<- CCBB 4941 mov r9, rINST, lsr #8 @ r9<- AA 4942 mov r3, r0, lsr #8 @ r3<- CC 4943 and r2, r0, #255 @ r2<- BB 4944 GET_VREG(r1, r3) @ r1<- vCC 4945 GET_VREG(r0, r2) @ r0<- vBB 4946 .if 0 4947 cmp r1, #0 @ is second operand zero? 4948 beq common_errDivideByZero 4949 .endif 4950 4951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4952 @ optional op; may set condition codes 4953 bl __aeabi_fadd @ r0<- op, r0-r3 changed 4954 GET_INST_OPCODE(ip) @ extract opcode from rINST 4955 SET_VREG(r0, r9) @ vAA<- r0 4956 GOTO_OPCODE(ip) @ jump to next instruction 4957 /* 11-14 instructions */ 4958 4959 4960 4961/* ------------------------------ */ 4962 .balign 64 4963.L_OP_SUB_FLOAT: /* 0xa7 */ 4964/* File: armv5te/OP_SUB_FLOAT.S */ 4965/* File: armv5te/binop.S */ 4966 /* 4967 * Generic 32-bit binary operation. Provide an "instr" line that 4968 * specifies an instruction that performs "result = r0 op r1". 4969 * This could be an ARM instruction or a function call. (If the result 4970 * comes back in a register other than r0, you can override "result".) 4971 * 4972 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4973 * vCC (r1). Useful for integer division and modulus. Note that we 4974 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4975 * handles it correctly. 4976 * 4977 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4978 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4979 * mul-float, div-float, rem-float 4980 */ 4981 /* binop vAA, vBB, vCC */ 4982 FETCH(r0, 1) @ r0<- CCBB 4983 mov r9, rINST, lsr #8 @ r9<- AA 4984 mov r3, r0, lsr #8 @ r3<- CC 4985 and r2, r0, #255 @ r2<- BB 4986 GET_VREG(r1, r3) @ r1<- vCC 4987 GET_VREG(r0, r2) @ r0<- vBB 4988 .if 0 4989 cmp r1, #0 @ is second operand zero? 4990 beq common_errDivideByZero 4991 .endif 4992 4993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4994 @ optional op; may set condition codes 4995 bl __aeabi_fsub @ r0<- op, r0-r3 changed 4996 GET_INST_OPCODE(ip) @ extract opcode from rINST 4997 SET_VREG(r0, r9) @ vAA<- r0 4998 GOTO_OPCODE(ip) @ jump to next instruction 4999 /* 11-14 instructions */ 5000 5001 5002 5003/* ------------------------------ */ 5004 .balign 64 5005.L_OP_MUL_FLOAT: /* 0xa8 */ 5006/* File: armv5te/OP_MUL_FLOAT.S */ 5007/* File: armv5te/binop.S */ 5008 /* 5009 * Generic 32-bit binary operation. Provide an "instr" line that 5010 * specifies an instruction that performs "result = r0 op r1". 5011 * This could be an ARM instruction or a function call. (If the result 5012 * comes back in a register other than r0, you can override "result".) 5013 * 5014 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5015 * vCC (r1). Useful for integer division and modulus. Note that we 5016 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5017 * handles it correctly. 5018 * 5019 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5020 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5021 * mul-float, div-float, rem-float 5022 */ 5023 /* binop vAA, vBB, vCC */ 5024 FETCH(r0, 1) @ r0<- CCBB 5025 mov r9, rINST, lsr #8 @ r9<- AA 5026 mov r3, r0, lsr #8 @ r3<- CC 5027 and r2, r0, #255 @ r2<- BB 5028 GET_VREG(r1, r3) @ r1<- vCC 5029 GET_VREG(r0, r2) @ r0<- vBB 5030 .if 0 5031 cmp r1, #0 @ is second operand zero? 5032 beq common_errDivideByZero 5033 .endif 5034 5035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5036 @ optional op; may set condition codes 5037 bl __aeabi_fmul @ r0<- op, r0-r3 changed 5038 GET_INST_OPCODE(ip) @ extract opcode from rINST 5039 SET_VREG(r0, r9) @ vAA<- r0 5040 GOTO_OPCODE(ip) @ jump to next instruction 5041 /* 11-14 instructions */ 5042 5043 5044 5045/* ------------------------------ */ 5046 .balign 64 5047.L_OP_DIV_FLOAT: /* 0xa9 */ 5048/* File: armv5te/OP_DIV_FLOAT.S */ 5049/* File: armv5te/binop.S */ 5050 /* 5051 * Generic 32-bit binary operation. Provide an "instr" line that 5052 * specifies an instruction that performs "result = r0 op r1". 5053 * This could be an ARM instruction or a function call. (If the result 5054 * comes back in a register other than r0, you can override "result".) 5055 * 5056 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5057 * vCC (r1). Useful for integer division and modulus. Note that we 5058 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5059 * handles it correctly. 5060 * 5061 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5062 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5063 * mul-float, div-float, rem-float 5064 */ 5065 /* binop vAA, vBB, vCC */ 5066 FETCH(r0, 1) @ r0<- CCBB 5067 mov r9, rINST, lsr #8 @ r9<- AA 5068 mov r3, r0, lsr #8 @ r3<- CC 5069 and r2, r0, #255 @ r2<- BB 5070 GET_VREG(r1, r3) @ r1<- vCC 5071 GET_VREG(r0, r2) @ r0<- vBB 5072 .if 0 5073 cmp r1, #0 @ is second operand zero? 5074 beq common_errDivideByZero 5075 .endif 5076 5077 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5078 @ optional op; may set condition codes 5079 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 5080 GET_INST_OPCODE(ip) @ extract opcode from rINST 5081 SET_VREG(r0, r9) @ vAA<- r0 5082 GOTO_OPCODE(ip) @ jump to next instruction 5083 /* 11-14 instructions */ 5084 5085 5086 5087/* ------------------------------ */ 5088 .balign 64 5089.L_OP_REM_FLOAT: /* 0xaa */ 5090/* File: armv5te/OP_REM_FLOAT.S */ 5091/* EABI doesn't define a float remainder function, but libm does */ 5092/* File: armv5te/binop.S */ 5093 /* 5094 * Generic 32-bit binary operation. Provide an "instr" line that 5095 * specifies an instruction that performs "result = r0 op r1". 5096 * This could be an ARM instruction or a function call. (If the result 5097 * comes back in a register other than r0, you can override "result".) 5098 * 5099 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5100 * vCC (r1). Useful for integer division and modulus. Note that we 5101 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5102 * handles it correctly. 5103 * 5104 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5105 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5106 * mul-float, div-float, rem-float 5107 */ 5108 /* binop vAA, vBB, vCC */ 5109 FETCH(r0, 1) @ r0<- CCBB 5110 mov r9, rINST, lsr #8 @ r9<- AA 5111 mov r3, r0, lsr #8 @ r3<- CC 5112 and r2, r0, #255 @ r2<- BB 5113 GET_VREG(r1, r3) @ r1<- vCC 5114 GET_VREG(r0, r2) @ r0<- vBB 5115 .if 0 5116 cmp r1, #0 @ is second operand zero? 5117 beq common_errDivideByZero 5118 .endif 5119 5120 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5121 @ optional op; may set condition codes 5122 bl fmodf @ r0<- op, r0-r3 changed 5123 GET_INST_OPCODE(ip) @ extract opcode from rINST 5124 SET_VREG(r0, r9) @ vAA<- r0 5125 GOTO_OPCODE(ip) @ jump to next instruction 5126 /* 11-14 instructions */ 5127 5128 5129 5130/* ------------------------------ */ 5131 .balign 64 5132.L_OP_ADD_DOUBLE: /* 0xab */ 5133/* File: armv5te/OP_ADD_DOUBLE.S */ 5134/* File: armv5te/binopWide.S */ 5135 /* 5136 * Generic 64-bit binary operation. Provide an "instr" line that 5137 * specifies an instruction that performs "result = r0-r1 op r2-r3". 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-long, sub-long, div-long, rem-long, and-long, or-long, 5145 * xor-long, add-double, sub-double, mul-double, div-double, 5146 * rem-double 5147 * 5148 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5149 */ 5150 /* binop vAA, vBB, vCC */ 5151 FETCH(r0, 1) @ r0<- CCBB 5152 mov r9, rINST, lsr #8 @ r9<- AA 5153 and r2, r0, #255 @ r2<- BB 5154 mov r3, r0, lsr #8 @ r3<- CC 5155 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5156 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5157 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5158 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5159 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5160 .if 0 5161 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5162 beq common_errDivideByZero 5163 .endif 5164 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5165 5166 @ optional op; may set condition codes 5167 bl __aeabi_dadd @ result<- op, r0-r3 changed 5168 GET_INST_OPCODE(ip) @ extract opcode from rINST 5169 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5170 GOTO_OPCODE(ip) @ jump to next instruction 5171 /* 14-17 instructions */ 5172 5173 5174 5175/* ------------------------------ */ 5176 .balign 64 5177.L_OP_SUB_DOUBLE: /* 0xac */ 5178/* File: armv5te/OP_SUB_DOUBLE.S */ 5179/* File: armv5te/binopWide.S */ 5180 /* 5181 * Generic 64-bit binary operation. Provide an "instr" line that 5182 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5183 * This could be an ARM instruction or a function call. (If the result 5184 * comes back in a register other than r0, you can override "result".) 5185 * 5186 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5187 * vCC (r1). Useful for integer division and modulus. 5188 * 5189 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5190 * xor-long, add-double, sub-double, mul-double, div-double, 5191 * rem-double 5192 * 5193 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5194 */ 5195 /* binop vAA, vBB, vCC */ 5196 FETCH(r0, 1) @ r0<- CCBB 5197 mov r9, rINST, lsr #8 @ r9<- AA 5198 and r2, r0, #255 @ r2<- BB 5199 mov r3, r0, lsr #8 @ r3<- CC 5200 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5201 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5202 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5203 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5204 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5205 .if 0 5206 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5207 beq common_errDivideByZero 5208 .endif 5209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5210 5211 @ optional op; may set condition codes 5212 bl __aeabi_dsub @ result<- op, r0-r3 changed 5213 GET_INST_OPCODE(ip) @ extract opcode from rINST 5214 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5215 GOTO_OPCODE(ip) @ jump to next instruction 5216 /* 14-17 instructions */ 5217 5218 5219 5220/* ------------------------------ */ 5221 .balign 64 5222.L_OP_MUL_DOUBLE: /* 0xad */ 5223/* File: armv5te/OP_MUL_DOUBLE.S */ 5224/* File: armv5te/binopWide.S */ 5225 /* 5226 * Generic 64-bit binary operation. Provide an "instr" line that 5227 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5228 * This could be an ARM instruction or a function call. (If the result 5229 * comes back in a register other than r0, you can override "result".) 5230 * 5231 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5232 * vCC (r1). Useful for integer division and modulus. 5233 * 5234 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5235 * xor-long, add-double, sub-double, mul-double, div-double, 5236 * rem-double 5237 * 5238 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5239 */ 5240 /* binop vAA, vBB, vCC */ 5241 FETCH(r0, 1) @ r0<- CCBB 5242 mov r9, rINST, lsr #8 @ r9<- AA 5243 and r2, r0, #255 @ r2<- BB 5244 mov r3, r0, lsr #8 @ r3<- CC 5245 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5246 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5247 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5248 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5249 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5250 .if 0 5251 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5252 beq common_errDivideByZero 5253 .endif 5254 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5255 5256 @ optional op; may set condition codes 5257 bl __aeabi_dmul @ result<- op, r0-r3 changed 5258 GET_INST_OPCODE(ip) @ extract opcode from rINST 5259 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5260 GOTO_OPCODE(ip) @ jump to next instruction 5261 /* 14-17 instructions */ 5262 5263 5264 5265/* ------------------------------ */ 5266 .balign 64 5267.L_OP_DIV_DOUBLE: /* 0xae */ 5268/* File: armv5te/OP_DIV_DOUBLE.S */ 5269/* File: armv5te/binopWide.S */ 5270 /* 5271 * Generic 64-bit binary operation. Provide an "instr" line that 5272 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5273 * This could be an ARM instruction or a function call. (If the result 5274 * comes back in a register other than r0, you can override "result".) 5275 * 5276 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5277 * vCC (r1). Useful for integer division and modulus. 5278 * 5279 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5280 * xor-long, add-double, sub-double, mul-double, div-double, 5281 * rem-double 5282 * 5283 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5284 */ 5285 /* binop vAA, vBB, vCC */ 5286 FETCH(r0, 1) @ r0<- CCBB 5287 mov r9, rINST, lsr #8 @ r9<- AA 5288 and r2, r0, #255 @ r2<- BB 5289 mov r3, r0, lsr #8 @ r3<- CC 5290 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5291 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5292 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5293 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5294 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5295 .if 0 5296 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5297 beq common_errDivideByZero 5298 .endif 5299 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5300 5301 @ optional op; may set condition codes 5302 bl __aeabi_ddiv @ result<- op, r0-r3 changed 5303 GET_INST_OPCODE(ip) @ extract opcode from rINST 5304 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5305 GOTO_OPCODE(ip) @ jump to next instruction 5306 /* 14-17 instructions */ 5307 5308 5309 5310/* ------------------------------ */ 5311 .balign 64 5312.L_OP_REM_DOUBLE: /* 0xaf */ 5313/* File: armv5te/OP_REM_DOUBLE.S */ 5314/* EABI doesn't define a double remainder function, but libm does */ 5315/* File: armv5te/binopWide.S */ 5316 /* 5317 * Generic 64-bit binary operation. Provide an "instr" line that 5318 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5319 * This could be an ARM instruction or a function call. (If the result 5320 * comes back in a register other than r0, you can override "result".) 5321 * 5322 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5323 * vCC (r1). Useful for integer division and modulus. 5324 * 5325 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5326 * xor-long, add-double, sub-double, mul-double, div-double, 5327 * rem-double 5328 * 5329 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5330 */ 5331 /* binop vAA, vBB, vCC */ 5332 FETCH(r0, 1) @ r0<- CCBB 5333 mov r9, rINST, lsr #8 @ r9<- AA 5334 and r2, r0, #255 @ r2<- BB 5335 mov r3, r0, lsr #8 @ r3<- CC 5336 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5337 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5338 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5339 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5340 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5341 .if 0 5342 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5343 beq common_errDivideByZero 5344 .endif 5345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5346 5347 @ optional op; may set condition codes 5348 bl fmod @ result<- op, r0-r3 changed 5349 GET_INST_OPCODE(ip) @ extract opcode from rINST 5350 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5351 GOTO_OPCODE(ip) @ jump to next instruction 5352 /* 14-17 instructions */ 5353 5354 5355 5356/* ------------------------------ */ 5357 .balign 64 5358.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5359/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5360/* File: armv5te/binop2addr.S */ 5361 /* 5362 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5363 * that specifies an instruction that performs "result = r0 op r1". 5364 * This could be an ARM instruction or a function call. (If the result 5365 * comes back in a register other than r0, you can override "result".) 5366 * 5367 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5368 * vCC (r1). Useful for integer division and modulus. 5369 * 5370 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5371 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5372 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5373 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5374 */ 5375 /* binop/2addr vA, vB */ 5376 mov r9, rINST, lsr #8 @ r9<- A+ 5377 mov r3, rINST, lsr #12 @ r3<- B 5378 and r9, r9, #15 5379 GET_VREG(r0, r9) @ r0<- vA 5380 GET_VREG(r1, r3) @ r1<- vB 5381 .if 0 5382 cmp r1, #0 @ is second operand zero? 5383 beq common_errDivideByZero 5384 .endif 5385 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5386 5387 @ optional op; may set condition codes 5388 add r0, r0, r1 @ r0<- op, r0-r3 changed 5389 GET_INST_OPCODE(ip) @ extract opcode from rINST 5390 SET_VREG(r0, r9) @ vAA<- r0 5391 GOTO_OPCODE(ip) @ jump to next instruction 5392 /* 10-13 instructions */ 5393 5394 5395 5396/* ------------------------------ */ 5397 .balign 64 5398.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5399/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5400/* File: armv5te/binop2addr.S */ 5401 /* 5402 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5403 * that specifies an instruction that performs "result = r0 op r1". 5404 * This could be an ARM instruction or a function call. (If the result 5405 * comes back in a register other than r0, you can override "result".) 5406 * 5407 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5408 * vCC (r1). Useful for integer division and modulus. 5409 * 5410 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5411 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5412 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5413 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5414 */ 5415 /* binop/2addr vA, vB */ 5416 mov r9, rINST, lsr #8 @ r9<- A+ 5417 mov r3, rINST, lsr #12 @ r3<- B 5418 and r9, r9, #15 5419 GET_VREG(r0, r9) @ r0<- vA 5420 GET_VREG(r1, r3) @ r1<- vB 5421 .if 0 5422 cmp r1, #0 @ is second operand zero? 5423 beq common_errDivideByZero 5424 .endif 5425 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5426 5427 @ optional op; may set condition codes 5428 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5429 GET_INST_OPCODE(ip) @ extract opcode from rINST 5430 SET_VREG(r0, r9) @ vAA<- r0 5431 GOTO_OPCODE(ip) @ jump to next instruction 5432 /* 10-13 instructions */ 5433 5434 5435 5436/* ------------------------------ */ 5437 .balign 64 5438.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5439/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5440/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5441/* File: armv5te/binop2addr.S */ 5442 /* 5443 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5444 * that specifies an instruction that performs "result = r0 op r1". 5445 * This could be an ARM instruction or a function call. (If the result 5446 * comes back in a register other than r0, you can override "result".) 5447 * 5448 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5449 * vCC (r1). Useful for integer division and modulus. 5450 * 5451 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5452 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5453 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5454 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5455 */ 5456 /* binop/2addr vA, vB */ 5457 mov r9, rINST, lsr #8 @ r9<- A+ 5458 mov r3, rINST, lsr #12 @ r3<- B 5459 and r9, r9, #15 5460 GET_VREG(r0, r9) @ r0<- vA 5461 GET_VREG(r1, r3) @ r1<- vB 5462 .if 0 5463 cmp r1, #0 @ is second operand zero? 5464 beq common_errDivideByZero 5465 .endif 5466 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5467 5468 @ optional op; may set condition codes 5469 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5470 GET_INST_OPCODE(ip) @ extract opcode from rINST 5471 SET_VREG(r0, r9) @ vAA<- r0 5472 GOTO_OPCODE(ip) @ jump to next instruction 5473 /* 10-13 instructions */ 5474 5475 5476 5477/* ------------------------------ */ 5478 .balign 64 5479.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5480/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5481/* File: armv5te/binop2addr.S */ 5482 /* 5483 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5484 * that specifies an instruction that performs "result = r0 op r1". 5485 * This could be an ARM instruction or a function call. (If the result 5486 * comes back in a register other than r0, you can override "result".) 5487 * 5488 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5489 * vCC (r1). Useful for integer division and modulus. 5490 * 5491 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5492 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5493 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5494 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5495 */ 5496 /* binop/2addr vA, vB */ 5497 mov r9, rINST, lsr #8 @ r9<- A+ 5498 mov r3, rINST, lsr #12 @ r3<- B 5499 and r9, r9, #15 5500 GET_VREG(r0, r9) @ r0<- vA 5501 GET_VREG(r1, r3) @ r1<- vB 5502 .if 1 5503 cmp r1, #0 @ is second operand zero? 5504 beq common_errDivideByZero 5505 .endif 5506 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5507 5508 @ optional op; may set condition codes 5509 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5510 GET_INST_OPCODE(ip) @ extract opcode from rINST 5511 SET_VREG(r0, r9) @ vAA<- r0 5512 GOTO_OPCODE(ip) @ jump to next instruction 5513 /* 10-13 instructions */ 5514 5515 5516 5517/* ------------------------------ */ 5518 .balign 64 5519.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5520/* File: armv5te/OP_REM_INT_2ADDR.S */ 5521/* idivmod returns quotient in r0 and remainder in r1 */ 5522/* File: armv5te/binop2addr.S */ 5523 /* 5524 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5525 * that specifies an instruction that performs "result = r0 op r1". 5526 * This could be an ARM instruction or a function call. (If the result 5527 * comes back in a register other than r0, you can override "result".) 5528 * 5529 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5530 * vCC (r1). Useful for integer division and modulus. 5531 * 5532 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5533 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5534 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5535 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5536 */ 5537 /* binop/2addr vA, vB */ 5538 mov r9, rINST, lsr #8 @ r9<- A+ 5539 mov r3, rINST, lsr #12 @ r3<- B 5540 and r9, r9, #15 5541 GET_VREG(r0, r9) @ r0<- vA 5542 GET_VREG(r1, r3) @ r1<- vB 5543 .if 1 5544 cmp r1, #0 @ is second operand zero? 5545 beq common_errDivideByZero 5546 .endif 5547 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5548 5549 @ optional op; may set condition codes 5550 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5551 GET_INST_OPCODE(ip) @ extract opcode from rINST 5552 SET_VREG(r1, r9) @ vAA<- r1 5553 GOTO_OPCODE(ip) @ jump to next instruction 5554 /* 10-13 instructions */ 5555 5556 5557 5558/* ------------------------------ */ 5559 .balign 64 5560.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5561/* File: armv5te/OP_AND_INT_2ADDR.S */ 5562/* File: armv5te/binop2addr.S */ 5563 /* 5564 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5565 * that specifies an instruction that performs "result = r0 op r1". 5566 * This could be an ARM instruction or a function call. (If the result 5567 * comes back in a register other than r0, you can override "result".) 5568 * 5569 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5570 * vCC (r1). Useful for integer division and modulus. 5571 * 5572 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5573 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5574 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5575 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5576 */ 5577 /* binop/2addr vA, vB */ 5578 mov r9, rINST, lsr #8 @ r9<- A+ 5579 mov r3, rINST, lsr #12 @ r3<- B 5580 and r9, r9, #15 5581 GET_VREG(r0, r9) @ r0<- vA 5582 GET_VREG(r1, r3) @ r1<- vB 5583 .if 0 5584 cmp r1, #0 @ is second operand zero? 5585 beq common_errDivideByZero 5586 .endif 5587 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5588 5589 @ optional op; may set condition codes 5590 and r0, r0, r1 @ r0<- op, r0-r3 changed 5591 GET_INST_OPCODE(ip) @ extract opcode from rINST 5592 SET_VREG(r0, r9) @ vAA<- r0 5593 GOTO_OPCODE(ip) @ jump to next instruction 5594 /* 10-13 instructions */ 5595 5596 5597 5598/* ------------------------------ */ 5599 .balign 64 5600.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5601/* File: armv5te/OP_OR_INT_2ADDR.S */ 5602/* File: armv5te/binop2addr.S */ 5603 /* 5604 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5605 * that specifies an instruction that performs "result = r0 op r1". 5606 * This could be an ARM instruction or a function call. (If the result 5607 * comes back in a register other than r0, you can override "result".) 5608 * 5609 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5610 * vCC (r1). Useful for integer division and modulus. 5611 * 5612 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5613 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5614 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5615 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5616 */ 5617 /* binop/2addr vA, vB */ 5618 mov r9, rINST, lsr #8 @ r9<- A+ 5619 mov r3, rINST, lsr #12 @ r3<- B 5620 and r9, r9, #15 5621 GET_VREG(r0, r9) @ r0<- vA 5622 GET_VREG(r1, r3) @ r1<- vB 5623 .if 0 5624 cmp r1, #0 @ is second operand zero? 5625 beq common_errDivideByZero 5626 .endif 5627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5628 5629 @ optional op; may set condition codes 5630 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5631 GET_INST_OPCODE(ip) @ extract opcode from rINST 5632 SET_VREG(r0, r9) @ vAA<- r0 5633 GOTO_OPCODE(ip) @ jump to next instruction 5634 /* 10-13 instructions */ 5635 5636 5637 5638/* ------------------------------ */ 5639 .balign 64 5640.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5641/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5642/* File: armv5te/binop2addr.S */ 5643 /* 5644 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5645 * that specifies an instruction that performs "result = r0 op r1". 5646 * This could be an ARM instruction or a function call. (If the result 5647 * comes back in a register other than r0, you can override "result".) 5648 * 5649 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5650 * vCC (r1). Useful for integer division and modulus. 5651 * 5652 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5653 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5654 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5655 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5656 */ 5657 /* binop/2addr vA, vB */ 5658 mov r9, rINST, lsr #8 @ r9<- A+ 5659 mov r3, rINST, lsr #12 @ r3<- B 5660 and r9, r9, #15 5661 GET_VREG(r0, r9) @ r0<- vA 5662 GET_VREG(r1, r3) @ r1<- vB 5663 .if 0 5664 cmp r1, #0 @ is second operand zero? 5665 beq common_errDivideByZero 5666 .endif 5667 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5668 5669 @ optional op; may set condition codes 5670 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5671 GET_INST_OPCODE(ip) @ extract opcode from rINST 5672 SET_VREG(r0, r9) @ vAA<- r0 5673 GOTO_OPCODE(ip) @ jump to next instruction 5674 /* 10-13 instructions */ 5675 5676 5677 5678/* ------------------------------ */ 5679 .balign 64 5680.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5681/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5682/* File: armv5te/binop2addr.S */ 5683 /* 5684 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5685 * that specifies an instruction that performs "result = r0 op r1". 5686 * This could be an ARM instruction or a function call. (If the result 5687 * comes back in a register other than r0, you can override "result".) 5688 * 5689 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5690 * vCC (r1). Useful for integer division and modulus. 5691 * 5692 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5693 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5694 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5695 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5696 */ 5697 /* binop/2addr vA, vB */ 5698 mov r9, rINST, lsr #8 @ r9<- A+ 5699 mov r3, rINST, lsr #12 @ r3<- B 5700 and r9, r9, #15 5701 GET_VREG(r0, r9) @ r0<- vA 5702 GET_VREG(r1, r3) @ r1<- vB 5703 .if 0 5704 cmp r1, #0 @ is second operand zero? 5705 beq common_errDivideByZero 5706 .endif 5707 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5708 5709 and r1, r1, #31 @ optional op; may set condition codes 5710 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5711 GET_INST_OPCODE(ip) @ extract opcode from rINST 5712 SET_VREG(r0, r9) @ vAA<- r0 5713 GOTO_OPCODE(ip) @ jump to next instruction 5714 /* 10-13 instructions */ 5715 5716 5717 5718/* ------------------------------ */ 5719 .balign 64 5720.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5721/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5722/* File: armv5te/binop2addr.S */ 5723 /* 5724 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5725 * that specifies an instruction that performs "result = r0 op r1". 5726 * This could be an ARM instruction or a function call. (If the result 5727 * comes back in a register other than r0, you can override "result".) 5728 * 5729 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5730 * vCC (r1). Useful for integer division and modulus. 5731 * 5732 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5733 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5734 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5735 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5736 */ 5737 /* binop/2addr vA, vB */ 5738 mov r9, rINST, lsr #8 @ r9<- A+ 5739 mov r3, rINST, lsr #12 @ r3<- B 5740 and r9, r9, #15 5741 GET_VREG(r0, r9) @ r0<- vA 5742 GET_VREG(r1, r3) @ r1<- vB 5743 .if 0 5744 cmp r1, #0 @ is second operand zero? 5745 beq common_errDivideByZero 5746 .endif 5747 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5748 5749 and r1, r1, #31 @ optional op; may set condition codes 5750 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5751 GET_INST_OPCODE(ip) @ extract opcode from rINST 5752 SET_VREG(r0, r9) @ vAA<- r0 5753 GOTO_OPCODE(ip) @ jump to next instruction 5754 /* 10-13 instructions */ 5755 5756 5757 5758/* ------------------------------ */ 5759 .balign 64 5760.L_OP_USHR_INT_2ADDR: /* 0xba */ 5761/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5762/* File: armv5te/binop2addr.S */ 5763 /* 5764 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5765 * that specifies an instruction that performs "result = r0 op r1". 5766 * This could be an ARM instruction or a function call. (If the result 5767 * comes back in a register other than r0, you can override "result".) 5768 * 5769 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5770 * vCC (r1). Useful for integer division and modulus. 5771 * 5772 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5773 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5774 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5775 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5776 */ 5777 /* binop/2addr vA, vB */ 5778 mov r9, rINST, lsr #8 @ r9<- A+ 5779 mov r3, rINST, lsr #12 @ r3<- B 5780 and r9, r9, #15 5781 GET_VREG(r0, r9) @ r0<- vA 5782 GET_VREG(r1, r3) @ r1<- vB 5783 .if 0 5784 cmp r1, #0 @ is second operand zero? 5785 beq common_errDivideByZero 5786 .endif 5787 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5788 5789 and r1, r1, #31 @ optional op; may set condition codes 5790 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5791 GET_INST_OPCODE(ip) @ extract opcode from rINST 5792 SET_VREG(r0, r9) @ vAA<- r0 5793 GOTO_OPCODE(ip) @ jump to next instruction 5794 /* 10-13 instructions */ 5795 5796 5797 5798/* ------------------------------ */ 5799 .balign 64 5800.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5801/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5802/* File: armv5te/binopWide2addr.S */ 5803 /* 5804 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5805 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5806 * This could be an ARM instruction or a function call. (If the result 5807 * comes back in a register other than r0, you can override "result".) 5808 * 5809 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5810 * vCC (r1). Useful for integer division and modulus. 5811 * 5812 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5813 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5814 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5815 * rem-double/2addr 5816 */ 5817 /* binop/2addr vA, vB */ 5818 mov r9, rINST, lsr #8 @ r9<- A+ 5819 mov r1, rINST, lsr #12 @ r1<- B 5820 and r9, r9, #15 5821 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5822 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5823 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5824 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5825 .if 0 5826 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5827 beq common_errDivideByZero 5828 .endif 5829 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5830 5831 adds r0, r0, r2 @ optional op; may set condition codes 5832 adc r1, r1, r3 @ result<- op, r0-r3 changed 5833 GET_INST_OPCODE(ip) @ extract opcode from rINST 5834 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5835 GOTO_OPCODE(ip) @ jump to next instruction 5836 /* 12-15 instructions */ 5837 5838 5839 5840/* ------------------------------ */ 5841 .balign 64 5842.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5843/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5844/* File: armv5te/binopWide2addr.S */ 5845 /* 5846 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5847 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5848 * This could be an ARM instruction or a function call. (If the result 5849 * comes back in a register other than r0, you can override "result".) 5850 * 5851 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5852 * vCC (r1). Useful for integer division and modulus. 5853 * 5854 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5855 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5856 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5857 * rem-double/2addr 5858 */ 5859 /* binop/2addr vA, vB */ 5860 mov r9, rINST, lsr #8 @ r9<- A+ 5861 mov r1, rINST, lsr #12 @ r1<- B 5862 and r9, r9, #15 5863 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5864 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5865 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5866 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5867 .if 0 5868 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5869 beq common_errDivideByZero 5870 .endif 5871 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5872 5873 subs r0, r0, r2 @ optional op; may set condition codes 5874 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5875 GET_INST_OPCODE(ip) @ extract opcode from rINST 5876 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5877 GOTO_OPCODE(ip) @ jump to next instruction 5878 /* 12-15 instructions */ 5879 5880 5881 5882/* ------------------------------ */ 5883 .balign 64 5884.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5885/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5886 /* 5887 * Signed 64-bit integer multiply, "/2addr" version. 5888 * 5889 * See OP_MUL_LONG for an explanation. 5890 * 5891 * We get a little tight on registers, so to avoid looking up &fp[A] 5892 * again we stuff it into rINST. 5893 */ 5894 /* mul-long/2addr vA, vB */ 5895 mov r9, rINST, lsr #8 @ r9<- A+ 5896 mov r1, rINST, lsr #12 @ r1<- B 5897 and r9, r9, #15 5898 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5899 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5900 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5901 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5902 mul ip, r2, r1 @ ip<- ZxW 5903 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5904 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5905 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5906 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5907 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5908 GET_INST_OPCODE(ip) @ extract opcode from rINST 5909 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5910 GOTO_OPCODE(ip) @ jump to next instruction 5911 5912 5913/* ------------------------------ */ 5914 .balign 64 5915.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5916/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5917/* File: armv5te/binopWide2addr.S */ 5918 /* 5919 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5920 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5921 * This could be an ARM instruction or a function call. (If the result 5922 * comes back in a register other than r0, you can override "result".) 5923 * 5924 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5925 * vCC (r1). Useful for integer division and modulus. 5926 * 5927 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5928 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5929 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5930 * rem-double/2addr 5931 */ 5932 /* binop/2addr vA, vB */ 5933 mov r9, rINST, lsr #8 @ r9<- A+ 5934 mov r1, rINST, lsr #12 @ r1<- B 5935 and r9, r9, #15 5936 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5937 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5938 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5939 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5940 .if 1 5941 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5942 beq common_errDivideByZero 5943 .endif 5944 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5945 5946 @ optional op; may set condition codes 5947 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5948 GET_INST_OPCODE(ip) @ extract opcode from rINST 5949 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5950 GOTO_OPCODE(ip) @ jump to next instruction 5951 /* 12-15 instructions */ 5952 5953 5954 5955/* ------------------------------ */ 5956 .balign 64 5957.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5958/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5959/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5960/* File: armv5te/binopWide2addr.S */ 5961 /* 5962 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5963 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5964 * This could be an ARM instruction or a function call. (If the result 5965 * comes back in a register other than r0, you can override "result".) 5966 * 5967 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5968 * vCC (r1). Useful for integer division and modulus. 5969 * 5970 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5971 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5972 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5973 * rem-double/2addr 5974 */ 5975 /* binop/2addr vA, vB */ 5976 mov r9, rINST, lsr #8 @ r9<- A+ 5977 mov r1, rINST, lsr #12 @ r1<- B 5978 and r9, r9, #15 5979 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5980 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5981 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5982 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5983 .if 1 5984 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5985 beq common_errDivideByZero 5986 .endif 5987 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5988 5989 @ optional op; may set condition codes 5990 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5991 GET_INST_OPCODE(ip) @ extract opcode from rINST 5992 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5993 GOTO_OPCODE(ip) @ jump to next instruction 5994 /* 12-15 instructions */ 5995 5996 5997 5998/* ------------------------------ */ 5999 .balign 64 6000.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 6001/* File: armv5te/OP_AND_LONG_2ADDR.S */ 6002/* File: armv5te/binopWide2addr.S */ 6003 /* 6004 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6005 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6006 * This could be an ARM instruction or a function call. (If the result 6007 * comes back in a register other than r0, you can override "result".) 6008 * 6009 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6010 * vCC (r1). Useful for integer division and modulus. 6011 * 6012 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6013 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6014 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6015 * rem-double/2addr 6016 */ 6017 /* binop/2addr vA, vB */ 6018 mov r9, rINST, lsr #8 @ r9<- A+ 6019 mov r1, rINST, lsr #12 @ r1<- B 6020 and r9, r9, #15 6021 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6022 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6023 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6024 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6025 .if 0 6026 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6027 beq common_errDivideByZero 6028 .endif 6029 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6030 6031 and r0, r0, r2 @ optional op; may set condition codes 6032 and r1, r1, r3 @ result<- op, r0-r3 changed 6033 GET_INST_OPCODE(ip) @ extract opcode from rINST 6034 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6035 GOTO_OPCODE(ip) @ jump to next instruction 6036 /* 12-15 instructions */ 6037 6038 6039 6040/* ------------------------------ */ 6041 .balign 64 6042.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6043/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6044/* File: armv5te/binopWide2addr.S */ 6045 /* 6046 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6047 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6048 * This could be an ARM instruction or a function call. (If the result 6049 * comes back in a register other than r0, you can override "result".) 6050 * 6051 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6052 * vCC (r1). Useful for integer division and modulus. 6053 * 6054 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6055 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6056 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6057 * rem-double/2addr 6058 */ 6059 /* binop/2addr vA, vB */ 6060 mov r9, rINST, lsr #8 @ r9<- A+ 6061 mov r1, rINST, lsr #12 @ r1<- B 6062 and r9, r9, #15 6063 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6064 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6065 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6066 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6067 .if 0 6068 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6069 beq common_errDivideByZero 6070 .endif 6071 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6072 6073 orr r0, r0, r2 @ optional op; may set condition codes 6074 orr r1, r1, r3 @ result<- op, r0-r3 changed 6075 GET_INST_OPCODE(ip) @ extract opcode from rINST 6076 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6077 GOTO_OPCODE(ip) @ jump to next instruction 6078 /* 12-15 instructions */ 6079 6080 6081 6082/* ------------------------------ */ 6083 .balign 64 6084.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6085/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6086/* File: armv5te/binopWide2addr.S */ 6087 /* 6088 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6089 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6090 * This could be an ARM instruction or a function call. (If the result 6091 * comes back in a register other than r0, you can override "result".) 6092 * 6093 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6094 * vCC (r1). Useful for integer division and modulus. 6095 * 6096 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6097 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6098 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6099 * rem-double/2addr 6100 */ 6101 /* binop/2addr vA, vB */ 6102 mov r9, rINST, lsr #8 @ r9<- A+ 6103 mov r1, rINST, lsr #12 @ r1<- B 6104 and r9, r9, #15 6105 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6106 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6107 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6108 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6109 .if 0 6110 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6111 beq common_errDivideByZero 6112 .endif 6113 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6114 6115 eor r0, r0, r2 @ optional op; may set condition codes 6116 eor r1, r1, r3 @ result<- op, r0-r3 changed 6117 GET_INST_OPCODE(ip) @ extract opcode from rINST 6118 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6119 GOTO_OPCODE(ip) @ jump to next instruction 6120 /* 12-15 instructions */ 6121 6122 6123 6124/* ------------------------------ */ 6125 .balign 64 6126.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6127/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6128 /* 6129 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6130 * 32-bit shift distance. 6131 */ 6132 /* shl-long/2addr vA, vB */ 6133 mov r9, rINST, lsr #8 @ r9<- A+ 6134 mov r3, rINST, lsr #12 @ r3<- B 6135 and r9, r9, #15 6136 GET_VREG(r2, r3) @ r2<- vB 6137 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6138 and r2, r2, #63 @ r2<- r2 & 0x3f 6139 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6140 6141 mov r1, r1, asl r2 @ r1<- r1 << r2 6142 rsb r3, r2, #32 @ r3<- 32 - r2 6143 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6144 subs ip, r2, #32 @ ip<- r2 - 32 6145 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6146 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6147 mov r0, r0, asl r2 @ r0<- r0 << r2 6148 b .LOP_SHL_LONG_2ADDR_finish 6149 6150/* ------------------------------ */ 6151 .balign 64 6152.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6153/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6154 /* 6155 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6156 * 32-bit shift distance. 6157 */ 6158 /* shr-long/2addr vA, vB */ 6159 mov r9, rINST, lsr #8 @ r9<- A+ 6160 mov r3, rINST, lsr #12 @ r3<- B 6161 and r9, r9, #15 6162 GET_VREG(r2, r3) @ r2<- vB 6163 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6164 and r2, r2, #63 @ r2<- r2 & 0x3f 6165 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6166 6167 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6168 rsb r3, r2, #32 @ r3<- 32 - r2 6169 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6170 subs ip, r2, #32 @ ip<- r2 - 32 6171 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6172 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6173 mov r1, r1, asr r2 @ r1<- r1 >> r2 6174 b .LOP_SHR_LONG_2ADDR_finish 6175 6176/* ------------------------------ */ 6177 .balign 64 6178.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6179/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6180 /* 6181 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6182 * 32-bit shift distance. 6183 */ 6184 /* ushr-long/2addr vA, vB */ 6185 mov r9, rINST, lsr #8 @ r9<- A+ 6186 mov r3, rINST, lsr #12 @ r3<- B 6187 and r9, r9, #15 6188 GET_VREG(r2, r3) @ r2<- vB 6189 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6190 and r2, r2, #63 @ r2<- r2 & 0x3f 6191 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6192 6193 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6194 rsb r3, r2, #32 @ r3<- 32 - r2 6195 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6196 subs ip, r2, #32 @ ip<- r2 - 32 6197 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6198 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6199 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6200 b .LOP_USHR_LONG_2ADDR_finish 6201 6202/* ------------------------------ */ 6203 .balign 64 6204.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6205/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */ 6206/* File: armv5te/binop2addr.S */ 6207 /* 6208 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6209 * that specifies an instruction that performs "result = r0 op r1". 6210 * This could be an ARM instruction or a function call. (If the result 6211 * comes back in a register other than r0, you can override "result".) 6212 * 6213 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6214 * vCC (r1). Useful for integer division and modulus. 6215 * 6216 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6217 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6218 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6219 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6220 */ 6221 /* binop/2addr vA, vB */ 6222 mov r9, rINST, lsr #8 @ r9<- A+ 6223 mov r3, rINST, lsr #12 @ r3<- B 6224 and r9, r9, #15 6225 GET_VREG(r0, r9) @ r0<- vA 6226 GET_VREG(r1, r3) @ r1<- vB 6227 .if 0 6228 cmp r1, #0 @ is second operand zero? 6229 beq common_errDivideByZero 6230 .endif 6231 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6232 6233 @ optional op; may set condition codes 6234 bl __aeabi_fadd @ r0<- op, r0-r3 changed 6235 GET_INST_OPCODE(ip) @ extract opcode from rINST 6236 SET_VREG(r0, r9) @ vAA<- r0 6237 GOTO_OPCODE(ip) @ jump to next instruction 6238 /* 10-13 instructions */ 6239 6240 6241 6242/* ------------------------------ */ 6243 .balign 64 6244.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6245/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */ 6246/* File: armv5te/binop2addr.S */ 6247 /* 6248 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6249 * that specifies an instruction that performs "result = r0 op r1". 6250 * This could be an ARM instruction or a function call. (If the result 6251 * comes back in a register other than r0, you can override "result".) 6252 * 6253 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6254 * vCC (r1). Useful for integer division and modulus. 6255 * 6256 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6257 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6258 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6259 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6260 */ 6261 /* binop/2addr vA, vB */ 6262 mov r9, rINST, lsr #8 @ r9<- A+ 6263 mov r3, rINST, lsr #12 @ r3<- B 6264 and r9, r9, #15 6265 GET_VREG(r0, r9) @ r0<- vA 6266 GET_VREG(r1, r3) @ r1<- vB 6267 .if 0 6268 cmp r1, #0 @ is second operand zero? 6269 beq common_errDivideByZero 6270 .endif 6271 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6272 6273 @ optional op; may set condition codes 6274 bl __aeabi_fsub @ r0<- op, r0-r3 changed 6275 GET_INST_OPCODE(ip) @ extract opcode from rINST 6276 SET_VREG(r0, r9) @ vAA<- r0 6277 GOTO_OPCODE(ip) @ jump to next instruction 6278 /* 10-13 instructions */ 6279 6280 6281 6282/* ------------------------------ */ 6283 .balign 64 6284.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6285/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */ 6286/* File: armv5te/binop2addr.S */ 6287 /* 6288 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6289 * that specifies an instruction that performs "result = r0 op r1". 6290 * This could be an ARM instruction or a function call. (If the result 6291 * comes back in a register other than r0, you can override "result".) 6292 * 6293 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6294 * vCC (r1). Useful for integer division and modulus. 6295 * 6296 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6297 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6298 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6299 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6300 */ 6301 /* binop/2addr vA, vB */ 6302 mov r9, rINST, lsr #8 @ r9<- A+ 6303 mov r3, rINST, lsr #12 @ r3<- B 6304 and r9, r9, #15 6305 GET_VREG(r0, r9) @ r0<- vA 6306 GET_VREG(r1, r3) @ r1<- vB 6307 .if 0 6308 cmp r1, #0 @ is second operand zero? 6309 beq common_errDivideByZero 6310 .endif 6311 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6312 6313 @ optional op; may set condition codes 6314 bl __aeabi_fmul @ r0<- op, r0-r3 changed 6315 GET_INST_OPCODE(ip) @ extract opcode from rINST 6316 SET_VREG(r0, r9) @ vAA<- r0 6317 GOTO_OPCODE(ip) @ jump to next instruction 6318 /* 10-13 instructions */ 6319 6320 6321 6322/* ------------------------------ */ 6323 .balign 64 6324.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6325/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */ 6326/* File: armv5te/binop2addr.S */ 6327 /* 6328 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6329 * that specifies an instruction that performs "result = r0 op r1". 6330 * This could be an ARM instruction or a function call. (If the result 6331 * comes back in a register other than r0, you can override "result".) 6332 * 6333 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6334 * vCC (r1). Useful for integer division and modulus. 6335 * 6336 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6337 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6338 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6339 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6340 */ 6341 /* binop/2addr vA, vB */ 6342 mov r9, rINST, lsr #8 @ r9<- A+ 6343 mov r3, rINST, lsr #12 @ r3<- B 6344 and r9, r9, #15 6345 GET_VREG(r0, r9) @ r0<- vA 6346 GET_VREG(r1, r3) @ r1<- vB 6347 .if 0 6348 cmp r1, #0 @ is second operand zero? 6349 beq common_errDivideByZero 6350 .endif 6351 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6352 6353 @ optional op; may set condition codes 6354 bl __aeabi_fdiv @ r0<- op, r0-r3 changed 6355 GET_INST_OPCODE(ip) @ extract opcode from rINST 6356 SET_VREG(r0, r9) @ vAA<- r0 6357 GOTO_OPCODE(ip) @ jump to next instruction 6358 /* 10-13 instructions */ 6359 6360 6361 6362/* ------------------------------ */ 6363 .balign 64 6364.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6365/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6366/* EABI doesn't define a float remainder function, but libm does */ 6367/* File: armv5te/binop2addr.S */ 6368 /* 6369 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6370 * that specifies an instruction that performs "result = r0 op r1". 6371 * This could be an ARM instruction or a function call. (If the result 6372 * comes back in a register other than r0, you can override "result".) 6373 * 6374 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6375 * vCC (r1). Useful for integer division and modulus. 6376 * 6377 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6378 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6379 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6380 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6381 */ 6382 /* binop/2addr vA, vB */ 6383 mov r9, rINST, lsr #8 @ r9<- A+ 6384 mov r3, rINST, lsr #12 @ r3<- B 6385 and r9, r9, #15 6386 GET_VREG(r0, r9) @ r0<- vA 6387 GET_VREG(r1, r3) @ r1<- vB 6388 .if 0 6389 cmp r1, #0 @ is second operand zero? 6390 beq common_errDivideByZero 6391 .endif 6392 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6393 6394 @ optional op; may set condition codes 6395 bl fmodf @ r0<- op, r0-r3 changed 6396 GET_INST_OPCODE(ip) @ extract opcode from rINST 6397 SET_VREG(r0, r9) @ vAA<- r0 6398 GOTO_OPCODE(ip) @ jump to next instruction 6399 /* 10-13 instructions */ 6400 6401 6402 6403/* ------------------------------ */ 6404 .balign 64 6405.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6406/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */ 6407/* File: armv5te/binopWide2addr.S */ 6408 /* 6409 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6410 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6411 * This could be an ARM instruction or a function call. (If the result 6412 * comes back in a register other than r0, you can override "result".) 6413 * 6414 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6415 * vCC (r1). Useful for integer division and modulus. 6416 * 6417 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6418 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6419 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6420 * rem-double/2addr 6421 */ 6422 /* binop/2addr vA, vB */ 6423 mov r9, rINST, lsr #8 @ r9<- A+ 6424 mov r1, rINST, lsr #12 @ r1<- B 6425 and r9, r9, #15 6426 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6427 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6428 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6429 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6430 .if 0 6431 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6432 beq common_errDivideByZero 6433 .endif 6434 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6435 6436 @ optional op; may set condition codes 6437 bl __aeabi_dadd @ result<- op, r0-r3 changed 6438 GET_INST_OPCODE(ip) @ extract opcode from rINST 6439 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6440 GOTO_OPCODE(ip) @ jump to next instruction 6441 /* 12-15 instructions */ 6442 6443 6444 6445/* ------------------------------ */ 6446 .balign 64 6447.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6448/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */ 6449/* File: armv5te/binopWide2addr.S */ 6450 /* 6451 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6452 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6453 * This could be an ARM instruction or a function call. (If the result 6454 * comes back in a register other than r0, you can override "result".) 6455 * 6456 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6457 * vCC (r1). Useful for integer division and modulus. 6458 * 6459 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6460 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6461 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6462 * rem-double/2addr 6463 */ 6464 /* binop/2addr vA, vB */ 6465 mov r9, rINST, lsr #8 @ r9<- A+ 6466 mov r1, rINST, lsr #12 @ r1<- B 6467 and r9, r9, #15 6468 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6469 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6470 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6471 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6472 .if 0 6473 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6474 beq common_errDivideByZero 6475 .endif 6476 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6477 6478 @ optional op; may set condition codes 6479 bl __aeabi_dsub @ result<- op, r0-r3 changed 6480 GET_INST_OPCODE(ip) @ extract opcode from rINST 6481 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6482 GOTO_OPCODE(ip) @ jump to next instruction 6483 /* 12-15 instructions */ 6484 6485 6486 6487/* ------------------------------ */ 6488 .balign 64 6489.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6490/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */ 6491/* File: armv5te/binopWide2addr.S */ 6492 /* 6493 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6494 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6495 * This could be an ARM instruction or a function call. (If the result 6496 * comes back in a register other than r0, you can override "result".) 6497 * 6498 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6499 * vCC (r1). Useful for integer division and modulus. 6500 * 6501 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6502 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6503 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6504 * rem-double/2addr 6505 */ 6506 /* binop/2addr vA, vB */ 6507 mov r9, rINST, lsr #8 @ r9<- A+ 6508 mov r1, rINST, lsr #12 @ r1<- B 6509 and r9, r9, #15 6510 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6511 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6512 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6513 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6514 .if 0 6515 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6516 beq common_errDivideByZero 6517 .endif 6518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6519 6520 @ optional op; may set condition codes 6521 bl __aeabi_dmul @ result<- op, r0-r3 changed 6522 GET_INST_OPCODE(ip) @ extract opcode from rINST 6523 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6524 GOTO_OPCODE(ip) @ jump to next instruction 6525 /* 12-15 instructions */ 6526 6527 6528 6529/* ------------------------------ */ 6530 .balign 64 6531.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6532/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */ 6533/* File: armv5te/binopWide2addr.S */ 6534 /* 6535 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6536 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6537 * This could be an ARM instruction or a function call. (If the result 6538 * comes back in a register other than r0, you can override "result".) 6539 * 6540 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6541 * vCC (r1). Useful for integer division and modulus. 6542 * 6543 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6544 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6545 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6546 * rem-double/2addr 6547 */ 6548 /* binop/2addr vA, vB */ 6549 mov r9, rINST, lsr #8 @ r9<- A+ 6550 mov r1, rINST, lsr #12 @ r1<- B 6551 and r9, r9, #15 6552 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6553 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6554 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6555 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6556 .if 0 6557 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6558 beq common_errDivideByZero 6559 .endif 6560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6561 6562 @ optional op; may set condition codes 6563 bl __aeabi_ddiv @ result<- op, r0-r3 changed 6564 GET_INST_OPCODE(ip) @ extract opcode from rINST 6565 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6566 GOTO_OPCODE(ip) @ jump to next instruction 6567 /* 12-15 instructions */ 6568 6569 6570 6571/* ------------------------------ */ 6572 .balign 64 6573.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6574/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6575/* EABI doesn't define a double remainder function, but libm does */ 6576/* File: armv5te/binopWide2addr.S */ 6577 /* 6578 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6579 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6580 * This could be an ARM instruction or a function call. (If the result 6581 * comes back in a register other than r0, you can override "result".) 6582 * 6583 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6584 * vCC (r1). Useful for integer division and modulus. 6585 * 6586 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6587 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6588 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6589 * rem-double/2addr 6590 */ 6591 /* binop/2addr vA, vB */ 6592 mov r9, rINST, lsr #8 @ r9<- A+ 6593 mov r1, rINST, lsr #12 @ r1<- B 6594 and r9, r9, #15 6595 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6596 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6597 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6598 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6599 .if 0 6600 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6601 beq common_errDivideByZero 6602 .endif 6603 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6604 6605 @ optional op; may set condition codes 6606 bl fmod @ result<- op, r0-r3 changed 6607 GET_INST_OPCODE(ip) @ extract opcode from rINST 6608 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6609 GOTO_OPCODE(ip) @ jump to next instruction 6610 /* 12-15 instructions */ 6611 6612 6613 6614/* ------------------------------ */ 6615 .balign 64 6616.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6617/* File: armv5te/OP_ADD_INT_LIT16.S */ 6618/* File: armv5te/binopLit16.S */ 6619 /* 6620 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6621 * that specifies an instruction that performs "result = r0 op r1". 6622 * This could be an ARM instruction or a function call. (If the result 6623 * comes back in a register other than r0, you can override "result".) 6624 * 6625 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6626 * vCC (r1). Useful for integer division and modulus. 6627 * 6628 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6629 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6630 */ 6631 /* binop/lit16 vA, vB, #+CCCC */ 6632 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6633 mov r2, rINST, lsr #12 @ r2<- B 6634 mov r9, rINST, lsr #8 @ r9<- A+ 6635 GET_VREG(r0, r2) @ r0<- vB 6636 and r9, r9, #15 6637 .if 0 6638 cmp r1, #0 @ is second operand zero? 6639 beq common_errDivideByZero 6640 .endif 6641 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6642 6643 add r0, r0, r1 @ r0<- op, r0-r3 changed 6644 GET_INST_OPCODE(ip) @ extract opcode from rINST 6645 SET_VREG(r0, r9) @ vAA<- r0 6646 GOTO_OPCODE(ip) @ jump to next instruction 6647 /* 10-13 instructions */ 6648 6649 6650 6651/* ------------------------------ */ 6652 .balign 64 6653.L_OP_RSUB_INT: /* 0xd1 */ 6654/* File: armv5te/OP_RSUB_INT.S */ 6655/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6656/* File: armv5te/binopLit16.S */ 6657 /* 6658 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6659 * that specifies an instruction that performs "result = r0 op r1". 6660 * This could be an ARM instruction or a function call. (If the result 6661 * comes back in a register other than r0, you can override "result".) 6662 * 6663 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6664 * vCC (r1). Useful for integer division and modulus. 6665 * 6666 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6667 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6668 */ 6669 /* binop/lit16 vA, vB, #+CCCC */ 6670 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6671 mov r2, rINST, lsr #12 @ r2<- B 6672 mov r9, rINST, lsr #8 @ r9<- A+ 6673 GET_VREG(r0, r2) @ r0<- vB 6674 and r9, r9, #15 6675 .if 0 6676 cmp r1, #0 @ is second operand zero? 6677 beq common_errDivideByZero 6678 .endif 6679 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6680 6681 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6682 GET_INST_OPCODE(ip) @ extract opcode from rINST 6683 SET_VREG(r0, r9) @ vAA<- r0 6684 GOTO_OPCODE(ip) @ jump to next instruction 6685 /* 10-13 instructions */ 6686 6687 6688 6689/* ------------------------------ */ 6690 .balign 64 6691.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6692/* File: armv5te/OP_MUL_INT_LIT16.S */ 6693/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6694/* File: armv5te/binopLit16.S */ 6695 /* 6696 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6697 * that specifies an instruction that performs "result = r0 op r1". 6698 * This could be an ARM instruction or a function call. (If the result 6699 * comes back in a register other than r0, you can override "result".) 6700 * 6701 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6702 * vCC (r1). Useful for integer division and modulus. 6703 * 6704 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6705 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6706 */ 6707 /* binop/lit16 vA, vB, #+CCCC */ 6708 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6709 mov r2, rINST, lsr #12 @ r2<- B 6710 mov r9, rINST, lsr #8 @ r9<- A+ 6711 GET_VREG(r0, r2) @ r0<- vB 6712 and r9, r9, #15 6713 .if 0 6714 cmp r1, #0 @ is second operand zero? 6715 beq common_errDivideByZero 6716 .endif 6717 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6718 6719 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6720 GET_INST_OPCODE(ip) @ extract opcode from rINST 6721 SET_VREG(r0, r9) @ vAA<- r0 6722 GOTO_OPCODE(ip) @ jump to next instruction 6723 /* 10-13 instructions */ 6724 6725 6726 6727/* ------------------------------ */ 6728 .balign 64 6729.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6730/* File: armv5te/OP_DIV_INT_LIT16.S */ 6731/* File: armv5te/binopLit16.S */ 6732 /* 6733 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6734 * that specifies an instruction that performs "result = r0 op r1". 6735 * This could be an ARM instruction or a function call. (If the result 6736 * comes back in a register other than r0, you can override "result".) 6737 * 6738 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6739 * vCC (r1). Useful for integer division and modulus. 6740 * 6741 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6742 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6743 */ 6744 /* binop/lit16 vA, vB, #+CCCC */ 6745 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6746 mov r2, rINST, lsr #12 @ r2<- B 6747 mov r9, rINST, lsr #8 @ r9<- A+ 6748 GET_VREG(r0, r2) @ r0<- vB 6749 and r9, r9, #15 6750 .if 1 6751 cmp r1, #0 @ is second operand zero? 6752 beq common_errDivideByZero 6753 .endif 6754 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6755 6756 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6757 GET_INST_OPCODE(ip) @ extract opcode from rINST 6758 SET_VREG(r0, r9) @ vAA<- r0 6759 GOTO_OPCODE(ip) @ jump to next instruction 6760 /* 10-13 instructions */ 6761 6762 6763 6764/* ------------------------------ */ 6765 .balign 64 6766.L_OP_REM_INT_LIT16: /* 0xd4 */ 6767/* File: armv5te/OP_REM_INT_LIT16.S */ 6768/* idivmod returns quotient in r0 and remainder in r1 */ 6769/* File: armv5te/binopLit16.S */ 6770 /* 6771 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6772 * that specifies an instruction that performs "result = r0 op r1". 6773 * This could be an ARM instruction or a function call. (If the result 6774 * comes back in a register other than r0, you can override "result".) 6775 * 6776 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6777 * vCC (r1). Useful for integer division and modulus. 6778 * 6779 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6780 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6781 */ 6782 /* binop/lit16 vA, vB, #+CCCC */ 6783 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6784 mov r2, rINST, lsr #12 @ r2<- B 6785 mov r9, rINST, lsr #8 @ r9<- A+ 6786 GET_VREG(r0, r2) @ r0<- vB 6787 and r9, r9, #15 6788 .if 1 6789 cmp r1, #0 @ is second operand zero? 6790 beq common_errDivideByZero 6791 .endif 6792 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6793 6794 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6795 GET_INST_OPCODE(ip) @ extract opcode from rINST 6796 SET_VREG(r1, r9) @ vAA<- r1 6797 GOTO_OPCODE(ip) @ jump to next instruction 6798 /* 10-13 instructions */ 6799 6800 6801 6802/* ------------------------------ */ 6803 .balign 64 6804.L_OP_AND_INT_LIT16: /* 0xd5 */ 6805/* File: armv5te/OP_AND_INT_LIT16.S */ 6806/* File: armv5te/binopLit16.S */ 6807 /* 6808 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6809 * that specifies an instruction that performs "result = r0 op r1". 6810 * This could be an ARM instruction or a function call. (If the result 6811 * comes back in a register other than r0, you can override "result".) 6812 * 6813 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6814 * vCC (r1). Useful for integer division and modulus. 6815 * 6816 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6817 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6818 */ 6819 /* binop/lit16 vA, vB, #+CCCC */ 6820 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6821 mov r2, rINST, lsr #12 @ r2<- B 6822 mov r9, rINST, lsr #8 @ r9<- A+ 6823 GET_VREG(r0, r2) @ r0<- vB 6824 and r9, r9, #15 6825 .if 0 6826 cmp r1, #0 @ is second operand zero? 6827 beq common_errDivideByZero 6828 .endif 6829 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6830 6831 and r0, r0, r1 @ r0<- op, r0-r3 changed 6832 GET_INST_OPCODE(ip) @ extract opcode from rINST 6833 SET_VREG(r0, r9) @ vAA<- r0 6834 GOTO_OPCODE(ip) @ jump to next instruction 6835 /* 10-13 instructions */ 6836 6837 6838 6839/* ------------------------------ */ 6840 .balign 64 6841.L_OP_OR_INT_LIT16: /* 0xd6 */ 6842/* File: armv5te/OP_OR_INT_LIT16.S */ 6843/* File: armv5te/binopLit16.S */ 6844 /* 6845 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6846 * that specifies an instruction that performs "result = r0 op r1". 6847 * This could be an ARM instruction or a function call. (If the result 6848 * comes back in a register other than r0, you can override "result".) 6849 * 6850 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6851 * vCC (r1). Useful for integer division and modulus. 6852 * 6853 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6854 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6855 */ 6856 /* binop/lit16 vA, vB, #+CCCC */ 6857 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6858 mov r2, rINST, lsr #12 @ r2<- B 6859 mov r9, rINST, lsr #8 @ r9<- A+ 6860 GET_VREG(r0, r2) @ r0<- vB 6861 and r9, r9, #15 6862 .if 0 6863 cmp r1, #0 @ is second operand zero? 6864 beq common_errDivideByZero 6865 .endif 6866 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6867 6868 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6869 GET_INST_OPCODE(ip) @ extract opcode from rINST 6870 SET_VREG(r0, r9) @ vAA<- r0 6871 GOTO_OPCODE(ip) @ jump to next instruction 6872 /* 10-13 instructions */ 6873 6874 6875 6876/* ------------------------------ */ 6877 .balign 64 6878.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6879/* File: armv5te/OP_XOR_INT_LIT16.S */ 6880/* File: armv5te/binopLit16.S */ 6881 /* 6882 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6883 * that specifies an instruction that performs "result = r0 op r1". 6884 * This could be an ARM instruction or a function call. (If the result 6885 * comes back in a register other than r0, you can override "result".) 6886 * 6887 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6888 * vCC (r1). Useful for integer division and modulus. 6889 * 6890 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6891 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6892 */ 6893 /* binop/lit16 vA, vB, #+CCCC */ 6894 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6895 mov r2, rINST, lsr #12 @ r2<- B 6896 mov r9, rINST, lsr #8 @ r9<- A+ 6897 GET_VREG(r0, r2) @ r0<- vB 6898 and r9, r9, #15 6899 .if 0 6900 cmp r1, #0 @ is second operand zero? 6901 beq common_errDivideByZero 6902 .endif 6903 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6904 6905 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6906 GET_INST_OPCODE(ip) @ extract opcode from rINST 6907 SET_VREG(r0, r9) @ vAA<- r0 6908 GOTO_OPCODE(ip) @ jump to next instruction 6909 /* 10-13 instructions */ 6910 6911 6912 6913/* ------------------------------ */ 6914 .balign 64 6915.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6916/* File: armv5te/OP_ADD_INT_LIT8.S */ 6917/* File: armv5te/binopLit8.S */ 6918 /* 6919 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6920 * that specifies an instruction that performs "result = r0 op r1". 6921 * This could be an ARM instruction or a function call. (If the result 6922 * comes back in a register other than r0, you can override "result".) 6923 * 6924 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6925 * vCC (r1). Useful for integer division and modulus. 6926 * 6927 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6928 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6929 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6930 */ 6931 /* binop/lit8 vAA, vBB, #+CC */ 6932 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6933 mov r9, rINST, lsr #8 @ r9<- AA 6934 and r2, r3, #255 @ r2<- BB 6935 GET_VREG(r0, r2) @ r0<- vBB 6936 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6937 .if 0 6938 @cmp r1, #0 @ is second operand zero? 6939 beq common_errDivideByZero 6940 .endif 6941 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6942 6943 @ optional op; may set condition codes 6944 add r0, r0, r1 @ r0<- op, r0-r3 changed 6945 GET_INST_OPCODE(ip) @ extract opcode from rINST 6946 SET_VREG(r0, r9) @ vAA<- r0 6947 GOTO_OPCODE(ip) @ jump to next instruction 6948 /* 10-12 instructions */ 6949 6950 6951 6952/* ------------------------------ */ 6953 .balign 64 6954.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6955/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6956/* File: armv5te/binopLit8.S */ 6957 /* 6958 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6959 * that specifies an instruction that performs "result = r0 op r1". 6960 * This could be an ARM instruction or a function call. (If the result 6961 * comes back in a register other than r0, you can override "result".) 6962 * 6963 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6964 * vCC (r1). Useful for integer division and modulus. 6965 * 6966 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6967 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6968 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6969 */ 6970 /* binop/lit8 vAA, vBB, #+CC */ 6971 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6972 mov r9, rINST, lsr #8 @ r9<- AA 6973 and r2, r3, #255 @ r2<- BB 6974 GET_VREG(r0, r2) @ r0<- vBB 6975 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6976 .if 0 6977 @cmp r1, #0 @ is second operand zero? 6978 beq common_errDivideByZero 6979 .endif 6980 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6981 6982 @ optional op; may set condition codes 6983 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6984 GET_INST_OPCODE(ip) @ extract opcode from rINST 6985 SET_VREG(r0, r9) @ vAA<- r0 6986 GOTO_OPCODE(ip) @ jump to next instruction 6987 /* 10-12 instructions */ 6988 6989 6990 6991/* ------------------------------ */ 6992 .balign 64 6993.L_OP_MUL_INT_LIT8: /* 0xda */ 6994/* File: armv5te/OP_MUL_INT_LIT8.S */ 6995/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6996/* File: armv5te/binopLit8.S */ 6997 /* 6998 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6999 * that specifies an instruction that performs "result = r0 op r1". 7000 * This could be an ARM instruction or a function call. (If the result 7001 * comes back in a register other than r0, you can override "result".) 7002 * 7003 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7004 * vCC (r1). Useful for integer division and modulus. 7005 * 7006 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7007 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7008 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7009 */ 7010 /* binop/lit8 vAA, vBB, #+CC */ 7011 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7012 mov r9, rINST, lsr #8 @ r9<- AA 7013 and r2, r3, #255 @ r2<- BB 7014 GET_VREG(r0, r2) @ r0<- vBB 7015 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7016 .if 0 7017 @cmp r1, #0 @ is second operand zero? 7018 beq common_errDivideByZero 7019 .endif 7020 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7021 7022 @ optional op; may set condition codes 7023 mul r0, r1, r0 @ r0<- op, r0-r3 changed 7024 GET_INST_OPCODE(ip) @ extract opcode from rINST 7025 SET_VREG(r0, r9) @ vAA<- r0 7026 GOTO_OPCODE(ip) @ jump to next instruction 7027 /* 10-12 instructions */ 7028 7029 7030 7031/* ------------------------------ */ 7032 .balign 64 7033.L_OP_DIV_INT_LIT8: /* 0xdb */ 7034/* File: armv5te/OP_DIV_INT_LIT8.S */ 7035/* File: armv5te/binopLit8.S */ 7036 /* 7037 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7038 * that specifies an instruction that performs "result = r0 op r1". 7039 * This could be an ARM instruction or a function call. (If the result 7040 * comes back in a register other than r0, you can override "result".) 7041 * 7042 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7043 * vCC (r1). Useful for integer division and modulus. 7044 * 7045 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7046 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7047 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7048 */ 7049 /* binop/lit8 vAA, vBB, #+CC */ 7050 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7051 mov r9, rINST, lsr #8 @ r9<- AA 7052 and r2, r3, #255 @ r2<- BB 7053 GET_VREG(r0, r2) @ r0<- vBB 7054 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7055 .if 1 7056 @cmp r1, #0 @ is second operand zero? 7057 beq common_errDivideByZero 7058 .endif 7059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7060 7061 @ optional op; may set condition codes 7062 bl __aeabi_idiv @ r0<- op, r0-r3 changed 7063 GET_INST_OPCODE(ip) @ extract opcode from rINST 7064 SET_VREG(r0, r9) @ vAA<- r0 7065 GOTO_OPCODE(ip) @ jump to next instruction 7066 /* 10-12 instructions */ 7067 7068 7069 7070/* ------------------------------ */ 7071 .balign 64 7072.L_OP_REM_INT_LIT8: /* 0xdc */ 7073/* File: armv5te/OP_REM_INT_LIT8.S */ 7074/* idivmod returns quotient in r0 and remainder in r1 */ 7075/* File: armv5te/binopLit8.S */ 7076 /* 7077 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7078 * that specifies an instruction that performs "result = r0 op r1". 7079 * This could be an ARM instruction or a function call. (If the result 7080 * comes back in a register other than r0, you can override "result".) 7081 * 7082 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7083 * vCC (r1). Useful for integer division and modulus. 7084 * 7085 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7086 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7087 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7088 */ 7089 /* binop/lit8 vAA, vBB, #+CC */ 7090 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7091 mov r9, rINST, lsr #8 @ r9<- AA 7092 and r2, r3, #255 @ r2<- BB 7093 GET_VREG(r0, r2) @ r0<- vBB 7094 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7095 .if 1 7096 @cmp r1, #0 @ is second operand zero? 7097 beq common_errDivideByZero 7098 .endif 7099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7100 7101 @ optional op; may set condition codes 7102 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 7103 GET_INST_OPCODE(ip) @ extract opcode from rINST 7104 SET_VREG(r1, r9) @ vAA<- r1 7105 GOTO_OPCODE(ip) @ jump to next instruction 7106 /* 10-12 instructions */ 7107 7108 7109 7110/* ------------------------------ */ 7111 .balign 64 7112.L_OP_AND_INT_LIT8: /* 0xdd */ 7113/* File: armv5te/OP_AND_INT_LIT8.S */ 7114/* File: armv5te/binopLit8.S */ 7115 /* 7116 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7117 * that specifies an instruction that performs "result = r0 op r1". 7118 * This could be an ARM instruction or a function call. (If the result 7119 * comes back in a register other than r0, you can override "result".) 7120 * 7121 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7122 * vCC (r1). Useful for integer division and modulus. 7123 * 7124 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7125 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7126 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7127 */ 7128 /* binop/lit8 vAA, vBB, #+CC */ 7129 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7130 mov r9, rINST, lsr #8 @ r9<- AA 7131 and r2, r3, #255 @ r2<- BB 7132 GET_VREG(r0, r2) @ r0<- vBB 7133 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7134 .if 0 7135 @cmp r1, #0 @ is second operand zero? 7136 beq common_errDivideByZero 7137 .endif 7138 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7139 7140 @ optional op; may set condition codes 7141 and r0, r0, r1 @ r0<- op, r0-r3 changed 7142 GET_INST_OPCODE(ip) @ extract opcode from rINST 7143 SET_VREG(r0, r9) @ vAA<- r0 7144 GOTO_OPCODE(ip) @ jump to next instruction 7145 /* 10-12 instructions */ 7146 7147 7148 7149/* ------------------------------ */ 7150 .balign 64 7151.L_OP_OR_INT_LIT8: /* 0xde */ 7152/* File: armv5te/OP_OR_INT_LIT8.S */ 7153/* File: armv5te/binopLit8.S */ 7154 /* 7155 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7156 * that specifies an instruction that performs "result = r0 op r1". 7157 * This could be an ARM instruction or a function call. (If the result 7158 * comes back in a register other than r0, you can override "result".) 7159 * 7160 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7161 * vCC (r1). Useful for integer division and modulus. 7162 * 7163 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7164 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7165 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7166 */ 7167 /* binop/lit8 vAA, vBB, #+CC */ 7168 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7169 mov r9, rINST, lsr #8 @ r9<- AA 7170 and r2, r3, #255 @ r2<- BB 7171 GET_VREG(r0, r2) @ r0<- vBB 7172 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7173 .if 0 7174 @cmp r1, #0 @ is second operand zero? 7175 beq common_errDivideByZero 7176 .endif 7177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7178 7179 @ optional op; may set condition codes 7180 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7181 GET_INST_OPCODE(ip) @ extract opcode from rINST 7182 SET_VREG(r0, r9) @ vAA<- r0 7183 GOTO_OPCODE(ip) @ jump to next instruction 7184 /* 10-12 instructions */ 7185 7186 7187 7188/* ------------------------------ */ 7189 .balign 64 7190.L_OP_XOR_INT_LIT8: /* 0xdf */ 7191/* File: armv5te/OP_XOR_INT_LIT8.S */ 7192/* File: armv5te/binopLit8.S */ 7193 /* 7194 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7195 * that specifies an instruction that performs "result = r0 op r1". 7196 * This could be an ARM instruction or a function call. (If the result 7197 * comes back in a register other than r0, you can override "result".) 7198 * 7199 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7200 * vCC (r1). Useful for integer division and modulus. 7201 * 7202 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7203 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7204 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7205 */ 7206 /* binop/lit8 vAA, vBB, #+CC */ 7207 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7208 mov r9, rINST, lsr #8 @ r9<- AA 7209 and r2, r3, #255 @ r2<- BB 7210 GET_VREG(r0, r2) @ r0<- vBB 7211 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7212 .if 0 7213 @cmp r1, #0 @ is second operand zero? 7214 beq common_errDivideByZero 7215 .endif 7216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7217 7218 @ optional op; may set condition codes 7219 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7220 GET_INST_OPCODE(ip) @ extract opcode from rINST 7221 SET_VREG(r0, r9) @ vAA<- r0 7222 GOTO_OPCODE(ip) @ jump to next instruction 7223 /* 10-12 instructions */ 7224 7225 7226 7227/* ------------------------------ */ 7228 .balign 64 7229.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7230/* File: armv5te/OP_SHL_INT_LIT8.S */ 7231/* File: armv5te/binopLit8.S */ 7232 /* 7233 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7234 * that specifies an instruction that performs "result = r0 op r1". 7235 * This could be an ARM instruction or a function call. (If the result 7236 * comes back in a register other than r0, you can override "result".) 7237 * 7238 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7239 * vCC (r1). Useful for integer division and modulus. 7240 * 7241 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7242 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7243 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7244 */ 7245 /* binop/lit8 vAA, vBB, #+CC */ 7246 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7247 mov r9, rINST, lsr #8 @ r9<- AA 7248 and r2, r3, #255 @ r2<- BB 7249 GET_VREG(r0, r2) @ r0<- vBB 7250 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7251 .if 0 7252 @cmp r1, #0 @ is second operand zero? 7253 beq common_errDivideByZero 7254 .endif 7255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7256 7257 and r1, r1, #31 @ optional op; may set condition codes 7258 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7259 GET_INST_OPCODE(ip) @ extract opcode from rINST 7260 SET_VREG(r0, r9) @ vAA<- r0 7261 GOTO_OPCODE(ip) @ jump to next instruction 7262 /* 10-12 instructions */ 7263 7264 7265 7266/* ------------------------------ */ 7267 .balign 64 7268.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7269/* File: armv5te/OP_SHR_INT_LIT8.S */ 7270/* File: armv5te/binopLit8.S */ 7271 /* 7272 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7273 * that specifies an instruction that performs "result = r0 op r1". 7274 * This could be an ARM instruction or a function call. (If the result 7275 * comes back in a register other than r0, you can override "result".) 7276 * 7277 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7278 * vCC (r1). Useful for integer division and modulus. 7279 * 7280 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7281 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7282 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7283 */ 7284 /* binop/lit8 vAA, vBB, #+CC */ 7285 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7286 mov r9, rINST, lsr #8 @ r9<- AA 7287 and r2, r3, #255 @ r2<- BB 7288 GET_VREG(r0, r2) @ r0<- vBB 7289 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7290 .if 0 7291 @cmp r1, #0 @ is second operand zero? 7292 beq common_errDivideByZero 7293 .endif 7294 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7295 7296 and r1, r1, #31 @ optional op; may set condition codes 7297 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7298 GET_INST_OPCODE(ip) @ extract opcode from rINST 7299 SET_VREG(r0, r9) @ vAA<- r0 7300 GOTO_OPCODE(ip) @ jump to next instruction 7301 /* 10-12 instructions */ 7302 7303 7304 7305/* ------------------------------ */ 7306 .balign 64 7307.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7308/* File: armv5te/OP_USHR_INT_LIT8.S */ 7309/* File: armv5te/binopLit8.S */ 7310 /* 7311 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7312 * that specifies an instruction that performs "result = r0 op r1". 7313 * This could be an ARM instruction or a function call. (If the result 7314 * comes back in a register other than r0, you can override "result".) 7315 * 7316 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7317 * vCC (r1). Useful for integer division and modulus. 7318 * 7319 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7320 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7321 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7322 */ 7323 /* binop/lit8 vAA, vBB, #+CC */ 7324 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7325 mov r9, rINST, lsr #8 @ r9<- AA 7326 and r2, r3, #255 @ r2<- BB 7327 GET_VREG(r0, r2) @ r0<- vBB 7328 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7329 .if 0 7330 @cmp r1, #0 @ is second operand zero? 7331 beq common_errDivideByZero 7332 .endif 7333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7334 7335 and r1, r1, #31 @ optional op; may set condition codes 7336 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7337 GET_INST_OPCODE(ip) @ extract opcode from rINST 7338 SET_VREG(r0, r9) @ vAA<- r0 7339 GOTO_OPCODE(ip) @ jump to next instruction 7340 /* 10-12 instructions */ 7341 7342 7343 7344/* ------------------------------ */ 7345 .balign 64 7346.L_OP_UNUSED_E3: /* 0xe3 */ 7347/* File: armv5te/OP_UNUSED_E3.S */ 7348/* File: armv5te/unused.S */ 7349 bl common_abort 7350 7351 7352 7353/* ------------------------------ */ 7354 .balign 64 7355.L_OP_UNUSED_E4: /* 0xe4 */ 7356/* File: armv5te/OP_UNUSED_E4.S */ 7357/* File: armv5te/unused.S */ 7358 bl common_abort 7359 7360 7361 7362/* ------------------------------ */ 7363 .balign 64 7364.L_OP_UNUSED_E5: /* 0xe5 */ 7365/* File: armv5te/OP_UNUSED_E5.S */ 7366/* File: armv5te/unused.S */ 7367 bl common_abort 7368 7369 7370 7371/* ------------------------------ */ 7372 .balign 64 7373.L_OP_UNUSED_E6: /* 0xe6 */ 7374/* File: armv5te/OP_UNUSED_E6.S */ 7375/* File: armv5te/unused.S */ 7376 bl common_abort 7377 7378 7379 7380/* ------------------------------ */ 7381 .balign 64 7382.L_OP_UNUSED_E7: /* 0xe7 */ 7383/* File: armv5te/OP_UNUSED_E7.S */ 7384/* File: armv5te/unused.S */ 7385 bl common_abort 7386 7387 7388 7389/* ------------------------------ */ 7390 .balign 64 7391.L_OP_UNUSED_E8: /* 0xe8 */ 7392/* File: armv5te/OP_UNUSED_E8.S */ 7393/* File: armv5te/unused.S */ 7394 bl common_abort 7395 7396 7397 7398/* ------------------------------ */ 7399 .balign 64 7400.L_OP_UNUSED_E9: /* 0xe9 */ 7401/* File: armv5te/OP_UNUSED_E9.S */ 7402/* File: armv5te/unused.S */ 7403 bl common_abort 7404 7405 7406 7407/* ------------------------------ */ 7408 .balign 64 7409.L_OP_UNUSED_EA: /* 0xea */ 7410/* File: armv5te/OP_UNUSED_EA.S */ 7411/* File: armv5te/unused.S */ 7412 bl common_abort 7413 7414 7415 7416/* ------------------------------ */ 7417 .balign 64 7418.L_OP_UNUSED_EB: /* 0xeb */ 7419/* File: armv5te/OP_UNUSED_EB.S */ 7420/* File: armv5te/unused.S */ 7421 bl common_abort 7422 7423 7424 7425/* ------------------------------ */ 7426 .balign 64 7427.L_OP_UNUSED_EC: /* 0xec */ 7428/* File: armv5te/OP_UNUSED_EC.S */ 7429/* File: armv5te/unused.S */ 7430 bl common_abort 7431 7432 7433 7434/* ------------------------------ */ 7435 .balign 64 7436.L_OP_UNUSED_ED: /* 0xed */ 7437/* File: armv5te/OP_UNUSED_ED.S */ 7438/* File: armv5te/unused.S */ 7439 bl common_abort 7440 7441 7442 7443/* ------------------------------ */ 7444 .balign 64 7445.L_OP_EXECUTE_INLINE: /* 0xee */ 7446/* File: armv5te/OP_EXECUTE_INLINE.S */ 7447 /* 7448 * Execute a "native inline" instruction. 7449 * 7450 * We need to call: 7451 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref) 7452 * 7453 * The first four args are in r0-r3, but the last two must be pushed 7454 * onto the stack. 7455 */ 7456 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7457 FETCH(r10, 1) @ r10<- BBBB 7458 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7459 EXPORT_PC() @ can throw 7460 sub sp, sp, #8 @ make room for arg(s) 7461 mov r0, rINST, lsr #12 @ r0<- B 7462 str r1, [sp] @ push &glue->retval 7463 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7464 add sp, sp, #8 @ pop stack 7465 cmp r0, #0 @ test boolean result of inline 7466 beq common_exceptionThrown @ returned false, handle exception 7467 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7468 GET_INST_OPCODE(ip) @ extract opcode from rINST 7469 GOTO_OPCODE(ip) @ jump to next instruction 7470 7471/* ------------------------------ */ 7472 .balign 64 7473.L_OP_UNUSED_EF: /* 0xef */ 7474/* File: armv5te/OP_UNUSED_EF.S */ 7475/* File: armv5te/unused.S */ 7476 bl common_abort 7477 7478 7479 7480/* ------------------------------ */ 7481 .balign 64 7482.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7483/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7484 /* 7485 * invoke-direct-empty is a no-op in a "standard" interpreter. 7486 */ 7487 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7488 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7489 GOTO_OPCODE(ip) @ execute it 7490 7491/* ------------------------------ */ 7492 .balign 64 7493.L_OP_UNUSED_F1: /* 0xf1 */ 7494/* File: armv5te/OP_UNUSED_F1.S */ 7495/* File: armv5te/unused.S */ 7496 bl common_abort 7497 7498 7499 7500/* ------------------------------ */ 7501 .balign 64 7502.L_OP_IGET_QUICK: /* 0xf2 */ 7503/* File: armv5te/OP_IGET_QUICK.S */ 7504 /* For: iget-quick, iget-object-quick */ 7505 /* op vA, vB, offset@CCCC */ 7506 mov r2, rINST, lsr #12 @ r2<- B 7507 GET_VREG(r3, r2) @ r3<- object we're operating on 7508 FETCH(r1, 1) @ r1<- field byte offset 7509 cmp r3, #0 @ check object for null 7510 mov r2, rINST, lsr #8 @ r2<- A(+) 7511 beq common_errNullObject @ object was null 7512 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7514 and r2, r2, #15 7515 GET_INST_OPCODE(ip) @ extract opcode from rINST 7516 SET_VREG(r0, r2) @ fp[A]<- r0 7517 GOTO_OPCODE(ip) @ jump to next instruction 7518 7519 7520/* ------------------------------ */ 7521 .balign 64 7522.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7523/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7524 /* iget-wide-quick vA, vB, offset@CCCC */ 7525 mov r2, rINST, lsr #12 @ r2<- B 7526 GET_VREG(r3, r2) @ r3<- object we're operating on 7527 FETCH(r1, 1) @ r1<- field byte offset 7528 cmp r3, #0 @ check object for null 7529 mov r2, rINST, lsr #8 @ r2<- A(+) 7530 beq common_errNullObject @ object was null 7531 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7532 and r2, r2, #15 7533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7534 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7535 GET_INST_OPCODE(ip) @ extract opcode from rINST 7536 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7537 GOTO_OPCODE(ip) @ jump to next instruction 7538 7539 7540/* ------------------------------ */ 7541 .balign 64 7542.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7543/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7544/* File: armv5te/OP_IGET_QUICK.S */ 7545 /* For: iget-quick, iget-object-quick */ 7546 /* op vA, vB, offset@CCCC */ 7547 mov r2, rINST, lsr #12 @ r2<- B 7548 GET_VREG(r3, r2) @ r3<- object we're operating on 7549 FETCH(r1, 1) @ r1<- field byte offset 7550 cmp r3, #0 @ check object for null 7551 mov r2, rINST, lsr #8 @ r2<- A(+) 7552 beq common_errNullObject @ object was null 7553 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7554 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7555 and r2, r2, #15 7556 GET_INST_OPCODE(ip) @ extract opcode from rINST 7557 SET_VREG(r0, r2) @ fp[A]<- r0 7558 GOTO_OPCODE(ip) @ jump to next instruction 7559 7560 7561 7562/* ------------------------------ */ 7563 .balign 64 7564.L_OP_IPUT_QUICK: /* 0xf5 */ 7565/* File: armv5te/OP_IPUT_QUICK.S */ 7566 /* For: iput-quick, iput-object-quick */ 7567 /* op vA, vB, offset@CCCC */ 7568 mov r2, rINST, lsr #12 @ r2<- B 7569 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7570 FETCH(r1, 1) @ r1<- field byte offset 7571 cmp r3, #0 @ check object for null 7572 mov r2, rINST, lsr #8 @ r2<- A(+) 7573 beq common_errNullObject @ object was null 7574 and r2, r2, #15 7575 GET_VREG(r0, r2) @ r0<- fp[A] 7576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7577 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7578 GET_INST_OPCODE(ip) @ extract opcode from rINST 7579 GOTO_OPCODE(ip) @ jump to next instruction 7580 7581 7582/* ------------------------------ */ 7583 .balign 64 7584.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7585/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7586 /* iput-wide-quick vA, vB, offset@CCCC */ 7587 mov r0, rINST, lsr #8 @ r0<- A(+) 7588 mov r1, rINST, lsr #12 @ r1<- B 7589 and r0, r0, #15 7590 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7591 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7592 cmp r2, #0 @ check object for null 7593 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7594 beq common_errNullObject @ object was null 7595 FETCH(r3, 1) @ r3<- field byte offset 7596 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7597 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7598 GET_INST_OPCODE(ip) @ extract opcode from rINST 7599 GOTO_OPCODE(ip) @ jump to next instruction 7600 7601 7602/* ------------------------------ */ 7603 .balign 64 7604.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7605/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7606/* File: armv5te/OP_IPUT_QUICK.S */ 7607 /* For: iput-quick, iput-object-quick */ 7608 /* op vA, vB, offset@CCCC */ 7609 mov r2, rINST, lsr #12 @ r2<- B 7610 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7611 FETCH(r1, 1) @ r1<- field byte offset 7612 cmp r3, #0 @ check object for null 7613 mov r2, rINST, lsr #8 @ r2<- A(+) 7614 beq common_errNullObject @ object was null 7615 and r2, r2, #15 7616 GET_VREG(r0, r2) @ r0<- fp[A] 7617 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7618 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7619 GET_INST_OPCODE(ip) @ extract opcode from rINST 7620 GOTO_OPCODE(ip) @ jump to next instruction 7621 7622 7623 7624/* ------------------------------ */ 7625 .balign 64 7626.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7627/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7628 /* 7629 * Handle an optimized virtual method call. 7630 * 7631 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7632 */ 7633 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7634 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7635 FETCH(r3, 2) @ r3<- FEDC or CCCC 7636 FETCH(r1, 1) @ r1<- BBBB 7637 .if (!0) 7638 and r3, r3, #15 @ r3<- C (or stays CCCC) 7639 .endif 7640 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7641 cmp r2, #0 @ is "this" null? 7642 beq common_errNullObject @ null "this", throw exception 7643 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7644 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7645 EXPORT_PC() @ invoke must export 7646 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7647 bl common_invokeMethodNoRange @ continue on 7648 7649/* ------------------------------ */ 7650 .balign 64 7651.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7652/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7653/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7654 /* 7655 * Handle an optimized virtual method call. 7656 * 7657 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7658 */ 7659 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7660 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7661 FETCH(r3, 2) @ r3<- FEDC or CCCC 7662 FETCH(r1, 1) @ r1<- BBBB 7663 .if (!1) 7664 and r3, r3, #15 @ r3<- C (or stays CCCC) 7665 .endif 7666 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7667 cmp r2, #0 @ is "this" null? 7668 beq common_errNullObject @ null "this", throw exception 7669 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7670 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7671 EXPORT_PC() @ invoke must export 7672 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7673 bl common_invokeMethodRange @ continue on 7674 7675 7676/* ------------------------------ */ 7677 .balign 64 7678.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7679/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7680 /* 7681 * Handle an optimized "super" method call. 7682 * 7683 * for: [opt] invoke-super-quick, invoke-super-quick/range 7684 */ 7685 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7686 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7687 FETCH(r10, 2) @ r10<- GFED or CCCC 7688 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7689 .if (!0) 7690 and r10, r10, #15 @ r10<- D (or stays CCCC) 7691 .endif 7692 FETCH(r1, 1) @ r1<- BBBB 7693 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7694 EXPORT_PC() @ must export for invoke 7695 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7696 GET_VREG(r3, r10) @ r3<- "this" 7697 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7698 cmp r3, #0 @ null "this" ref? 7699 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7700 beq common_errNullObject @ "this" is null, throw exception 7701 bl common_invokeMethodNoRange @ continue on 7702 7703 7704/* ------------------------------ */ 7705 .balign 64 7706.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7707/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7708/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7709 /* 7710 * Handle an optimized "super" method call. 7711 * 7712 * for: [opt] invoke-super-quick, invoke-super-quick/range 7713 */ 7714 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7715 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7716 FETCH(r10, 2) @ r10<- GFED or CCCC 7717 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7718 .if (!1) 7719 and r10, r10, #15 @ r10<- D (or stays CCCC) 7720 .endif 7721 FETCH(r1, 1) @ r1<- BBBB 7722 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7723 EXPORT_PC() @ must export for invoke 7724 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7725 GET_VREG(r3, r10) @ r3<- "this" 7726 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7727 cmp r3, #0 @ null "this" ref? 7728 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7729 beq common_errNullObject @ "this" is null, throw exception 7730 bl common_invokeMethodRange @ continue on 7731 7732 7733 7734/* ------------------------------ */ 7735 .balign 64 7736.L_OP_UNUSED_FC: /* 0xfc */ 7737/* File: armv5te/OP_UNUSED_FC.S */ 7738/* File: armv5te/unused.S */ 7739 bl common_abort 7740 7741 7742 7743/* ------------------------------ */ 7744 .balign 64 7745.L_OP_UNUSED_FD: /* 0xfd */ 7746/* File: armv5te/OP_UNUSED_FD.S */ 7747/* File: armv5te/unused.S */ 7748 bl common_abort 7749 7750 7751 7752/* ------------------------------ */ 7753 .balign 64 7754.L_OP_UNUSED_FE: /* 0xfe */ 7755/* File: armv5te/OP_UNUSED_FE.S */ 7756/* File: armv5te/unused.S */ 7757 bl common_abort 7758 7759 7760 7761/* ------------------------------ */ 7762 .balign 64 7763.L_OP_UNUSED_FF: /* 0xff */ 7764/* File: armv5te/OP_UNUSED_FF.S */ 7765/* File: armv5te/unused.S */ 7766 bl common_abort 7767 7768 7769 7770 7771 .balign 64 7772 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7773 .global dvmAsmInstructionEnd 7774dvmAsmInstructionEnd: 7775 7776/* 7777 * =========================================================================== 7778 * Sister implementations 7779 * =========================================================================== 7780 */ 7781 .global dvmAsmSisterStart 7782 .type dvmAsmSisterStart, %function 7783 .text 7784 .balign 4 7785dvmAsmSisterStart: 7786 7787/* continuation for OP_CONST_STRING */ 7788 7789 /* 7790 * Continuation if the String has not yet been resolved. 7791 * r1: BBBB (String ref) 7792 * r9: target register 7793 */ 7794.LOP_CONST_STRING_resolve: 7795 EXPORT_PC() 7796 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7797 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7798 bl dvmResolveString @ r0<- String reference 7799 cmp r0, #0 @ failed? 7800 beq common_exceptionThrown @ yup, handle the exception 7801 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7802 GET_INST_OPCODE(ip) @ extract opcode from rINST 7803 SET_VREG(r0, r9) @ vAA<- r0 7804 GOTO_OPCODE(ip) @ jump to next instruction 7805 7806 7807/* continuation for OP_CONST_STRING_JUMBO */ 7808 7809 /* 7810 * Continuation if the String has not yet been resolved. 7811 * r1: BBBBBBBB (String ref) 7812 * r9: target register 7813 */ 7814.LOP_CONST_STRING_JUMBO_resolve: 7815 EXPORT_PC() 7816 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7817 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7818 bl dvmResolveString @ r0<- String reference 7819 cmp r0, #0 @ failed? 7820 beq common_exceptionThrown @ yup, handle the exception 7821 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7822 GET_INST_OPCODE(ip) @ extract opcode from rINST 7823 SET_VREG(r0, r9) @ vAA<- r0 7824 GOTO_OPCODE(ip) @ jump to next instruction 7825 7826 7827/* continuation for OP_CONST_CLASS */ 7828 7829 /* 7830 * Continuation if the Class has not yet been resolved. 7831 * r1: BBBB (Class ref) 7832 * r9: target register 7833 */ 7834.LOP_CONST_CLASS_resolve: 7835 EXPORT_PC() 7836 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7837 mov r2, #1 @ r2<- true 7838 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7839 bl dvmResolveClass @ r0<- Class reference 7840 cmp r0, #0 @ failed? 7841 beq common_exceptionThrown @ yup, handle the exception 7842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7843 GET_INST_OPCODE(ip) @ extract opcode from rINST 7844 SET_VREG(r0, r9) @ vAA<- r0 7845 GOTO_OPCODE(ip) @ jump to next instruction 7846 7847 7848/* continuation for OP_CHECK_CAST */ 7849 7850 /* 7851 * Trivial test failed, need to perform full check. This is common. 7852 * r0 holds obj->clazz 7853 * r1 holds class resolved from BBBB 7854 * r9 holds object 7855 */ 7856.LOP_CHECK_CAST_fullcheck: 7857 bl dvmInstanceofNonTrivial @ r0<- boolean result 7858 cmp r0, #0 @ failed? 7859 bne .LOP_CHECK_CAST_okay @ no, success 7860 7861 @ A cast has failed. We need to throw a ClassCastException with the 7862 @ class of the object that failed to be cast. 7863 EXPORT_PC() @ about to throw 7864 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7865 ldr r0, .LstrClassCastExceptionPtr 7866 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7867 bl dvmThrowExceptionWithClassMessage 7868 b common_exceptionThrown 7869 7870 /* 7871 * Resolution required. This is the least-likely path. 7872 * 7873 * r2 holds BBBB 7874 * r9 holds object 7875 */ 7876.LOP_CHECK_CAST_resolve: 7877 EXPORT_PC() @ resolve() could throw 7878 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7879 mov r1, r2 @ r1<- BBBB 7880 mov r2, #0 @ r2<- false 7881 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7882 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7883 cmp r0, #0 @ got null? 7884 beq common_exceptionThrown @ yes, handle exception 7885 mov r1, r0 @ r1<- class resolved from BBB 7886 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7887 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7888 7889.LstrClassCastExceptionPtr: 7890 .word .LstrClassCastException 7891 7892 7893/* continuation for OP_INSTANCE_OF */ 7894 7895 /* 7896 * Trivial test failed, need to perform full check. This is common. 7897 * r0 holds obj->clazz 7898 * r1 holds class resolved from BBBB 7899 * r9 holds A 7900 */ 7901.LOP_INSTANCE_OF_fullcheck: 7902 bl dvmInstanceofNonTrivial @ r0<- boolean result 7903 @ fall through to OP_INSTANCE_OF_store 7904 7905 /* 7906 * r0 holds boolean result 7907 * r9 holds A 7908 */ 7909.LOP_INSTANCE_OF_store: 7910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7911 SET_VREG(r0, r9) @ vA<- r0 7912 GET_INST_OPCODE(ip) @ extract opcode from rINST 7913 GOTO_OPCODE(ip) @ jump to next instruction 7914 7915 /* 7916 * Trivial test succeeded, save and bail. 7917 * r9 holds A 7918 */ 7919.LOP_INSTANCE_OF_trivial: 7920 mov r0, #1 @ indicate success 7921 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7923 SET_VREG(r0, r9) @ vA<- r0 7924 GET_INST_OPCODE(ip) @ extract opcode from rINST 7925 GOTO_OPCODE(ip) @ jump to next instruction 7926 7927 /* 7928 * Resolution required. This is the least-likely path. 7929 * 7930 * r3 holds BBBB 7931 * r9 holds A 7932 */ 7933.LOP_INSTANCE_OF_resolve: 7934 EXPORT_PC() @ resolve() could throw 7935 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7936 mov r1, r3 @ r1<- BBBB 7937 mov r2, #1 @ r2<- true 7938 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7939 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7940 cmp r0, #0 @ got null? 7941 beq common_exceptionThrown @ yes, handle exception 7942 mov r1, r0 @ r1<- class resolved from BBB 7943 mov r3, rINST, lsr #12 @ r3<- B 7944 GET_VREG(r0, r3) @ r0<- vB (object) 7945 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7946 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7947 7948 7949/* continuation for OP_NEW_INSTANCE */ 7950 7951 .balign 32 @ minimize cache lines 7952.LOP_NEW_INSTANCE_finish: @ r0=class 7953 bl dvmAllocObject @ r0<- new object 7954 mov r3, rINST, lsr #8 @ r3<- AA 7955 cmp r0, #0 @ failed? 7956 beq common_exceptionThrown @ yes, handle the exception 7957 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7958 GET_INST_OPCODE(ip) @ extract opcode from rINST 7959 SET_VREG(r0, r3) @ vAA<- r0 7960 GOTO_OPCODE(ip) @ jump to next instruction 7961 7962 /* 7963 * Class initialization required. 7964 * 7965 * r0 holds class object 7966 */ 7967.LOP_NEW_INSTANCE_needinit: 7968 mov r9, r0 @ save r0 7969 bl dvmInitClass @ initialize class 7970 cmp r0, #0 @ check boolean result 7971 mov r0, r9 @ restore r0 7972 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7973 b common_exceptionThrown @ failed, deal with init exception 7974 7975 /* 7976 * Resolution required. This is the least-likely path. 7977 * 7978 * r1 holds BBBB 7979 */ 7980.LOP_NEW_INSTANCE_resolve: 7981 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7982 mov r2, #0 @ r2<- false 7983 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7984 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7985 cmp r0, #0 @ got null? 7986 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7987 b common_exceptionThrown @ yes, handle exception 7988 7989 /* 7990 * We can't instantiate an abstract class or interface, so throw an 7991 * InstantiationError with the class descriptor as the message. 7992 * 7993 * r0 holds class object 7994 */ 7995.LOP_NEW_INSTANCE_abstract: 7996 ldr r1, [r0, #offClassObject_descriptor] 7997 ldr r0, .LstrInstantiationErrorPtr 7998 bl dvmThrowExceptionWithClassMessage 7999 b common_exceptionThrown 8000 8001.LstrInstantiationErrorPtr: 8002 .word .LstrInstantiationError 8003 8004 8005/* continuation for OP_NEW_ARRAY */ 8006 8007 8008 /* 8009 * Resolve class. (This is an uncommon case.) 8010 * 8011 * r1 holds array length 8012 * r2 holds class ref CCCC 8013 */ 8014.LOP_NEW_ARRAY_resolve: 8015 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8016 mov r9, r1 @ r9<- length (save) 8017 mov r1, r2 @ r1<- CCCC 8018 mov r2, #0 @ r2<- false 8019 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8020 bl dvmResolveClass @ r0<- call(clazz, ref) 8021 cmp r0, #0 @ got null? 8022 mov r1, r9 @ r1<- length (restore) 8023 beq common_exceptionThrown @ yes, handle exception 8024 @ fall through to OP_NEW_ARRAY_finish 8025 8026 /* 8027 * Finish allocation. 8028 * 8029 * r0 holds class 8030 * r1 holds array length 8031 */ 8032.LOP_NEW_ARRAY_finish: 8033 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8034 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8035 cmp r0, #0 @ failed? 8036 mov r2, rINST, lsr #8 @ r2<- A+ 8037 beq common_exceptionThrown @ yes, handle the exception 8038 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8039 and r2, r2, #15 @ r2<- A 8040 GET_INST_OPCODE(ip) @ extract opcode from rINST 8041 SET_VREG(r0, r2) @ vA<- r0 8042 GOTO_OPCODE(ip) @ jump to next instruction 8043 8044 8045/* continuation for OP_FILLED_NEW_ARRAY */ 8046 8047 /* 8048 * On entry: 8049 * r0 holds array class 8050 * r10 holds AA or BA 8051 */ 8052.LOP_FILLED_NEW_ARRAY_continue: 8053 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8054 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8055 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8056 .if 0 8057 mov r1, r10 @ r1<- AA (length) 8058 .else 8059 mov r1, r10, lsr #4 @ r1<- B (length) 8060 .endif 8061 cmp r3, #'I' @ array of ints? 8062 cmpne r3, #'L' @ array of objects? 8063 cmpne r3, #'[' @ array of arrays? 8064 mov r9, r1 @ save length in r9 8065 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8066 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8067 cmp r0, #0 @ null return? 8068 beq common_exceptionThrown @ alloc failed, handle exception 8069 8070 FETCH(r1, 2) @ r1<- FEDC or CCCC 8071 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8072 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8073 subs r9, r9, #1 @ length--, check for neg 8074 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8075 bmi 2f @ was zero, bail 8076 8077 @ copy values from registers into the array 8078 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8079 .if 0 8080 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80811: ldr r3, [r2], #4 @ r3<- *r2++ 8082 subs r9, r9, #1 @ count-- 8083 str r3, [r0], #4 @ *contents++ = vX 8084 bpl 1b 8085 @ continue at 2 8086 .else 8087 cmp r9, #4 @ length was initially 5? 8088 and r2, r10, #15 @ r2<- A 8089 bne 1f @ <= 4 args, branch 8090 GET_VREG(r3, r2) @ r3<- vA 8091 sub r9, r9, #1 @ count-- 8092 str r3, [r0, #16] @ contents[4] = vA 80931: and r2, r1, #15 @ r2<- F/E/D/C 8094 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8095 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8096 subs r9, r9, #1 @ count-- 8097 str r3, [r0], #4 @ *contents++ = vX 8098 bpl 1b 8099 @ continue at 2 8100 .endif 8101 81022: 8103 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8104 GOTO_OPCODE(ip) @ execute it 8105 8106 /* 8107 * Throw an exception indicating that we have not implemented this 8108 * mode of filled-new-array. 8109 */ 8110.LOP_FILLED_NEW_ARRAY_notimpl: 8111 ldr r0, .L_strInternalError 8112 ldr r1, .L_strFilledNewArrayNotImpl 8113 bl dvmThrowException 8114 b common_exceptionThrown 8115 8116 .if (!0) @ define in one or the other, not both 8117.L_strFilledNewArrayNotImpl: 8118 .word .LstrFilledNewArrayNotImpl 8119.L_strInternalError: 8120 .word .LstrInternalError 8121 .endif 8122 8123 8124/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8125 8126 /* 8127 * On entry: 8128 * r0 holds array class 8129 * r10 holds AA or BA 8130 */ 8131.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8132 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8133 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8134 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8135 .if 1 8136 mov r1, r10 @ r1<- AA (length) 8137 .else 8138 mov r1, r10, lsr #4 @ r1<- B (length) 8139 .endif 8140 cmp r3, #'I' @ array of ints? 8141 cmpne r3, #'L' @ array of objects? 8142 cmpne r3, #'[' @ array of arrays? 8143 mov r9, r1 @ save length in r9 8144 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8145 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8146 cmp r0, #0 @ null return? 8147 beq common_exceptionThrown @ alloc failed, handle exception 8148 8149 FETCH(r1, 2) @ r1<- FEDC or CCCC 8150 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8151 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8152 subs r9, r9, #1 @ length--, check for neg 8153 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8154 bmi 2f @ was zero, bail 8155 8156 @ copy values from registers into the array 8157 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8158 .if 1 8159 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81601: ldr r3, [r2], #4 @ r3<- *r2++ 8161 subs r9, r9, #1 @ count-- 8162 str r3, [r0], #4 @ *contents++ = vX 8163 bpl 1b 8164 @ continue at 2 8165 .else 8166 cmp r9, #4 @ length was initially 5? 8167 and r2, r10, #15 @ r2<- A 8168 bne 1f @ <= 4 args, branch 8169 GET_VREG(r3, r2) @ r3<- vA 8170 sub r9, r9, #1 @ count-- 8171 str r3, [r0, #16] @ contents[4] = vA 81721: and r2, r1, #15 @ r2<- F/E/D/C 8173 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8174 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8175 subs r9, r9, #1 @ count-- 8176 str r3, [r0], #4 @ *contents++ = vX 8177 bpl 1b 8178 @ continue at 2 8179 .endif 8180 81812: 8182 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8183 GOTO_OPCODE(ip) @ execute it 8184 8185 /* 8186 * Throw an exception indicating that we have not implemented this 8187 * mode of filled-new-array. 8188 */ 8189.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8190 ldr r0, .L_strInternalError 8191 ldr r1, .L_strFilledNewArrayNotImpl 8192 bl dvmThrowException 8193 b common_exceptionThrown 8194 8195 .if (!1) @ define in one or the other, not both 8196.L_strFilledNewArrayNotImpl: 8197 .word .LstrFilledNewArrayNotImpl 8198.L_strInternalError: 8199 .word .LstrInternalError 8200 .endif 8201 8202 8203/* continuation for OP_CMPL_FLOAT */ 8204 8205 @ Test for NaN with a second comparison. EABI forbids testing bit 8206 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8207 @ make the library call. 8208.LOP_CMPL_FLOAT_gt_or_nan: 8209 mov r1, r9 @ reverse order 8210 mov r0, r10 8211 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8212 @bleq common_abort 8213 movcc r1, #1 @ (greater than) r1<- 1 8214 bcc .LOP_CMPL_FLOAT_finish 8215 mvn r1, #0 @ r1<- 1 or -1 for NaN 8216 b .LOP_CMPL_FLOAT_finish 8217 8218 8219#if 0 /* "clasic" form */ 8220 FETCH(r0, 1) @ r0<- CCBB 8221 and r2, r0, #255 @ r2<- BB 8222 mov r3, r0, lsr #8 @ r3<- CC 8223 GET_VREG(r9, r2) @ r9<- vBB 8224 GET_VREG(r10, r3) @ r10<- vCC 8225 mov r0, r9 @ r0<- vBB 8226 mov r1, r10 @ r1<- vCC 8227 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8228 cmp r0, #0 @ equal? 8229 movne r1, #0 @ yes, result is 0 8230 bne OP_CMPL_FLOAT_finish 8231 mov r0, r9 @ r0<- vBB 8232 mov r1, r10 @ r1<- vCC 8233 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8234 cmp r0, #0 @ less than? 8235 b OP_CMPL_FLOAT_continue 8236@%break 8237 8238OP_CMPL_FLOAT_continue: 8239 mvnne r1, #0 @ yes, result is -1 8240 bne OP_CMPL_FLOAT_finish 8241 mov r0, r9 @ r0<- vBB 8242 mov r1, r10 @ r1<- vCC 8243 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8244 cmp r0, #0 @ greater than? 8245 beq OP_CMPL_FLOAT_nan @ no, must be NaN 8246 mov r1, #1 @ yes, result is 1 8247 @ fall through to _finish 8248 8249OP_CMPL_FLOAT_finish: 8250 mov r3, rINST, lsr #8 @ r3<- AA 8251 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8252 SET_VREG(r1, r3) @ vAA<- r1 8253 GET_INST_OPCODE(ip) @ extract opcode from rINST 8254 GOTO_OPCODE(ip) @ jump to next instruction 8255 8256 /* 8257 * This is expected to be uncommon, so we double-branch (once to here, 8258 * again back to _finish). 8259 */ 8260OP_CMPL_FLOAT_nan: 8261 mvn r1, #0 @ r1<- 1 or -1 for NaN 8262 b OP_CMPL_FLOAT_finish 8263 8264#endif 8265 8266 8267/* continuation for OP_CMPG_FLOAT */ 8268 8269 @ Test for NaN with a second comparison. EABI forbids testing bit 8270 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8271 @ make the library call. 8272.LOP_CMPG_FLOAT_gt_or_nan: 8273 mov r1, r9 @ reverse order 8274 mov r0, r10 8275 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if < 8276 @bleq common_abort 8277 movcc r1, #1 @ (greater than) r1<- 1 8278 bcc .LOP_CMPG_FLOAT_finish 8279 mov r1, #1 @ r1<- 1 or -1 for NaN 8280 b .LOP_CMPG_FLOAT_finish 8281 8282 8283#if 0 /* "clasic" form */ 8284 FETCH(r0, 1) @ r0<- CCBB 8285 and r2, r0, #255 @ r2<- BB 8286 mov r3, r0, lsr #8 @ r3<- CC 8287 GET_VREG(r9, r2) @ r9<- vBB 8288 GET_VREG(r10, r3) @ r10<- vCC 8289 mov r0, r9 @ r0<- vBB 8290 mov r1, r10 @ r1<- vCC 8291 bl __aeabi_fcmpeq @ r0<- (vBB == vCC) 8292 cmp r0, #0 @ equal? 8293 movne r1, #0 @ yes, result is 0 8294 bne OP_CMPG_FLOAT_finish 8295 mov r0, r9 @ r0<- vBB 8296 mov r1, r10 @ r1<- vCC 8297 bl __aeabi_fcmplt @ r0<- (vBB < vCC) 8298 cmp r0, #0 @ less than? 8299 b OP_CMPG_FLOAT_continue 8300@%break 8301 8302OP_CMPG_FLOAT_continue: 8303 mvnne r1, #0 @ yes, result is -1 8304 bne OP_CMPG_FLOAT_finish 8305 mov r0, r9 @ r0<- vBB 8306 mov r1, r10 @ r1<- vCC 8307 bl __aeabi_fcmpgt @ r0<- (vBB > vCC) 8308 cmp r0, #0 @ greater than? 8309 beq OP_CMPG_FLOAT_nan @ no, must be NaN 8310 mov r1, #1 @ yes, result is 1 8311 @ fall through to _finish 8312 8313OP_CMPG_FLOAT_finish: 8314 mov r3, rINST, lsr #8 @ r3<- AA 8315 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8316 SET_VREG(r1, r3) @ vAA<- r1 8317 GET_INST_OPCODE(ip) @ extract opcode from rINST 8318 GOTO_OPCODE(ip) @ jump to next instruction 8319 8320 /* 8321 * This is expected to be uncommon, so we double-branch (once to here, 8322 * again back to _finish). 8323 */ 8324OP_CMPG_FLOAT_nan: 8325 mov r1, #1 @ r1<- 1 or -1 for NaN 8326 b OP_CMPG_FLOAT_finish 8327 8328#endif 8329 8330 8331/* continuation for OP_CMPL_DOUBLE */ 8332 8333 @ Test for NaN with a second comparison. EABI forbids testing bit 8334 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8335 @ make the library call. 8336.LOP_CMPL_DOUBLE_gt_or_nan: 8337 ldmia r10, {r0-r1} @ reverse order 8338 ldmia r9, {r2-r3} 8339 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8340 @bleq common_abort 8341 movcc r1, #1 @ (greater than) r1<- 1 8342 bcc .LOP_CMPL_DOUBLE_finish 8343 mvn r1, #0 @ r1<- 1 or -1 for NaN 8344 b .LOP_CMPL_DOUBLE_finish 8345 8346 8347/* continuation for OP_CMPG_DOUBLE */ 8348 8349 @ Test for NaN with a second comparison. EABI forbids testing bit 8350 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 8351 @ make the library call. 8352.LOP_CMPG_DOUBLE_gt_or_nan: 8353 ldmia r10, {r0-r1} @ reverse order 8354 ldmia r9, {r2-r3} 8355 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if < 8356 @bleq common_abort 8357 movcc r1, #1 @ (greater than) r1<- 1 8358 bcc .LOP_CMPG_DOUBLE_finish 8359 mov r1, #1 @ r1<- 1 or -1 for NaN 8360 b .LOP_CMPG_DOUBLE_finish 8361 8362 8363/* continuation for OP_CMP_LONG */ 8364 8365.LOP_CMP_LONG_less: 8366 mvn r1, #0 @ r1<- -1 8367 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8368 @ instead, we just replicate the tail end. 8369 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8370 SET_VREG(r1, r9) @ vAA<- r1 8371 GET_INST_OPCODE(ip) @ extract opcode from rINST 8372 GOTO_OPCODE(ip) @ jump to next instruction 8373 8374.LOP_CMP_LONG_greater: 8375 mov r1, #1 @ r1<- 1 8376 @ fall through to _finish 8377 8378.LOP_CMP_LONG_finish: 8379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8380 SET_VREG(r1, r9) @ vAA<- r1 8381 GET_INST_OPCODE(ip) @ extract opcode from rINST 8382 GOTO_OPCODE(ip) @ jump to next instruction 8383 8384 8385/* continuation for OP_AGET_WIDE */ 8386 8387.LOP_AGET_WIDE_finish: 8388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8389 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8390 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8391 GET_INST_OPCODE(ip) @ extract opcode from rINST 8392 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8393 GOTO_OPCODE(ip) @ jump to next instruction 8394 8395 8396/* continuation for OP_APUT_WIDE */ 8397 8398.LOP_APUT_WIDE_finish: 8399 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8400 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8401 GET_INST_OPCODE(ip) @ extract opcode from rINST 8402 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8403 GOTO_OPCODE(ip) @ jump to next instruction 8404 8405 8406/* continuation for OP_APUT_OBJECT */ 8407 /* 8408 * On entry: 8409 * r1 = vBB (arrayObj) 8410 * r9 = vAA (obj) 8411 * r10 = offset into array (vBB + vCC * width) 8412 */ 8413.LOP_APUT_OBJECT_finish: 8414 cmp r9, #0 @ storing null reference? 8415 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8416 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8417 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8418 bl dvmCanPutArrayElement @ test object type vs. array type 8419 cmp r0, #0 @ okay? 8420 beq common_errArrayStore @ no 8421.LOP_APUT_OBJECT_skip_check: 8422 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8423 GET_INST_OPCODE(ip) @ extract opcode from rINST 8424 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8425 GOTO_OPCODE(ip) @ jump to next instruction 8426 8427 8428/* continuation for OP_IGET */ 8429 8430 /* 8431 * Currently: 8432 * r0 holds resolved field 8433 * r9 holds object 8434 */ 8435.LOP_IGET_finish: 8436 @bl common_squeak0 8437 cmp r9, #0 @ check object for null 8438 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8439 beq common_errNullObject @ object was null 8440 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8441 mov r2, rINST, lsr #8 @ r2<- A+ 8442 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8443 and r2, r2, #15 @ r2<- A 8444 GET_INST_OPCODE(ip) @ extract opcode from rINST 8445 SET_VREG(r0, r2) @ fp[A]<- r0 8446 GOTO_OPCODE(ip) @ jump to next instruction 8447 8448 8449/* continuation for OP_IGET_WIDE */ 8450 8451 /* 8452 * Currently: 8453 * r0 holds resolved field 8454 * r9 holds object 8455 */ 8456.LOP_IGET_WIDE_finish: 8457 cmp r9, #0 @ check object for null 8458 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8459 beq common_errNullObject @ object was null 8460 mov r2, rINST, lsr #8 @ r2<- A+ 8461 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8462 and r2, r2, #15 @ r2<- A 8463 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8464 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8465 GET_INST_OPCODE(ip) @ extract opcode from rINST 8466 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8467 GOTO_OPCODE(ip) @ jump to next instruction 8468 8469 8470/* continuation for OP_IGET_OBJECT */ 8471 8472 /* 8473 * Currently: 8474 * r0 holds resolved field 8475 * r9 holds object 8476 */ 8477.LOP_IGET_OBJECT_finish: 8478 @bl common_squeak0 8479 cmp r9, #0 @ check object for null 8480 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8481 beq common_errNullObject @ object was null 8482 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8483 mov r2, rINST, lsr #8 @ r2<- A+ 8484 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8485 and r2, r2, #15 @ r2<- A 8486 GET_INST_OPCODE(ip) @ extract opcode from rINST 8487 SET_VREG(r0, r2) @ fp[A]<- r0 8488 GOTO_OPCODE(ip) @ jump to next instruction 8489 8490 8491/* continuation for OP_IGET_BOOLEAN */ 8492 8493 /* 8494 * Currently: 8495 * r0 holds resolved field 8496 * r9 holds object 8497 */ 8498.LOP_IGET_BOOLEAN_finish: 8499 @bl common_squeak1 8500 cmp r9, #0 @ check object for null 8501 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8502 beq common_errNullObject @ object was null 8503 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8504 mov r2, rINST, lsr #8 @ r2<- A+ 8505 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8506 and r2, r2, #15 @ r2<- A 8507 GET_INST_OPCODE(ip) @ extract opcode from rINST 8508 SET_VREG(r0, r2) @ fp[A]<- r0 8509 GOTO_OPCODE(ip) @ jump to next instruction 8510 8511 8512/* continuation for OP_IGET_BYTE */ 8513 8514 /* 8515 * Currently: 8516 * r0 holds resolved field 8517 * r9 holds object 8518 */ 8519.LOP_IGET_BYTE_finish: 8520 @bl common_squeak2 8521 cmp r9, #0 @ check object for null 8522 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8523 beq common_errNullObject @ object was null 8524 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8525 mov r2, rINST, lsr #8 @ r2<- A+ 8526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8527 and r2, r2, #15 @ r2<- A 8528 GET_INST_OPCODE(ip) @ extract opcode from rINST 8529 SET_VREG(r0, r2) @ fp[A]<- r0 8530 GOTO_OPCODE(ip) @ jump to next instruction 8531 8532 8533/* continuation for OP_IGET_CHAR */ 8534 8535 /* 8536 * Currently: 8537 * r0 holds resolved field 8538 * r9 holds object 8539 */ 8540.LOP_IGET_CHAR_finish: 8541 @bl common_squeak3 8542 cmp r9, #0 @ check object for null 8543 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8544 beq common_errNullObject @ object was null 8545 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8546 mov r2, rINST, lsr #8 @ r2<- A+ 8547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8548 and r2, r2, #15 @ r2<- A 8549 GET_INST_OPCODE(ip) @ extract opcode from rINST 8550 SET_VREG(r0, r2) @ fp[A]<- r0 8551 GOTO_OPCODE(ip) @ jump to next instruction 8552 8553 8554/* continuation for OP_IGET_SHORT */ 8555 8556 /* 8557 * Currently: 8558 * r0 holds resolved field 8559 * r9 holds object 8560 */ 8561.LOP_IGET_SHORT_finish: 8562 @bl common_squeak4 8563 cmp r9, #0 @ check object for null 8564 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8565 beq common_errNullObject @ object was null 8566 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8567 mov r2, rINST, lsr #8 @ r2<- A+ 8568 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8569 and r2, r2, #15 @ r2<- A 8570 GET_INST_OPCODE(ip) @ extract opcode from rINST 8571 SET_VREG(r0, r2) @ fp[A]<- r0 8572 GOTO_OPCODE(ip) @ jump to next instruction 8573 8574 8575/* continuation for OP_IPUT */ 8576 8577 /* 8578 * Currently: 8579 * r0 holds resolved field 8580 * r9 holds object 8581 */ 8582.LOP_IPUT_finish: 8583 @bl common_squeak0 8584 mov r1, rINST, lsr #8 @ r1<- A+ 8585 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8586 and r1, r1, #15 @ r1<- A 8587 cmp r9, #0 @ check object for null 8588 GET_VREG(r0, r1) @ r0<- fp[A] 8589 beq common_errNullObject @ object was null 8590 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8591 GET_INST_OPCODE(ip) @ extract opcode from rINST 8592 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8593 GOTO_OPCODE(ip) @ jump to next instruction 8594 8595 8596/* continuation for OP_IPUT_WIDE */ 8597 8598 /* 8599 * Currently: 8600 * r0 holds resolved field 8601 * r9 holds object 8602 */ 8603.LOP_IPUT_WIDE_finish: 8604 mov r2, rINST, lsr #8 @ r2<- A+ 8605 cmp r9, #0 @ check object for null 8606 and r2, r2, #15 @ r2<- A 8607 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8608 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8609 beq common_errNullObject @ object was null 8610 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8611 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8612 GET_INST_OPCODE(ip) @ extract opcode from rINST 8613 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8614 GOTO_OPCODE(ip) @ jump to next instruction 8615 8616 8617/* continuation for OP_IPUT_OBJECT */ 8618 8619 /* 8620 * Currently: 8621 * r0 holds resolved field 8622 * r9 holds object 8623 */ 8624.LOP_IPUT_OBJECT_finish: 8625 @bl common_squeak0 8626 mov r1, rINST, lsr #8 @ r1<- A+ 8627 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8628 and r1, r1, #15 @ r1<- A 8629 cmp r9, #0 @ check object for null 8630 GET_VREG(r0, r1) @ r0<- fp[A] 8631 beq common_errNullObject @ object was null 8632 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8633 GET_INST_OPCODE(ip) @ extract opcode from rINST 8634 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8635 GOTO_OPCODE(ip) @ jump to next instruction 8636 8637 8638/* continuation for OP_IPUT_BOOLEAN */ 8639 8640 /* 8641 * Currently: 8642 * r0 holds resolved field 8643 * r9 holds object 8644 */ 8645.LOP_IPUT_BOOLEAN_finish: 8646 @bl common_squeak1 8647 mov r1, rINST, lsr #8 @ r1<- A+ 8648 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8649 and r1, r1, #15 @ r1<- A 8650 cmp r9, #0 @ check object for null 8651 GET_VREG(r0, r1) @ r0<- fp[A] 8652 beq common_errNullObject @ object was null 8653 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8654 GET_INST_OPCODE(ip) @ extract opcode from rINST 8655 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8656 GOTO_OPCODE(ip) @ jump to next instruction 8657 8658 8659/* continuation for OP_IPUT_BYTE */ 8660 8661 /* 8662 * Currently: 8663 * r0 holds resolved field 8664 * r9 holds object 8665 */ 8666.LOP_IPUT_BYTE_finish: 8667 @bl common_squeak2 8668 mov r1, rINST, lsr #8 @ r1<- A+ 8669 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8670 and r1, r1, #15 @ r1<- A 8671 cmp r9, #0 @ check object for null 8672 GET_VREG(r0, r1) @ r0<- fp[A] 8673 beq common_errNullObject @ object was null 8674 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8675 GET_INST_OPCODE(ip) @ extract opcode from rINST 8676 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8677 GOTO_OPCODE(ip) @ jump to next instruction 8678 8679 8680/* continuation for OP_IPUT_CHAR */ 8681 8682 /* 8683 * Currently: 8684 * r0 holds resolved field 8685 * r9 holds object 8686 */ 8687.LOP_IPUT_CHAR_finish: 8688 @bl common_squeak3 8689 mov r1, rINST, lsr #8 @ r1<- A+ 8690 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8691 and r1, r1, #15 @ r1<- A 8692 cmp r9, #0 @ check object for null 8693 GET_VREG(r0, r1) @ r0<- fp[A] 8694 beq common_errNullObject @ object was null 8695 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8696 GET_INST_OPCODE(ip) @ extract opcode from rINST 8697 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8698 GOTO_OPCODE(ip) @ jump to next instruction 8699 8700 8701/* continuation for OP_IPUT_SHORT */ 8702 8703 /* 8704 * Currently: 8705 * r0 holds resolved field 8706 * r9 holds object 8707 */ 8708.LOP_IPUT_SHORT_finish: 8709 @bl common_squeak4 8710 mov r1, rINST, lsr #8 @ r1<- A+ 8711 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8712 and r1, r1, #15 @ r1<- A 8713 cmp r9, #0 @ check object for null 8714 GET_VREG(r0, r1) @ r0<- fp[A] 8715 beq common_errNullObject @ object was null 8716 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8717 GET_INST_OPCODE(ip) @ extract opcode from rINST 8718 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8719 GOTO_OPCODE(ip) @ jump to next instruction 8720 8721 8722/* continuation for OP_SGET */ 8723 8724 /* 8725 * Continuation if the field has not yet been resolved. 8726 * r1: BBBB field ref 8727 */ 8728.LOP_SGET_resolve: 8729 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8730 EXPORT_PC() @ resolve() could throw, so export now 8731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8732 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8733 cmp r0, #0 @ success? 8734 bne .LOP_SGET_finish @ yes, finish 8735 b common_exceptionThrown @ no, handle exception 8736 8737 8738/* continuation for OP_SGET_WIDE */ 8739 8740 /* 8741 * Continuation if the field has not yet been resolved. 8742 * r1: BBBB field ref 8743 */ 8744.LOP_SGET_WIDE_resolve: 8745 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8746 EXPORT_PC() @ resolve() could throw, so export now 8747 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8748 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8749 cmp r0, #0 @ success? 8750 bne .LOP_SGET_WIDE_finish @ yes, finish 8751 b common_exceptionThrown @ no, handle exception 8752 8753 8754/* continuation for OP_SGET_OBJECT */ 8755 8756 /* 8757 * Continuation if the field has not yet been resolved. 8758 * r1: BBBB field ref 8759 */ 8760.LOP_SGET_OBJECT_resolve: 8761 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8762 EXPORT_PC() @ resolve() could throw, so export now 8763 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8764 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8765 cmp r0, #0 @ success? 8766 bne .LOP_SGET_OBJECT_finish @ yes, finish 8767 b common_exceptionThrown @ no, handle exception 8768 8769 8770/* continuation for OP_SGET_BOOLEAN */ 8771 8772 /* 8773 * Continuation if the field has not yet been resolved. 8774 * r1: BBBB field ref 8775 */ 8776.LOP_SGET_BOOLEAN_resolve: 8777 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8778 EXPORT_PC() @ resolve() could throw, so export now 8779 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8780 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8781 cmp r0, #0 @ success? 8782 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8783 b common_exceptionThrown @ no, handle exception 8784 8785 8786/* continuation for OP_SGET_BYTE */ 8787 8788 /* 8789 * Continuation if the field has not yet been resolved. 8790 * r1: BBBB field ref 8791 */ 8792.LOP_SGET_BYTE_resolve: 8793 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8794 EXPORT_PC() @ resolve() could throw, so export now 8795 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8796 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8797 cmp r0, #0 @ success? 8798 bne .LOP_SGET_BYTE_finish @ yes, finish 8799 b common_exceptionThrown @ no, handle exception 8800 8801 8802/* continuation for OP_SGET_CHAR */ 8803 8804 /* 8805 * Continuation if the field has not yet been resolved. 8806 * r1: BBBB field ref 8807 */ 8808.LOP_SGET_CHAR_resolve: 8809 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8810 EXPORT_PC() @ resolve() could throw, so export now 8811 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8812 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8813 cmp r0, #0 @ success? 8814 bne .LOP_SGET_CHAR_finish @ yes, finish 8815 b common_exceptionThrown @ no, handle exception 8816 8817 8818/* continuation for OP_SGET_SHORT */ 8819 8820 /* 8821 * Continuation if the field has not yet been resolved. 8822 * r1: BBBB field ref 8823 */ 8824.LOP_SGET_SHORT_resolve: 8825 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8826 EXPORT_PC() @ resolve() could throw, so export now 8827 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8828 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8829 cmp r0, #0 @ success? 8830 bne .LOP_SGET_SHORT_finish @ yes, finish 8831 b common_exceptionThrown @ no, handle exception 8832 8833 8834/* continuation for OP_SPUT */ 8835 8836 /* 8837 * Continuation if the field has not yet been resolved. 8838 * r1: BBBB field ref 8839 */ 8840.LOP_SPUT_resolve: 8841 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8842 EXPORT_PC() @ resolve() could throw, so export now 8843 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8844 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8845 cmp r0, #0 @ success? 8846 bne .LOP_SPUT_finish @ yes, finish 8847 b common_exceptionThrown @ no, handle exception 8848 8849 8850/* continuation for OP_SPUT_WIDE */ 8851 8852 /* 8853 * Continuation if the field has not yet been resolved. 8854 * r1: BBBB field ref 8855 * r9: &fp[AA] 8856 */ 8857.LOP_SPUT_WIDE_resolve: 8858 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8859 EXPORT_PC() @ resolve() could throw, so export now 8860 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8861 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8862 cmp r0, #0 @ success? 8863 bne .LOP_SPUT_WIDE_finish @ yes, finish 8864 b common_exceptionThrown @ no, handle exception 8865 8866 8867/* continuation for OP_SPUT_OBJECT */ 8868 8869 /* 8870 * Continuation if the field has not yet been resolved. 8871 * r1: BBBB field ref 8872 */ 8873.LOP_SPUT_OBJECT_resolve: 8874 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8875 EXPORT_PC() @ resolve() could throw, so export now 8876 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8877 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8878 cmp r0, #0 @ success? 8879 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8880 b common_exceptionThrown @ no, handle exception 8881 8882 8883/* continuation for OP_SPUT_BOOLEAN */ 8884 8885 /* 8886 * Continuation if the field has not yet been resolved. 8887 * r1: BBBB field ref 8888 */ 8889.LOP_SPUT_BOOLEAN_resolve: 8890 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8891 EXPORT_PC() @ resolve() could throw, so export now 8892 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8893 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8894 cmp r0, #0 @ success? 8895 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8896 b common_exceptionThrown @ no, handle exception 8897 8898 8899/* continuation for OP_SPUT_BYTE */ 8900 8901 /* 8902 * Continuation if the field has not yet been resolved. 8903 * r1: BBBB field ref 8904 */ 8905.LOP_SPUT_BYTE_resolve: 8906 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8907 EXPORT_PC() @ resolve() could throw, so export now 8908 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8909 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8910 cmp r0, #0 @ success? 8911 bne .LOP_SPUT_BYTE_finish @ yes, finish 8912 b common_exceptionThrown @ no, handle exception 8913 8914 8915/* continuation for OP_SPUT_CHAR */ 8916 8917 /* 8918 * Continuation if the field has not yet been resolved. 8919 * r1: BBBB field ref 8920 */ 8921.LOP_SPUT_CHAR_resolve: 8922 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8923 EXPORT_PC() @ resolve() could throw, so export now 8924 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8925 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8926 cmp r0, #0 @ success? 8927 bne .LOP_SPUT_CHAR_finish @ yes, finish 8928 b common_exceptionThrown @ no, handle exception 8929 8930 8931/* continuation for OP_SPUT_SHORT */ 8932 8933 /* 8934 * Continuation if the field has not yet been resolved. 8935 * r1: BBBB field ref 8936 */ 8937.LOP_SPUT_SHORT_resolve: 8938 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8939 EXPORT_PC() @ resolve() could throw, so export now 8940 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8941 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8942 cmp r0, #0 @ success? 8943 bne .LOP_SPUT_SHORT_finish @ yes, finish 8944 b common_exceptionThrown @ no, handle exception 8945 8946 8947/* continuation for OP_INVOKE_VIRTUAL */ 8948 8949 /* 8950 * At this point: 8951 * r0 = resolved base method 8952 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8953 */ 8954.LOP_INVOKE_VIRTUAL_continue: 8955 GET_VREG(r1, r10) @ r1<- "this" ptr 8956 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8957 cmp r1, #0 @ is "this" null? 8958 beq common_errNullObject @ null "this", throw exception 8959 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8960 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8961 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8962 bl common_invokeMethodNoRange @ continue on 8963 8964 8965/* continuation for OP_INVOKE_SUPER */ 8966 8967 /* 8968 * At this point: 8969 * r0 = resolved base method 8970 * r9 = method->clazz 8971 */ 8972.LOP_INVOKE_SUPER_continue: 8973 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8974 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8975 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8976 EXPORT_PC() @ must export for invoke 8977 cmp r2, r3 @ compare (methodIndex, vtableCount) 8978 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8979 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8980 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8981 bl common_invokeMethodNoRange @ continue on 8982 8983.LOP_INVOKE_SUPER_resolve: 8984 mov r0, r9 @ r0<- method->clazz 8985 mov r2, #METHOD_VIRTUAL @ resolver method type 8986 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8987 cmp r0, #0 @ got null? 8988 bne .LOP_INVOKE_SUPER_continue @ no, continue 8989 b common_exceptionThrown @ yes, handle exception 8990 8991 /* 8992 * Throw a NoSuchMethodError with the method name as the message. 8993 * r0 = resolved base method 8994 */ 8995.LOP_INVOKE_SUPER_nsm: 8996 ldr r1, [r0, #offMethod_name] @ r1<- method name 8997 b common_errNoSuchMethod 8998 8999 9000/* continuation for OP_INVOKE_DIRECT */ 9001 9002 /* 9003 * On entry: 9004 * r1 = reference (BBBB or CCCC) 9005 * r10 = "this" register 9006 */ 9007.LOP_INVOKE_DIRECT_resolve: 9008 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9009 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9010 mov r2, #METHOD_DIRECT @ resolver method type 9011 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9012 cmp r0, #0 @ got null? 9013 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9014 bne .LOP_INVOKE_DIRECT_finish @ no, continue 9015 b common_exceptionThrown @ yes, handle exception 9016 9017 9018/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 9019 9020 /* 9021 * At this point: 9022 * r0 = resolved base method 9023 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 9024 */ 9025.LOP_INVOKE_VIRTUAL_RANGE_continue: 9026 GET_VREG(r1, r10) @ r1<- "this" ptr 9027 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9028 cmp r1, #0 @ is "this" null? 9029 beq common_errNullObject @ null "this", throw exception 9030 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 9031 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 9032 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 9033 bl common_invokeMethodRange @ continue on 9034 9035 9036/* continuation for OP_INVOKE_SUPER_RANGE */ 9037 9038 /* 9039 * At this point: 9040 * r0 = resolved base method 9041 * r9 = method->clazz 9042 */ 9043.LOP_INVOKE_SUPER_RANGE_continue: 9044 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 9045 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 9046 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 9047 EXPORT_PC() @ must export for invoke 9048 cmp r2, r3 @ compare (methodIndex, vtableCount) 9049 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 9050 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 9051 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 9052 bl common_invokeMethodRange @ continue on 9053 9054.LOP_INVOKE_SUPER_RANGE_resolve: 9055 mov r0, r9 @ r0<- method->clazz 9056 mov r2, #METHOD_VIRTUAL @ resolver method type 9057 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9058 cmp r0, #0 @ got null? 9059 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 9060 b common_exceptionThrown @ yes, handle exception 9061 9062 /* 9063 * Throw a NoSuchMethodError with the method name as the message. 9064 * r0 = resolved base method 9065 */ 9066.LOP_INVOKE_SUPER_RANGE_nsm: 9067 ldr r1, [r0, #offMethod_name] @ r1<- method name 9068 b common_errNoSuchMethod 9069 9070 9071/* continuation for OP_INVOKE_DIRECT_RANGE */ 9072 9073 /* 9074 * On entry: 9075 * r1 = reference (BBBB or CCCC) 9076 * r10 = "this" register 9077 */ 9078.LOP_INVOKE_DIRECT_RANGE_resolve: 9079 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 9080 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 9081 mov r2, #METHOD_DIRECT @ resolver method type 9082 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 9083 cmp r0, #0 @ got null? 9084 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 9085 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 9086 b common_exceptionThrown @ yes, handle exception 9087 9088 9089/* continuation for OP_FLOAT_TO_LONG */ 9090/* 9091 * Convert the float in r0 to a long in r0/r1. 9092 * 9093 * We have to clip values to long min/max per the specification. The 9094 * expected common case is a "reasonable" value that converts directly 9095 * to modest integer. The EABI convert function isn't doing this for us. 9096 */ 9097f2l_doconv: 9098 stmfd sp!, {r4, lr} 9099 mov r1, #0x5f000000 @ (float)maxlong 9100 mov r4, r0 9101 bl __aeabi_fcmpge @ is arg >= maxlong? 9102 cmp r0, #0 @ nonzero == yes 9103 mvnne r0, #0 @ return maxlong (7fffffff) 9104 mvnne r1, #0x80000000 9105 ldmnefd sp!, {r4, pc} 9106 9107 mov r0, r4 @ recover arg 9108 mov r1, #0xdf000000 @ (float)minlong 9109 bl __aeabi_fcmple @ is arg <= minlong? 9110 cmp r0, #0 @ nonzero == yes 9111 movne r0, #0 @ return minlong (80000000) 9112 movne r1, #0x80000000 9113 ldmnefd sp!, {r4, pc} 9114 9115 mov r0, r4 @ recover arg 9116 mov r1, r4 9117 bl __aeabi_fcmpeq @ is arg == self? 9118 cmp r0, #0 @ zero == no 9119 moveq r1, #0 @ return zero for NaN 9120 ldmeqfd sp!, {r4, pc} 9121 9122 mov r0, r4 @ recover arg 9123 bl __aeabi_f2lz @ convert float to long 9124 ldmfd sp!, {r4, pc} 9125 9126 9127/* continuation for OP_DOUBLE_TO_LONG */ 9128/* 9129 * Convert the double in r0/r1 to a long in r0/r1. 9130 * 9131 * We have to clip values to long min/max per the specification. The 9132 * expected common case is a "reasonable" value that converts directly 9133 * to modest integer. The EABI convert function isn't doing this for us. 9134 */ 9135d2l_doconv: 9136 stmfd sp!, {r4, r5, lr} @ save regs 9137 ldr r3, .LOP_DOUBLE_TO_LONG_max @ (double)maxlong, hi 9138 sub sp, sp, #4 @ align for EABI 9139 mov r2, #0 @ (double)maxlong, lo 9140 mov r4, r0 @ save r0 9141 mov r5, r1 @ and r1 9142 bl __aeabi_dcmpge @ is arg >= maxlong? 9143 cmp r0, #0 @ nonzero == yes 9144 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9145 mvnne r1, #0x80000000 9146 bne 1f 9147 9148 mov r0, r4 @ recover arg 9149 mov r1, r5 9150 ldr r3, .LOP_DOUBLE_TO_LONG_min @ (double)minlong, hi 9151 mov r2, #0 @ (double)minlong, lo 9152 bl __aeabi_dcmple @ is arg <= minlong? 9153 cmp r0, #0 @ nonzero == yes 9154 movne r0, #0 @ return minlong (8000000000000000) 9155 movne r1, #0x80000000 9156 bne 1f 9157 9158 mov r0, r4 @ recover arg 9159 mov r1, r5 9160 mov r2, r4 @ compare against self 9161 mov r3, r5 9162 bl __aeabi_dcmpeq @ is arg == self? 9163 cmp r0, #0 @ zero == no 9164 moveq r1, #0 @ return zero for NaN 9165 beq 1f 9166 9167 mov r0, r4 @ recover arg 9168 mov r1, r5 9169 bl __aeabi_d2lz @ convert double to long 9170 91711: 9172 add sp, sp, #4 9173 ldmfd sp!, {r4, r5, pc} 9174 9175.LOP_DOUBLE_TO_LONG_max: 9176 .word 0x43e00000 @ maxlong, as a double (high word) 9177.LOP_DOUBLE_TO_LONG_min: 9178 .word 0xc3e00000 @ minlong, as a double (high word) 9179 9180 9181/* continuation for OP_MUL_LONG */ 9182 9183.LOP_MUL_LONG_finish: 9184 GET_INST_OPCODE(ip) @ extract opcode from rINST 9185 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9186 GOTO_OPCODE(ip) @ jump to next instruction 9187 9188 9189/* continuation for OP_SHL_LONG */ 9190 9191.LOP_SHL_LONG_finish: 9192 mov r0, r0, asl r2 @ r0<- r0 << r2 9193 GET_INST_OPCODE(ip) @ extract opcode from rINST 9194 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9195 GOTO_OPCODE(ip) @ jump to next instruction 9196 9197 9198/* continuation for OP_SHR_LONG */ 9199 9200.LOP_SHR_LONG_finish: 9201 mov r1, r1, asr r2 @ r1<- r1 >> r2 9202 GET_INST_OPCODE(ip) @ extract opcode from rINST 9203 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9204 GOTO_OPCODE(ip) @ jump to next instruction 9205 9206 9207/* continuation for OP_USHR_LONG */ 9208 9209.LOP_USHR_LONG_finish: 9210 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9211 GET_INST_OPCODE(ip) @ extract opcode from rINST 9212 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9213 GOTO_OPCODE(ip) @ jump to next instruction 9214 9215 9216/* continuation for OP_SHL_LONG_2ADDR */ 9217 9218.LOP_SHL_LONG_2ADDR_finish: 9219 GET_INST_OPCODE(ip) @ extract opcode from rINST 9220 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9221 GOTO_OPCODE(ip) @ jump to next instruction 9222 9223 9224/* continuation for OP_SHR_LONG_2ADDR */ 9225 9226.LOP_SHR_LONG_2ADDR_finish: 9227 GET_INST_OPCODE(ip) @ extract opcode from rINST 9228 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9229 GOTO_OPCODE(ip) @ jump to next instruction 9230 9231 9232/* continuation for OP_USHR_LONG_2ADDR */ 9233 9234.LOP_USHR_LONG_2ADDR_finish: 9235 GET_INST_OPCODE(ip) @ extract opcode from rINST 9236 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9237 GOTO_OPCODE(ip) @ jump to next instruction 9238 9239 9240/* continuation for OP_EXECUTE_INLINE */ 9241 9242 /* 9243 * Extract args, call function. 9244 * r0 = #of args (0-4) 9245 * r10 = call index 9246 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9247 * 9248 * Other ideas: 9249 * - Use a jump table from the main piece to jump directly into the 9250 * AND/LDR pairs. Costs a data load, saves a branch. 9251 * - Have five separate pieces that do the loading, so we can work the 9252 * interleave a little better. Increases code size. 9253 */ 9254.LOP_EXECUTE_INLINE_continue: 9255 rsb r0, r0, #4 @ r0<- 4-r0 9256 FETCH(r9, 2) @ r9<- FEDC 9257 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9258 bl common_abort @ (skipped due to ARM prefetch) 92594: and ip, r9, #0xf000 @ isolate F 9260 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92613: and ip, r9, #0x0f00 @ isolate E 9262 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92632: and ip, r9, #0x00f0 @ isolate D 9264 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92651: and ip, r9, #0x000f @ isolate C 9266 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92670: 9268 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9269 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9270 @ (not reached) 9271 9272.LOP_EXECUTE_INLINE_table: 9273 .word gDvmInlineOpsTable 9274 9275 9276 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9277 .global dvmAsmSisterEnd 9278dvmAsmSisterEnd: 9279 9280/* File: armv5te/footer.S */ 9281/* 9282 * =========================================================================== 9283 * Common subroutines and data 9284 * =========================================================================== 9285 */ 9286 9287 .text 9288 .align 2 9289 9290/* 9291 * Common code when a backward branch is taken. 9292 * 9293 * On entry: 9294 * r9 is PC adjustment *in bytes* 9295 */ 9296common_backwardBranch: 9297 mov r0, #kInterpEntryInstr 9298 bl common_periodicChecks 9299 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9300 GET_INST_OPCODE(ip) @ extract opcode from rINST 9301 GOTO_OPCODE(ip) @ jump to next instruction 9302 9303 9304/* 9305 * Need to see if the thread needs to be suspended or debugger/profiler 9306 * activity has begun. 9307 * 9308 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't 9309 * have to do the second ldr. 9310 * 9311 * TODO: reduce this so we're just checking a single location. 9312 * 9313 * On entry: 9314 * r0 is reentry type, e.g. kInterpEntryInstr 9315 * r9 is trampoline PC adjustment *in bytes* 9316 */ 9317common_periodicChecks: 9318 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9319 9320#if defined(WITH_DEBUGGER) 9321 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9322#endif 9323#if defined(WITH_PROFILER) 9324 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9325#endif 9326 9327 ldr r3, [r3] @ r3<- suspendCount (int) 9328 9329#if defined(WITH_DEBUGGER) 9330 ldrb r1, [r1] @ r1<- debuggerActive (boolean) 9331#endif 9332#if defined (WITH_PROFILER) 9333 ldr r2, [r2] @ r2<- activeProfilers (int) 9334#endif 9335 9336 cmp r3, #0 @ suspend pending? 9337 bne 2f @ yes, do full suspension check 9338 9339#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9340# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9341 orrs r1, r1, r2 @ r1<- r1 | r2 9342 cmp r1, #0 @ debugger attached or profiler started? 9343# elif defined(WITH_DEBUGGER) 9344 cmp r1, #0 @ debugger attached? 9345# elif defined(WITH_PROFILER) 9346 cmp r2, #0 @ profiler started? 9347# endif 9348 bne 3f @ debugger/profiler, switch interp 9349#endif 9350 9351 bx lr @ nothing to do, return 9352 93532: @ check suspend 9354 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9355 EXPORT_PC() @ need for precise GC 9356 b dvmCheckSuspendPending @ suspend if necessary, then return 9357 93583: @ debugger/profiler enabled, bail out 9359 add rPC, rPC, r9 @ update rPC 9360 str r0, [rGLUE, #offGlue_entryPoint] 9361 mov r1, #1 @ "want switch" = true 9362 b common_gotoBail 9363 9364 9365/* 9366 * The equivalent of "goto bail", this calls through the "bail handler". 9367 * 9368 * State registers will be saved to the "glue" area before bailing. 9369 * 9370 * On entry: 9371 * r1 is "bool changeInterp", indicating if we want to switch to the 9372 * other interpreter or just bail all the way out 9373 */ 9374common_gotoBail: 9375 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9376 mov r0, rGLUE @ r0<- glue ptr 9377 b dvmMterpStdBail @ call(glue, changeInterp) 9378 9379 @add r1, r1, #1 @ using (boolean+1) 9380 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9381 @bl _longjmp @ does not return 9382 @bl common_abort 9383 9384 9385/* 9386 * Common code for method invocation with range. 9387 * 9388 * On entry: 9389 * r0 is "Method* methodToCall", the method we're trying to call 9390 */ 9391common_invokeMethodRange: 9392.LinvokeNewRange: 9393 @ prepare to copy args to "outs" area of current frame 9394 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9395 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9396 beq .LinvokeArgsDone @ if no args, skip the rest 9397 FETCH(r1, 2) @ r1<- CCCC 9398 9399 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9400 @ (very few methods have > 10 args; could unroll for common cases) 9401 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9402 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 94031: ldr r1, [r3], #4 @ val = *fp++ 9404 subs r2, r2, #1 @ count-- 9405 str r1, [r10], #4 @ *outs++ = val 9406 bne 1b @ ...while count != 0 9407 b .LinvokeArgsDone 9408 9409/* 9410 * Common code for method invocation without range. 9411 * 9412 * On entry: 9413 * r0 is "Method* methodToCall", the method we're trying to call 9414 */ 9415common_invokeMethodNoRange: 9416.LinvokeNewNoRange: 9417 @ prepare to copy args to "outs" area of current frame 9418 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9419 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9420 beq .LinvokeArgsDone @ if no args, skip the rest 9421 FETCH(r1, 2) @ r1<- GFED 9422 9423 @ r0=methodToCall, r1=GFED, r2=count, r10=outs 9424.LinvokeNonRange: 9425 rsb r2, r2, #5 @ r2<- 5-r2 9426 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9427 bl common_abort @ (skipped due to ARM prefetch) 94285: and ip, rINST, #0x0f00 @ isolate A 9429 ldr r3, [rFP, ip, lsr #6] @ r3<- vA (shift right 8, left 2) 9430 mov r0, r0 @ nop 9431 str r3, [r10, #-4]! @ *--outs = vA 94324: and ip, r1, #0xf000 @ isolate G 9433 ldr r3, [rFP, ip, lsr #10] @ r3<- vG (shift right 12, left 2) 9434 mov r0, r0 @ nop 9435 str r3, [r10, #-4]! @ *--outs = vG 94363: and ip, r1, #0x0f00 @ isolate F 9437 ldr r3, [rFP, ip, lsr #6] @ r3<- vF 9438 mov r0, r0 @ nop 9439 str r3, [r10, #-4]! @ *--outs = vF 94402: and ip, r1, #0x00f0 @ isolate E 9441 ldr r3, [rFP, ip, lsr #2] @ r3<- vE 9442 mov r0, r0 @ nop 9443 str r3, [r10, #-4]! @ *--outs = vE 94441: and ip, r1, #0x000f @ isolate D 9445 ldr r3, [rFP, ip, lsl #2] @ r3<- vD 9446 mov r0, r0 @ nop 9447 str r3, [r10, #-4]! @ *--outs = vD 94480: @ fall through to .LinvokeArgsDone 9449 9450.LinvokeArgsDone: @ r0=methodToCall 9451 @ find space for the new stack frame, check for overflow 9452 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9453 ldrh r2, [r0, #offMethod_registersSize] @ r2<- methodToCall->regsSize 9454 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9455 sub r1, r1, r2, lsl #2 @ r1<- newFp (old savearea - regsSize) 9456 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9457@ bl common_dumpRegs 9458 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9459 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9460 cmp r3, r9 @ bottom < interpStackEnd? 9461 blt .LstackOverflow @ yes, this frame will overflow stack 9462 9463 @ set up newSaveArea 9464#ifdef EASY_GDB 9465 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9466 str ip, [r10, #offStackSaveArea_prevSave] 9467#endif 9468 str rFP, [r10, #offStackSaveArea_prevFrame] 9469 str rPC, [r10, #offStackSaveArea_savedPc] 9470 str r0, [r10, #offStackSaveArea_method] 9471 9472 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9473 tst r3, #ACC_NATIVE 9474 bne .LinvokeNative 9475 9476 /* 9477 stmfd sp!, {r0-r3} 9478 bl common_printNewline 9479 mov r0, rFP 9480 mov r1, #0 9481 bl dvmDumpFp 9482 ldmfd sp!, {r0-r3} 9483 stmfd sp!, {r0-r3} 9484 mov r0, r1 9485 mov r1, r10 9486 bl dvmDumpFp 9487 bl common_printNewline 9488 ldmfd sp!, {r0-r3} 9489 */ 9490 9491 @ Update "glue" values for the new method 9492 @ r0=methodToCall, r1=newFp 9493 ldr r3, [r0, #offMethod_clazz] @ r3<- method->clazz 9494 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9495 ldr r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9496 ldr rPC, [r0, #offMethod_insns] @ rPC<- method->insns 9497 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9498 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9499 FETCH_INST() @ load rINST from rPC 9500 mov rFP, r1 @ fp = newFp 9501 GET_INST_OPCODE(ip) @ extract opcode from rINST 9502 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9503 GOTO_OPCODE(ip) @ jump to next instruction 9504 9505.LinvokeNative: 9506 @ Prep for the native call 9507 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9508 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9509 ldr r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext 9510 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9511 str r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext 9512 mov r9, r3 @ r9<- glue->self (preserve) 9513 9514 mov r2, r0 @ r2<- methodToCall 9515 mov r0, r1 @ r0<- newFp (points to args) 9516 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9517 9518#ifdef ASSIST_DEBUGGER 9519 /* insert fake function header to help gdb find the stack frame */ 9520 b .Lskip 9521 .type dalvik_mterp, %function 9522dalvik_mterp: 9523 .fnstart 9524 MTERP_ENTRY1 9525 MTERP_ENTRY2 9526.Lskip: 9527#endif 9528 9529 @mov lr, pc @ set return addr 9530 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9531 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9532 9533 @ native return; r9=self, r10=newSaveArea 9534 @ equivalent to dvmPopJniLocals 9535 ldr r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop 9536 ldr r1, [r9, #offThread_exception] @ check for exception 9537 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9538 cmp r1, #0 @ null? 9539 str r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0 9540 bne common_exceptionThrown @ no, handle exception 9541 9542 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9543 GET_INST_OPCODE(ip) @ extract opcode from rINST 9544 GOTO_OPCODE(ip) @ jump to next instruction 9545 9546.LstackOverflow: 9547 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9548 bl dvmHandleStackOverflow 9549 b common_exceptionThrown 9550#ifdef ASSIST_DEBUGGER 9551 .fnend 9552#endif 9553 9554 9555 /* 9556 * Common code for method invocation, calling through "glue code". 9557 * 9558 * TODO: now that we have range and non-range invoke handlers, this 9559 * needs to be split into two. Maybe just create entry points 9560 * that set r9 and jump here? 9561 * 9562 * On entry: 9563 * r0 is "Method* methodToCall", the method we're trying to call 9564 * r9 is "bool methodCallRange", indicating if this is a /range variant 9565 */ 9566 .if 0 9567.LinvokeOld: 9568 sub sp, sp, #8 @ space for args + pad 9569 FETCH(ip, 2) @ ip<- FEDC or CCCC 9570 mov r2, r0 @ A2<- methodToCall 9571 mov r0, rGLUE @ A0<- glue 9572 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9573 mov r1, r9 @ A1<- methodCallRange 9574 mov r3, rINST, lsr #8 @ A3<- AA 9575 str ip, [sp, #0] @ A4<- ip 9576 bl dvmMterp_invokeMethod @ call the C invokeMethod 9577 add sp, sp, #8 @ remove arg area 9578 b common_resumeAfterGlueCall @ continue to next instruction 9579 .endif 9580 9581 9582 9583/* 9584 * Common code for handling a return instruction. 9585 * 9586 * This does not return. 9587 */ 9588common_returnFromMethod: 9589.LreturnNew: 9590 mov r0, #kInterpEntryReturn 9591 mov r9, #0 9592 bl common_periodicChecks 9593 9594 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9595 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9596 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9597 @ r2<- method we're returning to 9598 cmp r2, #0 @ is this a break frame? 9599 mov r1, #0 @ "want switch" = false 9600 beq common_gotoBail @ break frame, bail out completely 9601 9602 ldr rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc 9603 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9604 str r2, [rGLUE, #offGlue_method] @ glue->method = newSave->method 9605 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9606 ldr r1, [r2, #offMethod_clazz] @ r1<- method->clazz 9607 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9608 ldr r1, [r1, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9609 GET_INST_OPCODE(ip) @ extract opcode from rINST 9610 str r1, [rGLUE, #offGlue_methodClassDex] 9611 GOTO_OPCODE(ip) @ jump to next instruction 9612 9613 /* 9614 * Return handling, calls through "glue code". 9615 */ 9616 .if 0 9617.LreturnOld: 9618 SAVE_PC_FP_TO_GLUE() @ export state 9619 mov r0, rGLUE @ arg to function 9620 bl dvmMterp_returnFromMethod 9621 b common_resumeAfterGlueCall 9622 .endif 9623 9624 9625/* 9626 * Somebody has thrown an exception. Handle it. 9627 * 9628 * If the exception processing code returns to us (instead of falling 9629 * out of the interpreter), continue with whatever the next instruction 9630 * now happens to be. 9631 * 9632 * This does not return. 9633 */ 9634common_exceptionThrown: 9635.LexceptionNew: 9636 mov r0, #kInterpEntryThrow 9637 mov r9, #0 9638 bl common_periodicChecks 9639 9640 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9641 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9642 mov r1, r10 @ r1<- self 9643 mov r0, r9 @ r0<- exception 9644 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9645 mov r3, #0 @ r3<- NULL 9646 str r3, [r10, #offThread_exception] @ self->exception = NULL 9647 9648 /* set up args and a local for "&fp" */ 9649 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 9650 str rFP, [sp, #-4]! @ *--sp = fp 9651 mov ip, sp @ ip<- &fp 9652 mov r3, #0 @ r3<- false 9653 str ip, [sp, #-4]! @ *--sp = &fp 9654 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 9655 mov r0, r10 @ r0<- self 9656 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 9657 mov r2, r9 @ r2<- exception 9658 sub r1, rPC, r1 @ r1<- pc - method->insns 9659 mov r1, r1, asr #1 @ r1<- offset in code units 9660 9661 /* call, r0 gets catchRelPc (a code-unit offset) */ 9662 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 9663 9664 /* fix earlier stack overflow if necessary; may trash rFP */ 9665 ldrb r1, [r10, #offThread_stackOverflowed] 9666 cmp r1, #0 @ did we overflow earlier? 9667 beq 1f @ no, skip ahead 9668 mov rFP, r0 @ save relPc result in rFP 9669 mov r0, r10 @ r0<- self 9670 bl dvmCleanupStackOverflow @ call(self) 9671 mov r0, rFP @ restore result 96721: 9673 9674 /* update frame pointer and check result from dvmFindCatchBlock */ 9675 ldr rFP, [sp, #4] @ retrieve the updated rFP 9676 cmp r0, #0 @ is catchRelPc < 0? 9677 add sp, sp, #8 @ restore stack 9678 bmi .LnotCaughtLocally 9679 9680 /* adjust locals to match self->curFrame and updated PC */ 9681 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 9682 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 9683 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 9684 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 9685 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 9686 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 9687 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 9688 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 9689 9690 /* release the tracked alloc on the exception */ 9691 mov r0, r9 @ r0<- exception 9692 mov r1, r10 @ r1<- self 9693 bl dvmReleaseTrackedAlloc @ release the exception 9694 9695 /* restore the exception if the handler wants it */ 9696 FETCH_INST() @ load rINST from rPC 9697 GET_INST_OPCODE(ip) @ extract opcode from rINST 9698 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 9699 streq r9, [r10, #offThread_exception] @ yes, restore the exception 9700 GOTO_OPCODE(ip) @ jump to next instruction 9701 9702.LnotCaughtLocally: @ r9=exception, r10=self 9703 /* fix stack overflow if necessary */ 9704 ldrb r1, [r10, #offThread_stackOverflowed] 9705 cmp r1, #0 @ did we overflow earlier? 9706 movne r0, r10 @ if yes: r0<- self 9707 blne dvmCleanupStackOverflow @ if yes: call(self) 9708 9709 @ may want to show "not caught locally" debug messages here 9710#if DVM_SHOW_EXCEPTION >= 2 9711 /* call __android_log_print(prio, tag, format, ...) */ 9712 /* "Exception %s from %s:%d not caught locally" */ 9713 @ dvmLineNumFromPC(method, pc - method->insns) 9714 ldr r0, [rGLUE, #offGlue_method] 9715 ldr r1, [r0, #offMethod_insns] 9716 sub r1, rPC, r1 9717 asr r1, r1, #1 9718 bl dvmLineNumFromPC 9719 str r0, [sp, #-4]! 9720 @ dvmGetMethodSourceFile(method) 9721 ldr r0, [rGLUE, #offGlue_method] 9722 bl dvmGetMethodSourceFile 9723 str r0, [sp, #-4]! 9724 @ exception->clazz->descriptor 9725 ldr r3, [r9, #offObject_clazz] 9726 ldr r3, [r3, #offClassObject_descriptor] 9727 @ 9728 ldr r2, strExceptionNotCaughtLocally 9729 ldr r1, strLogTag 9730 mov r0, #3 @ LOG_DEBUG 9731 bl __android_log_print 9732#endif 9733 str r9, [r10, #offThread_exception] @ restore exception 9734 mov r0, r9 @ r0<- exception 9735 mov r1, r10 @ r1<- self 9736 bl dvmReleaseTrackedAlloc @ release the exception 9737 mov r1, #0 @ "want switch" = false 9738 b common_gotoBail @ bail out 9739 9740 9741 /* 9742 * Exception handling, calls through "glue code". 9743 */ 9744 .if 0 9745.LexceptionOld: 9746 SAVE_PC_FP_TO_GLUE() @ export state 9747 mov r0, rGLUE @ arg to function 9748 bl dvmMterp_exceptionThrown 9749 b common_resumeAfterGlueCall 9750 .endif 9751 9752 9753/* 9754 * After returning from a "glued" function, pull out the updated 9755 * values and start executing at the next instruction. 9756 */ 9757common_resumeAfterGlueCall: 9758 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 9759 FETCH_INST() @ load rINST from rPC 9760 GET_INST_OPCODE(ip) @ extract opcode from rINST 9761 GOTO_OPCODE(ip) @ jump to next instruction 9762 9763/* 9764 * Invalid array index. 9765 */ 9766common_errArrayIndex: 9767 EXPORT_PC() 9768 ldr r0, strArrayIndexException 9769 mov r1, #0 9770 bl dvmThrowException 9771 b common_exceptionThrown 9772 9773/* 9774 * Invalid array value. 9775 */ 9776common_errArrayStore: 9777 EXPORT_PC() 9778 ldr r0, strArrayStoreException 9779 mov r1, #0 9780 bl dvmThrowException 9781 b common_exceptionThrown 9782 9783/* 9784 * Integer divide or mod by zero. 9785 */ 9786common_errDivideByZero: 9787 EXPORT_PC() 9788 ldr r0, strArithmeticException 9789 ldr r1, strDivideByZero 9790 bl dvmThrowException 9791 b common_exceptionThrown 9792 9793/* 9794 * Attempt to allocate an array with a negative size. 9795 */ 9796common_errNegativeArraySize: 9797 EXPORT_PC() 9798 ldr r0, strNegativeArraySizeException 9799 mov r1, #0 9800 bl dvmThrowException 9801 b common_exceptionThrown 9802 9803/* 9804 * Invocation of a non-existent method. 9805 */ 9806common_errNoSuchMethod: 9807 EXPORT_PC() 9808 ldr r0, strNoSuchMethodError 9809 mov r1, #0 9810 bl dvmThrowException 9811 b common_exceptionThrown 9812 9813/* 9814 * We encountered a null object when we weren't expecting one. We 9815 * export the PC, throw a NullPointerException, and goto the exception 9816 * processing code. 9817 */ 9818common_errNullObject: 9819 EXPORT_PC() 9820 ldr r0, strNullPointerException 9821 mov r1, #0 9822 bl dvmThrowException 9823 b common_exceptionThrown 9824 9825/* 9826 * For debugging, cause an immediate fault. The source address will 9827 * be in lr (use a bl instruction to jump here). 9828 */ 9829common_abort: 9830 ldr pc, .LdeadFood 9831.LdeadFood: 9832 .word 0xdeadf00d 9833 9834/* 9835 * Spit out a "we were here", preserving all registers. (The attempt 9836 * to save ip won't work, but we need to save an even number of 9837 * registers for EABI 64-bit stack alignment.) 9838 */ 9839 .macro SQUEAK num 9840common_squeak\num: 9841 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9842 ldr r0, strSqueak 9843 mov r1, #\num 9844 bl printf 9845 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9846 bx lr 9847 .endm 9848 9849 SQUEAK 0 9850 SQUEAK 1 9851 SQUEAK 2 9852 SQUEAK 3 9853 SQUEAK 4 9854 SQUEAK 5 9855 9856/* 9857 * Spit out the number in r0, preserving registers. 9858 */ 9859common_printNum: 9860 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9861 mov r1, r0 9862 ldr r0, strSqueak 9863 bl printf 9864 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9865 bx lr 9866 9867/* 9868 * Print a newline, preserving registers. 9869 */ 9870common_printNewline: 9871 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9872 ldr r0, strNewline 9873 bl printf 9874 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9875 bx lr 9876 9877 /* 9878 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 9879 */ 9880common_printHex: 9881 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9882 mov r1, r0 9883 ldr r0, strPrintHex 9884 bl printf 9885 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9886 bx lr 9887 9888/* 9889 * Print the 64-bit quantity in r0-r1, preserving registers. 9890 */ 9891common_printLong: 9892 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9893 mov r3, r1 9894 mov r2, r0 9895 ldr r0, strPrintLong 9896 bl printf 9897 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9898 bx lr 9899 9900/* 9901 * Print full method info. Pass the Method* in r0. Preserves regs. 9902 */ 9903common_printMethod: 9904 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9905 bl dvmMterpPrintMethod 9906 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9907 bx lr 9908 9909/* 9910 * Call a C helper function that dumps regs and possibly some 9911 * additional info. Requires the C function to be compiled in. 9912 */ 9913 .if 0 9914common_dumpRegs: 9915 stmfd sp!, {r0, r1, r2, r3, ip, lr} 9916 bl dvmMterpDumpArmRegs 9917 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 9918 bx lr 9919 .endif 9920 9921 9922/* 9923 * String references, must be close to the code that uses them. 9924 */ 9925 .align 2 9926strArithmeticException: 9927 .word .LstrArithmeticException 9928strArrayIndexException: 9929 .word .LstrArrayIndexException 9930strArrayStoreException: 9931 .word .LstrArrayStoreException 9932strDivideByZero: 9933 .word .LstrDivideByZero 9934strNegativeArraySizeException: 9935 .word .LstrNegativeArraySizeException 9936strNoSuchMethodError: 9937 .word .LstrNoSuchMethodError 9938strNullPointerException: 9939 .word .LstrNullPointerException 9940 9941strLogTag: 9942 .word .LstrLogTag 9943strExceptionNotCaughtLocally: 9944 .word .LstrExceptionNotCaughtLocally 9945 9946strNewline: 9947 .word .LstrNewline 9948strSqueak: 9949 .word .LstrSqueak 9950strPrintHex: 9951 .word .LstrPrintHex 9952strPrintLong: 9953 .word .LstrPrintLong 9954 9955/* 9956 * Zero-terminated ASCII string data. 9957 * 9958 * On ARM we have two choices: do like gcc does, and LDR from a .word 9959 * with the address, or use an ADR pseudo-op to get the address 9960 * directly. ADR saves 4 bytes and an indirection, but it's using a 9961 * PC-relative addressing mode and hence has a limited range, which 9962 * makes it not work well with mergeable string sections. 9963 */ 9964 .section .rodata.str1.4,"aMS",%progbits,1 9965 9966.LstrBadEntryPoint: 9967 .asciz "Bad entry point %d\n" 9968.LstrArithmeticException: 9969 .asciz "Ljava/lang/ArithmeticException;" 9970.LstrArrayIndexException: 9971 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9972.LstrArrayStoreException: 9973 .asciz "Ljava/lang/ArrayStoreException;" 9974.LstrClassCastException: 9975 .asciz "Ljava/lang/ClassCastException;" 9976.LstrDivideByZero: 9977 .asciz "divide by zero" 9978.LstrFilledNewArrayNotImpl: 9979 .asciz "filled-new-array only implemented for objects and 'int'" 9980.LstrInternalError: 9981 .asciz "Ljava/lang/InternalError;" 9982.LstrInstantiationError: 9983 .asciz "Ljava/lang/InstantiationError;" 9984.LstrNegativeArraySizeException: 9985 .asciz "Ljava/lang/NegativeArraySizeException;" 9986.LstrNoSuchMethodError: 9987 .asciz "Ljava/lang/NoSuchMethodError;" 9988.LstrNullPointerException: 9989 .asciz "Ljava/lang/NullPointerException;" 9990 9991.LstrLogTag: 9992 .asciz "mterp" 9993.LstrExceptionNotCaughtLocally: 9994 .asciz "Exception %s from %s:%d not caught locally\n" 9995 9996.LstrNewline: 9997 .asciz "\n" 9998.LstrSqueak: 9999 .asciz "<%d>" 10000.LstrPrintHex: 10001 .asciz "<0x%x>" 10002.LstrPrintLong: 10003 .asciz "<%lld>" 10004 10005 10006