2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
7 /* File: armv5te/header.S */
9 * Copyright (C) 2008 The Android Open Source Project
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
15 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 * ARMv5 definitions and declarations.
28 ARM EABI general notes:
30 r0-r3 hold first 4 args to a method; they are not preserved across method calls
31 r4-r8 are available for general use
32 r9 is given special treatment in some situations, but not for us
33 r10 (sl) seems to be generally available
34 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35 r12 (ip) is scratch -- not preserved across method calls
36 r13 (sp) should be managed carefully in case a signal arrives
37 r14 (lr) must be preserved
38 r15 (pc) can be tinkered with directly
40 r0 holds returns of <= 4 bytes
41 r0-r1 hold returns of 8 bytes, low word in r0
43 Callee must save/restore r4+ (except r12) if it modifies them. If VFP
44 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45 s0-s15 (d0-d7, q0-a3) do not need to be.
47 Stack is "full descending". Only the arguments that don't fit in the first 4
48 registers are placed on the stack. "sp" points at the first stacked argument
51 VFP: single-precision results in s0, double-precision results in d0.
53 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
54 64-bit quantities (long long, double) must be 64-bit aligned.
60 The following registers have fixed assignments:
63 r4 rPC interpreted program counter, used for fetching instructions
64 r5 rFP interpreted frame pointer, used for accessing locals and args
65 r6 rGLUE MterpGlue pointer
66 r7 rINST first 16-bit code unit of current instruction
67 r8 rIBASE interpreted instruction base pointer, used for computed goto
69 Macros are provided for common operations. Each macro MUST emit only
70 one instruction to make instruction-counting easier. They MUST NOT alter
71 unspecified registers or condition codes.
74 /* single-purpose registers, given names for clarity */
81 /* save/restore the PC and/or FP from the glue struct */
82 #define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc]
83 #define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc]
84 #define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp]
85 #define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp]
86 #define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP}
87 #define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP}
90 * "export" the PC to the stack frame, f/b/o future exception objects. Must
91 * be done *before* something calls dvmThrowException.
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 * It's okay to do this more than once.
99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
102 * Given a frame pointer, find the stack save area.
104 * In C this is "((StackSaveArea*)(_fp) -1)".
106 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
107 sub _reg, _fpreg, #sizeofStackSaveArea
110 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
112 #define FETCH_INST() ldrh rINST, [rPC]
115 * Fetch the next instruction from the specified offset. Advances rPC
116 * to point to the next instruction. "_count" is in 16-bit code units.
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss. (This also implies that it must come after
126 #define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]!
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133 ldrh _dreg, [_sreg, #(_count*2)]!
136 * Fetch the next instruction from an offset specified by _reg. Updates
137 * rPC to point to the next instruction. "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
145 #define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]!
148 * Fetch a half-word code unit from an offset past the current PC. The
149 * "_count" value is in 16-bit code units. Does not advance rPC.
151 * The "_S" variant works the same but treats the value as signed.
153 #define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)]
154 #define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)]
157 * Fetch one byte from an offset past the current PC. Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
161 #define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)]
164 * Put the instruction's opcode field into the specified register.
166 #define GET_INST_OPCODE(_reg) and _reg, rINST, #255
169 * Put the prefetched instruction's opcode field into the specified register.
171 #define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255
174 * Begin executing the opcode in _reg. Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 #define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6
178 #define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6
179 #define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6
182 * Get/set the 32-bit value from a Dalvik register.
184 #define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2]
185 #define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2]
187 #if defined(WITH_JIT)
188 #define GET_JIT_ENABLED(_reg) ldr _reg,[rGLUE,#offGlue_jitEnabled]
189 #define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable]
193 * Convert a virtual register index into an address.
195 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196 add _reg, rFP, _vreg, lsl #2
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
202 #include "../common/asm-constants.h"
205 /* File: armv5te/platform.S */
207 * ===========================================================================
208 * CPU-version-specific defines
209 * ===========================================================================
213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a
216 * May modify IP. Does not modify LR.
223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224 * Jump to subroutine.
226 * May modify IP and LR.
228 .macro LDR_PC_LR source
234 * Macro for "LDMFD SP!, {...regs...,PC}".
236 * May modify IP and LR.
239 ldmfd sp!, {\regs,pc}
243 /* File: armv5te/entry.S */
245 * Copyright (C) 2008 The Android Open Source Project
247 * Licensed under the Apache License, Version 2.0 (the "License");
248 * you may not use this file except in compliance with the License.
249 * You may obtain a copy of the License at
251 * http://www.apache.org/licenses/LICENSE-2.0
253 * Unless required by applicable law or agreed to in writing, software
254 * distributed under the License is distributed on an "AS IS" BASIS,
255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256 * See the License for the specific language governing permissions and
257 * limitations under the License.
260 * Interpreter entry point.
264 * We don't have formal stack frames, so gdb scans upward in the code
265 * to find the start of the function (a label with the %function type),
266 * and then looks at the next few instructions to figure out what
267 * got pushed onto the stack. From this it figures out how to restore
268 * the registers, including PC, for the previous stack frame. If gdb
269 * sees a non-function label, it stops scanning, so either we need to
270 * have nothing but assembler-local labels between the entry point and
271 * the break, or we need to fake it out.
273 * When this is defined, we add some stuff to make gdb less confused.
275 #define ASSIST_DEBUGGER 1
279 .global dvmMterpStdRun
280 .type dvmMterpStdRun, %function
286 * This function returns a boolean "changeInterp" value. The return comes
287 * via a call to dvmMterpStdBail().
290 #define MTERP_ENTRY1 \
291 .save {r4-r10,fp,lr}; \
292 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs
293 #define MTERP_ENTRY2 \
295 sub sp, sp, #4 @ align 64
301 /* save stack pointer, add magic word for debuggerd */
302 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return
304 /* set up "named" registers, figure out entry point */
305 mov rGLUE, r0 @ set rGLUE
306 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char
307 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue"
308 adr rIBASE, dvmAsmInstructionStart @ set rIBASE
309 cmp r1, #kInterpEntryInstr @ usual case?
310 bne .Lnot_instr @ no, handle it
312 #if defined(WITH_JIT)
314 /* Entry is always a possible trace start */
315 GET_JIT_PROF_TABLE(r0)
318 bne common_updateProfile
322 /* start executing the instruction at rPC */
323 FETCH_INST() @ load rINST from rPC
324 GET_INST_OPCODE(ip) @ extract opcode from rINST
325 GOTO_OPCODE(ip) @ jump to next instruction
329 cmp r1, #kInterpEntryReturn @ were we returning from a method?
330 beq common_returnFromMethod
333 cmp r1, #kInterpEntryThrow @ were we throwing an exception?
334 beq common_exceptionThrown
336 #if defined(WITH_JIT)
338 ldr r0,[rGLUE, #offGlue_jitResume]
339 ldr r2,[rGLUE, #offGlue_jitResumePC]
340 cmp r1, #kInterpEntryResume @ resuming after Jit single-step?
343 bne .Lno_singleStep @ must have branched, don't resume
344 mov r1, #kInterpEntryInstr
345 strb r1, [rGLUE, #offGlue_entryPoint]
346 ldr rINST, .LdvmCompilerTemplate
347 bx r0 @ re-enter the translation
348 .LdvmCompilerTemplate:
349 .word dvmCompilerTemplateStart
353 ldr r0, strBadEntryPoint
354 @ r1 holds value of entryPoint
360 .global dvmMterpStdBail
361 .type dvmMterpStdBail, %function
364 * Restore the stack pointer and PC from the save point established on entry.
365 * This is essentially the same as a longjmp, but should be cheaper. The
366 * last instruction causes us to return to whoever called dvmMterpStdRun.
368 * We pushed some registers on the stack in dvmMterpStdRun, then saved
369 * SP and LR. Here we restore SP, restore the registers, and then restore
374 * r1 bool changeInterp
377 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP
378 mov r0, r1 @ return the changeInterp value
379 add sp, sp, #4 @ un-align 64
380 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return
387 .word .LstrBadEntryPoint
391 .global dvmAsmInstructionStart
392 .type dvmAsmInstructionStart, %function
393 dvmAsmInstructionStart = .L_OP_NOP
396 /* ------------------------------ */
398 .L_OP_NOP: /* 0x00 */
399 /* File: armv5te/OP_NOP.S */
400 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST
401 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
402 GOTO_OPCODE(ip) @ execute it
404 #ifdef ASSIST_DEBUGGER
405 /* insert fake function header to help gdb find the stack frame */
406 .type dalvik_inst, %function
415 /* ------------------------------ */
417 .L_OP_MOVE: /* 0x01 */
418 /* File: armv6t2/OP_MOVE.S */
419 /* for move, move-object, long-to-int */
421 mov r1, rINST, lsr #12 @ r1<- B from 15:12
422 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8
423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
424 GET_VREG(r2, r1) @ r2<- fp[B]
425 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
426 SET_VREG(r2, r0) @ fp[A]<- r2
427 GOTO_OPCODE(ip) @ execute next instruction
430 /* ------------------------------ */
432 .L_OP_MOVE_FROM16: /* 0x02 */
433 /* File: armv5te/OP_MOVE_FROM16.S */
434 /* for: move/from16, move-object/from16 */
436 FETCH(r1, 1) @ r1<- BBBB
437 mov r0, rINST, lsr #8 @ r0<- AA
438 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
439 GET_VREG(r2, r1) @ r2<- fp[BBBB]
440 GET_INST_OPCODE(ip) @ extract opcode from rINST
441 SET_VREG(r2, r0) @ fp[AA]<- r2
442 GOTO_OPCODE(ip) @ jump to next instruction
445 /* ------------------------------ */
447 .L_OP_MOVE_16: /* 0x03 */
448 /* File: armv5te/OP_MOVE_16.S */
449 /* for: move/16, move-object/16 */
450 /* op vAAAA, vBBBB */
451 FETCH(r1, 2) @ r1<- BBBB
452 FETCH(r0, 1) @ r0<- AAAA
453 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
454 GET_VREG(r2, r1) @ r2<- fp[BBBB]
455 GET_INST_OPCODE(ip) @ extract opcode from rINST
456 SET_VREG(r2, r0) @ fp[AAAA]<- r2
457 GOTO_OPCODE(ip) @ jump to next instruction
460 /* ------------------------------ */
462 .L_OP_MOVE_WIDE: /* 0x04 */
463 /* File: armv6t2/OP_MOVE_WIDE.S */
464 /* move-wide vA, vB */
465 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466 mov r3, rINST, lsr #12 @ r3<- B
467 ubfx r2, rINST, #8, #4 @ r2<- A
468 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
469 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
470 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
471 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
472 GET_INST_OPCODE(ip) @ extract opcode from rINST
473 stmia r2, {r0-r1} @ fp[A]<- r0/r1
474 GOTO_OPCODE(ip) @ jump to next instruction
477 /* ------------------------------ */
479 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481 /* move-wide/from16 vAA, vBBBB */
482 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483 FETCH(r3, 1) @ r3<- BBBB
484 mov r2, rINST, lsr #8 @ r2<- AA
485 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
486 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
487 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
488 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
489 GET_INST_OPCODE(ip) @ extract opcode from rINST
490 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
491 GOTO_OPCODE(ip) @ jump to next instruction
494 /* ------------------------------ */
496 .L_OP_MOVE_WIDE_16: /* 0x06 */
497 /* File: armv5te/OP_MOVE_WIDE_16.S */
498 /* move-wide/16 vAAAA, vBBBB */
499 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
500 FETCH(r3, 2) @ r3<- BBBB
501 FETCH(r2, 1) @ r2<- AAAA
502 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
503 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
504 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
505 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
506 GET_INST_OPCODE(ip) @ extract opcode from rINST
507 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
508 GOTO_OPCODE(ip) @ jump to next instruction
511 /* ------------------------------ */
513 .L_OP_MOVE_OBJECT: /* 0x07 */
514 /* File: armv5te/OP_MOVE_OBJECT.S */
515 /* File: armv5te/OP_MOVE.S */
516 /* for move, move-object, long-to-int */
518 mov r1, rINST, lsr #12 @ r1<- B from 15:12
519 mov r0, rINST, lsr #8 @ r0<- A from 11:8
520 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
521 GET_VREG(r2, r1) @ r2<- fp[B]
523 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
524 SET_VREG(r2, r0) @ fp[A]<- r2
525 GOTO_OPCODE(ip) @ execute next instruction
529 /* ------------------------------ */
531 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
532 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
533 /* File: armv5te/OP_MOVE_FROM16.S */
534 /* for: move/from16, move-object/from16 */
536 FETCH(r1, 1) @ r1<- BBBB
537 mov r0, rINST, lsr #8 @ r0<- AA
538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
539 GET_VREG(r2, r1) @ r2<- fp[BBBB]
540 GET_INST_OPCODE(ip) @ extract opcode from rINST
541 SET_VREG(r2, r0) @ fp[AA]<- r2
542 GOTO_OPCODE(ip) @ jump to next instruction
546 /* ------------------------------ */
548 .L_OP_MOVE_OBJECT_16: /* 0x09 */
549 /* File: armv5te/OP_MOVE_OBJECT_16.S */
550 /* File: armv5te/OP_MOVE_16.S */
551 /* for: move/16, move-object/16 */
552 /* op vAAAA, vBBBB */
553 FETCH(r1, 2) @ r1<- BBBB
554 FETCH(r0, 1) @ r0<- AAAA
555 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
556 GET_VREG(r2, r1) @ r2<- fp[BBBB]
557 GET_INST_OPCODE(ip) @ extract opcode from rINST
558 SET_VREG(r2, r0) @ fp[AAAA]<- r2
559 GOTO_OPCODE(ip) @ jump to next instruction
563 /* ------------------------------ */
565 .L_OP_MOVE_RESULT: /* 0x0a */
566 /* File: armv5te/OP_MOVE_RESULT.S */
567 /* for: move-result, move-result-object */
569 mov r2, rINST, lsr #8 @ r2<- AA
570 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
571 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
572 GET_INST_OPCODE(ip) @ extract opcode from rINST
573 SET_VREG(r0, r2) @ fp[AA]<- r0
574 GOTO_OPCODE(ip) @ jump to next instruction
577 /* ------------------------------ */
579 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
580 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
581 /* move-result-wide vAA */
582 mov r2, rINST, lsr #8 @ r2<- AA
583 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
584 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
585 ldmia r3, {r0-r1} @ r0/r1<- retval.j
586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
587 GET_INST_OPCODE(ip) @ extract opcode from rINST
588 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
589 GOTO_OPCODE(ip) @ jump to next instruction
592 /* ------------------------------ */
594 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
595 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
596 /* File: armv5te/OP_MOVE_RESULT.S */
597 /* for: move-result, move-result-object */
599 mov r2, rINST, lsr #8 @ r2<- AA
600 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
601 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
602 GET_INST_OPCODE(ip) @ extract opcode from rINST
603 SET_VREG(r0, r2) @ fp[AA]<- r0
604 GOTO_OPCODE(ip) @ jump to next instruction
608 /* ------------------------------ */
610 .L_OP_MOVE_EXCEPTION: /* 0x0d */
611 /* File: armv5te/OP_MOVE_EXCEPTION.S */
612 /* move-exception vAA */
613 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
614 mov r2, rINST, lsr #8 @ r2<- AA
615 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
617 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
618 SET_VREG(r3, r2) @ fp[AA]<- exception obj
619 GET_INST_OPCODE(ip) @ extract opcode from rINST
620 str r1, [r0, #offThread_exception] @ dvmClearException bypass
621 GOTO_OPCODE(ip) @ jump to next instruction
624 /* ------------------------------ */
626 .L_OP_RETURN_VOID: /* 0x0e */
627 /* File: armv5te/OP_RETURN_VOID.S */
628 b common_returnFromMethod
631 /* ------------------------------ */
633 .L_OP_RETURN: /* 0x0f */
634 /* File: armv5te/OP_RETURN.S */
636 * Return a 32-bit value. Copies the return value into the "glue"
637 * structure, then jumps to the return handler.
639 * for: return, return-object
642 mov r2, rINST, lsr #8 @ r2<- AA
643 GET_VREG(r0, r2) @ r0<- vAA
644 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
645 b common_returnFromMethod
648 /* ------------------------------ */
650 .L_OP_RETURN_WIDE: /* 0x10 */
651 /* File: armv5te/OP_RETURN_WIDE.S */
653 * Return a 64-bit value. Copies the return value into the "glue"
654 * structure, then jumps to the return handler.
656 /* return-wide vAA */
657 mov r2, rINST, lsr #8 @ r2<- AA
658 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
659 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
660 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
661 stmia r3, {r0-r1} @ retval<- r0/r1
662 b common_returnFromMethod
665 /* ------------------------------ */
667 .L_OP_RETURN_OBJECT: /* 0x11 */
668 /* File: armv5te/OP_RETURN_OBJECT.S */
669 /* File: armv5te/OP_RETURN.S */
671 * Return a 32-bit value. Copies the return value into the "glue"
672 * structure, then jumps to the return handler.
674 * for: return, return-object
677 mov r2, rINST, lsr #8 @ r2<- AA
678 GET_VREG(r0, r2) @ r0<- vAA
679 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
680 b common_returnFromMethod
684 /* ------------------------------ */
686 .L_OP_CONST_4: /* 0x12 */
687 /* File: armv6t2/OP_CONST_4.S */
688 /* const/4 vA, #+B */
689 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
690 ubfx r0, rINST, #8, #4 @ r0<- A
691 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
692 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
693 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
694 SET_VREG(r1, r0) @ fp[A]<- r1
695 GOTO_OPCODE(ip) @ execute next instruction
698 /* ------------------------------ */
700 .L_OP_CONST_16: /* 0x13 */
701 /* File: armv5te/OP_CONST_16.S */
702 /* const/16 vAA, #+BBBB */
703 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
704 mov r3, rINST, lsr #8 @ r3<- AA
705 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
706 SET_VREG(r0, r3) @ vAA<- r0
707 GET_INST_OPCODE(ip) @ extract opcode from rINST
708 GOTO_OPCODE(ip) @ jump to next instruction
711 /* ------------------------------ */
713 .L_OP_CONST: /* 0x14 */
714 /* File: armv5te/OP_CONST.S */
715 /* const vAA, #+BBBBbbbb */
716 mov r3, rINST, lsr #8 @ r3<- AA
717 FETCH(r0, 1) @ r0<- bbbb (low)
718 FETCH(r1, 2) @ r1<- BBBB (high)
719 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
720 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
721 GET_INST_OPCODE(ip) @ extract opcode from rINST
722 SET_VREG(r0, r3) @ vAA<- r0
723 GOTO_OPCODE(ip) @ jump to next instruction
726 /* ------------------------------ */
728 .L_OP_CONST_HIGH16: /* 0x15 */
729 /* File: armv5te/OP_CONST_HIGH16.S */
730 /* const/high16 vAA, #+BBBB0000 */
731 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
732 mov r3, rINST, lsr #8 @ r3<- AA
733 mov r0, r0, lsl #16 @ r0<- BBBB0000
734 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
735 SET_VREG(r0, r3) @ vAA<- r0
736 GET_INST_OPCODE(ip) @ extract opcode from rINST
737 GOTO_OPCODE(ip) @ jump to next instruction
740 /* ------------------------------ */
742 .L_OP_CONST_WIDE_16: /* 0x16 */
743 /* File: armv5te/OP_CONST_WIDE_16.S */
744 /* const-wide/16 vAA, #+BBBB */
745 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
746 mov r3, rINST, lsr #8 @ r3<- AA
747 mov r1, r0, asr #31 @ r1<- ssssssss
748 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
749 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
750 GET_INST_OPCODE(ip) @ extract opcode from rINST
751 stmia r3, {r0-r1} @ vAA<- r0/r1
752 GOTO_OPCODE(ip) @ jump to next instruction
755 /* ------------------------------ */
757 .L_OP_CONST_WIDE_32: /* 0x17 */
758 /* File: armv5te/OP_CONST_WIDE_32.S */
759 /* const-wide/32 vAA, #+BBBBbbbb */
760 FETCH(r0, 1) @ r0<- 0000bbbb (low)
761 mov r3, rINST, lsr #8 @ r3<- AA
762 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
763 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
764 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
765 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
766 mov r1, r0, asr #31 @ r1<- ssssssss
767 GET_INST_OPCODE(ip) @ extract opcode from rINST
768 stmia r3, {r0-r1} @ vAA<- r0/r1
769 GOTO_OPCODE(ip) @ jump to next instruction
772 /* ------------------------------ */
774 .L_OP_CONST_WIDE: /* 0x18 */
775 /* File: armv5te/OP_CONST_WIDE.S */
776 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
777 FETCH(r0, 1) @ r0<- bbbb (low)
778 FETCH(r1, 2) @ r1<- BBBB (low middle)
779 FETCH(r2, 3) @ r2<- hhhh (high middle)
780 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
781 FETCH(r3, 4) @ r3<- HHHH (high)
782 mov r9, rINST, lsr #8 @ r9<- AA
783 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
784 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
785 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
786 GET_INST_OPCODE(ip) @ extract opcode from rINST
787 stmia r9, {r0-r1} @ vAA<- r0/r1
788 GOTO_OPCODE(ip) @ jump to next instruction
791 /* ------------------------------ */
793 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
794 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
795 /* const-wide/high16 vAA, #+BBBB000000000000 */
796 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
797 mov r3, rINST, lsr #8 @ r3<- AA
798 mov r0, #0 @ r0<- 00000000
799 mov r1, r1, lsl #16 @ r1<- BBBB0000
800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
801 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
802 GET_INST_OPCODE(ip) @ extract opcode from rINST
803 stmia r3, {r0-r1} @ vAA<- r0/r1
804 GOTO_OPCODE(ip) @ jump to next instruction
807 /* ------------------------------ */
809 .L_OP_CONST_STRING: /* 0x1a */
810 /* File: armv5te/OP_CONST_STRING.S */
811 /* const/string vAA, String@BBBB */
812 FETCH(r1, 1) @ r1<- BBBB
813 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
814 mov r9, rINST, lsr #8 @ r9<- AA
815 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
816 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
817 cmp r0, #0 @ not yet resolved?
818 beq .LOP_CONST_STRING_resolve
819 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
820 GET_INST_OPCODE(ip) @ extract opcode from rINST
821 SET_VREG(r0, r9) @ vAA<- r0
822 GOTO_OPCODE(ip) @ jump to next instruction
824 /* ------------------------------ */
826 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
827 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
828 /* const/string vAA, String@BBBBBBBB */
829 FETCH(r0, 1) @ r0<- bbbb (low)
830 FETCH(r1, 2) @ r1<- BBBB (high)
831 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
832 mov r9, rINST, lsr #8 @ r9<- AA
833 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
834 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
835 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
837 beq .LOP_CONST_STRING_JUMBO_resolve
838 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
839 GET_INST_OPCODE(ip) @ extract opcode from rINST
840 SET_VREG(r0, r9) @ vAA<- r0
841 GOTO_OPCODE(ip) @ jump to next instruction
843 /* ------------------------------ */
845 .L_OP_CONST_CLASS: /* 0x1c */
846 /* File: armv5te/OP_CONST_CLASS.S */
847 /* const/class vAA, Class@BBBB */
848 FETCH(r1, 1) @ r1<- BBBB
849 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
850 mov r9, rINST, lsr #8 @ r9<- AA
851 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
852 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
853 cmp r0, #0 @ not yet resolved?
854 beq .LOP_CONST_CLASS_resolve
855 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
856 GET_INST_OPCODE(ip) @ extract opcode from rINST
857 SET_VREG(r0, r9) @ vAA<- r0
858 GOTO_OPCODE(ip) @ jump to next instruction
860 /* ------------------------------ */
862 .L_OP_MONITOR_ENTER: /* 0x1d */
863 /* File: armv5te/OP_MONITOR_ENTER.S */
865 * Synchronize on an object.
867 /* monitor-enter vAA */
868 mov r2, rINST, lsr #8 @ r2<- AA
869 GET_VREG(r1, r2) @ r1<- vAA (object)
870 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
871 cmp r1, #0 @ null object?
872 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING
873 beq common_errNullObject @ null object, throw an exception
874 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
875 bl dvmLockObject @ call(self, obj)
876 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
877 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
878 ldr r1, [r0, #offThread_exception] @ check for exception
880 bne common_exceptionThrown @ exception raised, bail out
882 GET_INST_OPCODE(ip) @ extract opcode from rINST
883 GOTO_OPCODE(ip) @ jump to next instruction
886 /* ------------------------------ */
888 .L_OP_MONITOR_EXIT: /* 0x1e */
889 /* File: armv5te/OP_MONITOR_EXIT.S */
893 * Exceptions that occur when unlocking a monitor need to appear as
894 * if they happened at the following instruction. See the Dalvik
897 /* monitor-exit vAA */
898 mov r2, rINST, lsr #8 @ r2<- AA
899 EXPORT_PC() @ before fetch: export the PC
900 GET_VREG(r1, r2) @ r1<- vAA (object)
901 cmp r1, #0 @ null object?
902 beq common_errNullObject @ yes
903 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
904 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
906 beq common_exceptionThrown @ yes, exception is pending
907 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
908 GET_INST_OPCODE(ip) @ extract opcode from rINST
909 GOTO_OPCODE(ip) @ jump to next instruction
912 /* ------------------------------ */
914 .L_OP_CHECK_CAST: /* 0x1f */
915 /* File: armv5te/OP_CHECK_CAST.S */
917 * Check to see if a cast from one class to another is allowed.
919 /* check-cast vAA, class@BBBB */
920 mov r3, rINST, lsr #8 @ r3<- AA
921 FETCH(r2, 1) @ r2<- BBBB
922 GET_VREG(r9, r3) @ r9<- object
923 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
924 cmp r9, #0 @ is object null?
925 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
926 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
927 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
928 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
929 cmp r1, #0 @ have we resolved this before?
930 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
931 .LOP_CHECK_CAST_resolved:
932 cmp r0, r1 @ same class (trivial success)?
933 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
934 .LOP_CHECK_CAST_okay:
935 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
936 GET_INST_OPCODE(ip) @ extract opcode from rINST
937 GOTO_OPCODE(ip) @ jump to next instruction
939 /* ------------------------------ */
941 .L_OP_INSTANCE_OF: /* 0x20 */
942 /* File: armv5te/OP_INSTANCE_OF.S */
944 * Check to see if an object reference is an instance of a class.
946 * Most common situation is a non-null object, being compared against
947 * an already-resolved class.
949 /* instance-of vA, vB, class@CCCC */
950 mov r3, rINST, lsr #12 @ r3<- B
951 mov r9, rINST, lsr #8 @ r9<- A+
952 GET_VREG(r0, r3) @ r0<- vB (object)
953 and r9, r9, #15 @ r9<- A
954 cmp r0, #0 @ is object null?
955 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
956 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
957 FETCH(r3, 1) @ r3<- CCCC
958 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
959 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
960 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
961 cmp r1, #0 @ have we resolved this before?
962 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
963 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
964 cmp r0, r1 @ same class (trivial success)?
965 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
966 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
968 /* ------------------------------ */
970 .L_OP_ARRAY_LENGTH: /* 0x21 */
971 /* File: armv6t2/OP_ARRAY_LENGTH.S */
973 * Return the length of an array.
975 mov r1, rINST, lsr #12 @ r1<- B
976 ubfx r2, rINST, #8, #4 @ r2<- A
977 GET_VREG(r0, r1) @ r0<- vB (object ref)
978 cmp r0, #0 @ is object null?
979 beq common_errNullObject @ yup, fail
980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
981 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
982 GET_INST_OPCODE(ip) @ extract opcode from rINST
983 SET_VREG(r3, r2) @ vB<- length
984 GOTO_OPCODE(ip) @ jump to next instruction
987 /* ------------------------------ */
989 .L_OP_NEW_INSTANCE: /* 0x22 */
990 /* File: armv5te/OP_NEW_INSTANCE.S */
992 * Create a new instance of a class.
994 /* new-instance vAA, class@BBBB */
995 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
996 FETCH(r1, 1) @ r1<- BBBB
997 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
998 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
999 EXPORT_PC() @ req'd for init, resolve, alloc
1000 cmp r0, #0 @ already resolved?
1001 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
1002 .LOP_NEW_INSTANCE_resolved: @ r0=class
1003 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
1004 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
1005 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
1006 .LOP_NEW_INSTANCE_initialized: @ r0=class
1007 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
1008 bl dvmAllocObject @ r0<- new object
1009 b .LOP_NEW_INSTANCE_finish @ continue
1011 /* ------------------------------ */
1013 .L_OP_NEW_ARRAY: /* 0x23 */
1014 /* File: armv5te/OP_NEW_ARRAY.S */
1016 * Allocate an array of objects, specified with the array class
1019 * The verifier guarantees that this is an array class, so we don't
1020 * check for it here.
1022 /* new-array vA, vB, class@CCCC */
1023 mov r0, rINST, lsr #12 @ r0<- B
1024 FETCH(r2, 1) @ r2<- CCCC
1025 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1026 GET_VREG(r1, r0) @ r1<- vB (array length)
1027 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1028 cmp r1, #0 @ check length
1029 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
1030 bmi common_errNegativeArraySize @ negative length, bail
1031 cmp r0, #0 @ already resolved?
1032 EXPORT_PC() @ req'd for resolve, alloc
1033 bne .LOP_NEW_ARRAY_finish @ resolved, continue
1034 b .LOP_NEW_ARRAY_resolve @ do resolve now
1036 /* ------------------------------ */
1038 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1039 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1041 * Create a new array with elements filled from registers.
1043 * for: filled-new-array, filled-new-array/range
1045 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1046 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1047 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1048 FETCH(r1, 1) @ r1<- BBBB
1049 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1050 EXPORT_PC() @ need for resolve and alloc
1051 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1052 mov r10, rINST, lsr #8 @ r10<- AA or BA
1053 cmp r0, #0 @ already resolved?
1054 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
1055 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1056 mov r2, #0 @ r2<- false
1057 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1058 bl dvmResolveClass @ r0<- call(clazz, ref)
1059 cmp r0, #0 @ got null?
1060 beq common_exceptionThrown @ yes, handle exception
1061 b .LOP_FILLED_NEW_ARRAY_continue
1063 /* ------------------------------ */
1065 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1066 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1067 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1069 * Create a new array with elements filled from registers.
1071 * for: filled-new-array, filled-new-array/range
1073 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1074 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1075 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1076 FETCH(r1, 1) @ r1<- BBBB
1077 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1078 EXPORT_PC() @ need for resolve and alloc
1079 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1080 mov r10, rINST, lsr #8 @ r10<- AA or BA
1081 cmp r0, #0 @ already resolved?
1082 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
1083 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1084 mov r2, #0 @ r2<- false
1085 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1086 bl dvmResolveClass @ r0<- call(clazz, ref)
1087 cmp r0, #0 @ got null?
1088 beq common_exceptionThrown @ yes, handle exception
1089 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1092 /* ------------------------------ */
1094 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1095 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1096 /* fill-array-data vAA, +BBBBBBBB */
1097 FETCH(r0, 1) @ r0<- bbbb (lo)
1098 FETCH(r1, 2) @ r1<- BBBB (hi)
1099 mov r3, rINST, lsr #8 @ r3<- AA
1100 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1101 GET_VREG(r0, r3) @ r0<- vAA (array object)
1102 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1104 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1105 cmp r0, #0 @ 0 means an exception is thrown
1106 beq common_exceptionThrown @ has exception
1107 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1108 GET_INST_OPCODE(ip) @ extract opcode from rINST
1109 GOTO_OPCODE(ip) @ jump to next instruction
1111 /* ------------------------------ */
1113 .L_OP_THROW: /* 0x27 */
1114 /* File: armv5te/OP_THROW.S */
1116 * Throw an exception object in the current thread.
1119 mov r2, rINST, lsr #8 @ r2<- AA
1120 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1121 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1122 cmp r1, #0 @ null object?
1123 beq common_errNullObject @ yes, throw an NPE instead
1124 @ bypass dvmSetException, just store it
1125 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1126 b common_exceptionThrown
1129 /* ------------------------------ */
1131 .L_OP_GOTO: /* 0x28 */
1132 /* File: armv5te/OP_GOTO.S */
1134 * Unconditional branch, 8-bit offset.
1136 * The branch distance is a signed code-unit offset, which we need to
1137 * double to get a byte offset.
1140 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1141 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1142 mov r9, r9, lsl #1 @ r9<- byte offset
1143 bmi common_backwardBranch @ backward branch, do periodic checks
1144 #if defined(WITH_JIT)
1145 GET_JIT_PROF_TABLE(r0)
1146 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1148 bne common_updateProfile
1149 GET_INST_OPCODE(ip) @ extract opcode from rINST
1150 GOTO_OPCODE(ip) @ jump to next instruction
1152 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1153 GET_INST_OPCODE(ip) @ extract opcode from rINST
1154 GOTO_OPCODE(ip) @ jump to next instruction
1157 /* ------------------------------ */
1159 .L_OP_GOTO_16: /* 0x29 */
1160 /* File: armv5te/OP_GOTO_16.S */
1162 * Unconditional branch, 16-bit offset.
1164 * The branch distance is a signed code-unit offset, which we need to
1165 * double to get a byte offset.
1168 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1169 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1170 bmi common_backwardBranch @ backward branch, do periodic checks
1171 #if defined(WITH_JIT)
1172 GET_JIT_PROF_TABLE(r0)
1173 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1175 bne common_updateProfile
1176 GET_INST_OPCODE(ip) @ extract opcode from rINST
1177 GOTO_OPCODE(ip) @ jump to next instruction
1179 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1180 GET_INST_OPCODE(ip) @ extract opcode from rINST
1181 GOTO_OPCODE(ip) @ jump to next instruction
1185 /* ------------------------------ */
1187 .L_OP_GOTO_32: /* 0x2a */
1188 /* File: armv5te/OP_GOTO_32.S */
1190 * Unconditional branch, 32-bit offset.
1192 * The branch distance is a signed code-unit offset, which we need to
1193 * double to get a byte offset.
1195 * Unlike most opcodes, this one is allowed to branch to itself, so
1196 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1197 * instruction doesn't affect the V flag, so we need to clear it
1200 /* goto/32 +AAAAAAAA */
1201 FETCH(r0, 1) @ r0<- aaaa (lo)
1202 FETCH(r1, 2) @ r1<- AAAA (hi)
1203 cmp ip, ip @ (clear V flag during stall)
1204 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1205 mov r9, r0, asl #1 @ r9<- byte offset
1206 ble common_backwardBranch @ backward branch, do periodic checks
1207 #if defined(WITH_JIT)
1208 GET_JIT_PROF_TABLE(r0)
1209 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1211 bne common_updateProfile
1212 GET_INST_OPCODE(ip) @ extract opcode from rINST
1213 GOTO_OPCODE(ip) @ jump to next instruction
1215 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1216 GET_INST_OPCODE(ip) @ extract opcode from rINST
1217 GOTO_OPCODE(ip) @ jump to next instruction
1220 /* ------------------------------ */
1222 .L_OP_PACKED_SWITCH: /* 0x2b */
1223 /* File: armv5te/OP_PACKED_SWITCH.S */
1225 * Handle a packed-switch or sparse-switch instruction. In both cases
1226 * we decode it and hand it off to a helper function.
1228 * We don't really expect backward branches in a switch statement, but
1229 * they're perfectly legal, so we check for them here.
1231 * for: packed-switch, sparse-switch
1234 FETCH(r0, 1) @ r0<- bbbb (lo)
1235 FETCH(r1, 2) @ r1<- BBBB (hi)
1236 mov r3, rINST, lsr #8 @ r3<- AA
1237 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1238 GET_VREG(r1, r3) @ r1<- vAA
1239 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1240 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1241 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1242 bmi common_backwardBranch @ backward branch, do periodic checks
1243 beq common_backwardBranch @ (want to use BLE but V is unknown)
1244 #if defined(WITH_JIT)
1245 GET_JIT_PROF_TABLE(r0)
1246 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1248 bne common_updateProfile
1249 GET_INST_OPCODE(ip) @ extract opcode from rINST
1250 GOTO_OPCODE(ip) @ jump to next instruction
1252 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1253 GET_INST_OPCODE(ip) @ extract opcode from rINST
1254 GOTO_OPCODE(ip) @ jump to next instruction
1258 /* ------------------------------ */
1260 .L_OP_SPARSE_SWITCH: /* 0x2c */
1261 /* File: armv5te/OP_SPARSE_SWITCH.S */
1262 /* File: armv5te/OP_PACKED_SWITCH.S */
1264 * Handle a packed-switch or sparse-switch instruction. In both cases
1265 * we decode it and hand it off to a helper function.
1267 * We don't really expect backward branches in a switch statement, but
1268 * they're perfectly legal, so we check for them here.
1270 * for: packed-switch, sparse-switch
1273 FETCH(r0, 1) @ r0<- bbbb (lo)
1274 FETCH(r1, 2) @ r1<- BBBB (hi)
1275 mov r3, rINST, lsr #8 @ r3<- AA
1276 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1277 GET_VREG(r1, r3) @ r1<- vAA
1278 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1279 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1280 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1281 bmi common_backwardBranch @ backward branch, do periodic checks
1282 beq common_backwardBranch @ (want to use BLE but V is unknown)
1283 #if defined(WITH_JIT)
1284 GET_JIT_PROF_TABLE(r0)
1285 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1287 bne common_updateProfile
1288 GET_INST_OPCODE(ip) @ extract opcode from rINST
1289 GOTO_OPCODE(ip) @ jump to next instruction
1291 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1292 GET_INST_OPCODE(ip) @ extract opcode from rINST
1293 GOTO_OPCODE(ip) @ jump to next instruction
1298 /* ------------------------------ */
1300 .L_OP_CMPL_FLOAT: /* 0x2d */
1301 /* File: arm-vfp/OP_CMPL_FLOAT.S */
1303 * Compare two floating-point values. Puts 0, 1, or -1 into the
1304 * destination register based on the results of the comparison.
1306 * int compare(x, y) {
1309 * } else if (x > y) {
1311 * } else if (x < y) {
1318 /* op vAA, vBB, vCC */
1319 FETCH(r0, 1) @ r0<- CCBB
1320 mov r9, rINST, lsr #8 @ r9<- AA
1321 and r2, r0, #255 @ r2<- BB
1322 mov r3, r0, lsr #8 @ r3<- CC
1323 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1324 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1325 flds s0, [r2] @ s0<- vBB
1326 flds s1, [r3] @ s1<- vCC
1327 fcmpes s0, s1 @ compare (vBB, vCC)
1328 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1329 mvn r0, #0 @ r0<- -1 (default)
1330 GET_INST_OPCODE(ip) @ extract opcode from rINST
1331 fmstat @ export status flags
1332 movgt r0, #1 @ (greater than) r1<- 1
1333 moveq r0, #0 @ (equal) r1<- 0
1334 b .LOP_CMPL_FLOAT_finish @ argh
1337 /* ------------------------------ */
1339 .L_OP_CMPG_FLOAT: /* 0x2e */
1340 /* File: arm-vfp/OP_CMPG_FLOAT.S */
1342 * Compare two floating-point values. Puts 0, 1, or -1 into the
1343 * destination register based on the results of the comparison.
1345 * int compare(x, y) {
1348 * } else if (x < y) {
1350 * } else if (x > y) {
1357 /* op vAA, vBB, vCC */
1358 FETCH(r0, 1) @ r0<- CCBB
1359 mov r9, rINST, lsr #8 @ r9<- AA
1360 and r2, r0, #255 @ r2<- BB
1361 mov r3, r0, lsr #8 @ r3<- CC
1362 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1363 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1364 flds s0, [r2] @ s0<- vBB
1365 flds s1, [r3] @ s1<- vCC
1366 fcmpes s0, s1 @ compare (vBB, vCC)
1367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1368 mov r0, #1 @ r0<- 1 (default)
1369 GET_INST_OPCODE(ip) @ extract opcode from rINST
1370 fmstat @ export status flags
1371 mvnmi r0, #0 @ (less than) r1<- -1
1372 moveq r0, #0 @ (equal) r1<- 0
1373 b .LOP_CMPG_FLOAT_finish @ argh
1376 /* ------------------------------ */
1378 .L_OP_CMPL_DOUBLE: /* 0x2f */
1379 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
1381 * Compare two floating-point values. Puts 0, 1, or -1 into the
1382 * destination register based on the results of the comparison.
1384 * int compare(x, y) {
1387 * } else if (x > y) {
1389 * } else if (x < y) {
1396 /* op vAA, vBB, vCC */
1397 FETCH(r0, 1) @ r0<- CCBB
1398 mov r9, rINST, lsr #8 @ r9<- AA
1399 and r2, r0, #255 @ r2<- BB
1400 mov r3, r0, lsr #8 @ r3<- CC
1401 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1402 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1403 fldd d0, [r2] @ d0<- vBB
1404 fldd d1, [r3] @ d1<- vCC
1405 fcmped d0, d1 @ compare (vBB, vCC)
1406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1407 mvn r0, #0 @ r0<- -1 (default)
1408 GET_INST_OPCODE(ip) @ extract opcode from rINST
1409 fmstat @ export status flags
1410 movgt r0, #1 @ (greater than) r1<- 1
1411 moveq r0, #0 @ (equal) r1<- 0
1412 b .LOP_CMPL_DOUBLE_finish @ argh
1415 /* ------------------------------ */
1417 .L_OP_CMPG_DOUBLE: /* 0x30 */
1418 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
1420 * Compare two floating-point values. Puts 0, 1, or -1 into the
1421 * destination register based on the results of the comparison.
1423 * int compare(x, y) {
1426 * } else if (x < y) {
1428 * } else if (x > y) {
1435 /* op vAA, vBB, vCC */
1436 FETCH(r0, 1) @ r0<- CCBB
1437 mov r9, rINST, lsr #8 @ r9<- AA
1438 and r2, r0, #255 @ r2<- BB
1439 mov r3, r0, lsr #8 @ r3<- CC
1440 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1441 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1442 fldd d0, [r2] @ d0<- vBB
1443 fldd d1, [r3] @ d1<- vCC
1444 fcmped d0, d1 @ compare (vBB, vCC)
1445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1446 mov r0, #1 @ r0<- 1 (default)
1447 GET_INST_OPCODE(ip) @ extract opcode from rINST
1448 fmstat @ export status flags
1449 mvnmi r0, #0 @ (less than) r1<- -1
1450 moveq r0, #0 @ (equal) r1<- 0
1451 b .LOP_CMPG_DOUBLE_finish @ argh
1454 /* ------------------------------ */
1456 .L_OP_CMP_LONG: /* 0x31 */
1457 /* File: armv5te/OP_CMP_LONG.S */
1459 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1460 * register based on the results of the comparison.
1462 * We load the full values with LDM, but in practice many values could
1463 * be resolved by only looking at the high word. This could be made
1464 * faster or slower by splitting the LDM into a pair of LDRs.
1466 * If we just wanted to set condition flags, we could do this:
1470 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1471 * integer value, which we can do with 2 conditional mov/mvn instructions
1472 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1473 * us a constant 5-cycle path plus a branch at the end to the
1474 * instruction epilogue code. The multi-compare approach below needs
1475 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1476 * in the worst case (the 64-bit values are equal).
1478 /* cmp-long vAA, vBB, vCC */
1479 FETCH(r0, 1) @ r0<- CCBB
1480 mov r9, rINST, lsr #8 @ r9<- AA
1481 and r2, r0, #255 @ r2<- BB
1482 mov r3, r0, lsr #8 @ r3<- CC
1483 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1484 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1485 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1486 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1487 cmp r1, r3 @ compare (vBB+1, vCC+1)
1488 blt .LOP_CMP_LONG_less @ signed compare on high part
1489 bgt .LOP_CMP_LONG_greater
1490 subs r1, r0, r2 @ r1<- r0 - r2
1491 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1492 bne .LOP_CMP_LONG_less
1493 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1495 /* ------------------------------ */
1497 .L_OP_IF_EQ: /* 0x32 */
1498 /* File: armv6t2/OP_IF_EQ.S */
1499 /* File: armv6t2/bincmp.S */
1501 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1502 * fragment that specifies the *reverse* comparison to perform, e.g.
1503 * for "if-le" you would use "gt".
1505 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1507 /* if-cmp vA, vB, +CCCC */
1508 mov r1, rINST, lsr #12 @ r1<- B
1509 ubfx r0, rINST, #8, #4 @ r0<- A
1510 GET_VREG(r3, r1) @ r3<- vB
1511 GET_VREG(r2, r0) @ r2<- vA
1512 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1513 cmp r2, r3 @ compare (vA, vB)
1514 bne 1f @ branch to 1 if comparison failed
1515 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1516 movs r9, r9, asl #1 @ convert to bytes, check sign
1517 bmi common_backwardBranch @ yes, do periodic checks
1519 #if defined(WITH_JIT)
1520 GET_JIT_PROF_TABLE(r0)
1521 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1522 b common_testUpdateProfile
1524 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1525 GET_INST_OPCODE(ip) @ extract opcode from rINST
1526 GOTO_OPCODE(ip) @ jump to next instruction
1531 /* ------------------------------ */
1533 .L_OP_IF_NE: /* 0x33 */
1534 /* File: armv6t2/OP_IF_NE.S */
1535 /* File: armv6t2/bincmp.S */
1537 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1538 * fragment that specifies the *reverse* comparison to perform, e.g.
1539 * for "if-le" you would use "gt".
1541 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1543 /* if-cmp vA, vB, +CCCC */
1544 mov r1, rINST, lsr #12 @ r1<- B
1545 ubfx r0, rINST, #8, #4 @ r0<- A
1546 GET_VREG(r3, r1) @ r3<- vB
1547 GET_VREG(r2, r0) @ r2<- vA
1548 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1549 cmp r2, r3 @ compare (vA, vB)
1550 beq 1f @ branch to 1 if comparison failed
1551 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1552 movs r9, r9, asl #1 @ convert to bytes, check sign
1553 bmi common_backwardBranch @ yes, do periodic checks
1555 #if defined(WITH_JIT)
1556 GET_JIT_PROF_TABLE(r0)
1557 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1558 b common_testUpdateProfile
1560 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1561 GET_INST_OPCODE(ip) @ extract opcode from rINST
1562 GOTO_OPCODE(ip) @ jump to next instruction
1567 /* ------------------------------ */
1569 .L_OP_IF_LT: /* 0x34 */
1570 /* File: armv6t2/OP_IF_LT.S */
1571 /* File: armv6t2/bincmp.S */
1573 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1574 * fragment that specifies the *reverse* comparison to perform, e.g.
1575 * for "if-le" you would use "gt".
1577 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1579 /* if-cmp vA, vB, +CCCC */
1580 mov r1, rINST, lsr #12 @ r1<- B
1581 ubfx r0, rINST, #8, #4 @ r0<- A
1582 GET_VREG(r3, r1) @ r3<- vB
1583 GET_VREG(r2, r0) @ r2<- vA
1584 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1585 cmp r2, r3 @ compare (vA, vB)
1586 bge 1f @ branch to 1 if comparison failed
1587 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1588 movs r9, r9, asl #1 @ convert to bytes, check sign
1589 bmi common_backwardBranch @ yes, do periodic checks
1591 #if defined(WITH_JIT)
1592 GET_JIT_PROF_TABLE(r0)
1593 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1594 b common_testUpdateProfile
1596 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1597 GET_INST_OPCODE(ip) @ extract opcode from rINST
1598 GOTO_OPCODE(ip) @ jump to next instruction
1603 /* ------------------------------ */
1605 .L_OP_IF_GE: /* 0x35 */
1606 /* File: armv6t2/OP_IF_GE.S */
1607 /* File: armv6t2/bincmp.S */
1609 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1610 * fragment that specifies the *reverse* comparison to perform, e.g.
1611 * for "if-le" you would use "gt".
1613 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1615 /* if-cmp vA, vB, +CCCC */
1616 mov r1, rINST, lsr #12 @ r1<- B
1617 ubfx r0, rINST, #8, #4 @ r0<- A
1618 GET_VREG(r3, r1) @ r3<- vB
1619 GET_VREG(r2, r0) @ r2<- vA
1620 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1621 cmp r2, r3 @ compare (vA, vB)
1622 blt 1f @ branch to 1 if comparison failed
1623 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1624 movs r9, r9, asl #1 @ convert to bytes, check sign
1625 bmi common_backwardBranch @ yes, do periodic checks
1627 #if defined(WITH_JIT)
1628 GET_JIT_PROF_TABLE(r0)
1629 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1630 b common_testUpdateProfile
1632 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1633 GET_INST_OPCODE(ip) @ extract opcode from rINST
1634 GOTO_OPCODE(ip) @ jump to next instruction
1639 /* ------------------------------ */
1641 .L_OP_IF_GT: /* 0x36 */
1642 /* File: armv6t2/OP_IF_GT.S */
1643 /* File: armv6t2/bincmp.S */
1645 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1646 * fragment that specifies the *reverse* comparison to perform, e.g.
1647 * for "if-le" you would use "gt".
1649 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1651 /* if-cmp vA, vB, +CCCC */
1652 mov r1, rINST, lsr #12 @ r1<- B
1653 ubfx r0, rINST, #8, #4 @ r0<- A
1654 GET_VREG(r3, r1) @ r3<- vB
1655 GET_VREG(r2, r0) @ r2<- vA
1656 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1657 cmp r2, r3 @ compare (vA, vB)
1658 ble 1f @ branch to 1 if comparison failed
1659 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1660 movs r9, r9, asl #1 @ convert to bytes, check sign
1661 bmi common_backwardBranch @ yes, do periodic checks
1663 #if defined(WITH_JIT)
1664 GET_JIT_PROF_TABLE(r0)
1665 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1666 b common_testUpdateProfile
1668 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1669 GET_INST_OPCODE(ip) @ extract opcode from rINST
1670 GOTO_OPCODE(ip) @ jump to next instruction
1675 /* ------------------------------ */
1677 .L_OP_IF_LE: /* 0x37 */
1678 /* File: armv6t2/OP_IF_LE.S */
1679 /* File: armv6t2/bincmp.S */
1681 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1682 * fragment that specifies the *reverse* comparison to perform, e.g.
1683 * for "if-le" you would use "gt".
1685 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1687 /* if-cmp vA, vB, +CCCC */
1688 mov r1, rINST, lsr #12 @ r1<- B
1689 ubfx r0, rINST, #8, #4 @ r0<- A
1690 GET_VREG(r3, r1) @ r3<- vB
1691 GET_VREG(r2, r0) @ r2<- vA
1692 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1693 cmp r2, r3 @ compare (vA, vB)
1694 bgt 1f @ branch to 1 if comparison failed
1695 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1696 movs r9, r9, asl #1 @ convert to bytes, check sign
1697 bmi common_backwardBranch @ yes, do periodic checks
1699 #if defined(WITH_JIT)
1700 GET_JIT_PROF_TABLE(r0)
1701 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1702 b common_testUpdateProfile
1704 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1705 GET_INST_OPCODE(ip) @ extract opcode from rINST
1706 GOTO_OPCODE(ip) @ jump to next instruction
1711 /* ------------------------------ */
1713 .L_OP_IF_EQZ: /* 0x38 */
1714 /* File: armv5te/OP_IF_EQZ.S */
1715 /* File: armv5te/zcmp.S */
1717 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1718 * fragment that specifies the *reverse* comparison to perform, e.g.
1719 * for "if-le" you would use "gt".
1721 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1723 /* if-cmp vAA, +BBBB */
1724 mov r0, rINST, lsr #8 @ r0<- AA
1725 GET_VREG(r2, r0) @ r2<- vAA
1726 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1727 cmp r2, #0 @ compare (vA, 0)
1728 bne 1f @ branch to 1 if comparison failed
1729 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1730 movs r9, r9, asl #1 @ convert to bytes, check sign
1731 bmi common_backwardBranch @ backward branch, do periodic checks
1733 #if defined(WITH_JIT)
1734 GET_JIT_PROF_TABLE(r0)
1735 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1737 bne common_updateProfile
1738 GET_INST_OPCODE(ip) @ extract opcode from rINST
1739 GOTO_OPCODE(ip) @ jump to next instruction
1741 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1742 GET_INST_OPCODE(ip) @ extract opcode from rINST
1743 GOTO_OPCODE(ip) @ jump to next instruction
1748 /* ------------------------------ */
1750 .L_OP_IF_NEZ: /* 0x39 */
1751 /* File: armv5te/OP_IF_NEZ.S */
1752 /* File: armv5te/zcmp.S */
1754 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1755 * fragment that specifies the *reverse* comparison to perform, e.g.
1756 * for "if-le" you would use "gt".
1758 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1760 /* if-cmp vAA, +BBBB */
1761 mov r0, rINST, lsr #8 @ r0<- AA
1762 GET_VREG(r2, r0) @ r2<- vAA
1763 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1764 cmp r2, #0 @ compare (vA, 0)
1765 beq 1f @ branch to 1 if comparison failed
1766 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1767 movs r9, r9, asl #1 @ convert to bytes, check sign
1768 bmi common_backwardBranch @ backward branch, do periodic checks
1770 #if defined(WITH_JIT)
1771 GET_JIT_PROF_TABLE(r0)
1772 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1774 bne common_updateProfile
1775 GET_INST_OPCODE(ip) @ extract opcode from rINST
1776 GOTO_OPCODE(ip) @ jump to next instruction
1778 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1779 GET_INST_OPCODE(ip) @ extract opcode from rINST
1780 GOTO_OPCODE(ip) @ jump to next instruction
1785 /* ------------------------------ */
1787 .L_OP_IF_LTZ: /* 0x3a */
1788 /* File: armv5te/OP_IF_LTZ.S */
1789 /* File: armv5te/zcmp.S */
1791 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1792 * fragment that specifies the *reverse* comparison to perform, e.g.
1793 * for "if-le" you would use "gt".
1795 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1797 /* if-cmp vAA, +BBBB */
1798 mov r0, rINST, lsr #8 @ r0<- AA
1799 GET_VREG(r2, r0) @ r2<- vAA
1800 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1801 cmp r2, #0 @ compare (vA, 0)
1802 bge 1f @ branch to 1 if comparison failed
1803 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1804 movs r9, r9, asl #1 @ convert to bytes, check sign
1805 bmi common_backwardBranch @ backward branch, do periodic checks
1807 #if defined(WITH_JIT)
1808 GET_JIT_PROF_TABLE(r0)
1809 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1811 bne common_updateProfile
1812 GET_INST_OPCODE(ip) @ extract opcode from rINST
1813 GOTO_OPCODE(ip) @ jump to next instruction
1815 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1816 GET_INST_OPCODE(ip) @ extract opcode from rINST
1817 GOTO_OPCODE(ip) @ jump to next instruction
1822 /* ------------------------------ */
1824 .L_OP_IF_GEZ: /* 0x3b */
1825 /* File: armv5te/OP_IF_GEZ.S */
1826 /* File: armv5te/zcmp.S */
1828 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1829 * fragment that specifies the *reverse* comparison to perform, e.g.
1830 * for "if-le" you would use "gt".
1832 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1834 /* if-cmp vAA, +BBBB */
1835 mov r0, rINST, lsr #8 @ r0<- AA
1836 GET_VREG(r2, r0) @ r2<- vAA
1837 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1838 cmp r2, #0 @ compare (vA, 0)
1839 blt 1f @ branch to 1 if comparison failed
1840 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1841 movs r9, r9, asl #1 @ convert to bytes, check sign
1842 bmi common_backwardBranch @ backward branch, do periodic checks
1844 #if defined(WITH_JIT)
1845 GET_JIT_PROF_TABLE(r0)
1846 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1848 bne common_updateProfile
1849 GET_INST_OPCODE(ip) @ extract opcode from rINST
1850 GOTO_OPCODE(ip) @ jump to next instruction
1852 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1853 GET_INST_OPCODE(ip) @ extract opcode from rINST
1854 GOTO_OPCODE(ip) @ jump to next instruction
1859 /* ------------------------------ */
1861 .L_OP_IF_GTZ: /* 0x3c */
1862 /* File: armv5te/OP_IF_GTZ.S */
1863 /* File: armv5te/zcmp.S */
1865 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1866 * fragment that specifies the *reverse* comparison to perform, e.g.
1867 * for "if-le" you would use "gt".
1869 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1871 /* if-cmp vAA, +BBBB */
1872 mov r0, rINST, lsr #8 @ r0<- AA
1873 GET_VREG(r2, r0) @ r2<- vAA
1874 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1875 cmp r2, #0 @ compare (vA, 0)
1876 ble 1f @ branch to 1 if comparison failed
1877 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1878 movs r9, r9, asl #1 @ convert to bytes, check sign
1879 bmi common_backwardBranch @ backward branch, do periodic checks
1881 #if defined(WITH_JIT)
1882 GET_JIT_PROF_TABLE(r0)
1883 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1885 bne common_updateProfile
1886 GET_INST_OPCODE(ip) @ extract opcode from rINST
1887 GOTO_OPCODE(ip) @ jump to next instruction
1889 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1890 GET_INST_OPCODE(ip) @ extract opcode from rINST
1891 GOTO_OPCODE(ip) @ jump to next instruction
1896 /* ------------------------------ */
1898 .L_OP_IF_LEZ: /* 0x3d */
1899 /* File: armv5te/OP_IF_LEZ.S */
1900 /* File: armv5te/zcmp.S */
1902 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1903 * fragment that specifies the *reverse* comparison to perform, e.g.
1904 * for "if-le" you would use "gt".
1906 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1908 /* if-cmp vAA, +BBBB */
1909 mov r0, rINST, lsr #8 @ r0<- AA
1910 GET_VREG(r2, r0) @ r2<- vAA
1911 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1912 cmp r2, #0 @ compare (vA, 0)
1913 bgt 1f @ branch to 1 if comparison failed
1914 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1915 movs r9, r9, asl #1 @ convert to bytes, check sign
1916 bmi common_backwardBranch @ backward branch, do periodic checks
1918 #if defined(WITH_JIT)
1919 GET_JIT_PROF_TABLE(r0)
1920 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1922 bne common_updateProfile
1923 GET_INST_OPCODE(ip) @ extract opcode from rINST
1924 GOTO_OPCODE(ip) @ jump to next instruction
1926 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1927 GET_INST_OPCODE(ip) @ extract opcode from rINST
1928 GOTO_OPCODE(ip) @ jump to next instruction
1933 /* ------------------------------ */
1935 .L_OP_UNUSED_3E: /* 0x3e */
1936 /* File: armv5te/OP_UNUSED_3E.S */
1937 /* File: armv5te/unused.S */
1942 /* ------------------------------ */
1944 .L_OP_UNUSED_3F: /* 0x3f */
1945 /* File: armv5te/OP_UNUSED_3F.S */
1946 /* File: armv5te/unused.S */
1951 /* ------------------------------ */
1953 .L_OP_UNUSED_40: /* 0x40 */
1954 /* File: armv5te/OP_UNUSED_40.S */
1955 /* File: armv5te/unused.S */
1960 /* ------------------------------ */
1962 .L_OP_UNUSED_41: /* 0x41 */
1963 /* File: armv5te/OP_UNUSED_41.S */
1964 /* File: armv5te/unused.S */
1969 /* ------------------------------ */
1971 .L_OP_UNUSED_42: /* 0x42 */
1972 /* File: armv5te/OP_UNUSED_42.S */
1973 /* File: armv5te/unused.S */
1978 /* ------------------------------ */
1980 .L_OP_UNUSED_43: /* 0x43 */
1981 /* File: armv5te/OP_UNUSED_43.S */
1982 /* File: armv5te/unused.S */
1987 /* ------------------------------ */
1989 .L_OP_AGET: /* 0x44 */
1990 /* File: armv5te/OP_AGET.S */
1992 * Array get, 32 bits or less. vAA <- vBB[vCC].
1994 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1995 * instructions. We use a pair of FETCH_Bs instead.
1997 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1999 /* op vAA, vBB, vCC */
2000 FETCH_B(r2, 1, 0) @ r2<- BB
2001 mov r9, rINST, lsr #8 @ r9<- AA
2002 FETCH_B(r3, 1, 1) @ r3<- CC
2003 GET_VREG(r0, r2) @ r0<- vBB (array object)
2004 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2005 cmp r0, #0 @ null array object?
2006 beq common_errNullObject @ yes, bail
2007 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2008 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2009 cmp r1, r3 @ compare unsigned index, length
2010 bcs common_errArrayIndex @ index >= length, bail
2011 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2012 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2013 GET_INST_OPCODE(ip) @ extract opcode from rINST
2014 SET_VREG(r2, r9) @ vAA<- r2
2015 GOTO_OPCODE(ip) @ jump to next instruction
2018 /* ------------------------------ */
2020 .L_OP_AGET_WIDE: /* 0x45 */
2021 /* File: armv5te/OP_AGET_WIDE.S */
2023 * Array get, 64 bits. vAA <- vBB[vCC].
2025 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2027 /* aget-wide vAA, vBB, vCC */
2028 FETCH(r0, 1) @ r0<- CCBB
2029 mov r9, rINST, lsr #8 @ r9<- AA
2030 and r2, r0, #255 @ r2<- BB
2031 mov r3, r0, lsr #8 @ r3<- CC
2032 GET_VREG(r0, r2) @ r0<- vBB (array object)
2033 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2034 cmp r0, #0 @ null array object?
2035 beq common_errNullObject @ yes, bail
2036 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2037 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2038 cmp r1, r3 @ compare unsigned index, length
2039 bcc .LOP_AGET_WIDE_finish @ okay, continue below
2040 b common_errArrayIndex @ index >= length, bail
2041 @ May want to swap the order of these two branches depending on how the
2042 @ branch prediction (if any) handles conditional forward branches vs.
2043 @ unconditional forward branches.
2045 /* ------------------------------ */
2047 .L_OP_AGET_OBJECT: /* 0x46 */
2048 /* File: armv5te/OP_AGET_OBJECT.S */
2049 /* File: armv5te/OP_AGET.S */
2051 * Array get, 32 bits or less. vAA <- vBB[vCC].
2053 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2054 * instructions. We use a pair of FETCH_Bs instead.
2056 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2058 /* op vAA, vBB, vCC */
2059 FETCH_B(r2, 1, 0) @ r2<- BB
2060 mov r9, rINST, lsr #8 @ r9<- AA
2061 FETCH_B(r3, 1, 1) @ r3<- CC
2062 GET_VREG(r0, r2) @ r0<- vBB (array object)
2063 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2064 cmp r0, #0 @ null array object?
2065 beq common_errNullObject @ yes, bail
2066 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2067 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2068 cmp r1, r3 @ compare unsigned index, length
2069 bcs common_errArrayIndex @ index >= length, bail
2070 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2071 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2072 GET_INST_OPCODE(ip) @ extract opcode from rINST
2073 SET_VREG(r2, r9) @ vAA<- r2
2074 GOTO_OPCODE(ip) @ jump to next instruction
2078 /* ------------------------------ */
2080 .L_OP_AGET_BOOLEAN: /* 0x47 */
2081 /* File: armv5te/OP_AGET_BOOLEAN.S */
2082 /* File: armv5te/OP_AGET.S */
2084 * Array get, 32 bits or less. vAA <- vBB[vCC].
2086 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2087 * instructions. We use a pair of FETCH_Bs instead.
2089 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2091 /* op vAA, vBB, vCC */
2092 FETCH_B(r2, 1, 0) @ r2<- BB
2093 mov r9, rINST, lsr #8 @ r9<- AA
2094 FETCH_B(r3, 1, 1) @ r3<- CC
2095 GET_VREG(r0, r2) @ r0<- vBB (array object)
2096 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2097 cmp r0, #0 @ null array object?
2098 beq common_errNullObject @ yes, bail
2099 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2100 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2101 cmp r1, r3 @ compare unsigned index, length
2102 bcs common_errArrayIndex @ index >= length, bail
2103 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2104 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2105 GET_INST_OPCODE(ip) @ extract opcode from rINST
2106 SET_VREG(r2, r9) @ vAA<- r2
2107 GOTO_OPCODE(ip) @ jump to next instruction
2111 /* ------------------------------ */
2113 .L_OP_AGET_BYTE: /* 0x48 */
2114 /* File: armv5te/OP_AGET_BYTE.S */
2115 /* File: armv5te/OP_AGET.S */
2117 * Array get, 32 bits or less. vAA <- vBB[vCC].
2119 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2120 * instructions. We use a pair of FETCH_Bs instead.
2122 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2124 /* op vAA, vBB, vCC */
2125 FETCH_B(r2, 1, 0) @ r2<- BB
2126 mov r9, rINST, lsr #8 @ r9<- AA
2127 FETCH_B(r3, 1, 1) @ r3<- CC
2128 GET_VREG(r0, r2) @ r0<- vBB (array object)
2129 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2130 cmp r0, #0 @ null array object?
2131 beq common_errNullObject @ yes, bail
2132 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2133 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2134 cmp r1, r3 @ compare unsigned index, length
2135 bcs common_errArrayIndex @ index >= length, bail
2136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2137 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2138 GET_INST_OPCODE(ip) @ extract opcode from rINST
2139 SET_VREG(r2, r9) @ vAA<- r2
2140 GOTO_OPCODE(ip) @ jump to next instruction
2144 /* ------------------------------ */
2146 .L_OP_AGET_CHAR: /* 0x49 */
2147 /* File: armv5te/OP_AGET_CHAR.S */
2148 /* File: armv5te/OP_AGET.S */
2150 * Array get, 32 bits or less. vAA <- vBB[vCC].
2152 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2153 * instructions. We use a pair of FETCH_Bs instead.
2155 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2157 /* op vAA, vBB, vCC */
2158 FETCH_B(r2, 1, 0) @ r2<- BB
2159 mov r9, rINST, lsr #8 @ r9<- AA
2160 FETCH_B(r3, 1, 1) @ r3<- CC
2161 GET_VREG(r0, r2) @ r0<- vBB (array object)
2162 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2163 cmp r0, #0 @ null array object?
2164 beq common_errNullObject @ yes, bail
2165 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2166 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2167 cmp r1, r3 @ compare unsigned index, length
2168 bcs common_errArrayIndex @ index >= length, bail
2169 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2170 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2171 GET_INST_OPCODE(ip) @ extract opcode from rINST
2172 SET_VREG(r2, r9) @ vAA<- r2
2173 GOTO_OPCODE(ip) @ jump to next instruction
2177 /* ------------------------------ */
2179 .L_OP_AGET_SHORT: /* 0x4a */
2180 /* File: armv5te/OP_AGET_SHORT.S */
2181 /* File: armv5te/OP_AGET.S */
2183 * Array get, 32 bits or less. vAA <- vBB[vCC].
2185 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2186 * instructions. We use a pair of FETCH_Bs instead.
2188 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2190 /* op vAA, vBB, vCC */
2191 FETCH_B(r2, 1, 0) @ r2<- BB
2192 mov r9, rINST, lsr #8 @ r9<- AA
2193 FETCH_B(r3, 1, 1) @ r3<- CC
2194 GET_VREG(r0, r2) @ r0<- vBB (array object)
2195 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2196 cmp r0, #0 @ null array object?
2197 beq common_errNullObject @ yes, bail
2198 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2199 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2200 cmp r1, r3 @ compare unsigned index, length
2201 bcs common_errArrayIndex @ index >= length, bail
2202 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2203 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2204 GET_INST_OPCODE(ip) @ extract opcode from rINST
2205 SET_VREG(r2, r9) @ vAA<- r2
2206 GOTO_OPCODE(ip) @ jump to next instruction
2210 /* ------------------------------ */
2212 .L_OP_APUT: /* 0x4b */
2213 /* File: armv5te/OP_APUT.S */
2215 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2217 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2218 * instructions. We use a pair of FETCH_Bs instead.
2220 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2222 /* op vAA, vBB, vCC */
2223 FETCH_B(r2, 1, 0) @ r2<- BB
2224 mov r9, rINST, lsr #8 @ r9<- AA
2225 FETCH_B(r3, 1, 1) @ r3<- CC
2226 GET_VREG(r0, r2) @ r0<- vBB (array object)
2227 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2228 cmp r0, #0 @ null array object?
2229 beq common_errNullObject @ yes, bail
2230 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2231 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2232 cmp r1, r3 @ compare unsigned index, length
2233 bcs common_errArrayIndex @ index >= length, bail
2234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2235 GET_VREG(r2, r9) @ r2<- vAA
2236 GET_INST_OPCODE(ip) @ extract opcode from rINST
2237 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2238 GOTO_OPCODE(ip) @ jump to next instruction
2241 /* ------------------------------ */
2243 .L_OP_APUT_WIDE: /* 0x4c */
2244 /* File: armv5te/OP_APUT_WIDE.S */
2246 * Array put, 64 bits. vBB[vCC] <- vAA.
2248 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2250 /* aput-wide vAA, vBB, vCC */
2251 FETCH(r0, 1) @ r0<- CCBB
2252 mov r9, rINST, lsr #8 @ r9<- AA
2253 and r2, r0, #255 @ r2<- BB
2254 mov r3, r0, lsr #8 @ r3<- CC
2255 GET_VREG(r0, r2) @ r0<- vBB (array object)
2256 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2257 cmp r0, #0 @ null array object?
2258 beq common_errNullObject @ yes, bail
2259 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2260 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2261 cmp r1, r3 @ compare unsigned index, length
2262 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2263 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2264 b common_errArrayIndex @ index >= length, bail
2265 @ May want to swap the order of these two branches depending on how the
2266 @ branch prediction (if any) handles conditional forward branches vs.
2267 @ unconditional forward branches.
2269 /* ------------------------------ */
2271 .L_OP_APUT_OBJECT: /* 0x4d */
2272 /* File: armv5te/OP_APUT_OBJECT.S */
2274 * Store an object into an array. vBB[vCC] <- vAA.
2276 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2277 * instructions. We use a pair of FETCH_Bs instead.
2279 /* op vAA, vBB, vCC */
2280 FETCH(r0, 1) @ r0<- CCBB
2281 mov r9, rINST, lsr #8 @ r9<- AA
2282 and r2, r0, #255 @ r2<- BB
2283 mov r3, r0, lsr #8 @ r3<- CC
2284 GET_VREG(r1, r2) @ r1<- vBB (array object)
2285 GET_VREG(r0, r3) @ r0<- vCC (requested index)
2286 cmp r1, #0 @ null array object?
2287 GET_VREG(r9, r9) @ r9<- vAA
2288 beq common_errNullObject @ yes, bail
2289 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length
2290 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width
2291 cmp r0, r3 @ compare unsigned index, length
2292 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2293 b common_errArrayIndex @ index >= length, bail
2296 /* ------------------------------ */
2298 .L_OP_APUT_BOOLEAN: /* 0x4e */
2299 /* File: armv5te/OP_APUT_BOOLEAN.S */
2300 /* File: armv5te/OP_APUT.S */
2302 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2304 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2305 * instructions. We use a pair of FETCH_Bs instead.
2307 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2309 /* op vAA, vBB, vCC */
2310 FETCH_B(r2, 1, 0) @ r2<- BB
2311 mov r9, rINST, lsr #8 @ r9<- AA
2312 FETCH_B(r3, 1, 1) @ r3<- CC
2313 GET_VREG(r0, r2) @ r0<- vBB (array object)
2314 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2315 cmp r0, #0 @ null array object?
2316 beq common_errNullObject @ yes, bail
2317 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2318 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2319 cmp r1, r3 @ compare unsigned index, length
2320 bcs common_errArrayIndex @ index >= length, bail
2321 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2322 GET_VREG(r2, r9) @ r2<- vAA
2323 GET_INST_OPCODE(ip) @ extract opcode from rINST
2324 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2325 GOTO_OPCODE(ip) @ jump to next instruction
2329 /* ------------------------------ */
2331 .L_OP_APUT_BYTE: /* 0x4f */
2332 /* File: armv5te/OP_APUT_BYTE.S */
2333 /* File: armv5te/OP_APUT.S */
2335 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2337 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2338 * instructions. We use a pair of FETCH_Bs instead.
2340 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2342 /* op vAA, vBB, vCC */
2343 FETCH_B(r2, 1, 0) @ r2<- BB
2344 mov r9, rINST, lsr #8 @ r9<- AA
2345 FETCH_B(r3, 1, 1) @ r3<- CC
2346 GET_VREG(r0, r2) @ r0<- vBB (array object)
2347 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2348 cmp r0, #0 @ null array object?
2349 beq common_errNullObject @ yes, bail
2350 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2351 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2352 cmp r1, r3 @ compare unsigned index, length
2353 bcs common_errArrayIndex @ index >= length, bail
2354 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2355 GET_VREG(r2, r9) @ r2<- vAA
2356 GET_INST_OPCODE(ip) @ extract opcode from rINST
2357 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2358 GOTO_OPCODE(ip) @ jump to next instruction
2362 /* ------------------------------ */
2364 .L_OP_APUT_CHAR: /* 0x50 */
2365 /* File: armv5te/OP_APUT_CHAR.S */
2366 /* File: armv5te/OP_APUT.S */
2368 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2370 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2371 * instructions. We use a pair of FETCH_Bs instead.
2373 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2375 /* op vAA, vBB, vCC */
2376 FETCH_B(r2, 1, 0) @ r2<- BB
2377 mov r9, rINST, lsr #8 @ r9<- AA
2378 FETCH_B(r3, 1, 1) @ r3<- CC
2379 GET_VREG(r0, r2) @ r0<- vBB (array object)
2380 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2381 cmp r0, #0 @ null array object?
2382 beq common_errNullObject @ yes, bail
2383 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2384 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2385 cmp r1, r3 @ compare unsigned index, length
2386 bcs common_errArrayIndex @ index >= length, bail
2387 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2388 GET_VREG(r2, r9) @ r2<- vAA
2389 GET_INST_OPCODE(ip) @ extract opcode from rINST
2390 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2391 GOTO_OPCODE(ip) @ jump to next instruction
2395 /* ------------------------------ */
2397 .L_OP_APUT_SHORT: /* 0x51 */
2398 /* File: armv5te/OP_APUT_SHORT.S */
2399 /* File: armv5te/OP_APUT.S */
2401 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2403 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2404 * instructions. We use a pair of FETCH_Bs instead.
2406 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2408 /* op vAA, vBB, vCC */
2409 FETCH_B(r2, 1, 0) @ r2<- BB
2410 mov r9, rINST, lsr #8 @ r9<- AA
2411 FETCH_B(r3, 1, 1) @ r3<- CC
2412 GET_VREG(r0, r2) @ r0<- vBB (array object)
2413 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2414 cmp r0, #0 @ null array object?
2415 beq common_errNullObject @ yes, bail
2416 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2417 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2418 cmp r1, r3 @ compare unsigned index, length
2419 bcs common_errArrayIndex @ index >= length, bail
2420 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2421 GET_VREG(r2, r9) @ r2<- vAA
2422 GET_INST_OPCODE(ip) @ extract opcode from rINST
2423 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2424 GOTO_OPCODE(ip) @ jump to next instruction
2428 /* ------------------------------ */
2430 .L_OP_IGET: /* 0x52 */
2431 /* File: armv6t2/OP_IGET.S */
2433 * General 32-bit instance field get.
2435 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2437 /* op vA, vB, field@CCCC */
2438 mov r0, rINST, lsr #12 @ r0<- B
2439 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2440 FETCH(r1, 1) @ r1<- field ref CCCC
2441 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2442 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2443 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2444 cmp r0, #0 @ is resolved entry null?
2445 bne .LOP_IGET_finish @ no, already resolved
2446 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2447 EXPORT_PC() @ resolve() could throw
2448 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2449 bl dvmResolveInstField @ r0<- resolved InstField ptr
2451 bne .LOP_IGET_finish
2452 b common_exceptionThrown
2454 /* ------------------------------ */
2456 .L_OP_IGET_WIDE: /* 0x53 */
2457 /* File: armv6t2/OP_IGET_WIDE.S */
2459 * Wide 32-bit instance field get.
2461 /* iget-wide vA, vB, field@CCCC */
2462 mov r0, rINST, lsr #12 @ r0<- B
2463 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2464 FETCH(r1, 1) @ r1<- field ref CCCC
2465 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2466 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2467 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2468 cmp r0, #0 @ is resolved entry null?
2469 bne .LOP_IGET_WIDE_finish @ no, already resolved
2470 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2471 EXPORT_PC() @ resolve() could throw
2472 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2473 bl dvmResolveInstField @ r0<- resolved InstField ptr
2475 bne .LOP_IGET_WIDE_finish
2476 b common_exceptionThrown
2478 /* ------------------------------ */
2480 .L_OP_IGET_OBJECT: /* 0x54 */
2481 /* File: armv5te/OP_IGET_OBJECT.S */
2482 /* File: armv5te/OP_IGET.S */
2484 * General 32-bit instance field get.
2486 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2488 /* op vA, vB, field@CCCC */
2489 mov r0, rINST, lsr #12 @ r0<- B
2490 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2491 FETCH(r1, 1) @ r1<- field ref CCCC
2492 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2493 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2494 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2495 cmp r0, #0 @ is resolved entry null?
2496 bne .LOP_IGET_OBJECT_finish @ no, already resolved
2497 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2498 EXPORT_PC() @ resolve() could throw
2499 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2500 bl dvmResolveInstField @ r0<- resolved InstField ptr
2502 bne .LOP_IGET_OBJECT_finish
2503 b common_exceptionThrown
2506 /* ------------------------------ */
2508 .L_OP_IGET_BOOLEAN: /* 0x55 */
2509 /* File: armv5te/OP_IGET_BOOLEAN.S */
2510 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2511 /* File: armv5te/OP_IGET.S */
2513 * General 32-bit instance field get.
2515 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2517 /* op vA, vB, field@CCCC */
2518 mov r0, rINST, lsr #12 @ r0<- B
2519 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2520 FETCH(r1, 1) @ r1<- field ref CCCC
2521 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2522 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2523 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2524 cmp r0, #0 @ is resolved entry null?
2525 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved
2526 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2527 EXPORT_PC() @ resolve() could throw
2528 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2529 bl dvmResolveInstField @ r0<- resolved InstField ptr
2531 bne .LOP_IGET_BOOLEAN_finish
2532 b common_exceptionThrown
2535 /* ------------------------------ */
2537 .L_OP_IGET_BYTE: /* 0x56 */
2538 /* File: armv5te/OP_IGET_BYTE.S */
2539 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2540 /* File: armv5te/OP_IGET.S */
2542 * General 32-bit instance field get.
2544 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2546 /* op vA, vB, field@CCCC */
2547 mov r0, rINST, lsr #12 @ r0<- B
2548 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2549 FETCH(r1, 1) @ r1<- field ref CCCC
2550 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2551 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2552 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2553 cmp r0, #0 @ is resolved entry null?
2554 bne .LOP_IGET_BYTE_finish @ no, already resolved
2555 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2556 EXPORT_PC() @ resolve() could throw
2557 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2558 bl dvmResolveInstField @ r0<- resolved InstField ptr
2560 bne .LOP_IGET_BYTE_finish
2561 b common_exceptionThrown
2564 /* ------------------------------ */
2566 .L_OP_IGET_CHAR: /* 0x57 */
2567 /* File: armv5te/OP_IGET_CHAR.S */
2568 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2569 /* File: armv5te/OP_IGET.S */
2571 * General 32-bit instance field get.
2573 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2575 /* op vA, vB, field@CCCC */
2576 mov r0, rINST, lsr #12 @ r0<- B
2577 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2578 FETCH(r1, 1) @ r1<- field ref CCCC
2579 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2580 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2581 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2582 cmp r0, #0 @ is resolved entry null?
2583 bne .LOP_IGET_CHAR_finish @ no, already resolved
2584 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2585 EXPORT_PC() @ resolve() could throw
2586 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2587 bl dvmResolveInstField @ r0<- resolved InstField ptr
2589 bne .LOP_IGET_CHAR_finish
2590 b common_exceptionThrown
2593 /* ------------------------------ */
2595 .L_OP_IGET_SHORT: /* 0x58 */
2596 /* File: armv5te/OP_IGET_SHORT.S */
2597 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2598 /* File: armv5te/OP_IGET.S */
2600 * General 32-bit instance field get.
2602 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2604 /* op vA, vB, field@CCCC */
2605 mov r0, rINST, lsr #12 @ r0<- B
2606 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2607 FETCH(r1, 1) @ r1<- field ref CCCC
2608 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2609 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2610 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2611 cmp r0, #0 @ is resolved entry null?
2612 bne .LOP_IGET_SHORT_finish @ no, already resolved
2613 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2614 EXPORT_PC() @ resolve() could throw
2615 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2616 bl dvmResolveInstField @ r0<- resolved InstField ptr
2618 bne .LOP_IGET_SHORT_finish
2619 b common_exceptionThrown
2622 /* ------------------------------ */
2624 .L_OP_IPUT: /* 0x59 */
2625 /* File: armv6t2/OP_IPUT.S */
2627 * General 32-bit instance field put.
2629 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2631 /* op vA, vB, field@CCCC */
2632 mov r0, rINST, lsr #12 @ r0<- B
2633 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2634 FETCH(r1, 1) @ r1<- field ref CCCC
2635 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2636 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2637 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2638 cmp r0, #0 @ is resolved entry null?
2639 bne .LOP_IPUT_finish @ no, already resolved
2640 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2641 EXPORT_PC() @ resolve() could throw
2642 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2643 bl dvmResolveInstField @ r0<- resolved InstField ptr
2644 cmp r0, #0 @ success?
2645 bne .LOP_IPUT_finish @ yes, finish up
2646 b common_exceptionThrown
2648 /* ------------------------------ */
2650 .L_OP_IPUT_WIDE: /* 0x5a */
2651 /* File: armv6t2/OP_IPUT_WIDE.S */
2652 /* iput-wide vA, vB, field@CCCC */
2653 mov r0, rINST, lsr #12 @ r0<- B
2654 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2655 FETCH(r1, 1) @ r1<- field ref CCCC
2656 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2657 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2658 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2659 cmp r0, #0 @ is resolved entry null?
2660 bne .LOP_IPUT_WIDE_finish @ no, already resolved
2661 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2662 EXPORT_PC() @ resolve() could throw
2663 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2664 bl dvmResolveInstField @ r0<- resolved InstField ptr
2665 cmp r0, #0 @ success?
2666 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2667 b common_exceptionThrown
2669 /* ------------------------------ */
2671 .L_OP_IPUT_OBJECT: /* 0x5b */
2672 /* File: armv5te/OP_IPUT_OBJECT.S */
2673 /* File: armv5te/OP_IPUT.S */
2675 * General 32-bit instance field put.
2677 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2679 /* op vA, vB, field@CCCC */
2680 mov r0, rINST, lsr #12 @ r0<- B
2681 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2682 FETCH(r1, 1) @ r1<- field ref CCCC
2683 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2684 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2685 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2686 cmp r0, #0 @ is resolved entry null?
2687 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
2688 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2689 EXPORT_PC() @ resolve() could throw
2690 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2691 bl dvmResolveInstField @ r0<- resolved InstField ptr
2692 cmp r0, #0 @ success?
2693 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2694 b common_exceptionThrown
2697 /* ------------------------------ */
2699 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2700 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2701 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2702 /* File: armv5te/OP_IPUT.S */
2704 * General 32-bit instance field put.
2706 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2708 /* op vA, vB, field@CCCC */
2709 mov r0, rINST, lsr #12 @ r0<- B
2710 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2711 FETCH(r1, 1) @ r1<- field ref CCCC
2712 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2713 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2714 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2715 cmp r0, #0 @ is resolved entry null?
2716 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
2717 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2718 EXPORT_PC() @ resolve() could throw
2719 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2720 bl dvmResolveInstField @ r0<- resolved InstField ptr
2721 cmp r0, #0 @ success?
2722 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2723 b common_exceptionThrown
2726 /* ------------------------------ */
2728 .L_OP_IPUT_BYTE: /* 0x5d */
2729 /* File: armv5te/OP_IPUT_BYTE.S */
2730 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2731 /* File: armv5te/OP_IPUT.S */
2733 * General 32-bit instance field put.
2735 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2737 /* op vA, vB, field@CCCC */
2738 mov r0, rINST, lsr #12 @ r0<- B
2739 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2740 FETCH(r1, 1) @ r1<- field ref CCCC
2741 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2742 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2743 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2744 cmp r0, #0 @ is resolved entry null?
2745 bne .LOP_IPUT_BYTE_finish @ no, already resolved
2746 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2747 EXPORT_PC() @ resolve() could throw
2748 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2749 bl dvmResolveInstField @ r0<- resolved InstField ptr
2750 cmp r0, #0 @ success?
2751 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2752 b common_exceptionThrown
2755 /* ------------------------------ */
2757 .L_OP_IPUT_CHAR: /* 0x5e */
2758 /* File: armv5te/OP_IPUT_CHAR.S */
2759 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2760 /* File: armv5te/OP_IPUT.S */
2762 * General 32-bit instance field put.
2764 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2766 /* op vA, vB, field@CCCC */
2767 mov r0, rINST, lsr #12 @ r0<- B
2768 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2769 FETCH(r1, 1) @ r1<- field ref CCCC
2770 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2771 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2772 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2773 cmp r0, #0 @ is resolved entry null?
2774 bne .LOP_IPUT_CHAR_finish @ no, already resolved
2775 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2776 EXPORT_PC() @ resolve() could throw
2777 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2778 bl dvmResolveInstField @ r0<- resolved InstField ptr
2779 cmp r0, #0 @ success?
2780 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2781 b common_exceptionThrown
2784 /* ------------------------------ */
2786 .L_OP_IPUT_SHORT: /* 0x5f */
2787 /* File: armv5te/OP_IPUT_SHORT.S */
2788 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2789 /* File: armv5te/OP_IPUT.S */
2791 * General 32-bit instance field put.
2793 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2795 /* op vA, vB, field@CCCC */
2796 mov r0, rINST, lsr #12 @ r0<- B
2797 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2798 FETCH(r1, 1) @ r1<- field ref CCCC
2799 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2800 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2801 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2802 cmp r0, #0 @ is resolved entry null?
2803 bne .LOP_IPUT_SHORT_finish @ no, already resolved
2804 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2805 EXPORT_PC() @ resolve() could throw
2806 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2807 bl dvmResolveInstField @ r0<- resolved InstField ptr
2808 cmp r0, #0 @ success?
2809 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2810 b common_exceptionThrown
2813 /* ------------------------------ */
2815 .L_OP_SGET: /* 0x60 */
2816 /* File: armv5te/OP_SGET.S */
2818 * General 32-bit SGET handler.
2820 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2822 /* op vAA, field@BBBB */
2823 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2824 FETCH(r1, 1) @ r1<- field ref BBBB
2825 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2826 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2827 cmp r0, #0 @ is resolved entry null?
2828 beq .LOP_SGET_resolve @ yes, do resolve
2829 .LOP_SGET_finish: @ field ptr in r0
2830 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2831 mov r2, rINST, lsr #8 @ r2<- AA
2832 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2833 SET_VREG(r1, r2) @ fp[AA]<- r1
2834 GET_INST_OPCODE(ip) @ extract opcode from rINST
2835 GOTO_OPCODE(ip) @ jump to next instruction
2837 /* ------------------------------ */
2839 .L_OP_SGET_WIDE: /* 0x61 */
2840 /* File: armv5te/OP_SGET_WIDE.S */
2842 * 64-bit SGET handler.
2844 /* sget-wide vAA, field@BBBB */
2845 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2846 FETCH(r1, 1) @ r1<- field ref BBBB
2847 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2848 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2849 cmp r0, #0 @ is resolved entry null?
2850 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2851 .LOP_SGET_WIDE_finish:
2852 mov r1, rINST, lsr #8 @ r1<- AA
2853 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2854 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
2855 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2856 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
2857 GET_INST_OPCODE(ip) @ extract opcode from rINST
2858 GOTO_OPCODE(ip) @ jump to next instruction
2860 /* ------------------------------ */
2862 .L_OP_SGET_OBJECT: /* 0x62 */
2863 /* File: armv5te/OP_SGET_OBJECT.S */
2864 /* File: armv5te/OP_SGET.S */
2866 * General 32-bit SGET handler.
2868 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2870 /* op vAA, field@BBBB */
2871 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2872 FETCH(r1, 1) @ r1<- field ref BBBB
2873 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2874 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2875 cmp r0, #0 @ is resolved entry null?
2876 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2877 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2878 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2879 mov r2, rINST, lsr #8 @ r2<- AA
2880 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2881 SET_VREG(r1, r2) @ fp[AA]<- r1
2882 GET_INST_OPCODE(ip) @ extract opcode from rINST
2883 GOTO_OPCODE(ip) @ jump to next instruction
2886 /* ------------------------------ */
2888 .L_OP_SGET_BOOLEAN: /* 0x63 */
2889 /* File: armv5te/OP_SGET_BOOLEAN.S */
2890 /* File: armv5te/OP_SGET.S */
2892 * General 32-bit SGET handler.
2894 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2896 /* op vAA, field@BBBB */
2897 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2898 FETCH(r1, 1) @ r1<- field ref BBBB
2899 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2900 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2901 cmp r0, #0 @ is resolved entry null?
2902 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2903 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2904 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2905 mov r2, rINST, lsr #8 @ r2<- AA
2906 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2907 SET_VREG(r1, r2) @ fp[AA]<- r1
2908 GET_INST_OPCODE(ip) @ extract opcode from rINST
2909 GOTO_OPCODE(ip) @ jump to next instruction
2912 /* ------------------------------ */
2914 .L_OP_SGET_BYTE: /* 0x64 */
2915 /* File: armv5te/OP_SGET_BYTE.S */
2916 /* File: armv5te/OP_SGET.S */
2918 * General 32-bit SGET handler.
2920 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2922 /* op vAA, field@BBBB */
2923 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2924 FETCH(r1, 1) @ r1<- field ref BBBB
2925 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2926 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2927 cmp r0, #0 @ is resolved entry null?
2928 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2929 .LOP_SGET_BYTE_finish: @ field ptr in r0
2930 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2931 mov r2, rINST, lsr #8 @ r2<- AA
2932 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2933 SET_VREG(r1, r2) @ fp[AA]<- r1
2934 GET_INST_OPCODE(ip) @ extract opcode from rINST
2935 GOTO_OPCODE(ip) @ jump to next instruction
2938 /* ------------------------------ */
2940 .L_OP_SGET_CHAR: /* 0x65 */
2941 /* File: armv5te/OP_SGET_CHAR.S */
2942 /* File: armv5te/OP_SGET.S */
2944 * General 32-bit SGET handler.
2946 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2948 /* op vAA, field@BBBB */
2949 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2950 FETCH(r1, 1) @ r1<- field ref BBBB
2951 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2952 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2953 cmp r0, #0 @ is resolved entry null?
2954 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2955 .LOP_SGET_CHAR_finish: @ field ptr in r0
2956 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2957 mov r2, rINST, lsr #8 @ r2<- AA
2958 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2959 SET_VREG(r1, r2) @ fp[AA]<- r1
2960 GET_INST_OPCODE(ip) @ extract opcode from rINST
2961 GOTO_OPCODE(ip) @ jump to next instruction
2964 /* ------------------------------ */
2966 .L_OP_SGET_SHORT: /* 0x66 */
2967 /* File: armv5te/OP_SGET_SHORT.S */
2968 /* File: armv5te/OP_SGET.S */
2970 * General 32-bit SGET handler.
2972 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2974 /* op vAA, field@BBBB */
2975 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2976 FETCH(r1, 1) @ r1<- field ref BBBB
2977 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2978 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2979 cmp r0, #0 @ is resolved entry null?
2980 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
2981 .LOP_SGET_SHORT_finish: @ field ptr in r0
2982 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2983 mov r2, rINST, lsr #8 @ r2<- AA
2984 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2985 SET_VREG(r1, r2) @ fp[AA]<- r1
2986 GET_INST_OPCODE(ip) @ extract opcode from rINST
2987 GOTO_OPCODE(ip) @ jump to next instruction
2990 /* ------------------------------ */
2992 .L_OP_SPUT: /* 0x67 */
2993 /* File: armv5te/OP_SPUT.S */
2995 * General 32-bit SPUT handler.
2997 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2999 /* op vAA, field@BBBB */
3000 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3001 FETCH(r1, 1) @ r1<- field ref BBBB
3002 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3003 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3004 cmp r0, #0 @ is resolved entry null?
3005 beq .LOP_SPUT_resolve @ yes, do resolve
3006 .LOP_SPUT_finish: @ field ptr in r0
3007 mov r2, rINST, lsr #8 @ r2<- AA
3008 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3009 GET_VREG(r1, r2) @ r1<- fp[AA]
3010 GET_INST_OPCODE(ip) @ extract opcode from rINST
3011 str r1, [r0, #offStaticField_value] @ field<- vAA
3012 GOTO_OPCODE(ip) @ jump to next instruction
3014 /* ------------------------------ */
3016 .L_OP_SPUT_WIDE: /* 0x68 */
3017 /* File: armv5te/OP_SPUT_WIDE.S */
3019 * 64-bit SPUT handler.
3021 /* sput-wide vAA, field@BBBB */
3022 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3023 FETCH(r1, 1) @ r1<- field ref BBBB
3024 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3025 mov r9, rINST, lsr #8 @ r9<- AA
3026 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3027 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
3028 cmp r0, #0 @ is resolved entry null?
3029 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
3030 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3032 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
3033 GET_INST_OPCODE(ip) @ extract opcode from rINST
3034 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3035 GOTO_OPCODE(ip) @ jump to next instruction
3037 /* ------------------------------ */
3039 .L_OP_SPUT_OBJECT: /* 0x69 */
3040 /* File: armv5te/OP_SPUT_OBJECT.S */
3041 /* File: armv5te/OP_SPUT.S */
3043 * General 32-bit SPUT handler.
3045 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3047 /* op vAA, field@BBBB */
3048 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3049 FETCH(r1, 1) @ r1<- field ref BBBB
3050 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3051 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3052 cmp r0, #0 @ is resolved entry null?
3053 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
3054 .LOP_SPUT_OBJECT_finish: @ field ptr in r0
3055 mov r2, rINST, lsr #8 @ r2<- AA
3056 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3057 GET_VREG(r1, r2) @ r1<- fp[AA]
3058 GET_INST_OPCODE(ip) @ extract opcode from rINST
3059 str r1, [r0, #offStaticField_value] @ field<- vAA
3060 GOTO_OPCODE(ip) @ jump to next instruction
3063 /* ------------------------------ */
3065 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3066 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3067 /* File: armv5te/OP_SPUT.S */
3069 * General 32-bit SPUT handler.
3071 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3073 /* op vAA, field@BBBB */
3074 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3075 FETCH(r1, 1) @ r1<- field ref BBBB
3076 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3077 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3078 cmp r0, #0 @ is resolved entry null?
3079 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve
3080 .LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
3081 mov r2, rINST, lsr #8 @ r2<- AA
3082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3083 GET_VREG(r1, r2) @ r1<- fp[AA]
3084 GET_INST_OPCODE(ip) @ extract opcode from rINST
3085 str r1, [r0, #offStaticField_value] @ field<- vAA
3086 GOTO_OPCODE(ip) @ jump to next instruction
3089 /* ------------------------------ */
3091 .L_OP_SPUT_BYTE: /* 0x6b */
3092 /* File: armv5te/OP_SPUT_BYTE.S */
3093 /* File: armv5te/OP_SPUT.S */
3095 * General 32-bit SPUT handler.
3097 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3099 /* op vAA, field@BBBB */
3100 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3101 FETCH(r1, 1) @ r1<- field ref BBBB
3102 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3103 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3104 cmp r0, #0 @ is resolved entry null?
3105 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve
3106 .LOP_SPUT_BYTE_finish: @ field ptr in r0
3107 mov r2, rINST, lsr #8 @ r2<- AA
3108 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3109 GET_VREG(r1, r2) @ r1<- fp[AA]
3110 GET_INST_OPCODE(ip) @ extract opcode from rINST
3111 str r1, [r0, #offStaticField_value] @ field<- vAA
3112 GOTO_OPCODE(ip) @ jump to next instruction
3115 /* ------------------------------ */
3117 .L_OP_SPUT_CHAR: /* 0x6c */
3118 /* File: armv5te/OP_SPUT_CHAR.S */
3119 /* File: armv5te/OP_SPUT.S */
3121 * General 32-bit SPUT handler.
3123 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3125 /* op vAA, field@BBBB */
3126 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3127 FETCH(r1, 1) @ r1<- field ref BBBB
3128 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3129 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3130 cmp r0, #0 @ is resolved entry null?
3131 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve
3132 .LOP_SPUT_CHAR_finish: @ field ptr in r0
3133 mov r2, rINST, lsr #8 @ r2<- AA
3134 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3135 GET_VREG(r1, r2) @ r1<- fp[AA]
3136 GET_INST_OPCODE(ip) @ extract opcode from rINST
3137 str r1, [r0, #offStaticField_value] @ field<- vAA
3138 GOTO_OPCODE(ip) @ jump to next instruction
3141 /* ------------------------------ */
3143 .L_OP_SPUT_SHORT: /* 0x6d */
3144 /* File: armv5te/OP_SPUT_SHORT.S */
3145 /* File: armv5te/OP_SPUT.S */
3147 * General 32-bit SPUT handler.
3149 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3151 /* op vAA, field@BBBB */
3152 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3153 FETCH(r1, 1) @ r1<- field ref BBBB
3154 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3155 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3156 cmp r0, #0 @ is resolved entry null?
3157 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve
3158 .LOP_SPUT_SHORT_finish: @ field ptr in r0
3159 mov r2, rINST, lsr #8 @ r2<- AA
3160 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3161 GET_VREG(r1, r2) @ r1<- fp[AA]
3162 GET_INST_OPCODE(ip) @ extract opcode from rINST
3163 str r1, [r0, #offStaticField_value] @ field<- vAA
3164 GOTO_OPCODE(ip) @ jump to next instruction
3167 /* ------------------------------ */
3169 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3170 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3172 * Handle a virtual method call.
3174 * for: invoke-virtual, invoke-virtual/range
3176 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3179 FETCH(r1, 1) @ r1<- BBBB
3180 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3181 FETCH(r10, 2) @ r10<- GFED or CCCC
3182 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3184 and r10, r10, #15 @ r10<- D (or stays CCCC)
3186 cmp r0, #0 @ already resolved?
3187 EXPORT_PC() @ must export for invoke
3188 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3189 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3190 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3191 mov r2, #METHOD_VIRTUAL @ resolver method type
3192 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3193 cmp r0, #0 @ got null?
3194 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3195 b common_exceptionThrown @ yes, handle exception
3197 /* ------------------------------ */
3199 .L_OP_INVOKE_SUPER: /* 0x6f */
3200 /* File: armv5te/OP_INVOKE_SUPER.S */
3202 * Handle a "super" method call.
3204 * for: invoke-super, invoke-super/range
3206 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3207 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3208 FETCH(r10, 2) @ r10<- GFED or CCCC
3209 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3211 and r10, r10, #15 @ r10<- D (or stays CCCC)
3213 FETCH(r1, 1) @ r1<- BBBB
3214 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3215 GET_VREG(r2, r10) @ r2<- "this" ptr
3216 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3217 cmp r2, #0 @ null "this"?
3218 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3219 beq common_errNullObject @ null "this", throw exception
3220 cmp r0, #0 @ already resolved?
3221 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3222 EXPORT_PC() @ must export for invoke
3223 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3224 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3226 /* ------------------------------ */
3228 .L_OP_INVOKE_DIRECT: /* 0x70 */
3229 /* File: armv5te/OP_INVOKE_DIRECT.S */
3231 * Handle a direct method call.
3233 * (We could defer the "is 'this' pointer null" test to the common
3234 * method invocation code, and use a flag to indicate that static
3235 * calls don't count. If we do this as part of copying the arguments
3236 * out we could avoiding loading the first arg twice.)
3238 * for: invoke-direct, invoke-direct/range
3240 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3241 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3242 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3243 FETCH(r1, 1) @ r1<- BBBB
3244 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3245 FETCH(r10, 2) @ r10<- GFED or CCCC
3246 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3248 and r10, r10, #15 @ r10<- D (or stays CCCC)
3250 cmp r0, #0 @ already resolved?
3251 EXPORT_PC() @ must export for invoke
3252 GET_VREG(r2, r10) @ r2<- "this" ptr
3253 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3254 .LOP_INVOKE_DIRECT_finish:
3255 cmp r2, #0 @ null "this" ref?
3256 bne common_invokeMethodNoRange @ no, continue on
3257 b common_errNullObject @ yes, throw exception
3259 /* ------------------------------ */
3261 .L_OP_INVOKE_STATIC: /* 0x71 */
3262 /* File: armv5te/OP_INVOKE_STATIC.S */
3264 * Handle a static method call.
3266 * for: invoke-static, invoke-static/range
3268 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3269 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3270 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3271 FETCH(r1, 1) @ r1<- BBBB
3272 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3273 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3274 cmp r0, #0 @ already resolved?
3275 EXPORT_PC() @ must export for invoke
3276 bne common_invokeMethodNoRange @ yes, continue on
3277 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3278 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3279 mov r2, #METHOD_STATIC @ resolver method type
3280 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3281 cmp r0, #0 @ got null?
3282 bne common_invokeMethodNoRange @ no, continue
3283 b common_exceptionThrown @ yes, handle exception
3286 /* ------------------------------ */
3288 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3289 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3291 * Handle an interface method call.
3293 * for: invoke-interface, invoke-interface/range
3295 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3296 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3297 FETCH(r2, 2) @ r2<- FEDC or CCCC
3298 FETCH(r1, 1) @ r1<- BBBB
3300 and r2, r2, #15 @ r2<- C (or stays CCCC)
3302 EXPORT_PC() @ must export for invoke
3303 GET_VREG(r0, r2) @ r0<- first arg ("this")
3304 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3305 cmp r0, #0 @ null obj?
3306 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3307 beq common_errNullObject @ yes, fail
3308 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3309 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3310 cmp r0, #0 @ failed?
3311 beq common_exceptionThrown @ yes, handle exception
3312 b common_invokeMethodNoRange @ jump to common handler
3315 /* ------------------------------ */
3317 .L_OP_UNUSED_73: /* 0x73 */
3318 /* File: armv5te/OP_UNUSED_73.S */
3319 /* File: armv5te/unused.S */
3324 /* ------------------------------ */
3326 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3327 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3328 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3330 * Handle a virtual method call.
3332 * for: invoke-virtual, invoke-virtual/range
3334 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3335 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3337 FETCH(r1, 1) @ r1<- BBBB
3338 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3339 FETCH(r10, 2) @ r10<- GFED or CCCC
3340 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3342 and r10, r10, #15 @ r10<- D (or stays CCCC)
3344 cmp r0, #0 @ already resolved?
3345 EXPORT_PC() @ must export for invoke
3346 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3347 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3348 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3349 mov r2, #METHOD_VIRTUAL @ resolver method type
3350 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3351 cmp r0, #0 @ got null?
3352 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3353 b common_exceptionThrown @ yes, handle exception
3356 /* ------------------------------ */
3358 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3359 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3360 /* File: armv5te/OP_INVOKE_SUPER.S */
3362 * Handle a "super" method call.
3364 * for: invoke-super, invoke-super/range
3366 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368 FETCH(r10, 2) @ r10<- GFED or CCCC
3369 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3371 and r10, r10, #15 @ r10<- D (or stays CCCC)
3373 FETCH(r1, 1) @ r1<- BBBB
3374 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3375 GET_VREG(r2, r10) @ r2<- "this" ptr
3376 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3377 cmp r2, #0 @ null "this"?
3378 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3379 beq common_errNullObject @ null "this", throw exception
3380 cmp r0, #0 @ already resolved?
3381 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3382 EXPORT_PC() @ must export for invoke
3383 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3384 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3387 /* ------------------------------ */
3389 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3390 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3391 /* File: armv5te/OP_INVOKE_DIRECT.S */
3393 * Handle a direct method call.
3395 * (We could defer the "is 'this' pointer null" test to the common
3396 * method invocation code, and use a flag to indicate that static
3397 * calls don't count. If we do this as part of copying the arguments
3398 * out we could avoiding loading the first arg twice.)
3400 * for: invoke-direct, invoke-direct/range
3402 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3403 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3404 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3405 FETCH(r1, 1) @ r1<- BBBB
3406 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3407 FETCH(r10, 2) @ r10<- GFED or CCCC
3408 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3410 and r10, r10, #15 @ r10<- D (or stays CCCC)
3412 cmp r0, #0 @ already resolved?
3413 EXPORT_PC() @ must export for invoke
3414 GET_VREG(r2, r10) @ r2<- "this" ptr
3415 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3416 .LOP_INVOKE_DIRECT_RANGE_finish:
3417 cmp r2, #0 @ null "this" ref?
3418 bne common_invokeMethodRange @ no, continue on
3419 b common_errNullObject @ yes, throw exception
3422 /* ------------------------------ */
3424 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3425 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3426 /* File: armv5te/OP_INVOKE_STATIC.S */
3428 * Handle a static method call.
3430 * for: invoke-static, invoke-static/range
3432 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3433 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3434 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3435 FETCH(r1, 1) @ r1<- BBBB
3436 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3437 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3438 cmp r0, #0 @ already resolved?
3439 EXPORT_PC() @ must export for invoke
3440 bne common_invokeMethodRange @ yes, continue on
3441 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3442 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3443 mov r2, #METHOD_STATIC @ resolver method type
3444 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3445 cmp r0, #0 @ got null?
3446 bne common_invokeMethodRange @ no, continue
3447 b common_exceptionThrown @ yes, handle exception
3451 /* ------------------------------ */
3453 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3454 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3455 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3457 * Handle an interface method call.
3459 * for: invoke-interface, invoke-interface/range
3461 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3462 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3463 FETCH(r2, 2) @ r2<- FEDC or CCCC
3464 FETCH(r1, 1) @ r1<- BBBB
3466 and r2, r2, #15 @ r2<- C (or stays CCCC)
3468 EXPORT_PC() @ must export for invoke
3469 GET_VREG(r0, r2) @ r0<- first arg ("this")
3470 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3471 cmp r0, #0 @ null obj?
3472 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3473 beq common_errNullObject @ yes, fail
3474 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3475 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3476 cmp r0, #0 @ failed?
3477 beq common_exceptionThrown @ yes, handle exception
3478 b common_invokeMethodRange @ jump to common handler
3482 /* ------------------------------ */
3484 .L_OP_UNUSED_79: /* 0x79 */
3485 /* File: armv5te/OP_UNUSED_79.S */
3486 /* File: armv5te/unused.S */
3491 /* ------------------------------ */
3493 .L_OP_UNUSED_7A: /* 0x7a */
3494 /* File: armv5te/OP_UNUSED_7A.S */
3495 /* File: armv5te/unused.S */
3500 /* ------------------------------ */
3502 .L_OP_NEG_INT: /* 0x7b */
3503 /* File: armv6t2/OP_NEG_INT.S */
3504 /* File: armv6t2/unop.S */
3506 * Generic 32-bit unary operation. Provide an "instr" line that
3507 * specifies an instruction that performs "result = op r0".
3508 * This could be an ARM instruction or a function call.
3510 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3511 * int-to-byte, int-to-char, int-to-short
3514 mov r3, rINST, lsr #12 @ r3<- B
3515 ubfx r9, rINST, #8, #4 @ r9<- A
3516 GET_VREG(r0, r3) @ r0<- vB
3517 @ optional op; may set condition codes
3518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3519 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3520 GET_INST_OPCODE(ip) @ extract opcode from rINST
3521 SET_VREG(r0, r9) @ vAA<- r0
3522 GOTO_OPCODE(ip) @ jump to next instruction
3523 /* 8-9 instructions */
3526 /* ------------------------------ */
3528 .L_OP_NOT_INT: /* 0x7c */
3529 /* File: armv6t2/OP_NOT_INT.S */
3530 /* File: armv6t2/unop.S */
3532 * Generic 32-bit unary operation. Provide an "instr" line that
3533 * specifies an instruction that performs "result = op r0".
3534 * This could be an ARM instruction or a function call.
3536 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3537 * int-to-byte, int-to-char, int-to-short
3540 mov r3, rINST, lsr #12 @ r3<- B
3541 ubfx r9, rINST, #8, #4 @ r9<- A
3542 GET_VREG(r0, r3) @ r0<- vB
3543 @ optional op; may set condition codes
3544 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3545 mvn r0, r0 @ r0<- op, r0-r3 changed
3546 GET_INST_OPCODE(ip) @ extract opcode from rINST
3547 SET_VREG(r0, r9) @ vAA<- r0
3548 GOTO_OPCODE(ip) @ jump to next instruction
3549 /* 8-9 instructions */
3552 /* ------------------------------ */
3554 .L_OP_NEG_LONG: /* 0x7d */
3555 /* File: armv6t2/OP_NEG_LONG.S */
3556 /* File: armv6t2/unopWide.S */
3558 * Generic 64-bit unary operation. Provide an "instr" line that
3559 * specifies an instruction that performs "result = op r0/r1".
3560 * This could be an ARM instruction or a function call.
3562 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3565 mov r3, rINST, lsr #12 @ r3<- B
3566 ubfx r9, rINST, #8, #4 @ r9<- A
3567 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3568 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3569 ldmia r3, {r0-r1} @ r0/r1<- vAA
3570 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3571 rsbs r0, r0, #0 @ optional op; may set condition codes
3572 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3573 GET_INST_OPCODE(ip) @ extract opcode from rINST
3574 stmia r9, {r0-r1} @ vAA<- r0/r1
3575 GOTO_OPCODE(ip) @ jump to next instruction
3576 /* 10-11 instructions */
3580 /* ------------------------------ */
3582 .L_OP_NOT_LONG: /* 0x7e */
3583 /* File: armv6t2/OP_NOT_LONG.S */
3584 /* File: armv6t2/unopWide.S */
3586 * Generic 64-bit unary operation. Provide an "instr" line that
3587 * specifies an instruction that performs "result = op r0/r1".
3588 * This could be an ARM instruction or a function call.
3590 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3593 mov r3, rINST, lsr #12 @ r3<- B
3594 ubfx r9, rINST, #8, #4 @ r9<- A
3595 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3596 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3597 ldmia r3, {r0-r1} @ r0/r1<- vAA
3598 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3599 mvn r0, r0 @ optional op; may set condition codes
3600 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3601 GET_INST_OPCODE(ip) @ extract opcode from rINST
3602 stmia r9, {r0-r1} @ vAA<- r0/r1
3603 GOTO_OPCODE(ip) @ jump to next instruction
3604 /* 10-11 instructions */
3608 /* ------------------------------ */
3610 .L_OP_NEG_FLOAT: /* 0x7f */
3611 /* File: armv6t2/OP_NEG_FLOAT.S */
3612 /* File: armv6t2/unop.S */
3614 * Generic 32-bit unary operation. Provide an "instr" line that
3615 * specifies an instruction that performs "result = op r0".
3616 * This could be an ARM instruction or a function call.
3618 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3619 * int-to-byte, int-to-char, int-to-short
3622 mov r3, rINST, lsr #12 @ r3<- B
3623 ubfx r9, rINST, #8, #4 @ r9<- A
3624 GET_VREG(r0, r3) @ r0<- vB
3625 @ optional op; may set condition codes
3626 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3627 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3628 GET_INST_OPCODE(ip) @ extract opcode from rINST
3629 SET_VREG(r0, r9) @ vAA<- r0
3630 GOTO_OPCODE(ip) @ jump to next instruction
3631 /* 8-9 instructions */
3634 /* ------------------------------ */
3636 .L_OP_NEG_DOUBLE: /* 0x80 */
3637 /* File: armv6t2/OP_NEG_DOUBLE.S */
3638 /* File: armv6t2/unopWide.S */
3640 * Generic 64-bit unary operation. Provide an "instr" line that
3641 * specifies an instruction that performs "result = op r0/r1".
3642 * This could be an ARM instruction or a function call.
3644 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3647 mov r3, rINST, lsr #12 @ r3<- B
3648 ubfx r9, rINST, #8, #4 @ r9<- A
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 add r1, r1, #0x80000000 @ 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 /* 10-11 instructions */
3662 /* ------------------------------ */
3664 .L_OP_INT_TO_LONG: /* 0x81 */
3665 /* File: armv6t2/OP_INT_TO_LONG.S */
3666 /* File: armv6t2/unopWider.S */
3668 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3669 * that specifies an instruction that performs "result = op r0", where
3670 * "result" is a 64-bit quantity in r0/r1.
3672 * For: int-to-long, int-to-double, float-to-long, float-to-double
3675 mov r3, rINST, lsr #12 @ r3<- B
3676 ubfx r9, rINST, #8, #4 @ r9<- A
3677 GET_VREG(r0, r3) @ r0<- vB
3678 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3679 @ optional op; may set condition codes
3680 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3681 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3682 GET_INST_OPCODE(ip) @ extract opcode from rINST
3683 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3684 GOTO_OPCODE(ip) @ jump to next instruction
3685 /* 9-10 instructions */
3688 /* ------------------------------ */
3690 .L_OP_INT_TO_FLOAT: /* 0x82 */
3691 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
3692 /* File: arm-vfp/funop.S */
3694 * Generic 32-bit unary floating-point operation. Provide an "instr"
3695 * line that specifies an instruction that performs "s1 = op s0".
3697 * for: int-to-float, float-to-int
3700 mov r3, rINST, lsr #12 @ r3<- B
3701 mov r9, rINST, lsr #8 @ r9<- A+
3702 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3703 flds s0, [r3] @ s0<- vB
3704 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3705 and r9, r9, #15 @ r9<- A
3706 fsitos s1, s0 @ s1<- op
3707 GET_INST_OPCODE(ip) @ extract opcode from rINST
3708 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3709 fsts s1, [r9] @ vA<- s1
3710 GOTO_OPCODE(ip) @ jump to next instruction
3713 /* ------------------------------ */
3715 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3716 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3717 /* File: arm-vfp/funopWider.S */
3719 * Generic 32bit-to-64bit floating point unary operation. Provide an
3720 * "instr" line that specifies an instruction that performs "d0 = op s0".
3722 * For: int-to-double, float-to-double
3725 mov r3, rINST, lsr #12 @ r3<- B
3726 mov r9, rINST, lsr #8 @ r9<- A+
3727 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3728 flds s0, [r3] @ s0<- vB
3729 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3730 and r9, r9, #15 @ r9<- A
3731 fsitod d0, s0 @ d0<- op
3732 GET_INST_OPCODE(ip) @ extract opcode from rINST
3733 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3734 fstd d0, [r9] @ vA<- d0
3735 GOTO_OPCODE(ip) @ jump to next instruction
3738 /* ------------------------------ */
3740 .L_OP_LONG_TO_INT: /* 0x84 */
3741 /* File: armv5te/OP_LONG_TO_INT.S */
3742 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3743 /* File: armv5te/OP_MOVE.S */
3744 /* for move, move-object, long-to-int */
3746 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3747 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3748 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3749 GET_VREG(r2, r1) @ r2<- fp[B]
3751 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3752 SET_VREG(r2, r0) @ fp[A]<- r2
3753 GOTO_OPCODE(ip) @ execute next instruction
3757 /* ------------------------------ */
3759 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3760 /* File: armv6t2/OP_LONG_TO_FLOAT.S */
3761 /* File: armv6t2/unopNarrower.S */
3763 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3764 * that specifies an instruction that performs "result = op r0/r1", where
3765 * "result" is a 32-bit quantity in r0.
3767 * For: long-to-float, double-to-int, double-to-float
3769 * (This would work for long-to-int, but that instruction is actually
3770 * an exact match for OP_MOVE.)
3773 mov r3, rINST, lsr #12 @ r3<- B
3774 ubfx r9, rINST, #8, #4 @ r9<- A
3775 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3776 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3777 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3778 @ optional op; may set condition codes
3779 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3780 GET_INST_OPCODE(ip) @ extract opcode from rINST
3781 SET_VREG(r0, r9) @ vA<- r0
3782 GOTO_OPCODE(ip) @ jump to next instruction
3783 /* 9-10 instructions */
3786 /* ------------------------------ */
3788 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3789 /* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3790 /* File: armv6t2/unopWide.S */
3792 * Generic 64-bit unary operation. Provide an "instr" line that
3793 * specifies an instruction that performs "result = op r0/r1".
3794 * This could be an ARM instruction or a function call.
3796 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3799 mov r3, rINST, lsr #12 @ r3<- B
3800 ubfx r9, rINST, #8, #4 @ r9<- A
3801 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3802 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3803 ldmia r3, {r0-r1} @ r0/r1<- vAA
3804 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3805 @ optional op; may set condition codes
3806 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3807 GET_INST_OPCODE(ip) @ extract opcode from rINST
3808 stmia r9, {r0-r1} @ vAA<- r0/r1
3809 GOTO_OPCODE(ip) @ jump to next instruction
3810 /* 10-11 instructions */
3814 /* ------------------------------ */
3816 .L_OP_FLOAT_TO_INT: /* 0x87 */
3817 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
3818 /* File: arm-vfp/funop.S */
3820 * Generic 32-bit unary floating-point operation. Provide an "instr"
3821 * line that specifies an instruction that performs "s1 = op s0".
3823 * for: int-to-float, float-to-int
3826 mov r3, rINST, lsr #12 @ r3<- B
3827 mov r9, rINST, lsr #8 @ r9<- A+
3828 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3829 flds s0, [r3] @ s0<- vB
3830 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3831 and r9, r9, #15 @ r9<- A
3832 ftosizs s1, s0 @ s1<- op
3833 GET_INST_OPCODE(ip) @ extract opcode from rINST
3834 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3835 fsts s1, [r9] @ vA<- s1
3836 GOTO_OPCODE(ip) @ jump to next instruction
3839 /* ------------------------------ */
3841 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3842 /* File: armv6t2/OP_FLOAT_TO_LONG.S */
3843 @include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3844 /* File: armv6t2/unopWider.S */
3846 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3847 * that specifies an instruction that performs "result = op r0", where
3848 * "result" is a 64-bit quantity in r0/r1.
3850 * For: int-to-long, int-to-double, float-to-long, float-to-double
3853 mov r3, rINST, lsr #12 @ r3<- B
3854 ubfx r9, rINST, #8, #4 @ r9<- A
3855 GET_VREG(r0, r3) @ r0<- vB
3856 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3857 @ optional op; may set condition codes
3858 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3859 bl f2l_doconv @ r0<- op, r0-r3 changed
3860 GET_INST_OPCODE(ip) @ extract opcode from rINST
3861 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3862 GOTO_OPCODE(ip) @ jump to next instruction
3863 /* 9-10 instructions */
3867 /* ------------------------------ */
3869 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3870 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3871 /* File: arm-vfp/funopWider.S */
3873 * Generic 32bit-to-64bit floating point unary operation. Provide an
3874 * "instr" line that specifies an instruction that performs "d0 = op s0".
3876 * For: int-to-double, float-to-double
3879 mov r3, rINST, lsr #12 @ r3<- B
3880 mov r9, rINST, lsr #8 @ r9<- A+
3881 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3882 flds s0, [r3] @ s0<- vB
3883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3884 and r9, r9, #15 @ r9<- A
3885 fcvtds d0, s0 @ d0<- op
3886 GET_INST_OPCODE(ip) @ extract opcode from rINST
3887 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3888 fstd d0, [r9] @ vA<- d0
3889 GOTO_OPCODE(ip) @ jump to next instruction
3892 /* ------------------------------ */
3894 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3895 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3896 /* File: arm-vfp/funopNarrower.S */
3898 * Generic 64bit-to-32bit unary floating point operation. Provide an
3899 * "instr" line that specifies an instruction that performs "s0 = op d0".
3901 * For: double-to-int, double-to-float
3904 mov r3, rINST, lsr #12 @ r3<- B
3905 mov r9, rINST, lsr #8 @ r9<- A+
3906 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3907 fldd d0, [r3] @ d0<- vB
3908 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3909 and r9, r9, #15 @ r9<- A
3910 ftosizd s0, d0 @ s0<- op
3911 GET_INST_OPCODE(ip) @ extract opcode from rINST
3912 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3913 fsts s0, [r9] @ vA<- s0
3914 GOTO_OPCODE(ip) @ jump to next instruction
3917 /* ------------------------------ */
3919 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3920 /* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3921 @include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"}
3922 /* File: armv6t2/unopWide.S */
3924 * Generic 64-bit unary operation. Provide an "instr" line that
3925 * specifies an instruction that performs "result = op r0/r1".
3926 * This could be an ARM instruction or a function call.
3928 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3931 mov r3, rINST, lsr #12 @ r3<- B
3932 ubfx r9, rINST, #8, #4 @ r9<- A
3933 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3934 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3935 ldmia r3, {r0-r1} @ r0/r1<- vAA
3936 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3937 @ optional op; may set condition codes
3938 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
3939 GET_INST_OPCODE(ip) @ extract opcode from rINST
3940 stmia r9, {r0-r1} @ vAA<- r0/r1
3941 GOTO_OPCODE(ip) @ jump to next instruction
3942 /* 10-11 instructions */
3947 /* ------------------------------ */
3949 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3950 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3951 /* File: arm-vfp/funopNarrower.S */
3953 * Generic 64bit-to-32bit unary floating point operation. Provide an
3954 * "instr" line that specifies an instruction that performs "s0 = op d0".
3956 * For: double-to-int, double-to-float
3959 mov r3, rINST, lsr #12 @ r3<- B
3960 mov r9, rINST, lsr #8 @ r9<- A+
3961 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3962 fldd d0, [r3] @ d0<- vB
3963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3964 and r9, r9, #15 @ r9<- A
3965 fcvtsd s0, d0 @ s0<- op
3966 GET_INST_OPCODE(ip) @ extract opcode from rINST
3967 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3968 fsts s0, [r9] @ vA<- s0
3969 GOTO_OPCODE(ip) @ jump to next instruction
3972 /* ------------------------------ */
3974 .L_OP_INT_TO_BYTE: /* 0x8d */
3975 /* File: armv6t2/OP_INT_TO_BYTE.S */
3976 /* File: armv6t2/unop.S */
3978 * Generic 32-bit unary operation. Provide an "instr" line that
3979 * specifies an instruction that performs "result = op r0".
3980 * This could be an ARM instruction or a function call.
3982 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3983 * int-to-byte, int-to-char, int-to-short
3986 mov r3, rINST, lsr #12 @ r3<- B
3987 ubfx r9, rINST, #8, #4 @ r9<- A
3988 GET_VREG(r0, r3) @ r0<- vB
3989 @ optional op; may set condition codes
3990 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3991 sxtb r0, r0 @ r0<- op, r0-r3 changed
3992 GET_INST_OPCODE(ip) @ extract opcode from rINST
3993 SET_VREG(r0, r9) @ vAA<- r0
3994 GOTO_OPCODE(ip) @ jump to next instruction
3995 /* 8-9 instructions */
3998 /* ------------------------------ */
4000 .L_OP_INT_TO_CHAR: /* 0x8e */
4001 /* File: armv6t2/OP_INT_TO_CHAR.S */
4002 /* File: armv6t2/unop.S */
4004 * Generic 32-bit unary operation. Provide an "instr" line that
4005 * specifies an instruction that performs "result = op r0".
4006 * This could be an ARM instruction or a function call.
4008 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4009 * int-to-byte, int-to-char, int-to-short
4012 mov r3, rINST, lsr #12 @ r3<- B
4013 ubfx r9, rINST, #8, #4 @ r9<- A
4014 GET_VREG(r0, r3) @ r0<- vB
4015 @ optional op; may set condition codes
4016 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4017 uxth r0, r0 @ r0<- op, r0-r3 changed
4018 GET_INST_OPCODE(ip) @ extract opcode from rINST
4019 SET_VREG(r0, r9) @ vAA<- r0
4020 GOTO_OPCODE(ip) @ jump to next instruction
4021 /* 8-9 instructions */
4024 /* ------------------------------ */
4026 .L_OP_INT_TO_SHORT: /* 0x8f */
4027 /* File: armv6t2/OP_INT_TO_SHORT.S */
4028 /* File: armv6t2/unop.S */
4030 * Generic 32-bit unary operation. Provide an "instr" line that
4031 * specifies an instruction that performs "result = op r0".
4032 * This could be an ARM instruction or a function call.
4034 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4035 * int-to-byte, int-to-char, int-to-short
4038 mov r3, rINST, lsr #12 @ r3<- B
4039 ubfx r9, rINST, #8, #4 @ r9<- A
4040 GET_VREG(r0, r3) @ r0<- vB
4041 @ optional op; may set condition codes
4042 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4043 sxth r0, r0 @ r0<- op, r0-r3 changed
4044 GET_INST_OPCODE(ip) @ extract opcode from rINST
4045 SET_VREG(r0, r9) @ vAA<- r0
4046 GOTO_OPCODE(ip) @ jump to next instruction
4047 /* 8-9 instructions */
4050 /* ------------------------------ */
4052 .L_OP_ADD_INT: /* 0x90 */
4053 /* File: armv5te/OP_ADD_INT.S */
4054 /* File: armv5te/binop.S */
4056 * Generic 32-bit binary operation. Provide an "instr" line that
4057 * specifies an instruction that performs "result = r0 op r1".
4058 * This could be an ARM instruction or a function call. (If the result
4059 * comes back in a register other than r0, you can override "result".)
4061 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4062 * vCC (r1). Useful for integer division and modulus. Note that we
4063 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4064 * handles it correctly.
4066 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4067 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4068 * mul-float, div-float, rem-float
4070 /* binop vAA, vBB, vCC */
4071 FETCH(r0, 1) @ r0<- CCBB
4072 mov r9, rINST, lsr #8 @ r9<- AA
4073 mov r3, r0, lsr #8 @ r3<- CC
4074 and r2, r0, #255 @ r2<- BB
4075 GET_VREG(r1, r3) @ r1<- vCC
4076 GET_VREG(r0, r2) @ r0<- vBB
4078 cmp r1, #0 @ is second operand zero?
4079 beq common_errDivideByZero
4082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4083 @ optional op; may set condition codes
4084 add r0, r0, r1 @ r0<- op, r0-r3 changed
4085 GET_INST_OPCODE(ip) @ extract opcode from rINST
4086 SET_VREG(r0, r9) @ vAA<- r0
4087 GOTO_OPCODE(ip) @ jump to next instruction
4088 /* 11-14 instructions */
4092 /* ------------------------------ */
4094 .L_OP_SUB_INT: /* 0x91 */
4095 /* File: armv5te/OP_SUB_INT.S */
4096 /* File: armv5te/binop.S */
4098 * Generic 32-bit binary operation. Provide an "instr" line that
4099 * specifies an instruction that performs "result = r0 op r1".
4100 * This could be an ARM instruction or a function call. (If the result
4101 * comes back in a register other than r0, you can override "result".)
4103 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4104 * vCC (r1). Useful for integer division and modulus. Note that we
4105 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4106 * handles it correctly.
4108 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4109 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4110 * mul-float, div-float, rem-float
4112 /* binop vAA, vBB, vCC */
4113 FETCH(r0, 1) @ r0<- CCBB
4114 mov r9, rINST, lsr #8 @ r9<- AA
4115 mov r3, r0, lsr #8 @ r3<- CC
4116 and r2, r0, #255 @ r2<- BB
4117 GET_VREG(r1, r3) @ r1<- vCC
4118 GET_VREG(r0, r2) @ r0<- vBB
4120 cmp r1, #0 @ is second operand zero?
4121 beq common_errDivideByZero
4124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4125 @ optional op; may set condition codes
4126 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4127 GET_INST_OPCODE(ip) @ extract opcode from rINST
4128 SET_VREG(r0, r9) @ vAA<- r0
4129 GOTO_OPCODE(ip) @ jump to next instruction
4130 /* 11-14 instructions */
4134 /* ------------------------------ */
4136 .L_OP_MUL_INT: /* 0x92 */
4137 /* File: armv5te/OP_MUL_INT.S */
4138 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4139 /* File: armv5te/binop.S */
4141 * Generic 32-bit binary operation. Provide an "instr" line that
4142 * specifies an instruction that performs "result = r0 op r1".
4143 * This could be an ARM instruction or a function call. (If the result
4144 * comes back in a register other than r0, you can override "result".)
4146 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4147 * vCC (r1). Useful for integer division and modulus. Note that we
4148 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4149 * handles it correctly.
4151 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4152 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4153 * mul-float, div-float, rem-float
4155 /* binop vAA, vBB, vCC */
4156 FETCH(r0, 1) @ r0<- CCBB
4157 mov r9, rINST, lsr #8 @ r9<- AA
4158 mov r3, r0, lsr #8 @ r3<- CC
4159 and r2, r0, #255 @ r2<- BB
4160 GET_VREG(r1, r3) @ r1<- vCC
4161 GET_VREG(r0, r2) @ r0<- vBB
4163 cmp r1, #0 @ is second operand zero?
4164 beq common_errDivideByZero
4167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4168 @ optional op; may set condition codes
4169 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4170 GET_INST_OPCODE(ip) @ extract opcode from rINST
4171 SET_VREG(r0, r9) @ vAA<- r0
4172 GOTO_OPCODE(ip) @ jump to next instruction
4173 /* 11-14 instructions */
4177 /* ------------------------------ */
4179 .L_OP_DIV_INT: /* 0x93 */
4180 /* File: armv5te/OP_DIV_INT.S */
4181 /* File: armv5te/binop.S */
4183 * Generic 32-bit binary operation. Provide an "instr" line that
4184 * specifies an instruction that performs "result = r0 op r1".
4185 * This could be an ARM instruction or a function call. (If the result
4186 * comes back in a register other than r0, you can override "result".)
4188 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4189 * vCC (r1). Useful for integer division and modulus. Note that we
4190 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4191 * handles it correctly.
4193 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4194 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4195 * mul-float, div-float, rem-float
4197 /* binop vAA, vBB, vCC */
4198 FETCH(r0, 1) @ r0<- CCBB
4199 mov r9, rINST, lsr #8 @ r9<- AA
4200 mov r3, r0, lsr #8 @ r3<- CC
4201 and r2, r0, #255 @ r2<- BB
4202 GET_VREG(r1, r3) @ r1<- vCC
4203 GET_VREG(r0, r2) @ r0<- vBB
4205 cmp r1, #0 @ is second operand zero?
4206 beq common_errDivideByZero
4209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4210 @ optional op; may set condition codes
4211 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4212 GET_INST_OPCODE(ip) @ extract opcode from rINST
4213 SET_VREG(r0, r9) @ vAA<- r0
4214 GOTO_OPCODE(ip) @ jump to next instruction
4215 /* 11-14 instructions */
4219 /* ------------------------------ */
4221 .L_OP_REM_INT: /* 0x94 */
4222 /* File: armv5te/OP_REM_INT.S */
4223 /* idivmod returns quotient in r0 and remainder in r1 */
4224 /* File: armv5te/binop.S */
4226 * Generic 32-bit binary operation. Provide an "instr" line that
4227 * specifies an instruction that performs "result = r0 op r1".
4228 * This could be an ARM instruction or a function call. (If the result
4229 * comes back in a register other than r0, you can override "result".)
4231 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4232 * vCC (r1). Useful for integer division and modulus. Note that we
4233 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4234 * handles it correctly.
4236 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4237 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4238 * mul-float, div-float, rem-float
4240 /* binop vAA, vBB, vCC */
4241 FETCH(r0, 1) @ r0<- CCBB
4242 mov r9, rINST, lsr #8 @ r9<- AA
4243 mov r3, r0, lsr #8 @ r3<- CC
4244 and r2, r0, #255 @ r2<- BB
4245 GET_VREG(r1, r3) @ r1<- vCC
4246 GET_VREG(r0, r2) @ r0<- vBB
4248 cmp r1, #0 @ is second operand zero?
4249 beq common_errDivideByZero
4252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4253 @ optional op; may set condition codes
4254 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4255 GET_INST_OPCODE(ip) @ extract opcode from rINST
4256 SET_VREG(r1, r9) @ vAA<- r1
4257 GOTO_OPCODE(ip) @ jump to next instruction
4258 /* 11-14 instructions */
4262 /* ------------------------------ */
4264 .L_OP_AND_INT: /* 0x95 */
4265 /* File: armv5te/OP_AND_INT.S */
4266 /* File: armv5te/binop.S */
4268 * Generic 32-bit binary operation. Provide an "instr" line that
4269 * specifies an instruction that performs "result = r0 op r1".
4270 * This could be an ARM instruction or a function call. (If the result
4271 * comes back in a register other than r0, you can override "result".)
4273 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4274 * vCC (r1). Useful for integer division and modulus. Note that we
4275 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4276 * handles it correctly.
4278 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4279 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4280 * mul-float, div-float, rem-float
4282 /* binop vAA, vBB, vCC */
4283 FETCH(r0, 1) @ r0<- CCBB
4284 mov r9, rINST, lsr #8 @ r9<- AA
4285 mov r3, r0, lsr #8 @ r3<- CC
4286 and r2, r0, #255 @ r2<- BB
4287 GET_VREG(r1, r3) @ r1<- vCC
4288 GET_VREG(r0, r2) @ r0<- vBB
4290 cmp r1, #0 @ is second operand zero?
4291 beq common_errDivideByZero
4294 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4295 @ optional op; may set condition codes
4296 and r0, r0, r1 @ r0<- op, r0-r3 changed
4297 GET_INST_OPCODE(ip) @ extract opcode from rINST
4298 SET_VREG(r0, r9) @ vAA<- r0
4299 GOTO_OPCODE(ip) @ jump to next instruction
4300 /* 11-14 instructions */
4304 /* ------------------------------ */
4306 .L_OP_OR_INT: /* 0x96 */
4307 /* File: armv5te/OP_OR_INT.S */
4308 /* File: armv5te/binop.S */
4310 * Generic 32-bit binary operation. Provide an "instr" line that
4311 * specifies an instruction that performs "result = r0 op r1".
4312 * This could be an ARM instruction or a function call. (If the result
4313 * comes back in a register other than r0, you can override "result".)
4315 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4316 * vCC (r1). Useful for integer division and modulus. Note that we
4317 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4318 * handles it correctly.
4320 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4321 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4322 * mul-float, div-float, rem-float
4324 /* binop vAA, vBB, vCC */
4325 FETCH(r0, 1) @ r0<- CCBB
4326 mov r9, rINST, lsr #8 @ r9<- AA
4327 mov r3, r0, lsr #8 @ r3<- CC
4328 and r2, r0, #255 @ r2<- BB
4329 GET_VREG(r1, r3) @ r1<- vCC
4330 GET_VREG(r0, r2) @ r0<- vBB
4332 cmp r1, #0 @ is second operand zero?
4333 beq common_errDivideByZero
4336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4337 @ optional op; may set condition codes
4338 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4339 GET_INST_OPCODE(ip) @ extract opcode from rINST
4340 SET_VREG(r0, r9) @ vAA<- r0
4341 GOTO_OPCODE(ip) @ jump to next instruction
4342 /* 11-14 instructions */
4346 /* ------------------------------ */
4348 .L_OP_XOR_INT: /* 0x97 */
4349 /* File: armv5te/OP_XOR_INT.S */
4350 /* File: armv5te/binop.S */
4352 * Generic 32-bit binary operation. Provide an "instr" line that
4353 * specifies an instruction that performs "result = r0 op r1".
4354 * This could be an ARM instruction or a function call. (If the result
4355 * comes back in a register other than r0, you can override "result".)
4357 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4358 * vCC (r1). Useful for integer division and modulus. Note that we
4359 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4360 * handles it correctly.
4362 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4363 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4364 * mul-float, div-float, rem-float
4366 /* binop vAA, vBB, vCC */
4367 FETCH(r0, 1) @ r0<- CCBB
4368 mov r9, rINST, lsr #8 @ r9<- AA
4369 mov r3, r0, lsr #8 @ r3<- CC
4370 and r2, r0, #255 @ r2<- BB
4371 GET_VREG(r1, r3) @ r1<- vCC
4372 GET_VREG(r0, r2) @ r0<- vBB
4374 cmp r1, #0 @ is second operand zero?
4375 beq common_errDivideByZero
4378 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4379 @ optional op; may set condition codes
4380 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4381 GET_INST_OPCODE(ip) @ extract opcode from rINST
4382 SET_VREG(r0, r9) @ vAA<- r0
4383 GOTO_OPCODE(ip) @ jump to next instruction
4384 /* 11-14 instructions */
4388 /* ------------------------------ */
4390 .L_OP_SHL_INT: /* 0x98 */
4391 /* File: armv5te/OP_SHL_INT.S */
4392 /* File: armv5te/binop.S */
4394 * Generic 32-bit binary operation. Provide an "instr" line that
4395 * specifies an instruction that performs "result = r0 op r1".
4396 * This could be an ARM instruction or a function call. (If the result
4397 * comes back in a register other than r0, you can override "result".)
4399 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4400 * vCC (r1). Useful for integer division and modulus. Note that we
4401 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4402 * handles it correctly.
4404 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4405 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4406 * mul-float, div-float, rem-float
4408 /* binop vAA, vBB, vCC */
4409 FETCH(r0, 1) @ r0<- CCBB
4410 mov r9, rINST, lsr #8 @ r9<- AA
4411 mov r3, r0, lsr #8 @ r3<- CC
4412 and r2, r0, #255 @ r2<- BB
4413 GET_VREG(r1, r3) @ r1<- vCC
4414 GET_VREG(r0, r2) @ r0<- vBB
4416 cmp r1, #0 @ is second operand zero?
4417 beq common_errDivideByZero
4420 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4421 and r1, r1, #31 @ optional op; may set condition codes
4422 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4423 GET_INST_OPCODE(ip) @ extract opcode from rINST
4424 SET_VREG(r0, r9) @ vAA<- r0
4425 GOTO_OPCODE(ip) @ jump to next instruction
4426 /* 11-14 instructions */
4430 /* ------------------------------ */
4432 .L_OP_SHR_INT: /* 0x99 */
4433 /* File: armv5te/OP_SHR_INT.S */
4434 /* File: armv5te/binop.S */
4436 * Generic 32-bit binary operation. Provide an "instr" line that
4437 * specifies an instruction that performs "result = r0 op r1".
4438 * This could be an ARM instruction or a function call. (If the result
4439 * comes back in a register other than r0, you can override "result".)
4441 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4442 * vCC (r1). Useful for integer division and modulus. Note that we
4443 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4444 * handles it correctly.
4446 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4447 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4448 * mul-float, div-float, rem-float
4450 /* binop vAA, vBB, vCC */
4451 FETCH(r0, 1) @ r0<- CCBB
4452 mov r9, rINST, lsr #8 @ r9<- AA
4453 mov r3, r0, lsr #8 @ r3<- CC
4454 and r2, r0, #255 @ r2<- BB
4455 GET_VREG(r1, r3) @ r1<- vCC
4456 GET_VREG(r0, r2) @ r0<- vBB
4458 cmp r1, #0 @ is second operand zero?
4459 beq common_errDivideByZero
4462 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4463 and r1, r1, #31 @ optional op; may set condition codes
4464 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4465 GET_INST_OPCODE(ip) @ extract opcode from rINST
4466 SET_VREG(r0, r9) @ vAA<- r0
4467 GOTO_OPCODE(ip) @ jump to next instruction
4468 /* 11-14 instructions */
4472 /* ------------------------------ */
4474 .L_OP_USHR_INT: /* 0x9a */
4475 /* File: armv5te/OP_USHR_INT.S */
4476 /* File: armv5te/binop.S */
4478 * Generic 32-bit binary operation. Provide an "instr" line that
4479 * specifies an instruction that performs "result = r0 op r1".
4480 * This could be an ARM instruction or a function call. (If the result
4481 * comes back in a register other than r0, you can override "result".)
4483 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4484 * vCC (r1). Useful for integer division and modulus. Note that we
4485 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4486 * handles it correctly.
4488 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4489 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4490 * mul-float, div-float, rem-float
4492 /* binop vAA, vBB, vCC */
4493 FETCH(r0, 1) @ r0<- CCBB
4494 mov r9, rINST, lsr #8 @ r9<- AA
4495 mov r3, r0, lsr #8 @ r3<- CC
4496 and r2, r0, #255 @ r2<- BB
4497 GET_VREG(r1, r3) @ r1<- vCC
4498 GET_VREG(r0, r2) @ r0<- vBB
4500 cmp r1, #0 @ is second operand zero?
4501 beq common_errDivideByZero
4504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4505 and r1, r1, #31 @ optional op; may set condition codes
4506 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4507 GET_INST_OPCODE(ip) @ extract opcode from rINST
4508 SET_VREG(r0, r9) @ vAA<- r0
4509 GOTO_OPCODE(ip) @ jump to next instruction
4510 /* 11-14 instructions */
4514 /* ------------------------------ */
4516 .L_OP_ADD_LONG: /* 0x9b */
4517 /* File: armv5te/OP_ADD_LONG.S */
4518 /* File: armv5te/binopWide.S */
4520 * Generic 64-bit binary operation. Provide an "instr" line that
4521 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4522 * This could be an ARM instruction or a function call. (If the result
4523 * comes back in a register other than r0, you can override "result".)
4525 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4526 * vCC (r1). Useful for integer division and modulus.
4528 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4529 * xor-long, add-double, sub-double, mul-double, div-double,
4532 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4534 /* binop vAA, vBB, vCC */
4535 FETCH(r0, 1) @ r0<- CCBB
4536 mov r9, rINST, lsr #8 @ r9<- AA
4537 and r2, r0, #255 @ r2<- BB
4538 mov r3, r0, lsr #8 @ r3<- CC
4539 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4540 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4541 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4542 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4543 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4545 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4546 beq common_errDivideByZero
4548 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4550 adds r0, r0, r2 @ optional op; may set condition codes
4551 adc r1, r1, r3 @ result<- op, r0-r3 changed
4552 GET_INST_OPCODE(ip) @ extract opcode from rINST
4553 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4554 GOTO_OPCODE(ip) @ jump to next instruction
4555 /* 14-17 instructions */
4559 /* ------------------------------ */
4561 .L_OP_SUB_LONG: /* 0x9c */
4562 /* File: armv5te/OP_SUB_LONG.S */
4563 /* File: armv5te/binopWide.S */
4565 * Generic 64-bit binary operation. Provide an "instr" line that
4566 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4567 * This could be an ARM instruction or a function call. (If the result
4568 * comes back in a register other than r0, you can override "result".)
4570 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4571 * vCC (r1). Useful for integer division and modulus.
4573 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4574 * xor-long, add-double, sub-double, mul-double, div-double,
4577 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4579 /* binop vAA, vBB, vCC */
4580 FETCH(r0, 1) @ r0<- CCBB
4581 mov r9, rINST, lsr #8 @ r9<- AA
4582 and r2, r0, #255 @ r2<- BB
4583 mov r3, r0, lsr #8 @ r3<- CC
4584 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4585 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4586 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4587 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4588 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4590 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4591 beq common_errDivideByZero
4593 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4595 subs r0, r0, r2 @ optional op; may set condition codes
4596 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4597 GET_INST_OPCODE(ip) @ extract opcode from rINST
4598 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4599 GOTO_OPCODE(ip) @ jump to next instruction
4600 /* 14-17 instructions */
4604 /* ------------------------------ */
4606 .L_OP_MUL_LONG: /* 0x9d */
4607 /* File: armv5te/OP_MUL_LONG.S */
4609 * Signed 64-bit integer multiply.
4611 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4618 * The low word of the result holds ZX, the high word holds
4619 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4620 * it doesn't fit in the low 64 bits.
4622 * Unlike most ARM math operations, multiply instructions have
4623 * restrictions on using the same register more than once (Rd and Rm
4624 * cannot be the same).
4626 /* mul-long vAA, vBB, vCC */
4627 FETCH(r0, 1) @ r0<- CCBB
4628 and r2, r0, #255 @ r2<- BB
4629 mov r3, r0, lsr #8 @ r3<- CC
4630 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4631 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4632 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4633 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4634 mul ip, r2, r1 @ ip<- ZxW
4635 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4636 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4637 mov r0, rINST, lsr #8 @ r0<- AA
4638 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4639 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4640 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4641 b .LOP_MUL_LONG_finish
4643 /* ------------------------------ */
4645 .L_OP_DIV_LONG: /* 0x9e */
4646 /* File: armv5te/OP_DIV_LONG.S */
4647 /* File: armv5te/binopWide.S */
4649 * Generic 64-bit binary operation. Provide an "instr" line that
4650 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4651 * This could be an ARM instruction or a function call. (If the result
4652 * comes back in a register other than r0, you can override "result".)
4654 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4655 * vCC (r1). Useful for integer division and modulus.
4657 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4658 * xor-long, add-double, sub-double, mul-double, div-double,
4661 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4663 /* binop vAA, vBB, vCC */
4664 FETCH(r0, 1) @ r0<- CCBB
4665 mov r9, rINST, lsr #8 @ r9<- AA
4666 and r2, r0, #255 @ r2<- BB
4667 mov r3, r0, lsr #8 @ r3<- CC
4668 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4669 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4670 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4671 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4672 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4674 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4675 beq common_errDivideByZero
4677 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4679 @ optional op; may set condition codes
4680 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4681 GET_INST_OPCODE(ip) @ extract opcode from rINST
4682 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4683 GOTO_OPCODE(ip) @ jump to next instruction
4684 /* 14-17 instructions */
4688 /* ------------------------------ */
4690 .L_OP_REM_LONG: /* 0x9f */
4691 /* File: armv5te/OP_REM_LONG.S */
4692 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4693 /* File: armv5te/binopWide.S */
4695 * Generic 64-bit binary operation. Provide an "instr" line that
4696 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4697 * This could be an ARM instruction or a function call. (If the result
4698 * comes back in a register other than r0, you can override "result".)
4700 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4701 * vCC (r1). Useful for integer division and modulus.
4703 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4704 * xor-long, add-double, sub-double, mul-double, div-double,
4707 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4709 /* binop vAA, vBB, vCC */
4710 FETCH(r0, 1) @ r0<- CCBB
4711 mov r9, rINST, lsr #8 @ r9<- AA
4712 and r2, r0, #255 @ r2<- BB
4713 mov r3, r0, lsr #8 @ r3<- CC
4714 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4715 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4716 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4717 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4718 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4720 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4721 beq common_errDivideByZero
4723 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4725 @ optional op; may set condition codes
4726 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4727 GET_INST_OPCODE(ip) @ extract opcode from rINST
4728 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4729 GOTO_OPCODE(ip) @ jump to next instruction
4730 /* 14-17 instructions */
4734 /* ------------------------------ */
4736 .L_OP_AND_LONG: /* 0xa0 */
4737 /* File: armv5te/OP_AND_LONG.S */
4738 /* File: armv5te/binopWide.S */
4740 * Generic 64-bit binary operation. Provide an "instr" line that
4741 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742 * This could be an ARM instruction or a function call. (If the result
4743 * comes back in a register other than r0, you can override "result".)
4745 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746 * vCC (r1). Useful for integer division and modulus.
4748 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749 * xor-long, add-double, sub-double, mul-double, div-double,
4752 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4754 /* binop vAA, vBB, vCC */
4755 FETCH(r0, 1) @ r0<- CCBB
4756 mov r9, rINST, lsr #8 @ r9<- AA
4757 and r2, r0, #255 @ r2<- BB
4758 mov r3, r0, lsr #8 @ r3<- CC
4759 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4760 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4761 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4762 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4763 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4765 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4766 beq common_errDivideByZero
4768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4770 and r0, r0, r2 @ optional op; may set condition codes
4771 and r1, r1, r3 @ result<- op, r0-r3 changed
4772 GET_INST_OPCODE(ip) @ extract opcode from rINST
4773 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4774 GOTO_OPCODE(ip) @ jump to next instruction
4775 /* 14-17 instructions */
4779 /* ------------------------------ */
4781 .L_OP_OR_LONG: /* 0xa1 */
4782 /* File: armv5te/OP_OR_LONG.S */
4783 /* File: armv5te/binopWide.S */
4785 * Generic 64-bit binary operation. Provide an "instr" line that
4786 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4787 * This could be an ARM instruction or a function call. (If the result
4788 * comes back in a register other than r0, you can override "result".)
4790 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4791 * vCC (r1). Useful for integer division and modulus.
4793 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4794 * xor-long, add-double, sub-double, mul-double, div-double,
4797 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4799 /* binop vAA, vBB, vCC */
4800 FETCH(r0, 1) @ r0<- CCBB
4801 mov r9, rINST, lsr #8 @ r9<- AA
4802 and r2, r0, #255 @ r2<- BB
4803 mov r3, r0, lsr #8 @ r3<- CC
4804 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4805 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4806 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4807 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4808 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4810 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4811 beq common_errDivideByZero
4813 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4815 orr r0, r0, r2 @ optional op; may set condition codes
4816 orr r1, r1, r3 @ result<- op, r0-r3 changed
4817 GET_INST_OPCODE(ip) @ extract opcode from rINST
4818 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4819 GOTO_OPCODE(ip) @ jump to next instruction
4820 /* 14-17 instructions */
4824 /* ------------------------------ */
4826 .L_OP_XOR_LONG: /* 0xa2 */
4827 /* File: armv5te/OP_XOR_LONG.S */
4828 /* File: armv5te/binopWide.S */
4830 * Generic 64-bit binary operation. Provide an "instr" line that
4831 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4832 * This could be an ARM instruction or a function call. (If the result
4833 * comes back in a register other than r0, you can override "result".)
4835 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4836 * vCC (r1). Useful for integer division and modulus.
4838 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4839 * xor-long, add-double, sub-double, mul-double, div-double,
4842 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4844 /* binop vAA, vBB, vCC */
4845 FETCH(r0, 1) @ r0<- CCBB
4846 mov r9, rINST, lsr #8 @ r9<- AA
4847 and r2, r0, #255 @ r2<- BB
4848 mov r3, r0, lsr #8 @ r3<- CC
4849 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4850 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4851 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4852 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4853 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4855 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4856 beq common_errDivideByZero
4858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4860 eor r0, r0, r2 @ optional op; may set condition codes
4861 eor r1, r1, r3 @ result<- op, r0-r3 changed
4862 GET_INST_OPCODE(ip) @ extract opcode from rINST
4863 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4864 GOTO_OPCODE(ip) @ jump to next instruction
4865 /* 14-17 instructions */
4869 /* ------------------------------ */
4871 .L_OP_SHL_LONG: /* 0xa3 */
4872 /* File: armv5te/OP_SHL_LONG.S */
4874 * Long integer shift. This is different from the generic 32/64-bit
4875 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4876 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4877 * 6 bits of the shift distance.
4879 /* shl-long vAA, vBB, vCC */
4880 FETCH(r0, 1) @ r0<- CCBB
4881 mov r9, rINST, lsr #8 @ r9<- AA
4882 and r3, r0, #255 @ r3<- BB
4883 mov r0, r0, lsr #8 @ r0<- CC
4884 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4885 GET_VREG(r2, r0) @ r2<- vCC
4886 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4887 and r2, r2, #63 @ r2<- r2 & 0x3f
4888 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4890 mov r1, r1, asl r2 @ r1<- r1 << r2
4891 rsb r3, r2, #32 @ r3<- 32 - r2
4892 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
4893 subs ip, r2, #32 @ ip<- r2 - 32
4894 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
4895 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4896 b .LOP_SHL_LONG_finish
4898 /* ------------------------------ */
4900 .L_OP_SHR_LONG: /* 0xa4 */
4901 /* File: armv5te/OP_SHR_LONG.S */
4903 * Long integer shift. This is different from the generic 32/64-bit
4904 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4905 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4906 * 6 bits of the shift distance.
4908 /* shr-long vAA, vBB, vCC */
4909 FETCH(r0, 1) @ r0<- CCBB
4910 mov r9, rINST, lsr #8 @ r9<- AA
4911 and r3, r0, #255 @ r3<- BB
4912 mov r0, r0, lsr #8 @ r0<- CC
4913 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4914 GET_VREG(r2, r0) @ r2<- vCC
4915 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4916 and r2, r2, #63 @ r0<- r0 & 0x3f
4917 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4919 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4920 rsb r3, r2, #32 @ r3<- 32 - r2
4921 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4922 subs ip, r2, #32 @ ip<- r2 - 32
4923 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
4924 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4925 b .LOP_SHR_LONG_finish
4927 /* ------------------------------ */
4929 .L_OP_USHR_LONG: /* 0xa5 */
4930 /* File: armv5te/OP_USHR_LONG.S */
4932 * Long integer shift. This is different from the generic 32/64-bit
4933 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4934 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4935 * 6 bits of the shift distance.
4937 /* ushr-long vAA, vBB, vCC */
4938 FETCH(r0, 1) @ r0<- CCBB
4939 mov r9, rINST, lsr #8 @ r9<- AA
4940 and r3, r0, #255 @ r3<- BB
4941 mov r0, r0, lsr #8 @ r0<- CC
4942 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4943 GET_VREG(r2, r0) @ r2<- vCC
4944 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4945 and r2, r2, #63 @ r0<- r0 & 0x3f
4946 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4948 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4949 rsb r3, r2, #32 @ r3<- 32 - r2
4950 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4951 subs ip, r2, #32 @ ip<- r2 - 32
4952 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
4953 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4954 b .LOP_USHR_LONG_finish
4956 /* ------------------------------ */
4958 .L_OP_ADD_FLOAT: /* 0xa6 */
4959 /* File: arm-vfp/OP_ADD_FLOAT.S */
4960 /* File: arm-vfp/fbinop.S */
4962 * Generic 32-bit floating-point operation. Provide an "instr" line that
4963 * specifies an instruction that performs "s2 = s0 op s1". Because we
4964 * use the "softfp" ABI, this must be an instruction, not a function call.
4966 * For: add-float, sub-float, mul-float, div-float
4968 /* floatop vAA, vBB, vCC */
4969 FETCH(r0, 1) @ r0<- CCBB
4970 mov r9, rINST, lsr #8 @ r9<- AA
4971 mov r3, r0, lsr #8 @ r3<- CC
4972 and r2, r0, #255 @ r2<- BB
4973 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
4974 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
4975 flds s1, [r3] @ s1<- vCC
4976 flds s0, [r2] @ s0<- vBB
4978 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4979 fadds s2, s0, s1 @ s2<- op
4980 GET_INST_OPCODE(ip) @ extract opcode from rINST
4981 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
4982 fsts s2, [r9] @ vAA<- s2
4983 GOTO_OPCODE(ip) @ jump to next instruction
4986 /* ------------------------------ */
4988 .L_OP_SUB_FLOAT: /* 0xa7 */
4989 /* File: arm-vfp/OP_SUB_FLOAT.S */
4990 /* File: arm-vfp/fbinop.S */
4992 * Generic 32-bit floating-point operation. Provide an "instr" line that
4993 * specifies an instruction that performs "s2 = s0 op s1". Because we
4994 * use the "softfp" ABI, this must be an instruction, not a function call.
4996 * For: add-float, sub-float, mul-float, div-float
4998 /* floatop vAA, vBB, vCC */
4999 FETCH(r0, 1) @ r0<- CCBB
5000 mov r9, rINST, lsr #8 @ r9<- AA
5001 mov r3, r0, lsr #8 @ r3<- CC
5002 and r2, r0, #255 @ r2<- BB
5003 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5004 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5005 flds s1, [r3] @ s1<- vCC
5006 flds s0, [r2] @ s0<- vBB
5008 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5009 fsubs s2, s0, s1 @ s2<- op
5010 GET_INST_OPCODE(ip) @ extract opcode from rINST
5011 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5012 fsts s2, [r9] @ vAA<- s2
5013 GOTO_OPCODE(ip) @ jump to next instruction
5016 /* ------------------------------ */
5018 .L_OP_MUL_FLOAT: /* 0xa8 */
5019 /* File: arm-vfp/OP_MUL_FLOAT.S */
5020 /* File: arm-vfp/fbinop.S */
5022 * Generic 32-bit floating-point operation. Provide an "instr" line that
5023 * specifies an instruction that performs "s2 = s0 op s1". Because we
5024 * use the "softfp" ABI, this must be an instruction, not a function call.
5026 * For: add-float, sub-float, mul-float, div-float
5028 /* floatop vAA, vBB, vCC */
5029 FETCH(r0, 1) @ r0<- CCBB
5030 mov r9, rINST, lsr #8 @ r9<- AA
5031 mov r3, r0, lsr #8 @ r3<- CC
5032 and r2, r0, #255 @ r2<- BB
5033 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5034 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5035 flds s1, [r3] @ s1<- vCC
5036 flds s0, [r2] @ s0<- vBB
5038 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5039 fmuls s2, s0, s1 @ s2<- op
5040 GET_INST_OPCODE(ip) @ extract opcode from rINST
5041 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5042 fsts s2, [r9] @ vAA<- s2
5043 GOTO_OPCODE(ip) @ jump to next instruction
5046 /* ------------------------------ */
5048 .L_OP_DIV_FLOAT: /* 0xa9 */
5049 /* File: arm-vfp/OP_DIV_FLOAT.S */
5050 /* File: arm-vfp/fbinop.S */
5052 * Generic 32-bit floating-point operation. Provide an "instr" line that
5053 * specifies an instruction that performs "s2 = s0 op s1". Because we
5054 * use the "softfp" ABI, this must be an instruction, not a function call.
5056 * For: add-float, sub-float, mul-float, div-float
5058 /* floatop vAA, vBB, vCC */
5059 FETCH(r0, 1) @ r0<- CCBB
5060 mov r9, rINST, lsr #8 @ r9<- AA
5061 mov r3, r0, lsr #8 @ r3<- CC
5062 and r2, r0, #255 @ r2<- BB
5063 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5064 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5065 flds s1, [r3] @ s1<- vCC
5066 flds s0, [r2] @ s0<- vBB
5068 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5069 fdivs s2, s0, s1 @ s2<- op
5070 GET_INST_OPCODE(ip) @ extract opcode from rINST
5071 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5072 fsts s2, [r9] @ vAA<- s2
5073 GOTO_OPCODE(ip) @ jump to next instruction
5076 /* ------------------------------ */
5078 .L_OP_REM_FLOAT: /* 0xaa */
5079 /* File: armv5te/OP_REM_FLOAT.S */
5080 /* EABI doesn't define a float remainder function, but libm does */
5081 /* File: armv5te/binop.S */
5083 * Generic 32-bit binary operation. Provide an "instr" line that
5084 * specifies an instruction that performs "result = r0 op r1".
5085 * This could be an ARM instruction or a function call. (If the result
5086 * comes back in a register other than r0, you can override "result".)
5088 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5089 * vCC (r1). Useful for integer division and modulus. Note that we
5090 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5091 * handles it correctly.
5093 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5094 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5095 * mul-float, div-float, rem-float
5097 /* binop vAA, vBB, vCC */
5098 FETCH(r0, 1) @ r0<- CCBB
5099 mov r9, rINST, lsr #8 @ r9<- AA
5100 mov r3, r0, lsr #8 @ r3<- CC
5101 and r2, r0, #255 @ r2<- BB
5102 GET_VREG(r1, r3) @ r1<- vCC
5103 GET_VREG(r0, r2) @ r0<- vBB
5105 cmp r1, #0 @ is second operand zero?
5106 beq common_errDivideByZero
5109 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5110 @ optional op; may set condition codes
5111 bl fmodf @ r0<- op, r0-r3 changed
5112 GET_INST_OPCODE(ip) @ extract opcode from rINST
5113 SET_VREG(r0, r9) @ vAA<- r0
5114 GOTO_OPCODE(ip) @ jump to next instruction
5115 /* 11-14 instructions */
5119 /* ------------------------------ */
5121 .L_OP_ADD_DOUBLE: /* 0xab */
5122 /* File: arm-vfp/OP_ADD_DOUBLE.S */
5123 /* File: arm-vfp/fbinopWide.S */
5125 * Generic 64-bit double-precision floating point binary operation.
5126 * Provide an "instr" line that specifies an instruction that performs
5129 * for: add-double, sub-double, mul-double, div-double
5131 /* doubleop vAA, vBB, vCC */
5132 FETCH(r0, 1) @ r0<- CCBB
5133 mov r9, rINST, lsr #8 @ r9<- AA
5134 mov r3, r0, lsr #8 @ r3<- CC
5135 and r2, r0, #255 @ r2<- BB
5136 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5137 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5138 fldd d1, [r3] @ d1<- vCC
5139 fldd d0, [r2] @ d0<- vBB
5141 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5142 faddd d2, d0, d1 @ s2<- op
5143 GET_INST_OPCODE(ip) @ extract opcode from rINST
5144 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5145 fstd d2, [r9] @ vAA<- d2
5146 GOTO_OPCODE(ip) @ jump to next instruction
5149 /* ------------------------------ */
5151 .L_OP_SUB_DOUBLE: /* 0xac */
5152 /* File: arm-vfp/OP_SUB_DOUBLE.S */
5153 /* File: arm-vfp/fbinopWide.S */
5155 * Generic 64-bit double-precision floating point binary operation.
5156 * Provide an "instr" line that specifies an instruction that performs
5159 * for: add-double, sub-double, mul-double, div-double
5161 /* doubleop vAA, vBB, vCC */
5162 FETCH(r0, 1) @ r0<- CCBB
5163 mov r9, rINST, lsr #8 @ r9<- AA
5164 mov r3, r0, lsr #8 @ r3<- CC
5165 and r2, r0, #255 @ r2<- BB
5166 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5167 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5168 fldd d1, [r3] @ d1<- vCC
5169 fldd d0, [r2] @ d0<- vBB
5171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5172 fsubd d2, d0, d1 @ s2<- op
5173 GET_INST_OPCODE(ip) @ extract opcode from rINST
5174 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5175 fstd d2, [r9] @ vAA<- d2
5176 GOTO_OPCODE(ip) @ jump to next instruction
5179 /* ------------------------------ */
5181 .L_OP_MUL_DOUBLE: /* 0xad */
5182 /* File: arm-vfp/OP_MUL_DOUBLE.S */
5183 /* File: arm-vfp/fbinopWide.S */
5185 * Generic 64-bit double-precision floating point binary operation.
5186 * Provide an "instr" line that specifies an instruction that performs
5189 * for: add-double, sub-double, mul-double, div-double
5191 /* doubleop vAA, vBB, vCC */
5192 FETCH(r0, 1) @ r0<- CCBB
5193 mov r9, rINST, lsr #8 @ r9<- AA
5194 mov r3, r0, lsr #8 @ r3<- CC
5195 and r2, r0, #255 @ r2<- BB
5196 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5197 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5198 fldd d1, [r3] @ d1<- vCC
5199 fldd d0, [r2] @ d0<- vBB
5201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5202 fmuld d2, d0, d1 @ s2<- op
5203 GET_INST_OPCODE(ip) @ extract opcode from rINST
5204 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5205 fstd d2, [r9] @ vAA<- d2
5206 GOTO_OPCODE(ip) @ jump to next instruction
5209 /* ------------------------------ */
5211 .L_OP_DIV_DOUBLE: /* 0xae */
5212 /* File: arm-vfp/OP_DIV_DOUBLE.S */
5213 /* File: arm-vfp/fbinopWide.S */
5215 * Generic 64-bit double-precision floating point binary operation.
5216 * Provide an "instr" line that specifies an instruction that performs
5219 * for: add-double, sub-double, mul-double, div-double
5221 /* doubleop vAA, vBB, vCC */
5222 FETCH(r0, 1) @ r0<- CCBB
5223 mov r9, rINST, lsr #8 @ r9<- AA
5224 mov r3, r0, lsr #8 @ r3<- CC
5225 and r2, r0, #255 @ r2<- BB
5226 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5227 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5228 fldd d1, [r3] @ d1<- vCC
5229 fldd d0, [r2] @ d0<- vBB
5231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5232 fdivd d2, d0, d1 @ s2<- op
5233 GET_INST_OPCODE(ip) @ extract opcode from rINST
5234 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5235 fstd d2, [r9] @ vAA<- d2
5236 GOTO_OPCODE(ip) @ jump to next instruction
5239 /* ------------------------------ */
5241 .L_OP_REM_DOUBLE: /* 0xaf */
5242 /* File: armv5te/OP_REM_DOUBLE.S */
5243 /* EABI doesn't define a double remainder function, but libm does */
5244 /* File: armv5te/binopWide.S */
5246 * Generic 64-bit binary operation. Provide an "instr" line that
5247 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5248 * This could be an ARM instruction or a function call. (If the result
5249 * comes back in a register other than r0, you can override "result".)
5251 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5252 * vCC (r1). Useful for integer division and modulus.
5254 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5255 * xor-long, add-double, sub-double, mul-double, div-double,
5258 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5260 /* binop vAA, vBB, vCC */
5261 FETCH(r0, 1) @ r0<- CCBB
5262 mov r9, rINST, lsr #8 @ r9<- AA
5263 and r2, r0, #255 @ r2<- BB
5264 mov r3, r0, lsr #8 @ r3<- CC
5265 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5266 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5267 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5268 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5269 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5271 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5272 beq common_errDivideByZero
5274 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5276 @ optional op; may set condition codes
5277 bl fmod @ result<- op, r0-r3 changed
5278 GET_INST_OPCODE(ip) @ extract opcode from rINST
5279 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5280 GOTO_OPCODE(ip) @ jump to next instruction
5281 /* 14-17 instructions */
5285 /* ------------------------------ */
5287 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5288 /* File: armv6t2/OP_ADD_INT_2ADDR.S */
5289 /* File: armv6t2/binop2addr.S */
5291 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5292 * that specifies an instruction that performs "result = r0 op r1".
5293 * This could be an ARM instruction or a function call. (If the result
5294 * comes back in a register other than r0, you can override "result".)
5296 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5297 * vCC (r1). Useful for integer division and modulus.
5299 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5300 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5301 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5302 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5304 /* binop/2addr vA, vB */
5305 mov r3, rINST, lsr #12 @ r3<- B
5306 ubfx r9, rINST, #8, #4 @ r9<- A
5307 GET_VREG(r1, r3) @ r1<- vB
5308 GET_VREG(r0, r9) @ r0<- vA
5310 cmp r1, #0 @ is second operand zero?
5311 beq common_errDivideByZero
5313 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5315 @ optional op; may set condition codes
5316 add r0, r0, r1 @ r0<- op, r0-r3 changed
5317 GET_INST_OPCODE(ip) @ extract opcode from rINST
5318 SET_VREG(r0, r9) @ vAA<- r0
5319 GOTO_OPCODE(ip) @ jump to next instruction
5320 /* 10-13 instructions */
5324 /* ------------------------------ */
5326 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5327 /* File: armv6t2/OP_SUB_INT_2ADDR.S */
5328 /* File: armv6t2/binop2addr.S */
5330 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5331 * that specifies an instruction that performs "result = r0 op r1".
5332 * This could be an ARM instruction or a function call. (If the result
5333 * comes back in a register other than r0, you can override "result".)
5335 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5336 * vCC (r1). Useful for integer division and modulus.
5338 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5339 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5340 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5341 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5343 /* binop/2addr vA, vB */
5344 mov r3, rINST, lsr #12 @ r3<- B
5345 ubfx r9, rINST, #8, #4 @ r9<- A
5346 GET_VREG(r1, r3) @ r1<- vB
5347 GET_VREG(r0, r9) @ r0<- vA
5349 cmp r1, #0 @ is second operand zero?
5350 beq common_errDivideByZero
5352 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5354 @ optional op; may set condition codes
5355 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5356 GET_INST_OPCODE(ip) @ extract opcode from rINST
5357 SET_VREG(r0, r9) @ vAA<- r0
5358 GOTO_OPCODE(ip) @ jump to next instruction
5359 /* 10-13 instructions */
5363 /* ------------------------------ */
5365 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5366 /* File: armv6t2/OP_MUL_INT_2ADDR.S */
5367 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5368 /* File: armv6t2/binop2addr.S */
5370 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5371 * that specifies an instruction that performs "result = r0 op r1".
5372 * This could be an ARM instruction or a function call. (If the result
5373 * comes back in a register other than r0, you can override "result".)
5375 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5376 * vCC (r1). Useful for integer division and modulus.
5378 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5379 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5380 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5381 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5383 /* binop/2addr vA, vB */
5384 mov r3, rINST, lsr #12 @ r3<- B
5385 ubfx r9, rINST, #8, #4 @ r9<- A
5386 GET_VREG(r1, r3) @ r1<- vB
5387 GET_VREG(r0, r9) @ r0<- vA
5389 cmp r1, #0 @ is second operand zero?
5390 beq common_errDivideByZero
5392 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5394 @ optional op; may set condition codes
5395 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5396 GET_INST_OPCODE(ip) @ extract opcode from rINST
5397 SET_VREG(r0, r9) @ vAA<- r0
5398 GOTO_OPCODE(ip) @ jump to next instruction
5399 /* 10-13 instructions */
5403 /* ------------------------------ */
5405 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5406 /* File: armv6t2/OP_DIV_INT_2ADDR.S */
5407 /* File: armv6t2/binop2addr.S */
5409 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5410 * that specifies an instruction that performs "result = r0 op r1".
5411 * This could be an ARM instruction or a function call. (If the result
5412 * comes back in a register other than r0, you can override "result".)
5414 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5415 * vCC (r1). Useful for integer division and modulus.
5417 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5418 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5419 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5420 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5422 /* binop/2addr vA, vB */
5423 mov r3, rINST, lsr #12 @ r3<- B
5424 ubfx r9, rINST, #8, #4 @ r9<- A
5425 GET_VREG(r1, r3) @ r1<- vB
5426 GET_VREG(r0, r9) @ r0<- vA
5428 cmp r1, #0 @ is second operand zero?
5429 beq common_errDivideByZero
5431 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5433 @ optional op; may set condition codes
5434 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5435 GET_INST_OPCODE(ip) @ extract opcode from rINST
5436 SET_VREG(r0, r9) @ vAA<- r0
5437 GOTO_OPCODE(ip) @ jump to next instruction
5438 /* 10-13 instructions */
5442 /* ------------------------------ */
5444 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5445 /* File: armv6t2/OP_REM_INT_2ADDR.S */
5446 /* idivmod returns quotient in r0 and remainder in r1 */
5447 /* File: armv6t2/binop2addr.S */
5449 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5450 * that specifies an instruction that performs "result = r0 op r1".
5451 * This could be an ARM instruction or a function call. (If the result
5452 * comes back in a register other than r0, you can override "result".)
5454 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5455 * vCC (r1). Useful for integer division and modulus.
5457 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5458 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5459 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5460 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5462 /* binop/2addr vA, vB */
5463 mov r3, rINST, lsr #12 @ r3<- B
5464 ubfx r9, rINST, #8, #4 @ r9<- A
5465 GET_VREG(r1, r3) @ r1<- vB
5466 GET_VREG(r0, r9) @ r0<- vA
5468 cmp r1, #0 @ is second operand zero?
5469 beq common_errDivideByZero
5471 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5473 @ optional op; may set condition codes
5474 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5475 GET_INST_OPCODE(ip) @ extract opcode from rINST
5476 SET_VREG(r1, r9) @ vAA<- r1
5477 GOTO_OPCODE(ip) @ jump to next instruction
5478 /* 10-13 instructions */
5482 /* ------------------------------ */
5484 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5485 /* File: armv6t2/OP_AND_INT_2ADDR.S */
5486 /* File: armv6t2/binop2addr.S */
5488 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5489 * that specifies an instruction that performs "result = r0 op r1".
5490 * This could be an ARM instruction or a function call. (If the result
5491 * comes back in a register other than r0, you can override "result".)
5493 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5494 * vCC (r1). Useful for integer division and modulus.
5496 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5497 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5498 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5499 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5501 /* binop/2addr vA, vB */
5502 mov r3, rINST, lsr #12 @ r3<- B
5503 ubfx r9, rINST, #8, #4 @ r9<- A
5504 GET_VREG(r1, r3) @ r1<- vB
5505 GET_VREG(r0, r9) @ r0<- vA
5507 cmp r1, #0 @ is second operand zero?
5508 beq common_errDivideByZero
5510 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5512 @ optional op; may set condition codes
5513 and r0, r0, r1 @ r0<- op, r0-r3 changed
5514 GET_INST_OPCODE(ip) @ extract opcode from rINST
5515 SET_VREG(r0, r9) @ vAA<- r0
5516 GOTO_OPCODE(ip) @ jump to next instruction
5517 /* 10-13 instructions */
5521 /* ------------------------------ */
5523 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5524 /* File: armv6t2/OP_OR_INT_2ADDR.S */
5525 /* File: armv6t2/binop2addr.S */
5527 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5528 * that specifies an instruction that performs "result = r0 op r1".
5529 * This could be an ARM instruction or a function call. (If the result
5530 * comes back in a register other than r0, you can override "result".)
5532 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5533 * vCC (r1). Useful for integer division and modulus.
5535 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5536 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5537 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5538 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5540 /* binop/2addr vA, vB */
5541 mov r3, rINST, lsr #12 @ r3<- B
5542 ubfx r9, rINST, #8, #4 @ r9<- A
5543 GET_VREG(r1, r3) @ r1<- vB
5544 GET_VREG(r0, r9) @ r0<- vA
5546 cmp r1, #0 @ is second operand zero?
5547 beq common_errDivideByZero
5549 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5551 @ optional op; may set condition codes
5552 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5553 GET_INST_OPCODE(ip) @ extract opcode from rINST
5554 SET_VREG(r0, r9) @ vAA<- r0
5555 GOTO_OPCODE(ip) @ jump to next instruction
5556 /* 10-13 instructions */
5560 /* ------------------------------ */
5562 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5563 /* File: armv6t2/OP_XOR_INT_2ADDR.S */
5564 /* File: armv6t2/binop2addr.S */
5566 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5567 * that specifies an instruction that performs "result = r0 op r1".
5568 * This could be an ARM instruction or a function call. (If the result
5569 * comes back in a register other than r0, you can override "result".)
5571 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572 * vCC (r1). Useful for integer division and modulus.
5574 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5579 /* binop/2addr vA, vB */
5580 mov r3, rINST, lsr #12 @ r3<- B
5581 ubfx r9, rINST, #8, #4 @ r9<- A
5582 GET_VREG(r1, r3) @ r1<- vB
5583 GET_VREG(r0, r9) @ r0<- vA
5585 cmp r1, #0 @ is second operand zero?
5586 beq common_errDivideByZero
5588 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5590 @ optional op; may set condition codes
5591 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5592 GET_INST_OPCODE(ip) @ extract opcode from rINST
5593 SET_VREG(r0, r9) @ vAA<- r0
5594 GOTO_OPCODE(ip) @ jump to next instruction
5595 /* 10-13 instructions */
5599 /* ------------------------------ */
5601 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5602 /* File: armv6t2/OP_SHL_INT_2ADDR.S */
5603 /* File: armv6t2/binop2addr.S */
5605 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5606 * that specifies an instruction that performs "result = r0 op r1".
5607 * This could be an ARM instruction or a function call. (If the result
5608 * comes back in a register other than r0, you can override "result".)
5610 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5611 * vCC (r1). Useful for integer division and modulus.
5613 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5614 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5615 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5616 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5618 /* binop/2addr vA, vB */
5619 mov r3, rINST, lsr #12 @ r3<- B
5620 ubfx r9, rINST, #8, #4 @ r9<- A
5621 GET_VREG(r1, r3) @ r1<- vB
5622 GET_VREG(r0, r9) @ r0<- vA
5624 cmp r1, #0 @ is second operand zero?
5625 beq common_errDivideByZero
5627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5629 and r1, r1, #31 @ optional op; may set condition codes
5630 mov r0, r0, asl 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 */
5638 /* ------------------------------ */
5640 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5641 /* File: armv6t2/OP_SHR_INT_2ADDR.S */
5642 /* File: armv6t2/binop2addr.S */
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".)
5649 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5650 * vCC (r1). Useful for integer division and modulus.
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
5657 /* binop/2addr vA, vB */
5658 mov r3, rINST, lsr #12 @ r3<- B
5659 ubfx r9, rINST, #8, #4 @ r9<- A
5660 GET_VREG(r1, r3) @ r1<- vB
5661 GET_VREG(r0, r9) @ r0<- vA
5663 cmp r1, #0 @ is second operand zero?
5664 beq common_errDivideByZero
5666 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5668 and r1, r1, #31 @ optional op; may set condition codes
5669 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
5670 GET_INST_OPCODE(ip) @ extract opcode from rINST
5671 SET_VREG(r0, r9) @ vAA<- r0
5672 GOTO_OPCODE(ip) @ jump to next instruction
5673 /* 10-13 instructions */
5677 /* ------------------------------ */
5679 .L_OP_USHR_INT_2ADDR: /* 0xba */
5680 /* File: armv6t2/OP_USHR_INT_2ADDR.S */
5681 /* File: armv6t2/binop2addr.S */
5683 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5684 * that specifies an instruction that performs "result = r0 op r1".
5685 * This could be an ARM instruction or a function call. (If the result
5686 * comes back in a register other than r0, you can override "result".)
5688 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5689 * vCC (r1). Useful for integer division and modulus.
5691 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5692 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5693 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5694 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5696 /* binop/2addr vA, vB */
5697 mov r3, rINST, lsr #12 @ r3<- B
5698 ubfx r9, rINST, #8, #4 @ r9<- A
5699 GET_VREG(r1, r3) @ r1<- vB
5700 GET_VREG(r0, r9) @ r0<- vA
5702 cmp r1, #0 @ is second operand zero?
5703 beq common_errDivideByZero
5705 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5707 and r1, r1, #31 @ optional op; may set condition codes
5708 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
5709 GET_INST_OPCODE(ip) @ extract opcode from rINST
5710 SET_VREG(r0, r9) @ vAA<- r0
5711 GOTO_OPCODE(ip) @ jump to next instruction
5712 /* 10-13 instructions */
5716 /* ------------------------------ */
5718 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5719 /* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5720 /* File: armv6t2/binopWide2addr.S */
5722 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5723 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5724 * This could be an ARM instruction or a function call. (If the result
5725 * comes back in a register other than r0, you can override "result".)
5727 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5728 * vCC (r1). Useful for integer division and modulus.
5730 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5731 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5732 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5735 /* binop/2addr vA, vB */
5736 mov r1, rINST, lsr #12 @ r1<- B
5737 ubfx r9, rINST, #8, #4 @ r9<- A
5738 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5739 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5740 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5741 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5743 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5744 beq common_errDivideByZero
5746 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5748 adds r0, r0, r2 @ optional op; may set condition codes
5749 adc r1, r1, r3 @ result<- op, r0-r3 changed
5750 GET_INST_OPCODE(ip) @ extract opcode from rINST
5751 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5752 GOTO_OPCODE(ip) @ jump to next instruction
5753 /* 12-15 instructions */
5757 /* ------------------------------ */
5759 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5760 /* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5761 /* File: armv6t2/binopWide2addr.S */
5763 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5764 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5765 * This could be an ARM instruction or a function call. (If the result
5766 * comes back in a register other than r0, you can override "result".)
5768 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5769 * vCC (r1). Useful for integer division and modulus.
5771 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5772 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5773 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5776 /* binop/2addr vA, vB */
5777 mov r1, rINST, lsr #12 @ r1<- B
5778 ubfx r9, rINST, #8, #4 @ r9<- A
5779 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5780 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5781 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5782 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5784 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5785 beq common_errDivideByZero
5787 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5789 subs r0, r0, r2 @ optional op; may set condition codes
5790 sbc r1, r1, r3 @ result<- op, r0-r3 changed
5791 GET_INST_OPCODE(ip) @ extract opcode from rINST
5792 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5793 GOTO_OPCODE(ip) @ jump to next instruction
5794 /* 12-15 instructions */
5798 /* ------------------------------ */
5800 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5801 /* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5803 * Signed 64-bit integer multiply, "/2addr" version.
5805 * See OP_MUL_LONG for an explanation.
5807 * We get a little tight on registers, so to avoid looking up &fp[A]
5808 * again we stuff it into rINST.
5810 /* mul-long/2addr vA, vB */
5811 mov r1, rINST, lsr #12 @ r1<- B
5812 ubfx r9, rINST, #8, #4 @ r9<- A
5813 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5814 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
5815 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5816 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
5817 mul ip, r2, r1 @ ip<- ZxW
5818 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
5819 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
5820 mov r0, rINST @ r0<- &fp[A] (free up rINST)
5821 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5822 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
5823 GET_INST_OPCODE(ip) @ extract opcode from rINST
5824 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
5825 GOTO_OPCODE(ip) @ jump to next instruction
5828 /* ------------------------------ */
5830 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5831 /* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5832 /* File: armv6t2/binopWide2addr.S */
5834 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5835 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5836 * This could be an ARM instruction or a function call. (If the result
5837 * comes back in a register other than r0, you can override "result".)
5839 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5840 * vCC (r1). Useful for integer division and modulus.
5842 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5843 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5844 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5847 /* binop/2addr vA, vB */
5848 mov r1, rINST, lsr #12 @ r1<- B
5849 ubfx r9, rINST, #8, #4 @ r9<- A
5850 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5851 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5852 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5853 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5855 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5856 beq common_errDivideByZero
5858 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5860 @ optional op; may set condition codes
5861 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5862 GET_INST_OPCODE(ip) @ extract opcode from rINST
5863 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5864 GOTO_OPCODE(ip) @ jump to next instruction
5865 /* 12-15 instructions */
5869 /* ------------------------------ */
5871 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5872 /* File: armv6t2/OP_REM_LONG_2ADDR.S */
5873 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5874 /* File: armv6t2/binopWide2addr.S */
5876 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5877 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5878 * This could be an ARM instruction or a function call. (If the result
5879 * comes back in a register other than r0, you can override "result".)
5881 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5882 * vCC (r1). Useful for integer division and modulus.
5884 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5885 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5886 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5889 /* binop/2addr vA, vB */
5890 mov r1, rINST, lsr #12 @ r1<- B
5891 ubfx r9, rINST, #8, #4 @ r9<- A
5892 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5893 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5894 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5895 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5897 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5898 beq common_errDivideByZero
5900 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5902 @ optional op; may set condition codes
5903 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5904 GET_INST_OPCODE(ip) @ extract opcode from rINST
5905 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
5906 GOTO_OPCODE(ip) @ jump to next instruction
5907 /* 12-15 instructions */
5911 /* ------------------------------ */
5913 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
5914 /* File: armv6t2/OP_AND_LONG_2ADDR.S */
5915 /* File: armv6t2/binopWide2addr.S */
5917 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5918 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5919 * This could be an ARM instruction or a function call. (If the result
5920 * comes back in a register other than r0, you can override "result".)
5922 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5923 * vCC (r1). Useful for integer division and modulus.
5925 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5926 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5927 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5930 /* binop/2addr vA, vB */
5931 mov r1, rINST, lsr #12 @ r1<- B
5932 ubfx r9, rINST, #8, #4 @ r9<- A
5933 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5934 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5935 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5936 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5938 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5939 beq common_errDivideByZero
5941 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5943 and r0, r0, r2 @ optional op; may set condition codes
5944 and r1, r1, r3 @ result<- op, r0-r3 changed
5945 GET_INST_OPCODE(ip) @ extract opcode from rINST
5946 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5947 GOTO_OPCODE(ip) @ jump to next instruction
5948 /* 12-15 instructions */
5952 /* ------------------------------ */
5954 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
5955 /* File: armv6t2/OP_OR_LONG_2ADDR.S */
5956 /* File: armv6t2/binopWide2addr.S */
5958 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5959 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5960 * This could be an ARM instruction or a function call. (If the result
5961 * comes back in a register other than r0, you can override "result".)
5963 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5964 * vCC (r1). Useful for integer division and modulus.
5966 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5967 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5968 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5971 /* binop/2addr vA, vB */
5972 mov r1, rINST, lsr #12 @ r1<- B
5973 ubfx r9, rINST, #8, #4 @ r9<- A
5974 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5975 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5976 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5977 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5979 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5980 beq common_errDivideByZero
5982 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5984 orr r0, r0, r2 @ optional op; may set condition codes
5985 orr r1, r1, r3 @ result<- op, r0-r3 changed
5986 GET_INST_OPCODE(ip) @ extract opcode from rINST
5987 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5988 GOTO_OPCODE(ip) @ jump to next instruction
5989 /* 12-15 instructions */
5993 /* ------------------------------ */
5995 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5996 /* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5997 /* File: armv6t2/binopWide2addr.S */
5999 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6000 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6001 * This could be an ARM instruction or a function call. (If the result
6002 * comes back in a register other than r0, you can override "result".)
6004 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6005 * vCC (r1). Useful for integer division and modulus.
6007 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6008 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6009 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6012 /* binop/2addr vA, vB */
6013 mov r1, rINST, lsr #12 @ r1<- B
6014 ubfx r9, rINST, #8, #4 @ r9<- A
6015 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6016 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6017 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6018 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6020 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6021 beq common_errDivideByZero
6023 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6025 eor r0, r0, r2 @ optional op; may set condition codes
6026 eor r1, r1, r3 @ result<- op, r0-r3 changed
6027 GET_INST_OPCODE(ip) @ extract opcode from rINST
6028 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6029 GOTO_OPCODE(ip) @ jump to next instruction
6030 /* 12-15 instructions */
6034 /* ------------------------------ */
6036 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6037 /* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6039 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6040 * 32-bit shift distance.
6042 /* shl-long/2addr vA, vB */
6043 mov r3, rINST, lsr #12 @ r3<- B
6044 ubfx r9, rINST, #8, #4 @ r9<- A
6045 GET_VREG(r2, r3) @ r2<- vB
6046 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6047 and r2, r2, #63 @ r2<- r2 & 0x3f
6048 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6050 mov r1, r1, asl r2 @ r1<- r1 << r2
6051 rsb r3, r2, #32 @ r3<- 32 - r2
6052 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6053 subs ip, r2, #32 @ ip<- r2 - 32
6054 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6055 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6056 mov r0, r0, asl r2 @ r0<- r0 << r2
6057 b .LOP_SHL_LONG_2ADDR_finish
6059 /* ------------------------------ */
6061 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6062 /* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6064 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6065 * 32-bit shift distance.
6067 /* shr-long/2addr vA, vB */
6068 mov r3, rINST, lsr #12 @ r3<- B
6069 ubfx r9, rINST, #8, #4 @ r9<- A
6070 GET_VREG(r2, r3) @ r2<- vB
6071 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6072 and r2, r2, #63 @ r2<- r2 & 0x3f
6073 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6075 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6076 rsb r3, r2, #32 @ r3<- 32 - r2
6077 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6078 subs ip, r2, #32 @ ip<- r2 - 32
6079 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6080 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6081 mov r1, r1, asr r2 @ r1<- r1 >> r2
6082 b .LOP_SHR_LONG_2ADDR_finish
6084 /* ------------------------------ */
6086 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6087 /* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6089 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6090 * 32-bit shift distance.
6092 /* ushr-long/2addr vA, vB */
6093 mov r3, rINST, lsr #12 @ r3<- B
6094 ubfx r9, rINST, #8, #4 @ r9<- A
6095 GET_VREG(r2, r3) @ r2<- vB
6096 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6097 and r2, r2, #63 @ r2<- r2 & 0x3f
6098 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6100 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6101 rsb r3, r2, #32 @ r3<- 32 - r2
6102 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6103 subs ip, r2, #32 @ ip<- r2 - 32
6104 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6105 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6106 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6107 b .LOP_USHR_LONG_2ADDR_finish
6109 /* ------------------------------ */
6111 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6112 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6113 /* File: arm-vfp/fbinop2addr.S */
6115 * Generic 32-bit floating point "/2addr" binary operation. Provide
6116 * an "instr" line that specifies an instruction that performs
6119 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6121 /* binop/2addr vA, vB */
6122 mov r3, rINST, lsr #12 @ r3<- B
6123 mov r9, rINST, lsr #8 @ r9<- A+
6124 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6125 and r9, r9, #15 @ r9<- A
6126 flds s1, [r3] @ s1<- vB
6127 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6128 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6129 flds s0, [r9] @ s0<- vA
6131 fadds s2, s0, s1 @ s2<- op
6132 GET_INST_OPCODE(ip) @ extract opcode from rINST
6133 fsts s2, [r9] @ vAA<- s2
6134 GOTO_OPCODE(ip) @ jump to next instruction
6137 /* ------------------------------ */
6139 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6140 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6141 /* File: arm-vfp/fbinop2addr.S */
6143 * Generic 32-bit floating point "/2addr" binary operation. Provide
6144 * an "instr" line that specifies an instruction that performs
6147 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6149 /* binop/2addr vA, vB */
6150 mov r3, rINST, lsr #12 @ r3<- B
6151 mov r9, rINST, lsr #8 @ r9<- A+
6152 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6153 and r9, r9, #15 @ r9<- A
6154 flds s1, [r3] @ s1<- vB
6155 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6156 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6157 flds s0, [r9] @ s0<- vA
6159 fsubs s2, s0, s1 @ s2<- op
6160 GET_INST_OPCODE(ip) @ extract opcode from rINST
6161 fsts s2, [r9] @ vAA<- s2
6162 GOTO_OPCODE(ip) @ jump to next instruction
6165 /* ------------------------------ */
6167 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6168 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6169 /* File: arm-vfp/fbinop2addr.S */
6171 * Generic 32-bit floating point "/2addr" binary operation. Provide
6172 * an "instr" line that specifies an instruction that performs
6175 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6177 /* binop/2addr vA, vB */
6178 mov r3, rINST, lsr #12 @ r3<- B
6179 mov r9, rINST, lsr #8 @ r9<- A+
6180 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6181 and r9, r9, #15 @ r9<- A
6182 flds s1, [r3] @ s1<- vB
6183 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6184 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6185 flds s0, [r9] @ s0<- vA
6187 fmuls s2, s0, s1 @ s2<- op
6188 GET_INST_OPCODE(ip) @ extract opcode from rINST
6189 fsts s2, [r9] @ vAA<- s2
6190 GOTO_OPCODE(ip) @ jump to next instruction
6193 /* ------------------------------ */
6195 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6196 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6197 /* File: arm-vfp/fbinop2addr.S */
6199 * Generic 32-bit floating point "/2addr" binary operation. Provide
6200 * an "instr" line that specifies an instruction that performs
6203 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6205 /* binop/2addr vA, vB */
6206 mov r3, rINST, lsr #12 @ r3<- B
6207 mov r9, rINST, lsr #8 @ r9<- A+
6208 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6209 and r9, r9, #15 @ r9<- A
6210 flds s1, [r3] @ s1<- vB
6211 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6212 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6213 flds s0, [r9] @ s0<- vA
6215 fdivs s2, s0, s1 @ s2<- op
6216 GET_INST_OPCODE(ip) @ extract opcode from rINST
6217 fsts s2, [r9] @ vAA<- s2
6218 GOTO_OPCODE(ip) @ jump to next instruction
6221 /* ------------------------------ */
6223 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6224 /* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6225 /* EABI doesn't define a float remainder function, but libm does */
6226 /* File: armv6t2/binop2addr.S */
6228 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6229 * that specifies an instruction that performs "result = r0 op r1".
6230 * This could be an ARM instruction or a function call. (If the result
6231 * comes back in a register other than r0, you can override "result".)
6233 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6234 * vCC (r1). Useful for integer division and modulus.
6236 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6237 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6238 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6239 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6241 /* binop/2addr vA, vB */
6242 mov r3, rINST, lsr #12 @ r3<- B
6243 ubfx r9, rINST, #8, #4 @ r9<- A
6244 GET_VREG(r1, r3) @ r1<- vB
6245 GET_VREG(r0, r9) @ r0<- vA
6247 cmp r1, #0 @ is second operand zero?
6248 beq common_errDivideByZero
6250 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6252 @ optional op; may set condition codes
6253 bl fmodf @ r0<- op, r0-r3 changed
6254 GET_INST_OPCODE(ip) @ extract opcode from rINST
6255 SET_VREG(r0, r9) @ vAA<- r0
6256 GOTO_OPCODE(ip) @ jump to next instruction
6257 /* 10-13 instructions */
6261 /* ------------------------------ */
6263 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6264 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6265 /* File: arm-vfp/fbinopWide2addr.S */
6267 * Generic 64-bit floating point "/2addr" binary operation. Provide
6268 * an "instr" line that specifies an instruction that performs
6271 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6274 /* binop/2addr vA, vB */
6275 mov r3, rINST, lsr #12 @ r3<- B
6276 mov r9, rINST, lsr #8 @ r9<- A+
6277 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6278 and r9, r9, #15 @ r9<- A
6279 fldd d1, [r3] @ d1<- vB
6280 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6281 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6282 fldd d0, [r9] @ d0<- vA
6284 faddd d2, d0, d1 @ d2<- op
6285 GET_INST_OPCODE(ip) @ extract opcode from rINST
6286 fstd d2, [r9] @ vAA<- d2
6287 GOTO_OPCODE(ip) @ jump to next instruction
6290 /* ------------------------------ */
6292 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6293 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6294 /* File: arm-vfp/fbinopWide2addr.S */
6296 * Generic 64-bit floating point "/2addr" binary operation. Provide
6297 * an "instr" line that specifies an instruction that performs
6300 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6303 /* binop/2addr vA, vB */
6304 mov r3, rINST, lsr #12 @ r3<- B
6305 mov r9, rINST, lsr #8 @ r9<- A+
6306 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6307 and r9, r9, #15 @ r9<- A
6308 fldd d1, [r3] @ d1<- vB
6309 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6310 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6311 fldd d0, [r9] @ d0<- vA
6313 fsubd d2, d0, d1 @ d2<- op
6314 GET_INST_OPCODE(ip) @ extract opcode from rINST
6315 fstd d2, [r9] @ vAA<- d2
6316 GOTO_OPCODE(ip) @ jump to next instruction
6319 /* ------------------------------ */
6321 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6322 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6323 /* File: arm-vfp/fbinopWide2addr.S */
6325 * Generic 64-bit floating point "/2addr" binary operation. Provide
6326 * an "instr" line that specifies an instruction that performs
6329 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6332 /* binop/2addr vA, vB */
6333 mov r3, rINST, lsr #12 @ r3<- B
6334 mov r9, rINST, lsr #8 @ r9<- A+
6335 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6336 and r9, r9, #15 @ r9<- A
6337 fldd d1, [r3] @ d1<- vB
6338 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6339 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6340 fldd d0, [r9] @ d0<- vA
6342 fmuld d2, d0, d1 @ d2<- op
6343 GET_INST_OPCODE(ip) @ extract opcode from rINST
6344 fstd d2, [r9] @ vAA<- d2
6345 GOTO_OPCODE(ip) @ jump to next instruction
6348 /* ------------------------------ */
6350 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6351 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6352 /* File: arm-vfp/fbinopWide2addr.S */
6354 * Generic 64-bit floating point "/2addr" binary operation. Provide
6355 * an "instr" line that specifies an instruction that performs
6358 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6361 /* binop/2addr vA, vB */
6362 mov r3, rINST, lsr #12 @ r3<- B
6363 mov r9, rINST, lsr #8 @ r9<- A+
6364 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6365 and r9, r9, #15 @ r9<- A
6366 fldd d1, [r3] @ d1<- vB
6367 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6368 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6369 fldd d0, [r9] @ d0<- vA
6371 fdivd d2, d0, d1 @ d2<- op
6372 GET_INST_OPCODE(ip) @ extract opcode from rINST
6373 fstd d2, [r9] @ vAA<- d2
6374 GOTO_OPCODE(ip) @ jump to next instruction
6377 /* ------------------------------ */
6379 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6380 /* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6381 /* EABI doesn't define a double remainder function, but libm does */
6382 /* File: armv6t2/binopWide2addr.S */
6384 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6385 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6386 * This could be an ARM instruction or a function call. (If the result
6387 * comes back in a register other than r0, you can override "result".)
6389 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6390 * vCC (r1). Useful for integer division and modulus.
6392 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6393 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6394 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6397 /* binop/2addr vA, vB */
6398 mov r1, rINST, lsr #12 @ r1<- B
6399 ubfx r9, rINST, #8, #4 @ r9<- A
6400 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6401 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6402 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6403 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6405 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6406 beq common_errDivideByZero
6408 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6410 @ optional op; may set condition codes
6411 bl fmod @ result<- op, r0-r3 changed
6412 GET_INST_OPCODE(ip) @ extract opcode from rINST
6413 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6414 GOTO_OPCODE(ip) @ jump to next instruction
6415 /* 12-15 instructions */
6419 /* ------------------------------ */
6421 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6422 /* File: armv6t2/OP_ADD_INT_LIT16.S */
6423 /* File: armv6t2/binopLit16.S */
6425 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6426 * that specifies an instruction that performs "result = r0 op r1".
6427 * This could be an ARM instruction or a function call. (If the result
6428 * comes back in a register other than r0, you can override "result".)
6430 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6431 * vCC (r1). Useful for integer division and modulus.
6433 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6434 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6436 /* binop/lit16 vA, vB, #+CCCC */
6437 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6438 mov r2, rINST, lsr #12 @ r2<- B
6439 ubfx r9, rINST, #8, #4 @ r9<- A
6440 GET_VREG(r0, r2) @ r0<- vB
6442 cmp r1, #0 @ is second operand zero?
6443 beq common_errDivideByZero
6445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6447 add r0, r0, r1 @ r0<- op, r0-r3 changed
6448 GET_INST_OPCODE(ip) @ extract opcode from rINST
6449 SET_VREG(r0, r9) @ vAA<- r0
6450 GOTO_OPCODE(ip) @ jump to next instruction
6451 /* 10-13 instructions */
6455 /* ------------------------------ */
6457 .L_OP_RSUB_INT: /* 0xd1 */
6458 /* File: armv6t2/OP_RSUB_INT.S */
6459 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6460 /* File: armv6t2/binopLit16.S */
6462 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6463 * that specifies an instruction that performs "result = r0 op r1".
6464 * This could be an ARM instruction or a function call. (If the result
6465 * comes back in a register other than r0, you can override "result".)
6467 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6468 * vCC (r1). Useful for integer division and modulus.
6470 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6471 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6473 /* binop/lit16 vA, vB, #+CCCC */
6474 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6475 mov r2, rINST, lsr #12 @ r2<- B
6476 ubfx r9, rINST, #8, #4 @ r9<- A
6477 GET_VREG(r0, r2) @ r0<- vB
6479 cmp r1, #0 @ is second operand zero?
6480 beq common_errDivideByZero
6482 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6484 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6485 GET_INST_OPCODE(ip) @ extract opcode from rINST
6486 SET_VREG(r0, r9) @ vAA<- r0
6487 GOTO_OPCODE(ip) @ jump to next instruction
6488 /* 10-13 instructions */
6492 /* ------------------------------ */
6494 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6495 /* File: armv6t2/OP_MUL_INT_LIT16.S */
6496 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6497 /* File: armv6t2/binopLit16.S */
6499 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6500 * that specifies an instruction that performs "result = r0 op r1".
6501 * This could be an ARM instruction or a function call. (If the result
6502 * comes back in a register other than r0, you can override "result".)
6504 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6505 * vCC (r1). Useful for integer division and modulus.
6507 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6508 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6510 /* binop/lit16 vA, vB, #+CCCC */
6511 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6512 mov r2, rINST, lsr #12 @ r2<- B
6513 ubfx r9, rINST, #8, #4 @ r9<- A
6514 GET_VREG(r0, r2) @ r0<- vB
6516 cmp r1, #0 @ is second operand zero?
6517 beq common_errDivideByZero
6519 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6521 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6522 GET_INST_OPCODE(ip) @ extract opcode from rINST
6523 SET_VREG(r0, r9) @ vAA<- r0
6524 GOTO_OPCODE(ip) @ jump to next instruction
6525 /* 10-13 instructions */
6529 /* ------------------------------ */
6531 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6532 /* File: armv6t2/OP_DIV_INT_LIT16.S */
6533 /* File: armv6t2/binopLit16.S */
6535 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6536 * that specifies an instruction that performs "result = r0 op r1".
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".)
6540 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6541 * vCC (r1). Useful for integer division and modulus.
6543 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6544 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6546 /* binop/lit16 vA, vB, #+CCCC */
6547 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6548 mov r2, rINST, lsr #12 @ r2<- B
6549 ubfx r9, rINST, #8, #4 @ r9<- A
6550 GET_VREG(r0, r2) @ r0<- vB
6552 cmp r1, #0 @ is second operand zero?
6553 beq common_errDivideByZero
6555 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6557 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6558 GET_INST_OPCODE(ip) @ extract opcode from rINST
6559 SET_VREG(r0, r9) @ vAA<- r0
6560 GOTO_OPCODE(ip) @ jump to next instruction
6561 /* 10-13 instructions */
6565 /* ------------------------------ */
6567 .L_OP_REM_INT_LIT16: /* 0xd4 */
6568 /* File: armv6t2/OP_REM_INT_LIT16.S */
6569 /* idivmod returns quotient in r0 and remainder in r1 */
6570 /* File: armv6t2/binopLit16.S */
6572 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6573 * that specifies an instruction that performs "result = r0 op r1".
6574 * This could be an ARM instruction or a function call. (If the result
6575 * comes back in a register other than r0, you can override "result".)
6577 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6578 * vCC (r1). Useful for integer division and modulus.
6580 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6581 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6583 /* binop/lit16 vA, vB, #+CCCC */
6584 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6585 mov r2, rINST, lsr #12 @ r2<- B
6586 ubfx r9, rINST, #8, #4 @ r9<- A
6587 GET_VREG(r0, r2) @ r0<- vB
6589 cmp r1, #0 @ is second operand zero?
6590 beq common_errDivideByZero
6592 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6594 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6595 GET_INST_OPCODE(ip) @ extract opcode from rINST
6596 SET_VREG(r1, r9) @ vAA<- r1
6597 GOTO_OPCODE(ip) @ jump to next instruction
6598 /* 10-13 instructions */
6602 /* ------------------------------ */
6604 .L_OP_AND_INT_LIT16: /* 0xd5 */
6605 /* File: armv6t2/OP_AND_INT_LIT16.S */
6606 /* File: armv6t2/binopLit16.S */
6608 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6609 * that specifies an instruction that performs "result = r0 op r1".
6610 * This could be an ARM instruction or a function call. (If the result
6611 * comes back in a register other than r0, you can override "result".)
6613 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6614 * vCC (r1). Useful for integer division and modulus.
6616 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6617 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6619 /* binop/lit16 vA, vB, #+CCCC */
6620 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6621 mov r2, rINST, lsr #12 @ r2<- B
6622 ubfx r9, rINST, #8, #4 @ r9<- A
6623 GET_VREG(r0, r2) @ r0<- vB
6625 cmp r1, #0 @ is second operand zero?
6626 beq common_errDivideByZero
6628 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6630 and r0, r0, r1 @ r0<- op, r0-r3 changed
6631 GET_INST_OPCODE(ip) @ extract opcode from rINST
6632 SET_VREG(r0, r9) @ vAA<- r0
6633 GOTO_OPCODE(ip) @ jump to next instruction
6634 /* 10-13 instructions */
6638 /* ------------------------------ */
6640 .L_OP_OR_INT_LIT16: /* 0xd6 */
6641 /* File: armv6t2/OP_OR_INT_LIT16.S */
6642 /* File: armv6t2/binopLit16.S */
6644 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6645 * that specifies an instruction that performs "result = r0 op r1".
6646 * This could be an ARM instruction or a function call. (If the result
6647 * comes back in a register other than r0, you can override "result".)
6649 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6650 * vCC (r1). Useful for integer division and modulus.
6652 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6653 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6655 /* binop/lit16 vA, vB, #+CCCC */
6656 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6657 mov r2, rINST, lsr #12 @ r2<- B
6658 ubfx r9, rINST, #8, #4 @ r9<- A
6659 GET_VREG(r0, r2) @ r0<- vB
6661 cmp r1, #0 @ is second operand zero?
6662 beq common_errDivideByZero
6664 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6666 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6667 GET_INST_OPCODE(ip) @ extract opcode from rINST
6668 SET_VREG(r0, r9) @ vAA<- r0
6669 GOTO_OPCODE(ip) @ jump to next instruction
6670 /* 10-13 instructions */
6674 /* ------------------------------ */
6676 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6677 /* File: armv6t2/OP_XOR_INT_LIT16.S */
6678 /* File: armv6t2/binopLit16.S */
6680 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6681 * that specifies an instruction that performs "result = r0 op r1".
6682 * This could be an ARM instruction or a function call. (If the result
6683 * comes back in a register other than r0, you can override "result".)
6685 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6686 * vCC (r1). Useful for integer division and modulus.
6688 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6689 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6691 /* binop/lit16 vA, vB, #+CCCC */
6692 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6693 mov r2, rINST, lsr #12 @ r2<- B
6694 ubfx r9, rINST, #8, #4 @ r9<- A
6695 GET_VREG(r0, r2) @ r0<- vB
6697 cmp r1, #0 @ is second operand zero?
6698 beq common_errDivideByZero
6700 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6702 eor r0, r0, r1 @ r0<- op, r0-r3 changed
6703 GET_INST_OPCODE(ip) @ extract opcode from rINST
6704 SET_VREG(r0, r9) @ vAA<- r0
6705 GOTO_OPCODE(ip) @ jump to next instruction
6706 /* 10-13 instructions */
6710 /* ------------------------------ */
6712 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6713 /* File: armv5te/OP_ADD_INT_LIT8.S */
6714 /* File: armv5te/binopLit8.S */
6716 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6717 * that specifies an instruction that performs "result = r0 op r1".
6718 * This could be an ARM instruction or a function call. (If the result
6719 * comes back in a register other than r0, you can override "result".)
6721 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6722 * vCC (r1). Useful for integer division and modulus.
6724 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6725 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6726 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6728 /* binop/lit8 vAA, vBB, #+CC */
6729 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6730 mov r9, rINST, lsr #8 @ r9<- AA
6731 and r2, r3, #255 @ r2<- BB
6732 GET_VREG(r0, r2) @ r0<- vBB
6733 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6735 @cmp r1, #0 @ is second operand zero?
6736 beq common_errDivideByZero
6738 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6740 @ optional op; may set condition codes
6741 add r0, r0, r1 @ r0<- op, r0-r3 changed
6742 GET_INST_OPCODE(ip) @ extract opcode from rINST
6743 SET_VREG(r0, r9) @ vAA<- r0
6744 GOTO_OPCODE(ip) @ jump to next instruction
6745 /* 10-12 instructions */
6749 /* ------------------------------ */
6751 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6752 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6753 /* File: armv5te/binopLit8.S */
6755 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6756 * that specifies an instruction that performs "result = r0 op r1".
6757 * This could be an ARM instruction or a function call. (If the result
6758 * comes back in a register other than r0, you can override "result".)
6760 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6761 * vCC (r1). Useful for integer division and modulus.
6763 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6764 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6765 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6767 /* binop/lit8 vAA, vBB, #+CC */
6768 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6769 mov r9, rINST, lsr #8 @ r9<- AA
6770 and r2, r3, #255 @ r2<- BB
6771 GET_VREG(r0, r2) @ r0<- vBB
6772 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6774 @cmp r1, #0 @ is second operand zero?
6775 beq common_errDivideByZero
6777 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6779 @ optional op; may set condition codes
6780 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6781 GET_INST_OPCODE(ip) @ extract opcode from rINST
6782 SET_VREG(r0, r9) @ vAA<- r0
6783 GOTO_OPCODE(ip) @ jump to next instruction
6784 /* 10-12 instructions */
6788 /* ------------------------------ */
6790 .L_OP_MUL_INT_LIT8: /* 0xda */
6791 /* File: armv5te/OP_MUL_INT_LIT8.S */
6792 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6793 /* File: armv5te/binopLit8.S */
6795 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6796 * that specifies an instruction that performs "result = r0 op r1".
6797 * This could be an ARM instruction or a function call. (If the result
6798 * comes back in a register other than r0, you can override "result".)
6800 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6801 * vCC (r1). Useful for integer division and modulus.
6803 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6804 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6805 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6807 /* binop/lit8 vAA, vBB, #+CC */
6808 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6809 mov r9, rINST, lsr #8 @ r9<- AA
6810 and r2, r3, #255 @ r2<- BB
6811 GET_VREG(r0, r2) @ r0<- vBB
6812 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6814 @cmp r1, #0 @ is second operand zero?
6815 beq common_errDivideByZero
6817 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6819 @ optional op; may set condition codes
6820 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6821 GET_INST_OPCODE(ip) @ extract opcode from rINST
6822 SET_VREG(r0, r9) @ vAA<- r0
6823 GOTO_OPCODE(ip) @ jump to next instruction
6824 /* 10-12 instructions */
6828 /* ------------------------------ */
6830 .L_OP_DIV_INT_LIT8: /* 0xdb */
6831 /* File: armv5te/OP_DIV_INT_LIT8.S */
6832 /* File: armv5te/binopLit8.S */
6834 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6835 * that specifies an instruction that performs "result = r0 op r1".
6836 * This could be an ARM instruction or a function call. (If the result
6837 * comes back in a register other than r0, you can override "result".)
6839 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6840 * vCC (r1). Useful for integer division and modulus.
6842 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6843 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6844 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6846 /* binop/lit8 vAA, vBB, #+CC */
6847 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6848 mov r9, rINST, lsr #8 @ r9<- AA
6849 and r2, r3, #255 @ r2<- BB
6850 GET_VREG(r0, r2) @ r0<- vBB
6851 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6853 @cmp r1, #0 @ is second operand zero?
6854 beq common_errDivideByZero
6856 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6858 @ optional op; may set condition codes
6859 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6860 GET_INST_OPCODE(ip) @ extract opcode from rINST
6861 SET_VREG(r0, r9) @ vAA<- r0
6862 GOTO_OPCODE(ip) @ jump to next instruction
6863 /* 10-12 instructions */
6867 /* ------------------------------ */
6869 .L_OP_REM_INT_LIT8: /* 0xdc */
6870 /* File: armv5te/OP_REM_INT_LIT8.S */
6871 /* idivmod returns quotient in r0 and remainder in r1 */
6872 /* File: armv5te/binopLit8.S */
6874 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6875 * that specifies an instruction that performs "result = r0 op r1".
6876 * This could be an ARM instruction or a function call. (If the result
6877 * comes back in a register other than r0, you can override "result".)
6879 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6880 * vCC (r1). Useful for integer division and modulus.
6882 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6883 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6884 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6886 /* binop/lit8 vAA, vBB, #+CC */
6887 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6888 mov r9, rINST, lsr #8 @ r9<- AA
6889 and r2, r3, #255 @ r2<- BB
6890 GET_VREG(r0, r2) @ r0<- vBB
6891 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6893 @cmp r1, #0 @ is second operand zero?
6894 beq common_errDivideByZero
6896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6898 @ optional op; may set condition codes
6899 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6900 GET_INST_OPCODE(ip) @ extract opcode from rINST
6901 SET_VREG(r1, r9) @ vAA<- r1
6902 GOTO_OPCODE(ip) @ jump to next instruction
6903 /* 10-12 instructions */
6907 /* ------------------------------ */
6909 .L_OP_AND_INT_LIT8: /* 0xdd */
6910 /* File: armv5te/OP_AND_INT_LIT8.S */
6911 /* File: armv5te/binopLit8.S */
6913 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6914 * that specifies an instruction that performs "result = r0 op r1".
6915 * This could be an ARM instruction or a function call. (If the result
6916 * comes back in a register other than r0, you can override "result".)
6918 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6919 * vCC (r1). Useful for integer division and modulus.
6921 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6922 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6923 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6925 /* binop/lit8 vAA, vBB, #+CC */
6926 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6927 mov r9, rINST, lsr #8 @ r9<- AA
6928 and r2, r3, #255 @ r2<- BB
6929 GET_VREG(r0, r2) @ r0<- vBB
6930 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6932 @cmp r1, #0 @ is second operand zero?
6933 beq common_errDivideByZero
6935 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6937 @ optional op; may set condition codes
6938 and r0, r0, r1 @ r0<- op, r0-r3 changed
6939 GET_INST_OPCODE(ip) @ extract opcode from rINST
6940 SET_VREG(r0, r9) @ vAA<- r0
6941 GOTO_OPCODE(ip) @ jump to next instruction
6942 /* 10-12 instructions */
6946 /* ------------------------------ */
6948 .L_OP_OR_INT_LIT8: /* 0xde */
6949 /* File: armv5te/OP_OR_INT_LIT8.S */
6950 /* File: armv5te/binopLit8.S */
6952 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6953 * that specifies an instruction that performs "result = r0 op r1".
6954 * This could be an ARM instruction or a function call. (If the result
6955 * comes back in a register other than r0, you can override "result".)
6957 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6958 * vCC (r1). Useful for integer division and modulus.
6960 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6961 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6962 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6964 /* binop/lit8 vAA, vBB, #+CC */
6965 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6966 mov r9, rINST, lsr #8 @ r9<- AA
6967 and r2, r3, #255 @ r2<- BB
6968 GET_VREG(r0, r2) @ r0<- vBB
6969 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6971 @cmp r1, #0 @ is second operand zero?
6972 beq common_errDivideByZero
6974 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6976 @ optional op; may set condition codes
6977 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6978 GET_INST_OPCODE(ip) @ extract opcode from rINST
6979 SET_VREG(r0, r9) @ vAA<- r0
6980 GOTO_OPCODE(ip) @ jump to next instruction
6981 /* 10-12 instructions */
6985 /* ------------------------------ */
6987 .L_OP_XOR_INT_LIT8: /* 0xdf */
6988 /* File: armv5te/OP_XOR_INT_LIT8.S */
6989 /* File: armv5te/binopLit8.S */
6991 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6992 * that specifies an instruction that performs "result = r0 op r1".
6993 * This could be an ARM instruction or a function call. (If the result
6994 * comes back in a register other than r0, you can override "result".)
6996 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6997 * vCC (r1). Useful for integer division and modulus.
6999 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7000 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7001 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7003 /* binop/lit8 vAA, vBB, #+CC */
7004 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7005 mov r9, rINST, lsr #8 @ r9<- AA
7006 and r2, r3, #255 @ r2<- BB
7007 GET_VREG(r0, r2) @ r0<- vBB
7008 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7010 @cmp r1, #0 @ is second operand zero?
7011 beq common_errDivideByZero
7013 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7015 @ optional op; may set condition codes
7016 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7017 GET_INST_OPCODE(ip) @ extract opcode from rINST
7018 SET_VREG(r0, r9) @ vAA<- r0
7019 GOTO_OPCODE(ip) @ jump to next instruction
7020 /* 10-12 instructions */
7024 /* ------------------------------ */
7026 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7027 /* File: armv5te/OP_SHL_INT_LIT8.S */
7028 /* File: armv5te/binopLit8.S */
7030 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7031 * that specifies an instruction that performs "result = r0 op r1".
7032 * This could be an ARM instruction or a function call. (If the result
7033 * comes back in a register other than r0, you can override "result".)
7035 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7036 * vCC (r1). Useful for integer division and modulus.
7038 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7039 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7040 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7042 /* binop/lit8 vAA, vBB, #+CC */
7043 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7044 mov r9, rINST, lsr #8 @ r9<- AA
7045 and r2, r3, #255 @ r2<- BB
7046 GET_VREG(r0, r2) @ r0<- vBB
7047 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7049 @cmp r1, #0 @ is second operand zero?
7050 beq common_errDivideByZero
7052 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7054 and r1, r1, #31 @ optional op; may set condition codes
7055 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7056 GET_INST_OPCODE(ip) @ extract opcode from rINST
7057 SET_VREG(r0, r9) @ vAA<- r0
7058 GOTO_OPCODE(ip) @ jump to next instruction
7059 /* 10-12 instructions */
7063 /* ------------------------------ */
7065 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7066 /* File: armv5te/OP_SHR_INT_LIT8.S */
7067 /* File: armv5te/binopLit8.S */
7069 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7070 * that specifies an instruction that performs "result = r0 op r1".
7071 * This could be an ARM instruction or a function call. (If the result
7072 * comes back in a register other than r0, you can override "result".)
7074 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7075 * vCC (r1). Useful for integer division and modulus.
7077 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7078 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7079 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7081 /* binop/lit8 vAA, vBB, #+CC */
7082 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7083 mov r9, rINST, lsr #8 @ r9<- AA
7084 and r2, r3, #255 @ r2<- BB
7085 GET_VREG(r0, r2) @ r0<- vBB
7086 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7088 @cmp r1, #0 @ is second operand zero?
7089 beq common_errDivideByZero
7091 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7093 and r1, r1, #31 @ optional op; may set condition codes
7094 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7095 GET_INST_OPCODE(ip) @ extract opcode from rINST
7096 SET_VREG(r0, r9) @ vAA<- r0
7097 GOTO_OPCODE(ip) @ jump to next instruction
7098 /* 10-12 instructions */
7102 /* ------------------------------ */
7104 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7105 /* File: armv5te/OP_USHR_INT_LIT8.S */
7106 /* File: armv5te/binopLit8.S */
7108 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7109 * that specifies an instruction that performs "result = r0 op r1".
7110 * This could be an ARM instruction or a function call. (If the result
7111 * comes back in a register other than r0, you can override "result".)
7113 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7114 * vCC (r1). Useful for integer division and modulus.
7116 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7117 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7118 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7120 /* binop/lit8 vAA, vBB, #+CC */
7121 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7122 mov r9, rINST, lsr #8 @ r9<- AA
7123 and r2, r3, #255 @ r2<- BB
7124 GET_VREG(r0, r2) @ r0<- vBB
7125 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7127 @cmp r1, #0 @ is second operand zero?
7128 beq common_errDivideByZero
7130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7132 and r1, r1, #31 @ optional op; may set condition codes
7133 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7134 GET_INST_OPCODE(ip) @ extract opcode from rINST
7135 SET_VREG(r0, r9) @ vAA<- r0
7136 GOTO_OPCODE(ip) @ jump to next instruction
7137 /* 10-12 instructions */
7141 /* ------------------------------ */
7143 .L_OP_UNUSED_E3: /* 0xe3 */
7144 /* File: armv5te/OP_UNUSED_E3.S */
7145 /* File: armv5te/unused.S */
7150 /* ------------------------------ */
7152 .L_OP_UNUSED_E4: /* 0xe4 */
7153 /* File: armv5te/OP_UNUSED_E4.S */
7154 /* File: armv5te/unused.S */
7159 /* ------------------------------ */
7161 .L_OP_UNUSED_E5: /* 0xe5 */
7162 /* File: armv5te/OP_UNUSED_E5.S */
7163 /* File: armv5te/unused.S */
7168 /* ------------------------------ */
7170 .L_OP_UNUSED_E6: /* 0xe6 */
7171 /* File: armv5te/OP_UNUSED_E6.S */
7172 /* File: armv5te/unused.S */
7177 /* ------------------------------ */
7179 .L_OP_UNUSED_E7: /* 0xe7 */
7180 /* File: armv5te/OP_UNUSED_E7.S */
7181 /* File: armv5te/unused.S */
7186 /* ------------------------------ */
7188 .L_OP_UNUSED_E8: /* 0xe8 */
7189 /* File: armv5te/OP_UNUSED_E8.S */
7190 /* File: armv5te/unused.S */
7195 /* ------------------------------ */
7197 .L_OP_UNUSED_E9: /* 0xe9 */
7198 /* File: armv5te/OP_UNUSED_E9.S */
7199 /* File: armv5te/unused.S */
7204 /* ------------------------------ */
7206 .L_OP_UNUSED_EA: /* 0xea */
7207 /* File: armv5te/OP_UNUSED_EA.S */
7208 /* File: armv5te/unused.S */
7213 /* ------------------------------ */
7215 .L_OP_UNUSED_EB: /* 0xeb */
7216 /* File: armv5te/OP_UNUSED_EB.S */
7217 /* File: armv5te/unused.S */
7222 /* ------------------------------ */
7224 .L_OP_UNUSED_EC: /* 0xec */
7225 /* File: armv5te/OP_UNUSED_EC.S */
7226 /* File: armv5te/unused.S */
7231 /* ------------------------------ */
7233 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7234 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7236 * Handle a throw-verification-error instruction. This throws an
7237 * exception for an error discovered during verification. The
7238 * exception is indicated by AA, with some detail provided by BBBB.
7240 /* op AA, ref@BBBB */
7241 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7242 FETCH(r2, 1) @ r2<- BBBB
7243 EXPORT_PC() @ export the PC
7244 mov r1, rINST, lsr #8 @ r1<- AA
7245 bl dvmThrowVerificationError @ always throws
7246 b common_exceptionThrown @ handle exception
7249 /* ------------------------------ */
7251 .L_OP_EXECUTE_INLINE: /* 0xee */
7252 /* File: armv5te/OP_EXECUTE_INLINE.S */
7254 * Execute a "native inline" instruction.
7257 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7259 * The first four args are in r0-r3, but the last two must be pushed
7262 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7263 FETCH(r10, 1) @ r10<- BBBB
7264 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7265 EXPORT_PC() @ can throw
7266 sub sp, sp, #8 @ make room for arg(s)
7267 mov r0, rINST, lsr #12 @ r0<- B
7268 str r1, [sp] @ push &glue->retval
7269 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7270 add sp, sp, #8 @ pop stack
7271 cmp r0, #0 @ test boolean result of inline
7272 beq common_exceptionThrown @ returned false, handle exception
7273 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7274 GET_INST_OPCODE(ip) @ extract opcode from rINST
7275 GOTO_OPCODE(ip) @ jump to next instruction
7277 /* ------------------------------ */
7279 .L_OP_UNUSED_EF: /* 0xef */
7280 /* File: armv5te/OP_UNUSED_EF.S */
7281 /* File: armv5te/unused.S */
7286 /* ------------------------------ */
7288 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7289 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7291 * invoke-direct-empty is a no-op in a "standard" interpreter.
7293 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7294 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7295 GOTO_OPCODE(ip) @ execute it
7297 /* ------------------------------ */
7299 .L_OP_UNUSED_F1: /* 0xf1 */
7300 /* File: armv5te/OP_UNUSED_F1.S */
7301 /* File: armv5te/unused.S */
7306 /* ------------------------------ */
7308 .L_OP_IGET_QUICK: /* 0xf2 */
7309 /* File: armv6t2/OP_IGET_QUICK.S */
7310 /* For: iget-quick, iget-object-quick */
7311 /* op vA, vB, offset@CCCC */
7312 mov r2, rINST, lsr #12 @ r2<- B
7313 FETCH(r1, 1) @ r1<- field byte offset
7314 GET_VREG(r3, r2) @ r3<- object we're operating on
7315 ubfx r2, rINST, #8, #4 @ r2<- A
7316 cmp r3, #0 @ check object for null
7317 beq common_errNullObject @ object was null
7318 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7320 GET_INST_OPCODE(ip) @ extract opcode from rINST
7321 SET_VREG(r0, r2) @ fp[A]<- r0
7322 GOTO_OPCODE(ip) @ jump to next instruction
7325 /* ------------------------------ */
7327 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7328 /* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7329 /* iget-wide-quick vA, vB, offset@CCCC */
7330 mov r2, rINST, lsr #12 @ r2<- B
7331 FETCH(r1, 1) @ r1<- field byte offset
7332 GET_VREG(r3, r2) @ r3<- object we're operating on
7333 ubfx r2, rINST, #8, #4 @ r2<- A
7334 cmp r3, #0 @ check object for null
7335 beq common_errNullObject @ object was null
7336 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned)
7337 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7338 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7339 GET_INST_OPCODE(ip) @ extract opcode from rINST
7340 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7341 GOTO_OPCODE(ip) @ jump to next instruction
7344 /* ------------------------------ */
7346 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7347 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7348 /* File: armv5te/OP_IGET_QUICK.S */
7349 /* For: iget-quick, iget-object-quick */
7350 /* op vA, vB, offset@CCCC */
7351 mov r2, rINST, lsr #12 @ r2<- B
7352 GET_VREG(r3, r2) @ r3<- object we're operating on
7353 FETCH(r1, 1) @ r1<- field byte offset
7354 cmp r3, #0 @ check object for null
7355 mov r2, rINST, lsr #8 @ r2<- A(+)
7356 beq common_errNullObject @ object was null
7357 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7358 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7360 GET_INST_OPCODE(ip) @ extract opcode from rINST
7361 SET_VREG(r0, r2) @ fp[A]<- r0
7362 GOTO_OPCODE(ip) @ jump to next instruction
7366 /* ------------------------------ */
7368 .L_OP_IPUT_QUICK: /* 0xf5 */
7369 /* File: armv6t2/OP_IPUT_QUICK.S */
7370 /* For: iput-quick, iput-object-quick */
7371 /* op vA, vB, offset@CCCC */
7372 mov r2, rINST, lsr #12 @ r2<- B
7373 FETCH(r1, 1) @ r1<- field byte offset
7374 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7375 ubfx r2, rINST, #8, #4 @ r2<- A
7376 cmp r3, #0 @ check object for null
7377 beq common_errNullObject @ object was null
7378 GET_VREG(r0, r2) @ r0<- fp[A]
7379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7380 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7381 GET_INST_OPCODE(ip) @ extract opcode from rINST
7382 GOTO_OPCODE(ip) @ jump to next instruction
7385 /* ------------------------------ */
7387 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7388 /* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7389 /* iput-wide-quick vA, vB, offset@CCCC */
7390 mov r1, rINST, lsr #12 @ r1<- B
7391 ubfx r0, rINST, #8, #4 @ r0<- A
7392 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7393 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7394 cmp r2, #0 @ check object for null
7395 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7396 beq common_errNullObject @ object was null
7397 FETCH(r3, 1) @ r3<- field byte offset
7398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7399 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1
7400 GET_INST_OPCODE(ip) @ extract opcode from rINST
7401 GOTO_OPCODE(ip) @ jump to next instruction
7404 /* ------------------------------ */
7406 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7407 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7408 /* File: armv5te/OP_IPUT_QUICK.S */
7409 /* For: iput-quick, iput-object-quick */
7410 /* op vA, vB, offset@CCCC */
7411 mov r2, rINST, lsr #12 @ r2<- B
7412 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7413 FETCH(r1, 1) @ r1<- field byte offset
7414 cmp r3, #0 @ check object for null
7415 mov r2, rINST, lsr #8 @ r2<- A(+)
7416 beq common_errNullObject @ object was null
7418 GET_VREG(r0, r2) @ r0<- fp[A]
7419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7420 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7421 GET_INST_OPCODE(ip) @ extract opcode from rINST
7422 GOTO_OPCODE(ip) @ jump to next instruction
7426 /* ------------------------------ */
7428 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7429 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7431 * Handle an optimized virtual method call.
7433 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7435 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7436 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7437 FETCH(r3, 2) @ r3<- FEDC or CCCC
7438 FETCH(r1, 1) @ r1<- BBBB
7440 and r3, r3, #15 @ r3<- C (or stays CCCC)
7442 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7443 cmp r2, #0 @ is "this" null?
7444 beq common_errNullObject @ null "this", throw exception
7445 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7446 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7447 EXPORT_PC() @ invoke must export
7448 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7449 bl common_invokeMethodNoRange @ continue on
7451 /* ------------------------------ */
7453 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7454 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7455 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7457 * Handle an optimized virtual method call.
7459 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7461 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7462 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7463 FETCH(r3, 2) @ r3<- FEDC or CCCC
7464 FETCH(r1, 1) @ r1<- BBBB
7466 and r3, r3, #15 @ r3<- C (or stays CCCC)
7468 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7469 cmp r2, #0 @ is "this" null?
7470 beq common_errNullObject @ null "this", throw exception
7471 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7472 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7473 EXPORT_PC() @ invoke must export
7474 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7475 bl common_invokeMethodRange @ continue on
7478 /* ------------------------------ */
7480 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7481 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7483 * Handle an optimized "super" method call.
7485 * for: [opt] invoke-super-quick, invoke-super-quick/range
7487 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7488 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7489 FETCH(r10, 2) @ r10<- GFED or CCCC
7490 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7492 and r10, r10, #15 @ r10<- D (or stays CCCC)
7494 FETCH(r1, 1) @ r1<- BBBB
7495 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7496 EXPORT_PC() @ must export for invoke
7497 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7498 GET_VREG(r3, r10) @ r3<- "this"
7499 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7500 cmp r3, #0 @ null "this" ref?
7501 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7502 beq common_errNullObject @ "this" is null, throw exception
7503 bl common_invokeMethodNoRange @ continue on
7506 /* ------------------------------ */
7508 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7509 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7510 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7512 * Handle an optimized "super" method call.
7514 * for: [opt] invoke-super-quick, invoke-super-quick/range
7516 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7517 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7518 FETCH(r10, 2) @ r10<- GFED or CCCC
7519 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7521 and r10, r10, #15 @ r10<- D (or stays CCCC)
7523 FETCH(r1, 1) @ r1<- BBBB
7524 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7525 EXPORT_PC() @ must export for invoke
7526 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7527 GET_VREG(r3, r10) @ r3<- "this"
7528 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7529 cmp r3, #0 @ null "this" ref?
7530 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7531 beq common_errNullObject @ "this" is null, throw exception
7532 bl common_invokeMethodRange @ continue on
7536 /* ------------------------------ */
7538 .L_OP_UNUSED_FC: /* 0xfc */
7539 /* File: armv5te/OP_UNUSED_FC.S */
7540 /* File: armv5te/unused.S */
7545 /* ------------------------------ */
7547 .L_OP_UNUSED_FD: /* 0xfd */
7548 /* File: armv5te/OP_UNUSED_FD.S */
7549 /* File: armv5te/unused.S */
7554 /* ------------------------------ */
7556 .L_OP_UNUSED_FE: /* 0xfe */
7557 /* File: armv5te/OP_UNUSED_FE.S */
7558 /* File: armv5te/unused.S */
7563 /* ------------------------------ */
7565 .L_OP_UNUSED_FF: /* 0xff */
7566 /* File: armv5te/OP_UNUSED_FF.S */
7567 /* File: armv5te/unused.S */
7574 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
7575 .global dvmAsmInstructionEnd
7576 dvmAsmInstructionEnd:
7579 * ===========================================================================
7580 * Sister implementations
7581 * ===========================================================================
7583 .global dvmAsmSisterStart
7584 .type dvmAsmSisterStart, %function
7589 /* continuation for OP_CONST_STRING */
7592 * Continuation if the String has not yet been resolved.
7593 * r1: BBBB (String ref)
7594 * r9: target register
7596 .LOP_CONST_STRING_resolve:
7598 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7599 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7600 bl dvmResolveString @ r0<- String reference
7601 cmp r0, #0 @ failed?
7602 beq common_exceptionThrown @ yup, handle the exception
7603 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7604 GET_INST_OPCODE(ip) @ extract opcode from rINST
7605 SET_VREG(r0, r9) @ vAA<- r0
7606 GOTO_OPCODE(ip) @ jump to next instruction
7609 /* continuation for OP_CONST_STRING_JUMBO */
7612 * Continuation if the String has not yet been resolved.
7613 * r1: BBBBBBBB (String ref)
7614 * r9: target register
7616 .LOP_CONST_STRING_JUMBO_resolve:
7618 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7619 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7620 bl dvmResolveString @ r0<- String reference
7621 cmp r0, #0 @ failed?
7622 beq common_exceptionThrown @ yup, handle the exception
7623 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7624 GET_INST_OPCODE(ip) @ extract opcode from rINST
7625 SET_VREG(r0, r9) @ vAA<- r0
7626 GOTO_OPCODE(ip) @ jump to next instruction
7629 /* continuation for OP_CONST_CLASS */
7632 * Continuation if the Class has not yet been resolved.
7633 * r1: BBBB (Class ref)
7634 * r9: target register
7636 .LOP_CONST_CLASS_resolve:
7638 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7639 mov r2, #1 @ r2<- true
7640 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7641 bl dvmResolveClass @ r0<- Class reference
7642 cmp r0, #0 @ failed?
7643 beq common_exceptionThrown @ yup, handle the exception
7644 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7645 GET_INST_OPCODE(ip) @ extract opcode from rINST
7646 SET_VREG(r0, r9) @ vAA<- r0
7647 GOTO_OPCODE(ip) @ jump to next instruction
7650 /* continuation for OP_CHECK_CAST */
7653 * Trivial test failed, need to perform full check. This is common.
7654 * r0 holds obj->clazz
7655 * r1 holds class resolved from BBBB
7658 .LOP_CHECK_CAST_fullcheck:
7659 bl dvmInstanceofNonTrivial @ r0<- boolean result
7660 cmp r0, #0 @ failed?
7661 bne .LOP_CHECK_CAST_okay @ no, success
7663 @ A cast has failed. We need to throw a ClassCastException with the
7664 @ class of the object that failed to be cast.
7665 EXPORT_PC() @ about to throw
7666 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz
7667 ldr r0, .LstrClassCastExceptionPtr
7668 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7669 bl dvmThrowExceptionWithClassMessage
7670 b common_exceptionThrown
7673 * Resolution required. This is the least-likely path.
7678 .LOP_CHECK_CAST_resolve:
7679 EXPORT_PC() @ resolve() could throw
7680 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7681 mov r1, r2 @ r1<- BBBB
7682 mov r2, #0 @ r2<- false
7683 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7684 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7685 cmp r0, #0 @ got null?
7686 beq common_exceptionThrown @ yes, handle exception
7687 mov r1, r0 @ r1<- class resolved from BBB
7688 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
7689 b .LOP_CHECK_CAST_resolved @ pick up where we left off
7691 .LstrClassCastExceptionPtr:
7692 .word .LstrClassCastException
7695 /* continuation for OP_INSTANCE_OF */
7698 * Trivial test failed, need to perform full check. This is common.
7699 * r0 holds obj->clazz
7700 * r1 holds class resolved from BBBB
7703 .LOP_INSTANCE_OF_fullcheck:
7704 bl dvmInstanceofNonTrivial @ r0<- boolean result
7705 @ fall through to OP_INSTANCE_OF_store
7708 * r0 holds boolean result
7711 .LOP_INSTANCE_OF_store:
7712 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7713 SET_VREG(r0, r9) @ vA<- r0
7714 GET_INST_OPCODE(ip) @ extract opcode from rINST
7715 GOTO_OPCODE(ip) @ jump to next instruction
7718 * Trivial test succeeded, save and bail.
7721 .LOP_INSTANCE_OF_trivial:
7722 mov r0, #1 @ indicate success
7723 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7725 SET_VREG(r0, r9) @ vA<- r0
7726 GET_INST_OPCODE(ip) @ extract opcode from rINST
7727 GOTO_OPCODE(ip) @ jump to next instruction
7730 * Resolution required. This is the least-likely path.
7735 .LOP_INSTANCE_OF_resolve:
7736 EXPORT_PC() @ resolve() could throw
7737 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7738 mov r1, r3 @ r1<- BBBB
7739 mov r2, #1 @ r2<- true
7740 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7741 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7742 cmp r0, #0 @ got null?
7743 beq common_exceptionThrown @ yes, handle exception
7744 mov r1, r0 @ r1<- class resolved from BBB
7745 mov r3, rINST, lsr #12 @ r3<- B
7746 GET_VREG(r0, r3) @ r0<- vB (object)
7747 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
7748 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
7751 /* continuation for OP_NEW_INSTANCE */
7753 .balign 32 @ minimize cache lines
7754 .LOP_NEW_INSTANCE_finish: @ r0=new object
7755 mov r3, rINST, lsr #8 @ r3<- AA
7756 cmp r0, #0 @ failed?
7757 beq common_exceptionThrown @ yes, handle the exception
7758 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7759 GET_INST_OPCODE(ip) @ extract opcode from rINST
7760 SET_VREG(r0, r3) @ vAA<- r0
7761 GOTO_OPCODE(ip) @ jump to next instruction
7764 * Class initialization required.
7766 * r0 holds class object
7768 .LOP_NEW_INSTANCE_needinit:
7769 mov r9, r0 @ save r0
7770 bl dvmInitClass @ initialize class
7771 cmp r0, #0 @ check boolean result
7772 mov r0, r9 @ restore r0
7773 bne .LOP_NEW_INSTANCE_initialized @ success, continue
7774 b common_exceptionThrown @ failed, deal with init exception
7777 * Resolution required. This is the least-likely path.
7781 .LOP_NEW_INSTANCE_resolve:
7782 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7783 mov r2, #0 @ r2<- false
7784 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7785 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7786 cmp r0, #0 @ got null?
7787 bne .LOP_NEW_INSTANCE_resolved @ no, continue
7788 b common_exceptionThrown @ yes, handle exception
7790 .LstrInstantiationErrorPtr:
7791 .word .LstrInstantiationError
7794 /* continuation for OP_NEW_ARRAY */
7798 * Resolve class. (This is an uncommon case.)
7800 * r1 holds array length
7801 * r2 holds class ref CCCC
7803 .LOP_NEW_ARRAY_resolve:
7804 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7805 mov r9, r1 @ r9<- length (save)
7806 mov r1, r2 @ r1<- CCCC
7807 mov r2, #0 @ r2<- false
7808 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7809 bl dvmResolveClass @ r0<- call(clazz, ref)
7810 cmp r0, #0 @ got null?
7811 mov r1, r9 @ r1<- length (restore)
7812 beq common_exceptionThrown @ yes, handle exception
7813 @ fall through to OP_NEW_ARRAY_finish
7816 * Finish allocation.
7819 * r1 holds array length
7821 .LOP_NEW_ARRAY_finish:
7822 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
7823 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
7824 cmp r0, #0 @ failed?
7825 mov r2, rINST, lsr #8 @ r2<- A+
7826 beq common_exceptionThrown @ yes, handle the exception
7827 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7828 and r2, r2, #15 @ r2<- A
7829 GET_INST_OPCODE(ip) @ extract opcode from rINST
7830 SET_VREG(r0, r2) @ vA<- r0
7831 GOTO_OPCODE(ip) @ jump to next instruction
7834 /* continuation for OP_FILLED_NEW_ARRAY */
7838 * r0 holds array class
7839 * r10 holds AA or BA
7841 .LOP_FILLED_NEW_ARRAY_continue:
7842 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7843 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
7844 ldrb r3, [r3, #1] @ r3<- descriptor[1]
7846 mov r1, r10 @ r1<- AA (length)
7848 mov r1, r10, lsr #4 @ r1<- B (length)
7850 cmp r3, #'I' @ array of ints?
7851 cmpne r3, #'L' @ array of objects?
7852 cmpne r3, #'[' @ array of arrays?
7853 mov r9, r1 @ save length in r9
7854 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
7855 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
7856 cmp r0, #0 @ null return?
7857 beq common_exceptionThrown @ alloc failed, handle exception
7859 FETCH(r1, 2) @ r1<- FEDC or CCCC
7860 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
7861 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7862 subs r9, r9, #1 @ length--, check for neg
7863 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7864 bmi 2f @ was zero, bail
7866 @ copy values from registers into the array
7867 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7869 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
7870 1: ldr r3, [r2], #4 @ r3<- *r2++
7871 subs r9, r9, #1 @ count--
7872 str r3, [r0], #4 @ *contents++ = vX
7876 cmp r9, #4 @ length was initially 5?
7877 and r2, r10, #15 @ r2<- A
7878 bne 1f @ <= 4 args, branch
7879 GET_VREG(r3, r2) @ r3<- vA
7880 sub r9, r9, #1 @ count--
7881 str r3, [r0, #16] @ contents[4] = vA
7882 1: and r2, r1, #15 @ r2<- F/E/D/C
7883 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
7884 mov r1, r1, lsr #4 @ r1<- next reg in low 4
7885 subs r9, r9, #1 @ count--
7886 str r3, [r0], #4 @ *contents++ = vX
7892 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7893 GOTO_OPCODE(ip) @ execute it
7896 * Throw an exception indicating that we have not implemented this
7897 * mode of filled-new-array.
7899 .LOP_FILLED_NEW_ARRAY_notimpl:
7900 ldr r0, .L_strInternalError
7901 ldr r1, .L_strFilledNewArrayNotImpl
7902 bl dvmThrowException
7903 b common_exceptionThrown
7905 .if (!0) @ define in one or the other, not both
7906 .L_strFilledNewArrayNotImpl:
7907 .word .LstrFilledNewArrayNotImpl
7908 .L_strInternalError:
7909 .word .LstrInternalError
7913 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7917 * r0 holds array class
7918 * r10 holds AA or BA
7920 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
7921 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7922 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
7923 ldrb r3, [r3, #1] @ r3<- descriptor[1]
7925 mov r1, r10 @ r1<- AA (length)
7927 mov r1, r10, lsr #4 @ r1<- B (length)
7929 cmp r3, #'I' @ array of ints?
7930 cmpne r3, #'L' @ array of objects?
7931 cmpne r3, #'[' @ array of arrays?
7932 mov r9, r1 @ save length in r9
7933 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
7934 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
7935 cmp r0, #0 @ null return?
7936 beq common_exceptionThrown @ alloc failed, handle exception
7938 FETCH(r1, 2) @ r1<- FEDC or CCCC
7939 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
7940 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7941 subs r9, r9, #1 @ length--, check for neg
7942 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7943 bmi 2f @ was zero, bail
7945 @ copy values from registers into the array
7946 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7948 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
7949 1: ldr r3, [r2], #4 @ r3<- *r2++
7950 subs r9, r9, #1 @ count--
7951 str r3, [r0], #4 @ *contents++ = vX
7955 cmp r9, #4 @ length was initially 5?
7956 and r2, r10, #15 @ r2<- A
7957 bne 1f @ <= 4 args, branch
7958 GET_VREG(r3, r2) @ r3<- vA
7959 sub r9, r9, #1 @ count--
7960 str r3, [r0, #16] @ contents[4] = vA
7961 1: and r2, r1, #15 @ r2<- F/E/D/C
7962 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
7963 mov r1, r1, lsr #4 @ r1<- next reg in low 4
7964 subs r9, r9, #1 @ count--
7965 str r3, [r0], #4 @ *contents++ = vX
7971 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7972 GOTO_OPCODE(ip) @ execute it
7975 * Throw an exception indicating that we have not implemented this
7976 * mode of filled-new-array.
7978 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
7979 ldr r0, .L_strInternalError
7980 ldr r1, .L_strFilledNewArrayNotImpl
7981 bl dvmThrowException
7982 b common_exceptionThrown
7984 .if (!1) @ define in one or the other, not both
7985 .L_strFilledNewArrayNotImpl:
7986 .word .LstrFilledNewArrayNotImpl
7987 .L_strInternalError:
7988 .word .LstrInternalError
7992 /* continuation for OP_CMPL_FLOAT */
7993 .LOP_CMPL_FLOAT_finish:
7994 SET_VREG(r0, r9) @ vAA<- r0
7995 GOTO_OPCODE(ip) @ jump to next instruction
7998 /* continuation for OP_CMPG_FLOAT */
7999 .LOP_CMPG_FLOAT_finish:
8000 SET_VREG(r0, r9) @ vAA<- r0
8001 GOTO_OPCODE(ip) @ jump to next instruction
8004 /* continuation for OP_CMPL_DOUBLE */
8005 .LOP_CMPL_DOUBLE_finish:
8006 SET_VREG(r0, r9) @ vAA<- r0
8007 GOTO_OPCODE(ip) @ jump to next instruction
8010 /* continuation for OP_CMPG_DOUBLE */
8011 .LOP_CMPG_DOUBLE_finish:
8012 SET_VREG(r0, r9) @ vAA<- r0
8013 GOTO_OPCODE(ip) @ jump to next instruction
8016 /* continuation for OP_CMP_LONG */
8019 mvn r1, #0 @ r1<- -1
8020 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8021 @ instead, we just replicate the tail end.
8022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8023 SET_VREG(r1, r9) @ vAA<- r1
8024 GET_INST_OPCODE(ip) @ extract opcode from rINST
8025 GOTO_OPCODE(ip) @ jump to next instruction
8027 .LOP_CMP_LONG_greater:
8029 @ fall through to _finish
8031 .LOP_CMP_LONG_finish:
8032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8033 SET_VREG(r1, r9) @ vAA<- r1
8034 GET_INST_OPCODE(ip) @ extract opcode from rINST
8035 GOTO_OPCODE(ip) @ jump to next instruction
8038 /* continuation for OP_AGET_WIDE */
8040 .LOP_AGET_WIDE_finish:
8041 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8042 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8043 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8044 GET_INST_OPCODE(ip) @ extract opcode from rINST
8045 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8046 GOTO_OPCODE(ip) @ jump to next instruction
8049 /* continuation for OP_APUT_WIDE */
8051 .LOP_APUT_WIDE_finish:
8052 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8053 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8054 GET_INST_OPCODE(ip) @ extract opcode from rINST
8055 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8056 GOTO_OPCODE(ip) @ jump to next instruction
8059 /* continuation for OP_APUT_OBJECT */
8062 * r1 = vBB (arrayObj)
8064 * r10 = offset into array (vBB + vCC * width)
8066 .LOP_APUT_OBJECT_finish:
8067 cmp r9, #0 @ storing null reference?
8068 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8069 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8070 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz
8071 bl dvmCanPutArrayElement @ test object type vs. array type
8073 beq common_errArrayStore @ no
8074 .LOP_APUT_OBJECT_skip_check:
8075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8076 GET_INST_OPCODE(ip) @ extract opcode from rINST
8077 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8078 GOTO_OPCODE(ip) @ jump to next instruction
8081 /* continuation for OP_IGET */
8085 * r0 holds resolved field
8090 cmp r9, #0 @ check object for null
8091 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8092 beq common_errNullObject @ object was null
8093 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8094 ubfx r2, rINST, #8, #4 @ r2<- A
8095 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8096 GET_INST_OPCODE(ip) @ extract opcode from rINST
8097 SET_VREG(r0, r2) @ fp[A]<- r0
8098 GOTO_OPCODE(ip) @ jump to next instruction
8101 /* continuation for OP_IGET_WIDE */
8105 * r0 holds resolved field
8108 .LOP_IGET_WIDE_finish:
8109 cmp r9, #0 @ check object for null
8110 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8111 beq common_errNullObject @ object was null
8112 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
8113 ubfx r2, rINST, #8, #4 @ r2<- A
8114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8115 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8116 GET_INST_OPCODE(ip) @ extract opcode from rINST
8117 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8118 GOTO_OPCODE(ip) @ jump to next instruction
8121 /* continuation for OP_IGET_OBJECT */
8125 * r0 holds resolved field
8128 .LOP_IGET_OBJECT_finish:
8130 cmp r9, #0 @ check object for null
8131 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8132 beq common_errNullObject @ object was null
8133 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8134 mov r2, rINST, lsr #8 @ r2<- A+
8135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8136 and r2, r2, #15 @ r2<- A
8137 GET_INST_OPCODE(ip) @ extract opcode from rINST
8138 SET_VREG(r0, r2) @ fp[A]<- r0
8139 GOTO_OPCODE(ip) @ jump to next instruction
8142 /* continuation for OP_IGET_BOOLEAN */
8146 * r0 holds resolved field
8149 .LOP_IGET_BOOLEAN_finish:
8151 cmp r9, #0 @ check object for null
8152 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8153 beq common_errNullObject @ object was null
8154 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8155 mov r2, rINST, lsr #8 @ r2<- A+
8156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8157 and r2, r2, #15 @ r2<- A
8158 GET_INST_OPCODE(ip) @ extract opcode from rINST
8159 SET_VREG(r0, r2) @ fp[A]<- r0
8160 GOTO_OPCODE(ip) @ jump to next instruction
8163 /* continuation for OP_IGET_BYTE */
8167 * r0 holds resolved field
8170 .LOP_IGET_BYTE_finish:
8172 cmp r9, #0 @ check object for null
8173 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8174 beq common_errNullObject @ object was null
8175 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8176 mov r2, rINST, lsr #8 @ r2<- A+
8177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8178 and r2, r2, #15 @ r2<- A
8179 GET_INST_OPCODE(ip) @ extract opcode from rINST
8180 SET_VREG(r0, r2) @ fp[A]<- r0
8181 GOTO_OPCODE(ip) @ jump to next instruction
8184 /* continuation for OP_IGET_CHAR */
8188 * r0 holds resolved field
8191 .LOP_IGET_CHAR_finish:
8193 cmp r9, #0 @ check object for null
8194 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8195 beq common_errNullObject @ object was null
8196 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8197 mov r2, rINST, lsr #8 @ r2<- A+
8198 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8199 and r2, r2, #15 @ r2<- A
8200 GET_INST_OPCODE(ip) @ extract opcode from rINST
8201 SET_VREG(r0, r2) @ fp[A]<- r0
8202 GOTO_OPCODE(ip) @ jump to next instruction
8205 /* continuation for OP_IGET_SHORT */
8209 * r0 holds resolved field
8212 .LOP_IGET_SHORT_finish:
8214 cmp r9, #0 @ check object for null
8215 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8216 beq common_errNullObject @ object was null
8217 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8218 mov r2, rINST, lsr #8 @ r2<- A+
8219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8220 and r2, r2, #15 @ r2<- A
8221 GET_INST_OPCODE(ip) @ extract opcode from rINST
8222 SET_VREG(r0, r2) @ fp[A]<- r0
8223 GOTO_OPCODE(ip) @ jump to next instruction
8226 /* continuation for OP_IPUT */
8230 * r0 holds resolved field
8235 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8236 ubfx r1, rINST, #8, #4 @ r1<- A
8237 cmp r9, #0 @ check object for null
8238 GET_VREG(r0, r1) @ r0<- fp[A]
8239 beq common_errNullObject @ object was null
8240 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8241 GET_INST_OPCODE(ip) @ extract opcode from rINST
8242 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8243 GOTO_OPCODE(ip) @ jump to next instruction
8246 /* continuation for OP_IPUT_WIDE */
8250 * r0 holds resolved field
8253 .LOP_IPUT_WIDE_finish:
8254 ubfx r2, rINST, #8, #4 @ r2<- A
8255 cmp r9, #0 @ check object for null
8256 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8257 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8258 beq common_errNullObject @ object was null
8259 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8260 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8261 GET_INST_OPCODE(ip) @ extract opcode from rINST
8262 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
8263 GOTO_OPCODE(ip) @ jump to next instruction
8266 /* continuation for OP_IPUT_OBJECT */
8270 * r0 holds resolved field
8273 .LOP_IPUT_OBJECT_finish:
8275 mov r1, rINST, lsr #8 @ r1<- A+
8276 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8277 and r1, r1, #15 @ r1<- A
8278 cmp r9, #0 @ check object for null
8279 GET_VREG(r0, r1) @ r0<- fp[A]
8280 beq common_errNullObject @ object was null
8281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8282 GET_INST_OPCODE(ip) @ extract opcode from rINST
8283 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8284 GOTO_OPCODE(ip) @ jump to next instruction
8287 /* continuation for OP_IPUT_BOOLEAN */
8291 * r0 holds resolved field
8294 .LOP_IPUT_BOOLEAN_finish:
8296 mov r1, rINST, lsr #8 @ r1<- A+
8297 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8298 and r1, r1, #15 @ r1<- A
8299 cmp r9, #0 @ check object for null
8300 GET_VREG(r0, r1) @ r0<- fp[A]
8301 beq common_errNullObject @ object was null
8302 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8303 GET_INST_OPCODE(ip) @ extract opcode from rINST
8304 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8305 GOTO_OPCODE(ip) @ jump to next instruction
8308 /* continuation for OP_IPUT_BYTE */
8312 * r0 holds resolved field
8315 .LOP_IPUT_BYTE_finish:
8317 mov r1, rINST, lsr #8 @ r1<- A+
8318 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8319 and r1, r1, #15 @ r1<- A
8320 cmp r9, #0 @ check object for null
8321 GET_VREG(r0, r1) @ r0<- fp[A]
8322 beq common_errNullObject @ object was null
8323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8324 GET_INST_OPCODE(ip) @ extract opcode from rINST
8325 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8326 GOTO_OPCODE(ip) @ jump to next instruction
8329 /* continuation for OP_IPUT_CHAR */
8333 * r0 holds resolved field
8336 .LOP_IPUT_CHAR_finish:
8338 mov r1, rINST, lsr #8 @ r1<- A+
8339 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8340 and r1, r1, #15 @ r1<- A
8341 cmp r9, #0 @ check object for null
8342 GET_VREG(r0, r1) @ r0<- fp[A]
8343 beq common_errNullObject @ object was null
8344 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8345 GET_INST_OPCODE(ip) @ extract opcode from rINST
8346 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8347 GOTO_OPCODE(ip) @ jump to next instruction
8350 /* continuation for OP_IPUT_SHORT */
8354 * r0 holds resolved field
8357 .LOP_IPUT_SHORT_finish:
8359 mov r1, rINST, lsr #8 @ r1<- A+
8360 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8361 and r1, r1, #15 @ r1<- A
8362 cmp r9, #0 @ check object for null
8363 GET_VREG(r0, r1) @ r0<- fp[A]
8364 beq common_errNullObject @ object was null
8365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8366 GET_INST_OPCODE(ip) @ extract opcode from rINST
8367 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8368 GOTO_OPCODE(ip) @ jump to next instruction
8371 /* continuation for OP_SGET */
8374 * Continuation if the field has not yet been resolved.
8375 * r1: BBBB field ref
8378 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8379 EXPORT_PC() @ resolve() could throw, so export now
8380 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8381 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8382 cmp r0, #0 @ success?
8383 bne .LOP_SGET_finish @ yes, finish
8384 b common_exceptionThrown @ no, handle exception
8387 /* continuation for OP_SGET_WIDE */
8390 * Continuation if the field has not yet been resolved.
8391 * r1: BBBB field ref
8393 .LOP_SGET_WIDE_resolve:
8394 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8395 EXPORT_PC() @ resolve() could throw, so export now
8396 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8397 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8398 cmp r0, #0 @ success?
8399 bne .LOP_SGET_WIDE_finish @ yes, finish
8400 b common_exceptionThrown @ no, handle exception
8403 /* continuation for OP_SGET_OBJECT */
8406 * Continuation if the field has not yet been resolved.
8407 * r1: BBBB field ref
8409 .LOP_SGET_OBJECT_resolve:
8410 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8411 EXPORT_PC() @ resolve() could throw, so export now
8412 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8413 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8414 cmp r0, #0 @ success?
8415 bne .LOP_SGET_OBJECT_finish @ yes, finish
8416 b common_exceptionThrown @ no, handle exception
8419 /* continuation for OP_SGET_BOOLEAN */
8422 * Continuation if the field has not yet been resolved.
8423 * r1: BBBB field ref
8425 .LOP_SGET_BOOLEAN_resolve:
8426 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8427 EXPORT_PC() @ resolve() could throw, so export now
8428 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8429 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8430 cmp r0, #0 @ success?
8431 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
8432 b common_exceptionThrown @ no, handle exception
8435 /* continuation for OP_SGET_BYTE */
8438 * Continuation if the field has not yet been resolved.
8439 * r1: BBBB field ref
8441 .LOP_SGET_BYTE_resolve:
8442 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8443 EXPORT_PC() @ resolve() could throw, so export now
8444 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8445 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8446 cmp r0, #0 @ success?
8447 bne .LOP_SGET_BYTE_finish @ yes, finish
8448 b common_exceptionThrown @ no, handle exception
8451 /* continuation for OP_SGET_CHAR */
8454 * Continuation if the field has not yet been resolved.
8455 * r1: BBBB field ref
8457 .LOP_SGET_CHAR_resolve:
8458 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8459 EXPORT_PC() @ resolve() could throw, so export now
8460 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8461 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8462 cmp r0, #0 @ success?
8463 bne .LOP_SGET_CHAR_finish @ yes, finish
8464 b common_exceptionThrown @ no, handle exception
8467 /* continuation for OP_SGET_SHORT */
8470 * Continuation if the field has not yet been resolved.
8471 * r1: BBBB field ref
8473 .LOP_SGET_SHORT_resolve:
8474 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8475 EXPORT_PC() @ resolve() could throw, so export now
8476 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8477 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8478 cmp r0, #0 @ success?
8479 bne .LOP_SGET_SHORT_finish @ yes, finish
8480 b common_exceptionThrown @ no, handle exception
8483 /* continuation for OP_SPUT */
8486 * Continuation if the field has not yet been resolved.
8487 * r1: BBBB field ref
8490 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8491 EXPORT_PC() @ resolve() could throw, so export now
8492 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8493 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8494 cmp r0, #0 @ success?
8495 bne .LOP_SPUT_finish @ yes, finish
8496 b common_exceptionThrown @ no, handle exception
8499 /* continuation for OP_SPUT_WIDE */
8502 * Continuation if the field has not yet been resolved.
8503 * r1: BBBB field ref
8506 .LOP_SPUT_WIDE_resolve:
8507 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8508 EXPORT_PC() @ resolve() could throw, so export now
8509 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8510 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8511 cmp r0, #0 @ success?
8512 bne .LOP_SPUT_WIDE_finish @ yes, finish
8513 b common_exceptionThrown @ no, handle exception
8516 /* continuation for OP_SPUT_OBJECT */
8519 * Continuation if the field has not yet been resolved.
8520 * r1: BBBB field ref
8522 .LOP_SPUT_OBJECT_resolve:
8523 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8524 EXPORT_PC() @ resolve() could throw, so export now
8525 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8526 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8527 cmp r0, #0 @ success?
8528 bne .LOP_SPUT_OBJECT_finish @ yes, finish
8529 b common_exceptionThrown @ no, handle exception
8532 /* continuation for OP_SPUT_BOOLEAN */
8535 * Continuation if the field has not yet been resolved.
8536 * r1: BBBB field ref
8538 .LOP_SPUT_BOOLEAN_resolve:
8539 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8540 EXPORT_PC() @ resolve() could throw, so export now
8541 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8542 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8543 cmp r0, #0 @ success?
8544 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
8545 b common_exceptionThrown @ no, handle exception
8548 /* continuation for OP_SPUT_BYTE */
8551 * Continuation if the field has not yet been resolved.
8552 * r1: BBBB field ref
8554 .LOP_SPUT_BYTE_resolve:
8555 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8556 EXPORT_PC() @ resolve() could throw, so export now
8557 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8558 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8559 cmp r0, #0 @ success?
8560 bne .LOP_SPUT_BYTE_finish @ yes, finish
8561 b common_exceptionThrown @ no, handle exception
8564 /* continuation for OP_SPUT_CHAR */
8567 * Continuation if the field has not yet been resolved.
8568 * r1: BBBB field ref
8570 .LOP_SPUT_CHAR_resolve:
8571 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8572 EXPORT_PC() @ resolve() could throw, so export now
8573 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8574 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8575 cmp r0, #0 @ success?
8576 bne .LOP_SPUT_CHAR_finish @ yes, finish
8577 b common_exceptionThrown @ no, handle exception
8580 /* continuation for OP_SPUT_SHORT */
8583 * Continuation if the field has not yet been resolved.
8584 * r1: BBBB field ref
8586 .LOP_SPUT_SHORT_resolve:
8587 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8588 EXPORT_PC() @ resolve() could throw, so export now
8589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8590 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8591 cmp r0, #0 @ success?
8592 bne .LOP_SPUT_SHORT_finish @ yes, finish
8593 b common_exceptionThrown @ no, handle exception
8596 /* continuation for OP_INVOKE_VIRTUAL */
8600 * r0 = resolved base method
8601 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8603 .LOP_INVOKE_VIRTUAL_continue:
8604 GET_VREG(r1, r10) @ r1<- "this" ptr
8605 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8606 cmp r1, #0 @ is "this" null?
8607 beq common_errNullObject @ null "this", throw exception
8608 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8609 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8610 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8611 bl common_invokeMethodNoRange @ continue on
8614 /* continuation for OP_INVOKE_SUPER */
8618 * r0 = resolved base method
8619 * r9 = method->clazz
8621 .LOP_INVOKE_SUPER_continue:
8622 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8623 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8624 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8625 EXPORT_PC() @ must export for invoke
8626 cmp r2, r3 @ compare (methodIndex, vtableCount)
8627 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
8628 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8629 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8630 bl common_invokeMethodNoRange @ continue on
8632 .LOP_INVOKE_SUPER_resolve:
8633 mov r0, r9 @ r0<- method->clazz
8634 mov r2, #METHOD_VIRTUAL @ resolver method type
8635 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8636 cmp r0, #0 @ got null?
8637 bne .LOP_INVOKE_SUPER_continue @ no, continue
8638 b common_exceptionThrown @ yes, handle exception
8641 * Throw a NoSuchMethodError with the method name as the message.
8642 * r0 = resolved base method
8644 .LOP_INVOKE_SUPER_nsm:
8645 ldr r1, [r0, #offMethod_name] @ r1<- method name
8646 b common_errNoSuchMethod
8649 /* continuation for OP_INVOKE_DIRECT */
8653 * r1 = reference (BBBB or CCCC)
8654 * r10 = "this" register
8656 .LOP_INVOKE_DIRECT_resolve:
8657 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8658 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8659 mov r2, #METHOD_DIRECT @ resolver method type
8660 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8661 cmp r0, #0 @ got null?
8662 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8663 bne .LOP_INVOKE_DIRECT_finish @ no, continue
8664 b common_exceptionThrown @ yes, handle exception
8667 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
8671 * r0 = resolved base method
8672 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8674 .LOP_INVOKE_VIRTUAL_RANGE_continue:
8675 GET_VREG(r1, r10) @ r1<- "this" ptr
8676 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8677 cmp r1, #0 @ is "this" null?
8678 beq common_errNullObject @ null "this", throw exception
8679 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8680 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8681 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8682 bl common_invokeMethodRange @ continue on
8685 /* continuation for OP_INVOKE_SUPER_RANGE */
8689 * r0 = resolved base method
8690 * r9 = method->clazz
8692 .LOP_INVOKE_SUPER_RANGE_continue:
8693 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8694 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8695 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8696 EXPORT_PC() @ must export for invoke
8697 cmp r2, r3 @ compare (methodIndex, vtableCount)
8698 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
8699 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8700 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8701 bl common_invokeMethodRange @ continue on
8703 .LOP_INVOKE_SUPER_RANGE_resolve:
8704 mov r0, r9 @ r0<- method->clazz
8705 mov r2, #METHOD_VIRTUAL @ resolver method type
8706 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8707 cmp r0, #0 @ got null?
8708 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
8709 b common_exceptionThrown @ yes, handle exception
8712 * Throw a NoSuchMethodError with the method name as the message.
8713 * r0 = resolved base method
8715 .LOP_INVOKE_SUPER_RANGE_nsm:
8716 ldr r1, [r0, #offMethod_name] @ r1<- method name
8717 b common_errNoSuchMethod
8720 /* continuation for OP_INVOKE_DIRECT_RANGE */
8724 * r1 = reference (BBBB or CCCC)
8725 * r10 = "this" register
8727 .LOP_INVOKE_DIRECT_RANGE_resolve:
8728 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8729 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8730 mov r2, #METHOD_DIRECT @ resolver method type
8731 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8732 cmp r0, #0 @ got null?
8733 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8734 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
8735 b common_exceptionThrown @ yes, handle exception
8738 /* continuation for OP_FLOAT_TO_LONG */
8740 * Convert the float in r0 to a long in r0/r1.
8742 * We have to clip values to long min/max per the specification. The
8743 * expected common case is a "reasonable" value that converts directly
8744 * to modest integer. The EABI convert function isn't doing this for us.
8748 mov r1, #0x5f000000 @ (float)maxlong
8750 bl __aeabi_fcmpge @ is arg >= maxlong?
8751 cmp r0, #0 @ nonzero == yes
8752 mvnne r0, #0 @ return maxlong (7fffffff)
8753 mvnne r1, #0x80000000
8754 ldmnefd sp!, {r4, pc}
8756 mov r0, r4 @ recover arg
8757 mov r1, #0xdf000000 @ (float)minlong
8758 bl __aeabi_fcmple @ is arg <= minlong?
8759 cmp r0, #0 @ nonzero == yes
8760 movne r0, #0 @ return minlong (80000000)
8761 movne r1, #0x80000000
8762 ldmnefd sp!, {r4, pc}
8764 mov r0, r4 @ recover arg
8766 bl __aeabi_fcmpeq @ is arg == self?
8767 cmp r0, #0 @ zero == no
8768 moveq r1, #0 @ return zero for NaN
8769 ldmeqfd sp!, {r4, pc}
8771 mov r0, r4 @ recover arg
8772 bl __aeabi_f2lz @ convert float to long
8776 /* continuation for OP_DOUBLE_TO_LONG */
8778 * Convert the double in r0/r1 to a long in r0/r1.
8780 * We have to clip values to long min/max per the specification. The
8781 * expected common case is a "reasonable" value that converts directly
8782 * to modest integer. The EABI convert function isn't doing this for us.
8785 stmfd sp!, {r4, r5, lr} @ save regs
8786 mov r3, #0x43000000 @ maxlong, as a double (high word)
8787 add r3, #0x00e00000 @ 0x43e00000
8788 mov r2, #0 @ maxlong, as a double (low word)
8789 sub sp, sp, #4 @ align for EABI
8790 mov r4, r0 @ save a copy of r0
8792 bl __aeabi_dcmpge @ is arg >= maxlong?
8793 cmp r0, #0 @ nonzero == yes
8794 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
8795 mvnne r1, #0x80000000
8798 mov r0, r4 @ recover arg
8800 mov r3, #0xc3000000 @ minlong, as a double (high word)
8801 add r3, #0x00e00000 @ 0xc3e00000
8802 mov r2, #0 @ minlong, as a double (low word)
8803 bl __aeabi_dcmple @ is arg <= minlong?
8804 cmp r0, #0 @ nonzero == yes
8805 movne r0, #0 @ return minlong (8000000000000000)
8806 movne r1, #0x80000000
8809 mov r0, r4 @ recover arg
8811 mov r2, r4 @ compare against self
8813 bl __aeabi_dcmpeq @ is arg == self?
8814 cmp r0, #0 @ zero == no
8815 moveq r1, #0 @ return zero for NaN
8818 mov r0, r4 @ recover arg
8820 bl __aeabi_d2lz @ convert double to long
8824 ldmfd sp!, {r4, r5, pc}
8827 /* continuation for OP_MUL_LONG */
8829 .LOP_MUL_LONG_finish:
8830 GET_INST_OPCODE(ip) @ extract opcode from rINST
8831 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
8832 GOTO_OPCODE(ip) @ jump to next instruction
8835 /* continuation for OP_SHL_LONG */
8837 .LOP_SHL_LONG_finish:
8838 mov r0, r0, asl r2 @ r0<- r0 << r2
8839 GET_INST_OPCODE(ip) @ extract opcode from rINST
8840 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8841 GOTO_OPCODE(ip) @ jump to next instruction
8844 /* continuation for OP_SHR_LONG */
8846 .LOP_SHR_LONG_finish:
8847 mov r1, r1, asr r2 @ r1<- r1 >> r2
8848 GET_INST_OPCODE(ip) @ extract opcode from rINST
8849 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8850 GOTO_OPCODE(ip) @ jump to next instruction
8853 /* continuation for OP_USHR_LONG */
8855 .LOP_USHR_LONG_finish:
8856 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
8857 GET_INST_OPCODE(ip) @ extract opcode from rINST
8858 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8859 GOTO_OPCODE(ip) @ jump to next instruction
8862 /* continuation for OP_SHL_LONG_2ADDR */
8864 .LOP_SHL_LONG_2ADDR_finish:
8865 GET_INST_OPCODE(ip) @ extract opcode from rINST
8866 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8867 GOTO_OPCODE(ip) @ jump to next instruction
8870 /* continuation for OP_SHR_LONG_2ADDR */
8872 .LOP_SHR_LONG_2ADDR_finish:
8873 GET_INST_OPCODE(ip) @ extract opcode from rINST
8874 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8875 GOTO_OPCODE(ip) @ jump to next instruction
8878 /* continuation for OP_USHR_LONG_2ADDR */
8880 .LOP_USHR_LONG_2ADDR_finish:
8881 GET_INST_OPCODE(ip) @ extract opcode from rINST
8882 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8883 GOTO_OPCODE(ip) @ jump to next instruction
8886 /* continuation for OP_EXECUTE_INLINE */
8889 * Extract args, call function.
8890 * r0 = #of args (0-4)
8892 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
8895 * - Use a jump table from the main piece to jump directly into the
8896 * AND/LDR pairs. Costs a data load, saves a branch.
8897 * - Have five separate pieces that do the loading, so we can work the
8898 * interleave a little better. Increases code size.
8900 .LOP_EXECUTE_INLINE_continue:
8901 rsb r0, r0, #4 @ r0<- 4-r0
8902 FETCH(r9, 2) @ r9<- FEDC
8903 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
8904 bl common_abort @ (skipped due to ARM prefetch)
8905 4: and ip, r9, #0xf000 @ isolate F
8906 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
8907 3: and ip, r9, #0x0f00 @ isolate E
8908 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
8909 2: and ip, r9, #0x00f0 @ isolate D
8910 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
8911 1: and ip, r9, #0x000f @ isolate C
8912 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
8914 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
8915 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
8918 .LOP_EXECUTE_INLINE_table:
8919 .word gDvmInlineOpsTable
8922 .size dvmAsmSisterStart, .-dvmAsmSisterStart
8923 .global dvmAsmSisterEnd
8926 /* File: armv5te/footer.S */
8929 * ===========================================================================
8930 * Common subroutines and data
8931 * ===========================================================================
8939 #if defined(WITH_JIT)
8940 #if defined(WITH_SELF_VERIFICATION)
8941 .global dvmJitToInterpPunt
8943 mov r2,#kSVSPunt @ r2<- interpreter entry point
8944 b dvmJitSelfVerificationEnd @ doesn't return
8946 .global dvmJitToInterpSingleStep
8947 dvmJitToInterpSingleStep:
8948 mov r2,#kSVSSingleStep @ r2<- interpreter entry point
8949 b dvmJitSelfVerificationEnd @ doesn't return
8951 .global dvmJitToTraceSelect
8952 dvmJitToTraceSelect:
8953 ldr r0,[r14, #-1] @ pass our target PC
8954 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
8955 b dvmJitSelfVerificationEnd @ doesn't return
8957 .global dvmJitToBackwardBranch
8958 dvmJitToBackwardBranch:
8959 ldr r0,[r14, #-1] @ pass our target PC
8960 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
8961 b dvmJitSelfVerificationEnd @ doesn't return
8963 .global dvmJitToInterpNormal
8964 dvmJitToInterpNormal:
8965 ldr r0,[r14, #-1] @ pass our target PC
8966 mov r2,#kSVSNormal @ r2<- interpreter entry point
8967 b dvmJitSelfVerificationEnd @ doesn't return
8969 .global dvmJitToInterpNoChain
8970 dvmJitToInterpNoChain:
8971 mov r0,rPC @ pass our target PC
8972 mov r2,#kSVSNoChain @ r2<- interpreter entry point
8973 b dvmJitSelfVerificationEnd @ doesn't return
8976 * Return from the translation cache to the interpreter when the compiler is
8977 * having issues translating/executing a Dalvik instruction. We have to skip
8978 * the code cache lookup otherwise it is possible to indefinitely bouce
8979 * between the interpreter and the code cache if the instruction that fails
8980 * to be compiled happens to be at a trace start.
8982 .global dvmJitToInterpPunt
8990 adrl rIBASE, dvmAsmInstructionStart
8996 * Return to the interpreter to handle a single instruction.
8999 * r1 <= PC of resume instruction
9000 * lr <= resume point in translation
9002 .global dvmJitToInterpSingleStep
9003 dvmJitToInterpSingleStep:
9004 str lr,[rGLUE,#offGlue_jitResume]
9005 str r1,[rGLUE,#offGlue_jitResumePC]
9006 mov r1,#kInterpEntryInstr
9007 @ enum is 4 byte in aapcs-EABI
9008 str r1, [rGLUE, #offGlue_entryPoint]
9011 adrl rIBASE, dvmAsmInstructionStart
9012 mov r2,#kJitSingleStep @ Ask for single step and then revert
9013 str r2,[rGLUE,#offGlue_jitState]
9014 mov r1,#1 @ set changeInterp to bail to debug interp
9019 * Return from the translation cache and immediately request
9020 * a translation for the exit target. Commonly used following
9023 .global dvmJitToTraceSelect
9024 dvmJitToTraceSelect:
9025 ldr rPC,[r14, #-1] @ get our target PC
9026 add rINST,r14,#-5 @ save start of chain branch
9028 bl dvmJitGetCodeAddr @ Is there a translation?
9032 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9033 cmp r0,#0 @ successful chain?
9034 bxne r0 @ continue native execution
9035 b toInterpreter @ didn't chain - resume with interpreter
9037 /* No translation, so request one if profiling isn't disabled*/
9039 adrl rIBASE, dvmAsmInstructionStart
9040 GET_JIT_PROF_TABLE(r0)
9043 bne common_selectTrace
9048 * Return from the translation cache to the interpreter.
9049 * The return was done with a BLX from thumb mode, and
9050 * the following 32-bit word contains the target rPC value.
9051 * Note that lr (r14) will have its low-order bit set to denote
9052 * its thumb-mode origin.
9054 * We'll need to stash our lr origin away, recover the new
9055 * target and then check to see if there is a translation available
9056 * for our new target. If so, we do a translation chain and
9057 * go back to native execution. Otherwise, it's back to the
9058 * interpreter (after treating this entry as a potential
9061 .global dvmJitToInterpNormal
9062 dvmJitToInterpNormal:
9063 ldr rPC,[r14, #-1] @ get our target PC
9064 add rINST,r14,#-5 @ save start of chain branch
9069 bl dvmJitGetCodeAddr @ Is there a translation?
9071 beq toInterpreter @ go if not, otherwise do chain
9073 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9074 cmp r0,#0 @ successful chain?
9075 bxne r0 @ continue native execution
9076 b toInterpreter @ didn't chain - resume with interpreter
9079 * Return from the translation cache to the interpreter to do method invocation.
9080 * Check if translation exists for the callee, but don't chain to it.
9082 .global dvmJitToInterpNoChain
9083 dvmJitToInterpNoChain:
9088 bl dvmJitGetCodeAddr @ Is there a translation?
9090 bxne r0 @ continue native execution if so
9094 * No translation, restore interpreter regs and start interpreting.
9095 * rGLUE & rFP were preserved in the translated code, and rPC has
9096 * already been restored by the time we get here. We'll need to set
9097 * up rIBASE & rINST, and load the address of the JitTable into r0.
9101 adrl rIBASE, dvmAsmInstructionStart
9103 GET_JIT_PROF_TABLE(r0)
9104 @ NOTE: intended fallthrough
9106 * Common code to update potential trace start counter, and initiate
9107 * a trace-build if appropriate. On entry, rPC should point to the
9108 * next instruction to execute, and rINST should be already loaded with
9109 * the next opcode word, and r0 holds a pointer to the jit profile
9110 * table (pJitProfTable).
9112 common_testUpdateProfile:
9115 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */
9117 common_updateProfile:
9118 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9119 lsl r3,r3,#23 @ shift out excess 511
9120 ldrb r1,[r0,r3,lsr #23] @ get counter
9122 subs r1,r1,#1 @ decrement counter
9123 strb r1,[r0,r3,lsr #23] @ and store it
9124 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
9127 * Here, we switch to the debug interpreter to request
9128 * trace selection. First, though, check to see if there
9129 * is already a native translation in place (and, if so,
9133 strb r1,[r0,r3,lsr #23] @ reset counter
9136 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
9138 beq common_selectTrace
9139 #if !defined(WITH_SELF_VERIFICATION)
9140 bxne r0 @ jump to the translation
9142 bne dvmJitSelfVerificationStart @ set up self verification
9145 mov r2,#kJitTSelectRequest @ ask for trace selection
9146 str r2,[rGLUE,#offGlue_jitState]
9147 mov r2,#kInterpEntryInstr @ normal entry reason
9148 str r2,[rGLUE,#offGlue_entryPoint]
9149 mov r1,#1 @ set changeInterp
9152 #if defined(WITH_SELF_VERIFICATION)
9154 * Save PC and registers to shadow memory for self verification mode
9155 * before jumping to native translation.
9157 dvmJitSelfVerificationStart:
9158 sub sp,sp,#4 @ allocate stack space
9159 str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
9160 mov r0,rPC @ r0<- program counter
9161 mov r1,rFP @ r1<- frame pointer
9162 mov r2,rGLUE @ r2<- InterpState pointer
9163 bl dvmSelfVerificationSaveState @ save registers to shadow space
9164 ldr rFP,[r0,#20] @ rFP<- fp in shadow space
9165 add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
9166 ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
9167 add sp,sp,#4 @ restore stack
9168 bx r0 @ jump to the translation
9171 * Restore PC, registers, and interpState to original values
9172 * before jumping back to the interpreter.
9174 dvmJitSelfVerificationEnd:
9175 mov r1,rFP @ pass ending fp
9176 bl dvmSelfVerificationRestoreState @ restore pc and fp values
9177 ldr rPC,[r0,#0] @ restore PC
9178 ldr rFP,[r0,#4] @ restore FP
9179 ldr rGLUE,[r0,#8] @ restore InterpState
9180 ldr r1,[r0,#12] @ get exitPoint
9181 cmp r1,#0 @ check for punt condition
9183 mov r2,#kJitSelfVerification @ ask for self verification
9184 str r2,[rGLUE,#offGlue_jitState]
9185 mov r2,#kInterpEntryInstr @ normal entry reason
9186 str r2,[rGLUE,#offGlue_entryPoint]
9187 mov r1,#1 @ set changeInterp
9190 1: @ exit to interpreter without check
9192 adrl rIBASE, dvmAsmInstructionStart
9201 * Common code when a backward branch is taken.
9204 * r9 is PC adjustment *in bytes*
9206 common_backwardBranch:
9207 mov r0, #kInterpEntryInstr
9208 bl common_periodicChecks
9209 #if defined(WITH_JIT)
9210 GET_JIT_PROF_TABLE(r0)
9211 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9213 bne common_updateProfile
9217 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9218 GET_INST_OPCODE(ip) @ extract opcode from rINST
9219 GOTO_OPCODE(ip) @ jump to next instruction
9224 * Need to see if the thread needs to be suspended or debugger/profiler
9225 * activity has begun.
9227 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9228 * have to do the second ldr.
9230 * TODO: reduce this so we're just checking a single location.
9233 * r0 is reentry type, e.g. kInterpEntryInstr
9234 * r9 is trampoline PC adjustment *in bytes*
9236 common_periodicChecks:
9237 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9239 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9240 str r0, [rGLUE, #offGlue_entryPoint]
9242 #if defined(WITH_DEBUGGER)
9243 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9245 #if defined(WITH_PROFILER)
9246 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9249 ldr r3, [r3] @ r3<- suspendCount (int)
9251 #if defined(WITH_DEBUGGER)
9252 ldrb r1, [r1] @ r1<- debuggerActive (boolean)
9254 #if defined (WITH_PROFILER)
9255 ldr r2, [r2] @ r2<- activeProfilers (int)
9258 cmp r3, #0 @ suspend pending?
9259 bne 2f @ yes, do full suspension check
9261 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9262 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9263 orrs r1, r1, r2 @ r1<- r1 | r2
9264 cmp r1, #0 @ debugger attached or profiler started?
9265 # elif defined(WITH_DEBUGGER)
9266 cmp r1, #0 @ debugger attached?
9267 # elif defined(WITH_PROFILER)
9268 cmp r2, #0 @ profiler started?
9270 bne 3f @ debugger/profiler, switch interp
9273 bx lr @ nothing to do, return
9276 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9277 EXPORT_PC() @ need for precise GC
9278 b dvmCheckSuspendPending @ suspend if necessary, then return
9280 3: @ debugger/profiler enabled, bail out
9281 add rPC, rPC, r9 @ update rPC
9282 mov r1, #1 @ "want switch" = true
9287 * The equivalent of "goto bail", this calls through the "bail handler".
9289 * State registers will be saved to the "glue" area before bailing.
9292 * r1 is "bool changeInterp", indicating if we want to switch to the
9293 * other interpreter or just bail all the way out
9296 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9297 mov r0, rGLUE @ r0<- glue ptr
9298 b dvmMterpStdBail @ call(glue, changeInterp)
9300 @add r1, r1, #1 @ using (boolean+1)
9301 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9302 @bl _longjmp @ does not return
9307 * Common code for method invocation with range.
9310 * r0 is "Method* methodToCall", the method we're trying to call
9312 common_invokeMethodRange:
9314 @ prepare to copy args to "outs" area of current frame
9315 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9316 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9317 beq .LinvokeArgsDone @ if no args, skip the rest
9318 FETCH(r1, 2) @ r1<- CCCC
9320 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9321 @ (very few methods have > 10 args; could unroll for common cases)
9322 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9323 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9324 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9325 1: ldr r1, [r3], #4 @ val = *fp++
9326 subs r2, r2, #1 @ count--
9327 str r1, [r10], #4 @ *outs++ = val
9328 bne 1b @ ...while count != 0
9329 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9333 * Common code for method invocation without range.
9336 * r0 is "Method* methodToCall", the method we're trying to call
9338 common_invokeMethodNoRange:
9340 @ prepare to copy args to "outs" area of current frame
9341 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9342 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9343 FETCH(r1, 2) @ r1<- GFED (load here to hide latency)
9344 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9345 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9346 beq .LinvokeArgsDone
9348 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9350 rsb r2, r2, #5 @ r2<- 5-r2
9351 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
9352 bl common_abort @ (skipped due to ARM prefetch)
9353 5: and ip, rINST, #0x0f00 @ isolate A
9354 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2)
9356 str r2, [r10, #-4]! @ *--outs = vA
9357 4: and ip, r1, #0xf000 @ isolate G
9358 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2)
9360 str r2, [r10, #-4]! @ *--outs = vG
9361 3: and ip, r1, #0x0f00 @ isolate F
9362 ldr r2, [rFP, ip, lsr #6] @ r2<- vF
9364 str r2, [r10, #-4]! @ *--outs = vF
9365 2: and ip, r1, #0x00f0 @ isolate E
9366 ldr r2, [rFP, ip, lsr #2] @ r2<- vE
9368 str r2, [r10, #-4]! @ *--outs = vE
9369 1: and ip, r1, #0x000f @ isolate D
9370 ldr r2, [rFP, ip, lsl #2] @ r2<- vD
9372 str r2, [r10, #-4]! @ *--outs = vD
9373 0: @ fall through to .LinvokeArgsDone
9375 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9376 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns
9377 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz
9378 @ find space for the new stack frame, check for overflow
9379 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
9380 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize)
9381 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
9382 @ bl common_dumpRegs
9383 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
9384 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
9385 cmp r3, r9 @ bottom < interpStackEnd?
9386 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9387 blt .LstackOverflow @ yes, this frame will overflow stack
9389 @ set up newSaveArea
9391 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
9392 str ip, [r10, #offStackSaveArea_prevSave]
9394 str rFP, [r10, #offStackSaveArea_prevFrame]
9395 str rPC, [r10, #offStackSaveArea_savedPc]
9396 #if defined(WITH_JIT)
9398 str r9, [r10, #offStackSaveArea_returnAddr]
9400 str r0, [r10, #offStackSaveArea_method]
9406 bl common_printNewline
9415 bl common_printNewline
9419 ldrh r9, [r2] @ r9 <- load INST from new PC
9420 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9421 mov rPC, r2 @ publish new rPC
9422 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
9424 @ Update "glue" values for the new method
9425 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9426 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
9427 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9428 #if defined(WITH_JIT)
9429 GET_JIT_PROF_TABLE(r0)
9430 mov rFP, r1 @ fp = newFp
9431 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9432 mov rINST, r9 @ publish new rINST
9433 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9435 bne common_updateProfile
9436 GOTO_OPCODE(ip) @ jump to next instruction
9438 mov rFP, r1 @ fp = newFp
9439 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9440 mov rINST, r9 @ publish new rINST
9441 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9442 GOTO_OPCODE(ip) @ jump to next instruction
9446 @ Prep for the native call
9447 @ r0=methodToCall, r1=newFp, r10=newSaveArea
9448 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9449 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9450 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
9451 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9452 mov r9, r3 @ r9<- glue->self (preserve)
9454 mov r2, r0 @ r2<- methodToCall
9455 mov r0, r1 @ r0<- newFp (points to args)
9456 add r1, rGLUE, #offGlue_retval @ r1<- &retval
9458 #ifdef ASSIST_DEBUGGER
9459 /* insert fake function header to help gdb find the stack frame */
9461 .type dalvik_mterp, %function
9469 @mov lr, pc @ set return addr
9470 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9471 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9473 @ native return; r9=self, r10=newSaveArea
9474 @ equivalent to dvmPopJniLocals
9475 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9476 ldr r1, [r9, #offThread_exception] @ check for exception
9477 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
9479 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9480 bne common_exceptionThrown @ no, handle exception
9482 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
9483 GET_INST_OPCODE(ip) @ extract opcode from rINST
9484 GOTO_OPCODE(ip) @ jump to next instruction
9486 .LstackOverflow: @ r0=methodToCall
9487 mov r1, r0 @ r1<- methodToCall
9488 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
9489 bl dvmHandleStackOverflow
9490 b common_exceptionThrown
9491 #ifdef ASSIST_DEBUGGER
9497 * Common code for method invocation, calling through "glue code".
9499 * TODO: now that we have range and non-range invoke handlers, this
9500 * needs to be split into two. Maybe just create entry points
9501 * that set r9 and jump here?
9504 * r0 is "Method* methodToCall", the method we're trying to call
9505 * r9 is "bool methodCallRange", indicating if this is a /range variant
9509 sub sp, sp, #8 @ space for args + pad
9510 FETCH(ip, 2) @ ip<- FEDC or CCCC
9511 mov r2, r0 @ A2<- methodToCall
9512 mov r0, rGLUE @ A0<- glue
9513 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9514 mov r1, r9 @ A1<- methodCallRange
9515 mov r3, rINST, lsr #8 @ A3<- AA
9516 str ip, [sp, #0] @ A4<- ip
9517 bl dvmMterp_invokeMethod @ call the C invokeMethod
9518 add sp, sp, #8 @ remove arg area
9519 b common_resumeAfterGlueCall @ continue to next instruction
9525 * Common code for handling a return instruction.
9527 * This does not return.
9529 common_returnFromMethod:
9531 mov r0, #kInterpEntryReturn
9533 bl common_periodicChecks
9535 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
9536 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9537 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9538 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9539 @ r2<- method we're returning to
9540 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9541 cmp r2, #0 @ is this a break frame?
9542 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9543 mov r1, #0 @ "want switch" = false
9544 beq common_gotoBail @ break frame, bail out completely
9546 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9547 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9548 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
9549 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
9550 #if defined(WITH_JIT)
9551 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9552 GET_JIT_PROF_TABLE(r0)
9553 mov rPC, r9 @ publish new rPC
9554 str r1, [rGLUE, #offGlue_methodClassDex]
9555 cmp r3, #0 @ caller is compiled code
9557 GET_INST_OPCODE(ip) @ extract opcode from rINST
9559 bne common_updateProfile
9560 GOTO_OPCODE(ip) @ jump to next instruction
9562 GET_INST_OPCODE(ip) @ extract opcode from rINST
9563 mov rPC, r9 @ publish new rPC
9564 str r1, [rGLUE, #offGlue_methodClassDex]
9565 GOTO_OPCODE(ip) @ jump to next instruction
9569 * Return handling, calls through "glue code".
9573 SAVE_PC_FP_TO_GLUE() @ export state
9574 mov r0, rGLUE @ arg to function
9575 bl dvmMterp_returnFromMethod
9576 b common_resumeAfterGlueCall
9581 * Somebody has thrown an exception. Handle it.
9583 * If the exception processing code returns to us (instead of falling
9584 * out of the interpreter), continue with whatever the next instruction
9585 * now happens to be.
9587 * This does not return.
9589 .global dvmMterpCommonExceptionThrown
9590 dvmMterpCommonExceptionThrown:
9591 common_exceptionThrown:
9593 mov r0, #kInterpEntryThrow
9595 bl common_periodicChecks
9597 #if defined(WITH_JIT)
9598 mov r2,#kJitTSelectAbort @ abandon trace selection in progress
9599 str r2,[rGLUE,#offGlue_jitState]
9602 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9603 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
9604 mov r1, r10 @ r1<- self
9605 mov r0, r9 @ r0<- exception
9606 bl dvmAddTrackedAlloc @ don't let the exception be GCed
9607 mov r3, #0 @ r3<- NULL
9608 str r3, [r10, #offThread_exception] @ self->exception = NULL
9610 /* set up args and a local for "&fp" */
9611 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
9612 str rFP, [sp, #-4]! @ *--sp = fp
9613 mov ip, sp @ ip<- &fp
9614 mov r3, #0 @ r3<- false
9615 str ip, [sp, #-4]! @ *--sp = &fp
9616 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9617 mov r0, r10 @ r0<- self
9618 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
9619 mov r2, r9 @ r2<- exception
9620 sub r1, rPC, r1 @ r1<- pc - method->insns
9621 mov r1, r1, asr #1 @ r1<- offset in code units
9623 /* call, r0 gets catchRelPc (a code-unit offset) */
9624 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
9626 /* fix earlier stack overflow if necessary; may trash rFP */
9627 ldrb r1, [r10, #offThread_stackOverflowed]
9628 cmp r1, #0 @ did we overflow earlier?
9629 beq 1f @ no, skip ahead
9630 mov rFP, r0 @ save relPc result in rFP
9631 mov r0, r10 @ r0<- self
9632 bl dvmCleanupStackOverflow @ call(self)
9633 mov r0, rFP @ restore result
9636 /* update frame pointer and check result from dvmFindCatchBlock */
9637 ldr rFP, [sp, #4] @ retrieve the updated rFP
9638 cmp r0, #0 @ is catchRelPc < 0?
9639 add sp, sp, #8 @ restore stack
9640 bmi .LnotCaughtLocally
9642 /* adjust locals to match self->curFrame and updated PC */
9643 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
9644 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
9645 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
9646 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
9647 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
9648 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9649 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
9650 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9652 /* release the tracked alloc on the exception */
9653 mov r0, r9 @ r0<- exception
9654 mov r1, r10 @ r1<- self
9655 bl dvmReleaseTrackedAlloc @ release the exception
9657 /* restore the exception if the handler wants it */
9658 FETCH_INST() @ load rINST from rPC
9659 GET_INST_OPCODE(ip) @ extract opcode from rINST
9660 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
9661 streq r9, [r10, #offThread_exception] @ yes, restore the exception
9662 GOTO_OPCODE(ip) @ jump to next instruction
9664 .LnotCaughtLocally: @ r9=exception, r10=self
9665 /* fix stack overflow if necessary */
9666 ldrb r1, [r10, #offThread_stackOverflowed]
9667 cmp r1, #0 @ did we overflow earlier?
9668 movne r0, r10 @ if yes: r0<- self
9669 blne dvmCleanupStackOverflow @ if yes: call(self)
9671 @ may want to show "not caught locally" debug messages here
9672 #if DVM_SHOW_EXCEPTION >= 2
9673 /* call __android_log_print(prio, tag, format, ...) */
9674 /* "Exception %s from %s:%d not caught locally" */
9675 @ dvmLineNumFromPC(method, pc - method->insns)
9676 ldr r0, [rGLUE, #offGlue_method]
9677 ldr r1, [r0, #offMethod_insns]
9682 @ dvmGetMethodSourceFile(method)
9683 ldr r0, [rGLUE, #offGlue_method]
9684 bl dvmGetMethodSourceFile
9686 @ exception->clazz->descriptor
9687 ldr r3, [r9, #offObject_clazz]
9688 ldr r3, [r3, #offClassObject_descriptor]
9690 ldr r2, strExceptionNotCaughtLocally
9692 mov r0, #3 @ LOG_DEBUG
9693 bl __android_log_print
9695 str r9, [r10, #offThread_exception] @ restore exception
9696 mov r0, r9 @ r0<- exception
9697 mov r1, r10 @ r1<- self
9698 bl dvmReleaseTrackedAlloc @ release the exception
9699 mov r1, #0 @ "want switch" = false
9700 b common_gotoBail @ bail out
9704 * Exception handling, calls through "glue code".
9708 SAVE_PC_FP_TO_GLUE() @ export state
9709 mov r0, rGLUE @ arg to function
9710 bl dvmMterp_exceptionThrown
9711 b common_resumeAfterGlueCall
9716 * After returning from a "glued" function, pull out the updated
9717 * values and start executing at the next instruction.
9719 common_resumeAfterGlueCall:
9720 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
9721 FETCH_INST() @ load rINST from rPC
9722 GET_INST_OPCODE(ip) @ extract opcode from rINST
9723 GOTO_OPCODE(ip) @ jump to next instruction
9726 * Invalid array index.
9728 common_errArrayIndex:
9730 ldr r0, strArrayIndexException
9732 bl dvmThrowException
9733 b common_exceptionThrown
9736 * Invalid array value.
9738 common_errArrayStore:
9740 ldr r0, strArrayStoreException
9742 bl dvmThrowException
9743 b common_exceptionThrown
9746 * Integer divide or mod by zero.
9748 common_errDivideByZero:
9750 ldr r0, strArithmeticException
9751 ldr r1, strDivideByZero
9752 bl dvmThrowException
9753 b common_exceptionThrown
9756 * Attempt to allocate an array with a negative size.
9758 common_errNegativeArraySize:
9760 ldr r0, strNegativeArraySizeException
9762 bl dvmThrowException
9763 b common_exceptionThrown
9766 * Invocation of a non-existent method.
9768 common_errNoSuchMethod:
9770 ldr r0, strNoSuchMethodError
9772 bl dvmThrowException
9773 b common_exceptionThrown
9776 * We encountered a null object when we weren't expecting one. We
9777 * export the PC, throw a NullPointerException, and goto the exception
9780 common_errNullObject:
9782 ldr r0, strNullPointerException
9784 bl dvmThrowException
9785 b common_exceptionThrown
9788 * For debugging, cause an immediate fault. The source address will
9789 * be in lr (use a bl instruction to jump here).
9797 * Spit out a "we were here", preserving all registers. (The attempt
9798 * to save ip won't work, but we need to save an even number of
9799 * registers for EABI 64-bit stack alignment.)
9803 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9807 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9819 * Spit out the number in r0, preserving registers.
9822 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9826 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9830 * Print a newline, preserving registers.
9832 common_printNewline:
9833 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9836 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9840 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9843 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9847 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9851 * Print the 64-bit quantity in r0-r1, preserving registers.
9854 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9857 ldr r0, strPrintLong
9859 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9863 * Print full method info. Pass the Method* in r0. Preserves regs.
9866 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9867 bl dvmMterpPrintMethod
9868 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9872 * Call a C helper function that dumps regs and possibly some
9873 * additional info. Requires the C function to be compiled in.
9877 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9878 bl dvmMterpDumpArmRegs
9879 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9885 * Experiment on VFP mode.
9887 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
9889 * Updates the bits specified by "mask", setting them to the values in "val".
9892 and r0, r0, r1 @ make sure no stray bits are set
9893 fmrx r2, fpscr @ get VFP reg
9894 mvn r1, r1 @ bit-invert mask
9895 and r2, r2, r1 @ clear masked bits
9896 orr r2, r2, r0 @ set specified bits
9897 fmxr fpscr, r2 @ set VFP reg
9898 mov r0, r2 @ return new value
9902 .global dvmConfigureFP
9903 .type dvmConfigureFP, %function
9906 /* 0x03000000 sets DN/FZ */
9907 /* 0x00009f00 clears the six exception enable flags */
9909 mov r0, #0x03000000 @ r0<- 0x03000000
9910 add r1, r0, #0x9f00 @ r1<- 0x03009f00
9917 * String references, must be close to the code that uses them.
9920 strArithmeticException:
9921 .word .LstrArithmeticException
9922 strArrayIndexException:
9923 .word .LstrArrayIndexException
9924 strArrayStoreException:
9925 .word .LstrArrayStoreException
9927 .word .LstrDivideByZero
9928 strNegativeArraySizeException:
9929 .word .LstrNegativeArraySizeException
9930 strNoSuchMethodError:
9931 .word .LstrNoSuchMethodError
9932 strNullPointerException:
9933 .word .LstrNullPointerException
9937 strExceptionNotCaughtLocally:
9938 .word .LstrExceptionNotCaughtLocally
9947 .word .LstrPrintLong
9950 * Zero-terminated ASCII string data.
9952 * On ARM we have two choices: do like gcc does, and LDR from a .word
9953 * with the address, or use an ADR pseudo-op to get the address
9954 * directly. ADR saves 4 bytes and an indirection, but it's using a
9955 * PC-relative addressing mode and hence has a limited range, which
9956 * makes it not work well with mergeable string sections.
9958 .section .rodata.str1.4,"aMS",%progbits,1
9961 .asciz "Bad entry point %d\n"
9962 .LstrArithmeticException:
9963 .asciz "Ljava/lang/ArithmeticException;"
9964 .LstrArrayIndexException:
9965 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
9966 .LstrArrayStoreException:
9967 .asciz "Ljava/lang/ArrayStoreException;"
9968 .LstrClassCastException:
9969 .asciz "Ljava/lang/ClassCastException;"
9971 .asciz "divide by zero"
9972 .LstrFilledNewArrayNotImpl:
9973 .asciz "filled-new-array only implemented for objects and 'int'"
9975 .asciz "Ljava/lang/InternalError;"
9976 .LstrInstantiationError:
9977 .asciz "Ljava/lang/InstantiationError;"
9978 .LstrNegativeArraySizeException:
9979 .asciz "Ljava/lang/NegativeArraySizeException;"
9980 .LstrNoSuchMethodError:
9981 .asciz "Ljava/lang/NoSuchMethodError;"
9982 .LstrNullPointerException:
9983 .asciz "Ljava/lang/NullPointerException;"
9987 .LstrExceptionNotCaughtLocally:
9988 .asciz "Exception %s from %s:%d not caught locally\n"