2 * This file was generated automatically by gen-mterp.py for 'armv5te'.
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: armv5te/OP_MOVE.S */
419 /* for move, move-object, long-to-int */
421 mov r1, rINST, lsr #12 @ r1<- B from 15:12
422 mov r0, rINST, lsr #8 @ r0<- A from 11:8
423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
424 GET_VREG(r2, r1) @ r2<- fp[B]
426 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
427 SET_VREG(r2, r0) @ fp[A]<- r2
428 GOTO_OPCODE(ip) @ execute next instruction
431 /* ------------------------------ */
433 .L_OP_MOVE_FROM16: /* 0x02 */
434 /* File: armv5te/OP_MOVE_FROM16.S */
435 /* for: move/from16, move-object/from16 */
437 FETCH(r1, 1) @ r1<- BBBB
438 mov r0, rINST, lsr #8 @ r0<- AA
439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
440 GET_VREG(r2, r1) @ r2<- fp[BBBB]
441 GET_INST_OPCODE(ip) @ extract opcode from rINST
442 SET_VREG(r2, r0) @ fp[AA]<- r2
443 GOTO_OPCODE(ip) @ jump to next instruction
446 /* ------------------------------ */
448 .L_OP_MOVE_16: /* 0x03 */
449 /* File: armv5te/OP_MOVE_16.S */
450 /* for: move/16, move-object/16 */
451 /* op vAAAA, vBBBB */
452 FETCH(r1, 2) @ r1<- BBBB
453 FETCH(r0, 1) @ r0<- AAAA
454 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
455 GET_VREG(r2, r1) @ r2<- fp[BBBB]
456 GET_INST_OPCODE(ip) @ extract opcode from rINST
457 SET_VREG(r2, r0) @ fp[AAAA]<- r2
458 GOTO_OPCODE(ip) @ jump to next instruction
461 /* ------------------------------ */
463 .L_OP_MOVE_WIDE: /* 0x04 */
464 /* File: armv5te/OP_MOVE_WIDE.S */
465 /* move-wide vA, vB */
466 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
467 mov r2, rINST, lsr #8 @ r2<- A(+)
468 mov r3, rINST, lsr #12 @ r3<- B
470 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
471 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
472 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
473 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
474 GET_INST_OPCODE(ip) @ extract opcode from rINST
475 stmia r2, {r0-r1} @ fp[A]<- r0/r1
476 GOTO_OPCODE(ip) @ jump to next instruction
479 /* ------------------------------ */
481 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
482 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
483 /* move-wide/from16 vAA, vBBBB */
484 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
485 FETCH(r3, 1) @ r3<- BBBB
486 mov r2, rINST, lsr #8 @ r2<- AA
487 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
488 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
489 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
490 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
491 GET_INST_OPCODE(ip) @ extract opcode from rINST
492 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
493 GOTO_OPCODE(ip) @ jump to next instruction
496 /* ------------------------------ */
498 .L_OP_MOVE_WIDE_16: /* 0x06 */
499 /* File: armv5te/OP_MOVE_WIDE_16.S */
500 /* move-wide/16 vAAAA, vBBBB */
501 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
502 FETCH(r3, 2) @ r3<- BBBB
503 FETCH(r2, 1) @ r2<- AAAA
504 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
505 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
506 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
507 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
508 GET_INST_OPCODE(ip) @ extract opcode from rINST
509 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
510 GOTO_OPCODE(ip) @ jump to next instruction
513 /* ------------------------------ */
515 .L_OP_MOVE_OBJECT: /* 0x07 */
516 /* File: armv5te/OP_MOVE_OBJECT.S */
517 /* File: armv5te/OP_MOVE.S */
518 /* for move, move-object, long-to-int */
520 mov r1, rINST, lsr #12 @ r1<- B from 15:12
521 mov r0, rINST, lsr #8 @ r0<- A from 11:8
522 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
523 GET_VREG(r2, r1) @ r2<- fp[B]
525 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
526 SET_VREG(r2, r0) @ fp[A]<- r2
527 GOTO_OPCODE(ip) @ execute next instruction
531 /* ------------------------------ */
533 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
534 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
535 /* File: armv5te/OP_MOVE_FROM16.S */
536 /* for: move/from16, move-object/from16 */
538 FETCH(r1, 1) @ r1<- BBBB
539 mov r0, rINST, lsr #8 @ r0<- AA
540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
541 GET_VREG(r2, r1) @ r2<- fp[BBBB]
542 GET_INST_OPCODE(ip) @ extract opcode from rINST
543 SET_VREG(r2, r0) @ fp[AA]<- r2
544 GOTO_OPCODE(ip) @ jump to next instruction
548 /* ------------------------------ */
550 .L_OP_MOVE_OBJECT_16: /* 0x09 */
551 /* File: armv5te/OP_MOVE_OBJECT_16.S */
552 /* File: armv5te/OP_MOVE_16.S */
553 /* for: move/16, move-object/16 */
554 /* op vAAAA, vBBBB */
555 FETCH(r1, 2) @ r1<- BBBB
556 FETCH(r0, 1) @ r0<- AAAA
557 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
558 GET_VREG(r2, r1) @ r2<- fp[BBBB]
559 GET_INST_OPCODE(ip) @ extract opcode from rINST
560 SET_VREG(r2, r0) @ fp[AAAA]<- r2
561 GOTO_OPCODE(ip) @ jump to next instruction
565 /* ------------------------------ */
567 .L_OP_MOVE_RESULT: /* 0x0a */
568 /* File: armv5te/OP_MOVE_RESULT.S */
569 /* for: move-result, move-result-object */
571 mov r2, rINST, lsr #8 @ r2<- AA
572 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
573 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
574 GET_INST_OPCODE(ip) @ extract opcode from rINST
575 SET_VREG(r0, r2) @ fp[AA]<- r0
576 GOTO_OPCODE(ip) @ jump to next instruction
579 /* ------------------------------ */
581 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
582 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
583 /* move-result-wide vAA */
584 mov r2, rINST, lsr #8 @ r2<- AA
585 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
586 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
587 ldmia r3, {r0-r1} @ r0/r1<- retval.j
588 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
589 GET_INST_OPCODE(ip) @ extract opcode from rINST
590 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
591 GOTO_OPCODE(ip) @ jump to next instruction
594 /* ------------------------------ */
596 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
597 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
598 /* File: armv5te/OP_MOVE_RESULT.S */
599 /* for: move-result, move-result-object */
601 mov r2, rINST, lsr #8 @ r2<- AA
602 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
603 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
604 GET_INST_OPCODE(ip) @ extract opcode from rINST
605 SET_VREG(r0, r2) @ fp[AA]<- r0
606 GOTO_OPCODE(ip) @ jump to next instruction
610 /* ------------------------------ */
612 .L_OP_MOVE_EXCEPTION: /* 0x0d */
613 /* File: armv5te/OP_MOVE_EXCEPTION.S */
614 /* move-exception vAA */
615 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
616 mov r2, rINST, lsr #8 @ r2<- AA
617 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
620 SET_VREG(r3, r2) @ fp[AA]<- exception obj
621 GET_INST_OPCODE(ip) @ extract opcode from rINST
622 str r1, [r0, #offThread_exception] @ dvmClearException bypass
623 GOTO_OPCODE(ip) @ jump to next instruction
626 /* ------------------------------ */
628 .L_OP_RETURN_VOID: /* 0x0e */
629 /* File: armv5te/OP_RETURN_VOID.S */
630 b common_returnFromMethod
633 /* ------------------------------ */
635 .L_OP_RETURN: /* 0x0f */
636 /* File: armv5te/OP_RETURN.S */
638 * Return a 32-bit value. Copies the return value into the "glue"
639 * structure, then jumps to the return handler.
641 * for: return, return-object
644 mov r2, rINST, lsr #8 @ r2<- AA
645 GET_VREG(r0, r2) @ r0<- vAA
646 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647 b common_returnFromMethod
650 /* ------------------------------ */
652 .L_OP_RETURN_WIDE: /* 0x10 */
653 /* File: armv5te/OP_RETURN_WIDE.S */
655 * Return a 64-bit value. Copies the return value into the "glue"
656 * structure, then jumps to the return handler.
658 /* return-wide vAA */
659 mov r2, rINST, lsr #8 @ r2<- AA
660 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
661 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
662 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
663 stmia r3, {r0-r1} @ retval<- r0/r1
664 b common_returnFromMethod
667 /* ------------------------------ */
669 .L_OP_RETURN_OBJECT: /* 0x11 */
670 /* File: armv5te/OP_RETURN_OBJECT.S */
671 /* File: armv5te/OP_RETURN.S */
673 * Return a 32-bit value. Copies the return value into the "glue"
674 * structure, then jumps to the return handler.
676 * for: return, return-object
679 mov r2, rINST, lsr #8 @ r2<- AA
680 GET_VREG(r0, r2) @ r0<- vAA
681 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
682 b common_returnFromMethod
686 /* ------------------------------ */
688 .L_OP_CONST_4: /* 0x12 */
689 /* File: armv5te/OP_CONST_4.S */
690 /* const/4 vA, #+B */
691 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
692 mov r0, rINST, lsr #8 @ r0<- A+
693 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
694 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
696 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
697 SET_VREG(r1, r0) @ fp[A]<- r1
698 GOTO_OPCODE(ip) @ execute next instruction
701 /* ------------------------------ */
703 .L_OP_CONST_16: /* 0x13 */
704 /* File: armv5te/OP_CONST_16.S */
705 /* const/16 vAA, #+BBBB */
706 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
707 mov r3, rINST, lsr #8 @ r3<- AA
708 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
709 SET_VREG(r0, r3) @ vAA<- r0
710 GET_INST_OPCODE(ip) @ extract opcode from rINST
711 GOTO_OPCODE(ip) @ jump to next instruction
714 /* ------------------------------ */
716 .L_OP_CONST: /* 0x14 */
717 /* File: armv5te/OP_CONST.S */
718 /* const vAA, #+BBBBbbbb */
719 mov r3, rINST, lsr #8 @ r3<- AA
720 FETCH(r0, 1) @ r0<- bbbb (low)
721 FETCH(r1, 2) @ r1<- BBBB (high)
722 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
723 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
724 GET_INST_OPCODE(ip) @ extract opcode from rINST
725 SET_VREG(r0, r3) @ vAA<- r0
726 GOTO_OPCODE(ip) @ jump to next instruction
729 /* ------------------------------ */
731 .L_OP_CONST_HIGH16: /* 0x15 */
732 /* File: armv5te/OP_CONST_HIGH16.S */
733 /* const/high16 vAA, #+BBBB0000 */
734 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
735 mov r3, rINST, lsr #8 @ r3<- AA
736 mov r0, r0, lsl #16 @ r0<- BBBB0000
737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
738 SET_VREG(r0, r3) @ vAA<- r0
739 GET_INST_OPCODE(ip) @ extract opcode from rINST
740 GOTO_OPCODE(ip) @ jump to next instruction
743 /* ------------------------------ */
745 .L_OP_CONST_WIDE_16: /* 0x16 */
746 /* File: armv5te/OP_CONST_WIDE_16.S */
747 /* const-wide/16 vAA, #+BBBB */
748 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
749 mov r3, rINST, lsr #8 @ r3<- AA
750 mov r1, r0, asr #31 @ r1<- ssssssss
751 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
752 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
753 GET_INST_OPCODE(ip) @ extract opcode from rINST
754 stmia r3, {r0-r1} @ vAA<- r0/r1
755 GOTO_OPCODE(ip) @ jump to next instruction
758 /* ------------------------------ */
760 .L_OP_CONST_WIDE_32: /* 0x17 */
761 /* File: armv5te/OP_CONST_WIDE_32.S */
762 /* const-wide/32 vAA, #+BBBBbbbb */
763 FETCH(r0, 1) @ r0<- 0000bbbb (low)
764 mov r3, rINST, lsr #8 @ r3<- AA
765 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
766 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
767 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
768 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
769 mov r1, r0, asr #31 @ r1<- ssssssss
770 GET_INST_OPCODE(ip) @ extract opcode from rINST
771 stmia r3, {r0-r1} @ vAA<- r0/r1
772 GOTO_OPCODE(ip) @ jump to next instruction
775 /* ------------------------------ */
777 .L_OP_CONST_WIDE: /* 0x18 */
778 /* File: armv5te/OP_CONST_WIDE.S */
779 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
780 FETCH(r0, 1) @ r0<- bbbb (low)
781 FETCH(r1, 2) @ r1<- BBBB (low middle)
782 FETCH(r2, 3) @ r2<- hhhh (high middle)
783 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
784 FETCH(r3, 4) @ r3<- HHHH (high)
785 mov r9, rINST, lsr #8 @ r9<- AA
786 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
787 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
788 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
789 GET_INST_OPCODE(ip) @ extract opcode from rINST
790 stmia r9, {r0-r1} @ vAA<- r0/r1
791 GOTO_OPCODE(ip) @ jump to next instruction
794 /* ------------------------------ */
796 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
797 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
798 /* const-wide/high16 vAA, #+BBBB000000000000 */
799 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
800 mov r3, rINST, lsr #8 @ r3<- AA
801 mov r0, #0 @ r0<- 00000000
802 mov r1, r1, lsl #16 @ r1<- BBBB0000
803 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
804 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
805 GET_INST_OPCODE(ip) @ extract opcode from rINST
806 stmia r3, {r0-r1} @ vAA<- r0/r1
807 GOTO_OPCODE(ip) @ jump to next instruction
810 /* ------------------------------ */
812 .L_OP_CONST_STRING: /* 0x1a */
813 /* File: armv5te/OP_CONST_STRING.S */
814 /* const/string vAA, String@BBBB */
815 FETCH(r1, 1) @ r1<- BBBB
816 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
817 mov r9, rINST, lsr #8 @ r9<- AA
818 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
819 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
820 cmp r0, #0 @ not yet resolved?
821 beq .LOP_CONST_STRING_resolve
822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
823 GET_INST_OPCODE(ip) @ extract opcode from rINST
824 SET_VREG(r0, r9) @ vAA<- r0
825 GOTO_OPCODE(ip) @ jump to next instruction
827 /* ------------------------------ */
829 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
830 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
831 /* const/string vAA, String@BBBBBBBB */
832 FETCH(r0, 1) @ r0<- bbbb (low)
833 FETCH(r1, 2) @ r1<- BBBB (high)
834 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
835 mov r9, rINST, lsr #8 @ r9<- AA
836 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
837 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
838 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
840 beq .LOP_CONST_STRING_JUMBO_resolve
841 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
842 GET_INST_OPCODE(ip) @ extract opcode from rINST
843 SET_VREG(r0, r9) @ vAA<- r0
844 GOTO_OPCODE(ip) @ jump to next instruction
846 /* ------------------------------ */
848 .L_OP_CONST_CLASS: /* 0x1c */
849 /* File: armv5te/OP_CONST_CLASS.S */
850 /* const/class vAA, Class@BBBB */
851 FETCH(r1, 1) @ r1<- BBBB
852 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
853 mov r9, rINST, lsr #8 @ r9<- AA
854 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
855 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
856 cmp r0, #0 @ not yet resolved?
857 beq .LOP_CONST_CLASS_resolve
858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
859 GET_INST_OPCODE(ip) @ extract opcode from rINST
860 SET_VREG(r0, r9) @ vAA<- r0
861 GOTO_OPCODE(ip) @ jump to next instruction
863 /* ------------------------------ */
865 .L_OP_MONITOR_ENTER: /* 0x1d */
866 /* File: armv5te/OP_MONITOR_ENTER.S */
868 * Synchronize on an object.
870 /* monitor-enter vAA */
871 mov r2, rINST, lsr #8 @ r2<- AA
872 GET_VREG(r1, r2) @ r1<- vAA (object)
873 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
874 cmp r1, #0 @ null object?
875 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING
876 beq common_errNullObject @ null object, throw an exception
877 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
878 bl dvmLockObject @ call(self, obj)
879 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
880 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
881 ldr r1, [r0, #offThread_exception] @ check for exception
883 bne common_exceptionThrown @ exception raised, bail out
885 GET_INST_OPCODE(ip) @ extract opcode from rINST
886 GOTO_OPCODE(ip) @ jump to next instruction
889 /* ------------------------------ */
891 .L_OP_MONITOR_EXIT: /* 0x1e */
892 /* File: armv5te/OP_MONITOR_EXIT.S */
896 * Exceptions that occur when unlocking a monitor need to appear as
897 * if they happened at the following instruction. See the Dalvik
900 /* monitor-exit vAA */
901 mov r2, rINST, lsr #8 @ r2<- AA
902 EXPORT_PC() @ before fetch: export the PC
903 GET_VREG(r1, r2) @ r1<- vAA (object)
904 cmp r1, #0 @ null object?
905 beq common_errNullObject @ yes
906 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
907 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
909 beq common_exceptionThrown @ yes, exception is pending
910 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
911 GET_INST_OPCODE(ip) @ extract opcode from rINST
912 GOTO_OPCODE(ip) @ jump to next instruction
915 /* ------------------------------ */
917 .L_OP_CHECK_CAST: /* 0x1f */
918 /* File: armv5te/OP_CHECK_CAST.S */
920 * Check to see if a cast from one class to another is allowed.
922 /* check-cast vAA, class@BBBB */
923 mov r3, rINST, lsr #8 @ r3<- AA
924 FETCH(r2, 1) @ r2<- BBBB
925 GET_VREG(r9, r3) @ r9<- object
926 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
927 cmp r9, #0 @ is object null?
928 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
929 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
930 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
931 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
932 cmp r1, #0 @ have we resolved this before?
933 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
934 .LOP_CHECK_CAST_resolved:
935 cmp r0, r1 @ same class (trivial success)?
936 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
937 .LOP_CHECK_CAST_okay:
938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
939 GET_INST_OPCODE(ip) @ extract opcode from rINST
940 GOTO_OPCODE(ip) @ jump to next instruction
942 /* ------------------------------ */
944 .L_OP_INSTANCE_OF: /* 0x20 */
945 /* File: armv5te/OP_INSTANCE_OF.S */
947 * Check to see if an object reference is an instance of a class.
949 * Most common situation is a non-null object, being compared against
950 * an already-resolved class.
952 /* instance-of vA, vB, class@CCCC */
953 mov r3, rINST, lsr #12 @ r3<- B
954 mov r9, rINST, lsr #8 @ r9<- A+
955 GET_VREG(r0, r3) @ r0<- vB (object)
956 and r9, r9, #15 @ r9<- A
957 cmp r0, #0 @ is object null?
958 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
959 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
960 FETCH(r3, 1) @ r3<- CCCC
961 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
962 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
963 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
964 cmp r1, #0 @ have we resolved this before?
965 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
966 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
967 cmp r0, r1 @ same class (trivial success)?
968 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
969 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
971 /* ------------------------------ */
973 .L_OP_ARRAY_LENGTH: /* 0x21 */
974 /* File: armv5te/OP_ARRAY_LENGTH.S */
976 * Return the length of an array.
978 mov r1, rINST, lsr #12 @ r1<- B
979 mov r2, rINST, lsr #8 @ r2<- A+
980 GET_VREG(r0, r1) @ r0<- vB (object ref)
981 and r2, r2, #15 @ r2<- A
982 cmp r0, #0 @ is object null?
983 beq common_errNullObject @ yup, fail
984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
985 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
986 GET_INST_OPCODE(ip) @ extract opcode from rINST
987 SET_VREG(r3, r2) @ vB<- length
988 GOTO_OPCODE(ip) @ jump to next instruction
991 /* ------------------------------ */
993 .L_OP_NEW_INSTANCE: /* 0x22 */
994 /* File: armv5te/OP_NEW_INSTANCE.S */
996 * Create a new instance of a class.
998 /* new-instance vAA, class@BBBB */
999 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1000 FETCH(r1, 1) @ r1<- BBBB
1001 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1002 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1003 EXPORT_PC() @ req'd for init, resolve, alloc
1004 cmp r0, #0 @ already resolved?
1005 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
1006 .LOP_NEW_INSTANCE_resolved: @ r0=class
1007 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
1008 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
1009 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
1010 .LOP_NEW_INSTANCE_initialized: @ r0=class
1011 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
1012 bl dvmAllocObject @ r0<- new object
1013 b .LOP_NEW_INSTANCE_finish @ continue
1015 /* ------------------------------ */
1017 .L_OP_NEW_ARRAY: /* 0x23 */
1018 /* File: armv5te/OP_NEW_ARRAY.S */
1020 * Allocate an array of objects, specified with the array class
1023 * The verifier guarantees that this is an array class, so we don't
1024 * check for it here.
1026 /* new-array vA, vB, class@CCCC */
1027 mov r0, rINST, lsr #12 @ r0<- B
1028 FETCH(r2, 1) @ r2<- CCCC
1029 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1030 GET_VREG(r1, r0) @ r1<- vB (array length)
1031 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1032 cmp r1, #0 @ check length
1033 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
1034 bmi common_errNegativeArraySize @ negative length, bail
1035 cmp r0, #0 @ already resolved?
1036 EXPORT_PC() @ req'd for resolve, alloc
1037 bne .LOP_NEW_ARRAY_finish @ resolved, continue
1038 b .LOP_NEW_ARRAY_resolve @ do resolve now
1040 /* ------------------------------ */
1042 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1043 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1045 * Create a new array with elements filled from registers.
1047 * for: filled-new-array, filled-new-array/range
1049 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1050 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1051 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1052 FETCH(r1, 1) @ r1<- BBBB
1053 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1054 EXPORT_PC() @ need for resolve and alloc
1055 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1056 mov r10, rINST, lsr #8 @ r10<- AA or BA
1057 cmp r0, #0 @ already resolved?
1058 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
1059 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1060 mov r2, #0 @ r2<- false
1061 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1062 bl dvmResolveClass @ r0<- call(clazz, ref)
1063 cmp r0, #0 @ got null?
1064 beq common_exceptionThrown @ yes, handle exception
1065 b .LOP_FILLED_NEW_ARRAY_continue
1067 /* ------------------------------ */
1069 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1070 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1071 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1073 * Create a new array with elements filled from registers.
1075 * for: filled-new-array, filled-new-array/range
1077 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1078 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1079 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1080 FETCH(r1, 1) @ r1<- BBBB
1081 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1082 EXPORT_PC() @ need for resolve and alloc
1083 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1084 mov r10, rINST, lsr #8 @ r10<- AA or BA
1085 cmp r0, #0 @ already resolved?
1086 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
1087 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1088 mov r2, #0 @ r2<- false
1089 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1090 bl dvmResolveClass @ r0<- call(clazz, ref)
1091 cmp r0, #0 @ got null?
1092 beq common_exceptionThrown @ yes, handle exception
1093 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1096 /* ------------------------------ */
1098 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1099 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1100 /* fill-array-data vAA, +BBBBBBBB */
1101 FETCH(r0, 1) @ r0<- bbbb (lo)
1102 FETCH(r1, 2) @ r1<- BBBB (hi)
1103 mov r3, rINST, lsr #8 @ r3<- AA
1104 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1105 GET_VREG(r0, r3) @ r0<- vAA (array object)
1106 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1108 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1109 cmp r0, #0 @ 0 means an exception is thrown
1110 beq common_exceptionThrown @ has exception
1111 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1112 GET_INST_OPCODE(ip) @ extract opcode from rINST
1113 GOTO_OPCODE(ip) @ jump to next instruction
1115 /* ------------------------------ */
1117 .L_OP_THROW: /* 0x27 */
1118 /* File: armv5te/OP_THROW.S */
1120 * Throw an exception object in the current thread.
1123 mov r2, rINST, lsr #8 @ r2<- AA
1124 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1125 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1126 cmp r1, #0 @ null object?
1127 beq common_errNullObject @ yes, throw an NPE instead
1128 @ bypass dvmSetException, just store it
1129 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1130 b common_exceptionThrown
1133 /* ------------------------------ */
1135 .L_OP_GOTO: /* 0x28 */
1136 /* File: armv5te/OP_GOTO.S */
1138 * Unconditional branch, 8-bit offset.
1140 * The branch distance is a signed code-unit offset, which we need to
1141 * double to get a byte offset.
1144 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1145 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1146 mov r9, r9, lsl #1 @ r9<- byte offset
1147 bmi common_backwardBranch @ backward branch, do periodic checks
1148 #if defined(WITH_JIT)
1149 GET_JIT_PROF_TABLE(r0)
1150 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1152 bne common_updateProfile
1153 GET_INST_OPCODE(ip) @ extract opcode from rINST
1154 GOTO_OPCODE(ip) @ jump to next instruction
1156 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1157 GET_INST_OPCODE(ip) @ extract opcode from rINST
1158 GOTO_OPCODE(ip) @ jump to next instruction
1161 /* ------------------------------ */
1163 .L_OP_GOTO_16: /* 0x29 */
1164 /* File: armv5te/OP_GOTO_16.S */
1166 * Unconditional branch, 16-bit offset.
1168 * The branch distance is a signed code-unit offset, which we need to
1169 * double to get a byte offset.
1172 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1173 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1174 bmi common_backwardBranch @ backward branch, do periodic checks
1175 #if defined(WITH_JIT)
1176 GET_JIT_PROF_TABLE(r0)
1177 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1179 bne common_updateProfile
1180 GET_INST_OPCODE(ip) @ extract opcode from rINST
1181 GOTO_OPCODE(ip) @ jump to next instruction
1183 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1184 GET_INST_OPCODE(ip) @ extract opcode from rINST
1185 GOTO_OPCODE(ip) @ jump to next instruction
1189 /* ------------------------------ */
1191 .L_OP_GOTO_32: /* 0x2a */
1192 /* File: armv5te/OP_GOTO_32.S */
1194 * Unconditional branch, 32-bit offset.
1196 * The branch distance is a signed code-unit offset, which we need to
1197 * double to get a byte offset.
1199 * Unlike most opcodes, this one is allowed to branch to itself, so
1200 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1201 * instruction doesn't affect the V flag, so we need to clear it
1204 /* goto/32 +AAAAAAAA */
1205 FETCH(r0, 1) @ r0<- aaaa (lo)
1206 FETCH(r1, 2) @ r1<- AAAA (hi)
1207 cmp ip, ip @ (clear V flag during stall)
1208 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1209 mov r9, r0, asl #1 @ r9<- byte offset
1210 ble common_backwardBranch @ backward branch, do periodic checks
1211 #if defined(WITH_JIT)
1212 GET_JIT_PROF_TABLE(r0)
1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1215 bne common_updateProfile
1216 GET_INST_OPCODE(ip) @ extract opcode from rINST
1217 GOTO_OPCODE(ip) @ jump to next instruction
1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1220 GET_INST_OPCODE(ip) @ extract opcode from rINST
1221 GOTO_OPCODE(ip) @ jump to next instruction
1224 /* ------------------------------ */
1226 .L_OP_PACKED_SWITCH: /* 0x2b */
1227 /* File: armv5te/OP_PACKED_SWITCH.S */
1229 * Handle a packed-switch or sparse-switch instruction. In both cases
1230 * we decode it and hand it off to a helper function.
1232 * We don't really expect backward branches in a switch statement, but
1233 * they're perfectly legal, so we check for them here.
1235 * for: packed-switch, sparse-switch
1238 FETCH(r0, 1) @ r0<- bbbb (lo)
1239 FETCH(r1, 2) @ r1<- BBBB (hi)
1240 mov r3, rINST, lsr #8 @ r3<- AA
1241 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1242 GET_VREG(r1, r3) @ r1<- vAA
1243 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1244 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1245 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1246 bmi common_backwardBranch @ backward branch, do periodic checks
1247 beq common_backwardBranch @ (want to use BLE but V is unknown)
1248 #if defined(WITH_JIT)
1249 GET_JIT_PROF_TABLE(r0)
1250 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1252 bne common_updateProfile
1253 GET_INST_OPCODE(ip) @ extract opcode from rINST
1254 GOTO_OPCODE(ip) @ jump to next instruction
1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1257 GET_INST_OPCODE(ip) @ extract opcode from rINST
1258 GOTO_OPCODE(ip) @ jump to next instruction
1262 /* ------------------------------ */
1264 .L_OP_SPARSE_SWITCH: /* 0x2c */
1265 /* File: armv5te/OP_SPARSE_SWITCH.S */
1266 /* File: armv5te/OP_PACKED_SWITCH.S */
1268 * Handle a packed-switch or sparse-switch instruction. In both cases
1269 * we decode it and hand it off to a helper function.
1271 * We don't really expect backward branches in a switch statement, but
1272 * they're perfectly legal, so we check for them here.
1274 * for: packed-switch, sparse-switch
1277 FETCH(r0, 1) @ r0<- bbbb (lo)
1278 FETCH(r1, 2) @ r1<- BBBB (hi)
1279 mov r3, rINST, lsr #8 @ r3<- AA
1280 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1281 GET_VREG(r1, r3) @ r1<- vAA
1282 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1283 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1284 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1285 bmi common_backwardBranch @ backward branch, do periodic checks
1286 beq common_backwardBranch @ (want to use BLE but V is unknown)
1287 #if defined(WITH_JIT)
1288 GET_JIT_PROF_TABLE(r0)
1289 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1291 bne common_updateProfile
1292 GET_INST_OPCODE(ip) @ extract opcode from rINST
1293 GOTO_OPCODE(ip) @ jump to next instruction
1295 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1296 GET_INST_OPCODE(ip) @ extract opcode from rINST
1297 GOTO_OPCODE(ip) @ jump to next instruction
1302 /* ------------------------------ */
1304 .L_OP_CMPL_FLOAT: /* 0x2d */
1305 /* File: armv5te/OP_CMPL_FLOAT.S */
1307 * Compare two floating-point values. Puts 0, 1, or -1 into the
1308 * destination register based on the results of the comparison.
1310 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1311 * on what value we'd like to return when one of the operands is NaN.
1313 * The operation we're implementing is:
1321 * return {-1,1}; // one or both operands was NaN
1323 * The straightforward implementation requires 3 calls to functions
1324 * that return a result in r0. We can do it with two calls if our
1325 * EABI library supports __aeabi_cfcmple (only one if we want to check
1326 * for NaN directly):
1334 * for: cmpl-float, cmpg-float
1336 /* op vAA, vBB, vCC */
1337 FETCH(r0, 1) @ r0<- CCBB
1338 and r2, r0, #255 @ r2<- BB
1339 mov r3, r0, lsr #8 @ r3<- CC
1340 GET_VREG(r9, r2) @ r9<- vBB
1341 GET_VREG(r10, r3) @ r10<- vCC
1342 mov r0, r9 @ copy to arg registers
1344 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1345 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1346 mvncc r1, #0 @ (less than) r1<- -1
1347 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1348 .LOP_CMPL_FLOAT_finish:
1349 mov r3, rINST, lsr #8 @ r3<- AA
1350 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1351 SET_VREG(r1, r3) @ vAA<- r1
1352 GET_INST_OPCODE(ip) @ extract opcode from rINST
1353 GOTO_OPCODE(ip) @ jump to next instruction
1355 /* ------------------------------ */
1357 .L_OP_CMPG_FLOAT: /* 0x2e */
1358 /* File: armv5te/OP_CMPG_FLOAT.S */
1359 /* File: armv5te/OP_CMPL_FLOAT.S */
1361 * Compare two floating-point values. Puts 0, 1, or -1 into the
1362 * destination register based on the results of the comparison.
1364 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1365 * on what value we'd like to return when one of the operands is NaN.
1367 * The operation we're implementing is:
1375 * return {-1,1}; // one or both operands was NaN
1377 * The straightforward implementation requires 3 calls to functions
1378 * that return a result in r0. We can do it with two calls if our
1379 * EABI library supports __aeabi_cfcmple (only one if we want to check
1380 * for NaN directly):
1388 * for: cmpl-float, cmpg-float
1390 /* op vAA, vBB, vCC */
1391 FETCH(r0, 1) @ r0<- CCBB
1392 and r2, r0, #255 @ r2<- BB
1393 mov r3, r0, lsr #8 @ r3<- CC
1394 GET_VREG(r9, r2) @ r9<- vBB
1395 GET_VREG(r10, r3) @ r10<- vCC
1396 mov r0, r9 @ copy to arg registers
1398 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1399 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1400 mvncc r1, #0 @ (less than) r1<- -1
1401 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1402 .LOP_CMPG_FLOAT_finish:
1403 mov r3, rINST, lsr #8 @ r3<- AA
1404 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1405 SET_VREG(r1, r3) @ vAA<- r1
1406 GET_INST_OPCODE(ip) @ extract opcode from rINST
1407 GOTO_OPCODE(ip) @ jump to next instruction
1410 /* ------------------------------ */
1412 .L_OP_CMPL_DOUBLE: /* 0x2f */
1413 /* File: armv5te/OP_CMPL_DOUBLE.S */
1415 * Compare two floating-point values. Puts 0, 1, or -1 into the
1416 * destination register based on the results of the comparison.
1418 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1419 * on what value we'd like to return when one of the operands is NaN.
1421 * See OP_CMPL_FLOAT for an explanation.
1423 * For: cmpl-double, cmpg-double
1425 /* op vAA, vBB, vCC */
1426 FETCH(r0, 1) @ r0<- CCBB
1427 and r9, r0, #255 @ r9<- BB
1428 mov r10, r0, lsr #8 @ r10<- CC
1429 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1430 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1431 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1432 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1433 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1434 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1435 mvncc r1, #0 @ (less than) r1<- -1
1436 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1437 .LOP_CMPL_DOUBLE_finish:
1438 mov r3, rINST, lsr #8 @ r3<- AA
1439 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1440 SET_VREG(r1, r3) @ vAA<- r1
1441 GET_INST_OPCODE(ip) @ extract opcode from rINST
1442 GOTO_OPCODE(ip) @ jump to next instruction
1444 /* ------------------------------ */
1446 .L_OP_CMPG_DOUBLE: /* 0x30 */
1447 /* File: armv5te/OP_CMPG_DOUBLE.S */
1448 /* File: armv5te/OP_CMPL_DOUBLE.S */
1450 * Compare two floating-point values. Puts 0, 1, or -1 into the
1451 * destination register based on the results of the comparison.
1453 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1454 * on what value we'd like to return when one of the operands is NaN.
1456 * See OP_CMPL_FLOAT for an explanation.
1458 * For: cmpl-double, cmpg-double
1460 /* op vAA, vBB, vCC */
1461 FETCH(r0, 1) @ r0<- CCBB
1462 and r9, r0, #255 @ r9<- BB
1463 mov r10, r0, lsr #8 @ r10<- CC
1464 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1465 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1466 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1467 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1468 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1469 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1470 mvncc r1, #0 @ (less than) r1<- -1
1471 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1472 .LOP_CMPG_DOUBLE_finish:
1473 mov r3, rINST, lsr #8 @ r3<- AA
1474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1475 SET_VREG(r1, r3) @ vAA<- r1
1476 GET_INST_OPCODE(ip) @ extract opcode from rINST
1477 GOTO_OPCODE(ip) @ jump to next instruction
1480 /* ------------------------------ */
1482 .L_OP_CMP_LONG: /* 0x31 */
1483 /* File: armv5te/OP_CMP_LONG.S */
1485 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1486 * register based on the results of the comparison.
1488 * We load the full values with LDM, but in practice many values could
1489 * be resolved by only looking at the high word. This could be made
1490 * faster or slower by splitting the LDM into a pair of LDRs.
1492 * If we just wanted to set condition flags, we could do this:
1496 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1497 * integer value, which we can do with 2 conditional mov/mvn instructions
1498 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1499 * us a constant 5-cycle path plus a branch at the end to the
1500 * instruction epilogue code. The multi-compare approach below needs
1501 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1502 * in the worst case (the 64-bit values are equal).
1504 /* cmp-long vAA, vBB, vCC */
1505 FETCH(r0, 1) @ r0<- CCBB
1506 mov r9, rINST, lsr #8 @ r9<- AA
1507 and r2, r0, #255 @ r2<- BB
1508 mov r3, r0, lsr #8 @ r3<- CC
1509 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1510 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1511 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1512 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1513 cmp r1, r3 @ compare (vBB+1, vCC+1)
1514 blt .LOP_CMP_LONG_less @ signed compare on high part
1515 bgt .LOP_CMP_LONG_greater
1516 subs r1, r0, r2 @ r1<- r0 - r2
1517 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1518 bne .LOP_CMP_LONG_less
1519 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1521 /* ------------------------------ */
1523 .L_OP_IF_EQ: /* 0x32 */
1524 /* File: armv5te/OP_IF_EQ.S */
1525 /* File: armv5te/bincmp.S */
1527 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1528 * fragment that specifies the *reverse* comparison to perform, e.g.
1529 * for "if-le" you would use "gt".
1531 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1533 /* if-cmp vA, vB, +CCCC */
1534 mov r0, rINST, lsr #8 @ r0<- A+
1535 mov r1, rINST, lsr #12 @ r1<- B
1537 GET_VREG(r3, r1) @ r3<- vB
1538 GET_VREG(r2, r0) @ r2<- vA
1539 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1540 cmp r2, r3 @ compare (vA, vB)
1541 bne 1f @ branch to 1 if comparison failed
1542 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1543 movs r9, r9, asl #1 @ convert to bytes, check sign
1544 bmi common_backwardBranch @ yes, do periodic checks
1546 #if defined(WITH_JIT)
1547 GET_JIT_PROF_TABLE(r0)
1548 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1549 b common_testUpdateProfile
1551 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1552 GET_INST_OPCODE(ip) @ extract opcode from rINST
1553 GOTO_OPCODE(ip) @ jump to next instruction
1558 /* ------------------------------ */
1560 .L_OP_IF_NE: /* 0x33 */
1561 /* File: armv5te/OP_IF_NE.S */
1562 /* File: armv5te/bincmp.S */
1564 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1565 * fragment that specifies the *reverse* comparison to perform, e.g.
1566 * for "if-le" you would use "gt".
1568 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1570 /* if-cmp vA, vB, +CCCC */
1571 mov r0, rINST, lsr #8 @ r0<- A+
1572 mov r1, rINST, lsr #12 @ r1<- B
1574 GET_VREG(r3, r1) @ r3<- vB
1575 GET_VREG(r2, r0) @ r2<- vA
1576 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1577 cmp r2, r3 @ compare (vA, vB)
1578 beq 1f @ branch to 1 if comparison failed
1579 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1580 movs r9, r9, asl #1 @ convert to bytes, check sign
1581 bmi common_backwardBranch @ yes, do periodic checks
1583 #if defined(WITH_JIT)
1584 GET_JIT_PROF_TABLE(r0)
1585 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1586 b common_testUpdateProfile
1588 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1589 GET_INST_OPCODE(ip) @ extract opcode from rINST
1590 GOTO_OPCODE(ip) @ jump to next instruction
1595 /* ------------------------------ */
1597 .L_OP_IF_LT: /* 0x34 */
1598 /* File: armv5te/OP_IF_LT.S */
1599 /* File: armv5te/bincmp.S */
1601 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1602 * fragment that specifies the *reverse* comparison to perform, e.g.
1603 * for "if-le" you would use "gt".
1605 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1607 /* if-cmp vA, vB, +CCCC */
1608 mov r0, rINST, lsr #8 @ r0<- A+
1609 mov r1, rINST, lsr #12 @ r1<- B
1611 GET_VREG(r3, r1) @ r3<- vB
1612 GET_VREG(r2, r0) @ r2<- vA
1613 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1614 cmp r2, r3 @ compare (vA, vB)
1615 bge 1f @ branch to 1 if comparison failed
1616 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1617 movs r9, r9, asl #1 @ convert to bytes, check sign
1618 bmi common_backwardBranch @ yes, do periodic checks
1620 #if defined(WITH_JIT)
1621 GET_JIT_PROF_TABLE(r0)
1622 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1623 b common_testUpdateProfile
1625 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1626 GET_INST_OPCODE(ip) @ extract opcode from rINST
1627 GOTO_OPCODE(ip) @ jump to next instruction
1632 /* ------------------------------ */
1634 .L_OP_IF_GE: /* 0x35 */
1635 /* File: armv5te/OP_IF_GE.S */
1636 /* File: armv5te/bincmp.S */
1638 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1639 * fragment that specifies the *reverse* comparison to perform, e.g.
1640 * for "if-le" you would use "gt".
1642 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1644 /* if-cmp vA, vB, +CCCC */
1645 mov r0, rINST, lsr #8 @ r0<- A+
1646 mov r1, rINST, lsr #12 @ r1<- B
1648 GET_VREG(r3, r1) @ r3<- vB
1649 GET_VREG(r2, r0) @ r2<- vA
1650 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1651 cmp r2, r3 @ compare (vA, vB)
1652 blt 1f @ branch to 1 if comparison failed
1653 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1654 movs r9, r9, asl #1 @ convert to bytes, check sign
1655 bmi common_backwardBranch @ yes, do periodic checks
1657 #if defined(WITH_JIT)
1658 GET_JIT_PROF_TABLE(r0)
1659 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1660 b common_testUpdateProfile
1662 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1663 GET_INST_OPCODE(ip) @ extract opcode from rINST
1664 GOTO_OPCODE(ip) @ jump to next instruction
1669 /* ------------------------------ */
1671 .L_OP_IF_GT: /* 0x36 */
1672 /* File: armv5te/OP_IF_GT.S */
1673 /* File: armv5te/bincmp.S */
1675 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1676 * fragment that specifies the *reverse* comparison to perform, e.g.
1677 * for "if-le" you would use "gt".
1679 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1681 /* if-cmp vA, vB, +CCCC */
1682 mov r0, rINST, lsr #8 @ r0<- A+
1683 mov r1, rINST, lsr #12 @ r1<- B
1685 GET_VREG(r3, r1) @ r3<- vB
1686 GET_VREG(r2, r0) @ r2<- vA
1687 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1688 cmp r2, r3 @ compare (vA, vB)
1689 ble 1f @ branch to 1 if comparison failed
1690 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1691 movs r9, r9, asl #1 @ convert to bytes, check sign
1692 bmi common_backwardBranch @ yes, do periodic checks
1694 #if defined(WITH_JIT)
1695 GET_JIT_PROF_TABLE(r0)
1696 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1697 b common_testUpdateProfile
1699 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1700 GET_INST_OPCODE(ip) @ extract opcode from rINST
1701 GOTO_OPCODE(ip) @ jump to next instruction
1706 /* ------------------------------ */
1708 .L_OP_IF_LE: /* 0x37 */
1709 /* File: armv5te/OP_IF_LE.S */
1710 /* File: armv5te/bincmp.S */
1712 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1713 * fragment that specifies the *reverse* comparison to perform, e.g.
1714 * for "if-le" you would use "gt".
1716 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1718 /* if-cmp vA, vB, +CCCC */
1719 mov r0, rINST, lsr #8 @ r0<- A+
1720 mov r1, rINST, lsr #12 @ r1<- B
1722 GET_VREG(r3, r1) @ r3<- vB
1723 GET_VREG(r2, r0) @ r2<- vA
1724 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1725 cmp r2, r3 @ compare (vA, vB)
1726 bgt 1f @ branch to 1 if comparison failed
1727 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1728 movs r9, r9, asl #1 @ convert to bytes, check sign
1729 bmi common_backwardBranch @ yes, do periodic checks
1731 #if defined(WITH_JIT)
1732 GET_JIT_PROF_TABLE(r0)
1733 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1734 b common_testUpdateProfile
1736 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1737 GET_INST_OPCODE(ip) @ extract opcode from rINST
1738 GOTO_OPCODE(ip) @ jump to next instruction
1743 /* ------------------------------ */
1745 .L_OP_IF_EQZ: /* 0x38 */
1746 /* File: armv5te/OP_IF_EQZ.S */
1747 /* File: armv5te/zcmp.S */
1749 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1750 * fragment that specifies the *reverse* comparison to perform, e.g.
1751 * for "if-le" you would use "gt".
1753 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1755 /* if-cmp vAA, +BBBB */
1756 mov r0, rINST, lsr #8 @ r0<- AA
1757 GET_VREG(r2, r0) @ r2<- vAA
1758 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1759 cmp r2, #0 @ compare (vA, 0)
1760 bne 1f @ branch to 1 if comparison failed
1761 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1762 movs r9, r9, asl #1 @ convert to bytes, check sign
1763 bmi common_backwardBranch @ backward branch, do periodic checks
1765 #if defined(WITH_JIT)
1766 GET_JIT_PROF_TABLE(r0)
1767 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1769 bne common_updateProfile
1770 GET_INST_OPCODE(ip) @ extract opcode from rINST
1771 GOTO_OPCODE(ip) @ jump to next instruction
1773 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1774 GET_INST_OPCODE(ip) @ extract opcode from rINST
1775 GOTO_OPCODE(ip) @ jump to next instruction
1780 /* ------------------------------ */
1782 .L_OP_IF_NEZ: /* 0x39 */
1783 /* File: armv5te/OP_IF_NEZ.S */
1784 /* File: armv5te/zcmp.S */
1786 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1787 * fragment that specifies the *reverse* comparison to perform, e.g.
1788 * for "if-le" you would use "gt".
1790 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1792 /* if-cmp vAA, +BBBB */
1793 mov r0, rINST, lsr #8 @ r0<- AA
1794 GET_VREG(r2, r0) @ r2<- vAA
1795 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1796 cmp r2, #0 @ compare (vA, 0)
1797 beq 1f @ branch to 1 if comparison failed
1798 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1799 movs r9, r9, asl #1 @ convert to bytes, check sign
1800 bmi common_backwardBranch @ backward branch, do periodic checks
1802 #if defined(WITH_JIT)
1803 GET_JIT_PROF_TABLE(r0)
1804 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1806 bne common_updateProfile
1807 GET_INST_OPCODE(ip) @ extract opcode from rINST
1808 GOTO_OPCODE(ip) @ jump to next instruction
1810 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1811 GET_INST_OPCODE(ip) @ extract opcode from rINST
1812 GOTO_OPCODE(ip) @ jump to next instruction
1817 /* ------------------------------ */
1819 .L_OP_IF_LTZ: /* 0x3a */
1820 /* File: armv5te/OP_IF_LTZ.S */
1821 /* File: armv5te/zcmp.S */
1823 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1824 * fragment that specifies the *reverse* comparison to perform, e.g.
1825 * for "if-le" you would use "gt".
1827 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1829 /* if-cmp vAA, +BBBB */
1830 mov r0, rINST, lsr #8 @ r0<- AA
1831 GET_VREG(r2, r0) @ r2<- vAA
1832 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1833 cmp r2, #0 @ compare (vA, 0)
1834 bge 1f @ branch to 1 if comparison failed
1835 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1836 movs r9, r9, asl #1 @ convert to bytes, check sign
1837 bmi common_backwardBranch @ backward branch, do periodic checks
1839 #if defined(WITH_JIT)
1840 GET_JIT_PROF_TABLE(r0)
1841 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1843 bne common_updateProfile
1844 GET_INST_OPCODE(ip) @ extract opcode from rINST
1845 GOTO_OPCODE(ip) @ jump to next instruction
1847 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1848 GET_INST_OPCODE(ip) @ extract opcode from rINST
1849 GOTO_OPCODE(ip) @ jump to next instruction
1854 /* ------------------------------ */
1856 .L_OP_IF_GEZ: /* 0x3b */
1857 /* File: armv5te/OP_IF_GEZ.S */
1858 /* File: armv5te/zcmp.S */
1860 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1861 * fragment that specifies the *reverse* comparison to perform, e.g.
1862 * for "if-le" you would use "gt".
1864 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1866 /* if-cmp vAA, +BBBB */
1867 mov r0, rINST, lsr #8 @ r0<- AA
1868 GET_VREG(r2, r0) @ r2<- vAA
1869 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1870 cmp r2, #0 @ compare (vA, 0)
1871 blt 1f @ branch to 1 if comparison failed
1872 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1873 movs r9, r9, asl #1 @ convert to bytes, check sign
1874 bmi common_backwardBranch @ backward branch, do periodic checks
1876 #if defined(WITH_JIT)
1877 GET_JIT_PROF_TABLE(r0)
1878 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1880 bne common_updateProfile
1881 GET_INST_OPCODE(ip) @ extract opcode from rINST
1882 GOTO_OPCODE(ip) @ jump to next instruction
1884 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1885 GET_INST_OPCODE(ip) @ extract opcode from rINST
1886 GOTO_OPCODE(ip) @ jump to next instruction
1891 /* ------------------------------ */
1893 .L_OP_IF_GTZ: /* 0x3c */
1894 /* File: armv5te/OP_IF_GTZ.S */
1895 /* File: armv5te/zcmp.S */
1897 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1898 * fragment that specifies the *reverse* comparison to perform, e.g.
1899 * for "if-le" you would use "gt".
1901 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1903 /* if-cmp vAA, +BBBB */
1904 mov r0, rINST, lsr #8 @ r0<- AA
1905 GET_VREG(r2, r0) @ r2<- vAA
1906 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1907 cmp r2, #0 @ compare (vA, 0)
1908 ble 1f @ branch to 1 if comparison failed
1909 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1910 movs r9, r9, asl #1 @ convert to bytes, check sign
1911 bmi common_backwardBranch @ backward branch, do periodic checks
1913 #if defined(WITH_JIT)
1914 GET_JIT_PROF_TABLE(r0)
1915 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1917 bne common_updateProfile
1918 GET_INST_OPCODE(ip) @ extract opcode from rINST
1919 GOTO_OPCODE(ip) @ jump to next instruction
1921 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1922 GET_INST_OPCODE(ip) @ extract opcode from rINST
1923 GOTO_OPCODE(ip) @ jump to next instruction
1928 /* ------------------------------ */
1930 .L_OP_IF_LEZ: /* 0x3d */
1931 /* File: armv5te/OP_IF_LEZ.S */
1932 /* File: armv5te/zcmp.S */
1934 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1935 * fragment that specifies the *reverse* comparison to perform, e.g.
1936 * for "if-le" you would use "gt".
1938 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1940 /* if-cmp vAA, +BBBB */
1941 mov r0, rINST, lsr #8 @ r0<- AA
1942 GET_VREG(r2, r0) @ r2<- vAA
1943 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1944 cmp r2, #0 @ compare (vA, 0)
1945 bgt 1f @ branch to 1 if comparison failed
1946 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1947 movs r9, r9, asl #1 @ convert to bytes, check sign
1948 bmi common_backwardBranch @ backward branch, do periodic checks
1950 #if defined(WITH_JIT)
1951 GET_JIT_PROF_TABLE(r0)
1952 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1954 bne common_updateProfile
1955 GET_INST_OPCODE(ip) @ extract opcode from rINST
1956 GOTO_OPCODE(ip) @ jump to next instruction
1958 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1959 GET_INST_OPCODE(ip) @ extract opcode from rINST
1960 GOTO_OPCODE(ip) @ jump to next instruction
1965 /* ------------------------------ */
1967 .L_OP_UNUSED_3E: /* 0x3e */
1968 /* File: armv5te/OP_UNUSED_3E.S */
1969 /* File: armv5te/unused.S */
1974 /* ------------------------------ */
1976 .L_OP_UNUSED_3F: /* 0x3f */
1977 /* File: armv5te/OP_UNUSED_3F.S */
1978 /* File: armv5te/unused.S */
1983 /* ------------------------------ */
1985 .L_OP_UNUSED_40: /* 0x40 */
1986 /* File: armv5te/OP_UNUSED_40.S */
1987 /* File: armv5te/unused.S */
1992 /* ------------------------------ */
1994 .L_OP_UNUSED_41: /* 0x41 */
1995 /* File: armv5te/OP_UNUSED_41.S */
1996 /* File: armv5te/unused.S */
2001 /* ------------------------------ */
2003 .L_OP_UNUSED_42: /* 0x42 */
2004 /* File: armv5te/OP_UNUSED_42.S */
2005 /* File: armv5te/unused.S */
2010 /* ------------------------------ */
2012 .L_OP_UNUSED_43: /* 0x43 */
2013 /* File: armv5te/OP_UNUSED_43.S */
2014 /* File: armv5te/unused.S */
2019 /* ------------------------------ */
2021 .L_OP_AGET: /* 0x44 */
2022 /* File: armv5te/OP_AGET.S */
2024 * Array get, 32 bits or less. vAA <- vBB[vCC].
2026 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2027 * instructions. We use a pair of FETCH_Bs instead.
2029 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2031 /* op vAA, vBB, vCC */
2032 FETCH_B(r2, 1, 0) @ r2<- BB
2033 mov r9, rINST, lsr #8 @ r9<- AA
2034 FETCH_B(r3, 1, 1) @ r3<- CC
2035 GET_VREG(r0, r2) @ r0<- vBB (array object)
2036 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2037 cmp r0, #0 @ null array object?
2038 beq common_errNullObject @ yes, bail
2039 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2040 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2041 cmp r1, r3 @ compare unsigned index, length
2042 bcs common_errArrayIndex @ index >= length, bail
2043 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2044 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2045 GET_INST_OPCODE(ip) @ extract opcode from rINST
2046 SET_VREG(r2, r9) @ vAA<- r2
2047 GOTO_OPCODE(ip) @ jump to next instruction
2050 /* ------------------------------ */
2052 .L_OP_AGET_WIDE: /* 0x45 */
2053 /* File: armv5te/OP_AGET_WIDE.S */
2055 * Array get, 64 bits. vAA <- vBB[vCC].
2057 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2059 /* aget-wide vAA, vBB, vCC */
2060 FETCH(r0, 1) @ r0<- CCBB
2061 mov r9, rINST, lsr #8 @ r9<- AA
2062 and r2, r0, #255 @ r2<- BB
2063 mov r3, r0, lsr #8 @ r3<- CC
2064 GET_VREG(r0, r2) @ r0<- vBB (array object)
2065 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2066 cmp r0, #0 @ null array object?
2067 beq common_errNullObject @ yes, bail
2068 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2069 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2070 cmp r1, r3 @ compare unsigned index, length
2071 bcc .LOP_AGET_WIDE_finish @ okay, continue below
2072 b common_errArrayIndex @ index >= length, bail
2073 @ May want to swap the order of these two branches depending on how the
2074 @ branch prediction (if any) handles conditional forward branches vs.
2075 @ unconditional forward branches.
2077 /* ------------------------------ */
2079 .L_OP_AGET_OBJECT: /* 0x46 */
2080 /* File: armv5te/OP_AGET_OBJECT.S */
2081 /* File: armv5te/OP_AGET.S */
2083 * Array get, 32 bits or less. vAA <- vBB[vCC].
2085 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2086 * instructions. We use a pair of FETCH_Bs instead.
2088 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2090 /* op vAA, vBB, vCC */
2091 FETCH_B(r2, 1, 0) @ r2<- BB
2092 mov r9, rINST, lsr #8 @ r9<- AA
2093 FETCH_B(r3, 1, 1) @ r3<- CC
2094 GET_VREG(r0, r2) @ r0<- vBB (array object)
2095 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2096 cmp r0, #0 @ null array object?
2097 beq common_errNullObject @ yes, bail
2098 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2099 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2100 cmp r1, r3 @ compare unsigned index, length
2101 bcs common_errArrayIndex @ index >= length, bail
2102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2103 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2104 GET_INST_OPCODE(ip) @ extract opcode from rINST
2105 SET_VREG(r2, r9) @ vAA<- r2
2106 GOTO_OPCODE(ip) @ jump to next instruction
2110 /* ------------------------------ */
2112 .L_OP_AGET_BOOLEAN: /* 0x47 */
2113 /* File: armv5te/OP_AGET_BOOLEAN.S */
2114 /* File: armv5te/OP_AGET.S */
2116 * Array get, 32 bits or less. vAA <- vBB[vCC].
2118 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2119 * instructions. We use a pair of FETCH_Bs instead.
2121 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2123 /* op vAA, vBB, vCC */
2124 FETCH_B(r2, 1, 0) @ r2<- BB
2125 mov r9, rINST, lsr #8 @ r9<- AA
2126 FETCH_B(r3, 1, 1) @ r3<- CC
2127 GET_VREG(r0, r2) @ r0<- vBB (array object)
2128 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2129 cmp r0, #0 @ null array object?
2130 beq common_errNullObject @ yes, bail
2131 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2132 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2133 cmp r1, r3 @ compare unsigned index, length
2134 bcs common_errArrayIndex @ index >= length, bail
2135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2136 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2137 GET_INST_OPCODE(ip) @ extract opcode from rINST
2138 SET_VREG(r2, r9) @ vAA<- r2
2139 GOTO_OPCODE(ip) @ jump to next instruction
2143 /* ------------------------------ */
2145 .L_OP_AGET_BYTE: /* 0x48 */
2146 /* File: armv5te/OP_AGET_BYTE.S */
2147 /* File: armv5te/OP_AGET.S */
2149 * Array get, 32 bits or less. vAA <- vBB[vCC].
2151 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2152 * instructions. We use a pair of FETCH_Bs instead.
2154 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2156 /* op vAA, vBB, vCC */
2157 FETCH_B(r2, 1, 0) @ r2<- BB
2158 mov r9, rINST, lsr #8 @ r9<- AA
2159 FETCH_B(r3, 1, 1) @ r3<- CC
2160 GET_VREG(r0, r2) @ r0<- vBB (array object)
2161 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2162 cmp r0, #0 @ null array object?
2163 beq common_errNullObject @ yes, bail
2164 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2165 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2166 cmp r1, r3 @ compare unsigned index, length
2167 bcs common_errArrayIndex @ index >= length, bail
2168 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2169 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2170 GET_INST_OPCODE(ip) @ extract opcode from rINST
2171 SET_VREG(r2, r9) @ vAA<- r2
2172 GOTO_OPCODE(ip) @ jump to next instruction
2176 /* ------------------------------ */
2178 .L_OP_AGET_CHAR: /* 0x49 */
2179 /* File: armv5te/OP_AGET_CHAR.S */
2180 /* File: armv5te/OP_AGET.S */
2182 * Array get, 32 bits or less. vAA <- vBB[vCC].
2184 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2185 * instructions. We use a pair of FETCH_Bs instead.
2187 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2189 /* op vAA, vBB, vCC */
2190 FETCH_B(r2, 1, 0) @ r2<- BB
2191 mov r9, rINST, lsr #8 @ r9<- AA
2192 FETCH_B(r3, 1, 1) @ r3<- CC
2193 GET_VREG(r0, r2) @ r0<- vBB (array object)
2194 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2195 cmp r0, #0 @ null array object?
2196 beq common_errNullObject @ yes, bail
2197 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2198 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2199 cmp r1, r3 @ compare unsigned index, length
2200 bcs common_errArrayIndex @ index >= length, bail
2201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2202 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2203 GET_INST_OPCODE(ip) @ extract opcode from rINST
2204 SET_VREG(r2, r9) @ vAA<- r2
2205 GOTO_OPCODE(ip) @ jump to next instruction
2209 /* ------------------------------ */
2211 .L_OP_AGET_SHORT: /* 0x4a */
2212 /* File: armv5te/OP_AGET_SHORT.S */
2213 /* File: armv5te/OP_AGET.S */
2215 * Array get, 32 bits or less. vAA <- vBB[vCC].
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: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-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 #1 @ r0<- arrayObj + index*width
2232 cmp r1, r3 @ compare unsigned index, length
2233 bcs common_errArrayIndex @ index >= length, bail
2234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2235 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2236 GET_INST_OPCODE(ip) @ extract opcode from rINST
2237 SET_VREG(r2, r9) @ vAA<- r2
2238 GOTO_OPCODE(ip) @ jump to next instruction
2242 /* ------------------------------ */
2244 .L_OP_APUT: /* 0x4b */
2245 /* File: armv5te/OP_APUT.S */
2247 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2249 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2250 * instructions. We use a pair of FETCH_Bs instead.
2252 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2254 /* op vAA, vBB, vCC */
2255 FETCH_B(r2, 1, 0) @ r2<- BB
2256 mov r9, rINST, lsr #8 @ r9<- AA
2257 FETCH_B(r3, 1, 1) @ r3<- CC
2258 GET_VREG(r0, r2) @ r0<- vBB (array object)
2259 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2260 cmp r0, #0 @ null array object?
2261 beq common_errNullObject @ yes, bail
2262 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2263 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2264 cmp r1, r3 @ compare unsigned index, length
2265 bcs common_errArrayIndex @ index >= length, bail
2266 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2267 GET_VREG(r2, r9) @ r2<- vAA
2268 GET_INST_OPCODE(ip) @ extract opcode from rINST
2269 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2270 GOTO_OPCODE(ip) @ jump to next instruction
2273 /* ------------------------------ */
2275 .L_OP_APUT_WIDE: /* 0x4c */
2276 /* File: armv5te/OP_APUT_WIDE.S */
2278 * Array put, 64 bits. vBB[vCC] <- vAA.
2280 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2282 /* aput-wide vAA, vBB, vCC */
2283 FETCH(r0, 1) @ r0<- CCBB
2284 mov r9, rINST, lsr #8 @ r9<- AA
2285 and r2, r0, #255 @ r2<- BB
2286 mov r3, r0, lsr #8 @ r3<- CC
2287 GET_VREG(r0, r2) @ r0<- vBB (array object)
2288 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2289 cmp r0, #0 @ null array object?
2290 beq common_errNullObject @ yes, bail
2291 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2292 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2293 cmp r1, r3 @ compare unsigned index, length
2294 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2295 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2296 b common_errArrayIndex @ index >= length, bail
2297 @ May want to swap the order of these two branches depending on how the
2298 @ branch prediction (if any) handles conditional forward branches vs.
2299 @ unconditional forward branches.
2301 /* ------------------------------ */
2303 .L_OP_APUT_OBJECT: /* 0x4d */
2304 /* File: armv5te/OP_APUT_OBJECT.S */
2306 * Store an object into an array. vBB[vCC] <- vAA.
2308 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2309 * instructions. We use a pair of FETCH_Bs instead.
2311 /* op vAA, vBB, vCC */
2312 FETCH(r0, 1) @ r0<- CCBB
2313 mov r9, rINST, lsr #8 @ r9<- AA
2314 and r2, r0, #255 @ r2<- BB
2315 mov r3, r0, lsr #8 @ r3<- CC
2316 GET_VREG(r1, r2) @ r1<- vBB (array object)
2317 GET_VREG(r0, r3) @ r0<- vCC (requested index)
2318 cmp r1, #0 @ null array object?
2319 GET_VREG(r9, r9) @ r9<- vAA
2320 beq common_errNullObject @ yes, bail
2321 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length
2322 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width
2323 cmp r0, r3 @ compare unsigned index, length
2324 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2325 b common_errArrayIndex @ index >= length, bail
2328 /* ------------------------------ */
2330 .L_OP_APUT_BOOLEAN: /* 0x4e */
2331 /* File: armv5te/OP_APUT_BOOLEAN.S */
2332 /* File: armv5te/OP_APUT.S */
2334 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2336 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2337 * instructions. We use a pair of FETCH_Bs instead.
2339 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2341 /* op vAA, vBB, vCC */
2342 FETCH_B(r2, 1, 0) @ r2<- BB
2343 mov r9, rINST, lsr #8 @ r9<- AA
2344 FETCH_B(r3, 1, 1) @ r3<- CC
2345 GET_VREG(r0, r2) @ r0<- vBB (array object)
2346 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2347 cmp r0, #0 @ null array object?
2348 beq common_errNullObject @ yes, bail
2349 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2350 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2351 cmp r1, r3 @ compare unsigned index, length
2352 bcs common_errArrayIndex @ index >= length, bail
2353 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2354 GET_VREG(r2, r9) @ r2<- vAA
2355 GET_INST_OPCODE(ip) @ extract opcode from rINST
2356 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2357 GOTO_OPCODE(ip) @ jump to next instruction
2361 /* ------------------------------ */
2363 .L_OP_APUT_BYTE: /* 0x4f */
2364 /* File: armv5te/OP_APUT_BYTE.S */
2365 /* File: armv5te/OP_APUT.S */
2367 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2369 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2370 * instructions. We use a pair of FETCH_Bs instead.
2372 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2374 /* op vAA, vBB, vCC */
2375 FETCH_B(r2, 1, 0) @ r2<- BB
2376 mov r9, rINST, lsr #8 @ r9<- AA
2377 FETCH_B(r3, 1, 1) @ r3<- CC
2378 GET_VREG(r0, r2) @ r0<- vBB (array object)
2379 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2380 cmp r0, #0 @ null array object?
2381 beq common_errNullObject @ yes, bail
2382 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2383 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2384 cmp r1, r3 @ compare unsigned index, length
2385 bcs common_errArrayIndex @ index >= length, bail
2386 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2387 GET_VREG(r2, r9) @ r2<- vAA
2388 GET_INST_OPCODE(ip) @ extract opcode from rINST
2389 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2390 GOTO_OPCODE(ip) @ jump to next instruction
2394 /* ------------------------------ */
2396 .L_OP_APUT_CHAR: /* 0x50 */
2397 /* File: armv5te/OP_APUT_CHAR.S */
2398 /* File: armv5te/OP_APUT.S */
2400 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2402 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2403 * instructions. We use a pair of FETCH_Bs instead.
2405 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2407 /* op vAA, vBB, vCC */
2408 FETCH_B(r2, 1, 0) @ r2<- BB
2409 mov r9, rINST, lsr #8 @ r9<- AA
2410 FETCH_B(r3, 1, 1) @ r3<- CC
2411 GET_VREG(r0, r2) @ r0<- vBB (array object)
2412 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2413 cmp r0, #0 @ null array object?
2414 beq common_errNullObject @ yes, bail
2415 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2416 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2417 cmp r1, r3 @ compare unsigned index, length
2418 bcs common_errArrayIndex @ index >= length, bail
2419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2420 GET_VREG(r2, r9) @ r2<- vAA
2421 GET_INST_OPCODE(ip) @ extract opcode from rINST
2422 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2423 GOTO_OPCODE(ip) @ jump to next instruction
2427 /* ------------------------------ */
2429 .L_OP_APUT_SHORT: /* 0x51 */
2430 /* File: armv5te/OP_APUT_SHORT.S */
2431 /* File: armv5te/OP_APUT.S */
2433 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2435 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2436 * instructions. We use a pair of FETCH_Bs instead.
2438 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2440 /* op vAA, vBB, vCC */
2441 FETCH_B(r2, 1, 0) @ r2<- BB
2442 mov r9, rINST, lsr #8 @ r9<- AA
2443 FETCH_B(r3, 1, 1) @ r3<- CC
2444 GET_VREG(r0, r2) @ r0<- vBB (array object)
2445 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2446 cmp r0, #0 @ null array object?
2447 beq common_errNullObject @ yes, bail
2448 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2449 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2450 cmp r1, r3 @ compare unsigned index, length
2451 bcs common_errArrayIndex @ index >= length, bail
2452 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2453 GET_VREG(r2, r9) @ r2<- vAA
2454 GET_INST_OPCODE(ip) @ extract opcode from rINST
2455 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2456 GOTO_OPCODE(ip) @ jump to next instruction
2460 /* ------------------------------ */
2462 .L_OP_IGET: /* 0x52 */
2463 /* File: armv5te/OP_IGET.S */
2465 * General 32-bit instance field get.
2467 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2469 /* op vA, vB, field@CCCC */
2470 mov r0, rINST, lsr #12 @ r0<- B
2471 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2472 FETCH(r1, 1) @ r1<- field ref CCCC
2473 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2475 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2476 cmp r0, #0 @ is resolved entry null?
2477 bne .LOP_IGET_finish @ no, already resolved
2478 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2479 EXPORT_PC() @ resolve() could throw
2480 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2481 bl dvmResolveInstField @ r0<- resolved InstField ptr
2483 bne .LOP_IGET_finish
2484 b common_exceptionThrown
2486 /* ------------------------------ */
2488 .L_OP_IGET_WIDE: /* 0x53 */
2489 /* File: armv5te/OP_IGET_WIDE.S */
2491 * Wide 32-bit instance field get.
2493 /* iget-wide vA, vB, field@CCCC */
2494 mov r0, rINST, lsr #12 @ r0<- B
2495 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2496 FETCH(r1, 1) @ r1<- field ref CCCC
2497 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2498 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2499 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2500 cmp r0, #0 @ is resolved entry null?
2501 bne .LOP_IGET_WIDE_finish @ no, already resolved
2502 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2503 EXPORT_PC() @ resolve() could throw
2504 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2505 bl dvmResolveInstField @ r0<- resolved InstField ptr
2507 bne .LOP_IGET_WIDE_finish
2508 b common_exceptionThrown
2510 /* ------------------------------ */
2512 .L_OP_IGET_OBJECT: /* 0x54 */
2513 /* File: armv5te/OP_IGET_OBJECT.S */
2514 /* File: armv5te/OP_IGET.S */
2516 * General 32-bit instance field get.
2518 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2520 /* op vA, vB, field@CCCC */
2521 mov r0, rINST, lsr #12 @ r0<- B
2522 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2523 FETCH(r1, 1) @ r1<- field ref CCCC
2524 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2525 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2526 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2527 cmp r0, #0 @ is resolved entry null?
2528 bne .LOP_IGET_OBJECT_finish @ no, already resolved
2529 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2530 EXPORT_PC() @ resolve() could throw
2531 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2532 bl dvmResolveInstField @ r0<- resolved InstField ptr
2534 bne .LOP_IGET_OBJECT_finish
2535 b common_exceptionThrown
2538 /* ------------------------------ */
2540 .L_OP_IGET_BOOLEAN: /* 0x55 */
2541 /* File: armv5te/OP_IGET_BOOLEAN.S */
2542 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2543 /* File: armv5te/OP_IGET.S */
2545 * General 32-bit instance field get.
2547 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2549 /* op vA, vB, field@CCCC */
2550 mov r0, rINST, lsr #12 @ r0<- B
2551 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2552 FETCH(r1, 1) @ r1<- field ref CCCC
2553 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2554 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2555 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2556 cmp r0, #0 @ is resolved entry null?
2557 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved
2558 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2559 EXPORT_PC() @ resolve() could throw
2560 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2561 bl dvmResolveInstField @ r0<- resolved InstField ptr
2563 bne .LOP_IGET_BOOLEAN_finish
2564 b common_exceptionThrown
2567 /* ------------------------------ */
2569 .L_OP_IGET_BYTE: /* 0x56 */
2570 /* File: armv5te/OP_IGET_BYTE.S */
2571 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2572 /* File: armv5te/OP_IGET.S */
2574 * General 32-bit instance field get.
2576 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2578 /* op vA, vB, field@CCCC */
2579 mov r0, rINST, lsr #12 @ r0<- B
2580 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2581 FETCH(r1, 1) @ r1<- field ref CCCC
2582 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2583 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2584 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2585 cmp r0, #0 @ is resolved entry null?
2586 bne .LOP_IGET_BYTE_finish @ no, already resolved
2587 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2588 EXPORT_PC() @ resolve() could throw
2589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2590 bl dvmResolveInstField @ r0<- resolved InstField ptr
2592 bne .LOP_IGET_BYTE_finish
2593 b common_exceptionThrown
2596 /* ------------------------------ */
2598 .L_OP_IGET_CHAR: /* 0x57 */
2599 /* File: armv5te/OP_IGET_CHAR.S */
2600 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2601 /* File: armv5te/OP_IGET.S */
2603 * General 32-bit instance field get.
2605 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2607 /* op vA, vB, field@CCCC */
2608 mov r0, rINST, lsr #12 @ r0<- B
2609 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2610 FETCH(r1, 1) @ r1<- field ref CCCC
2611 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2612 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2613 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2614 cmp r0, #0 @ is resolved entry null?
2615 bne .LOP_IGET_CHAR_finish @ no, already resolved
2616 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2617 EXPORT_PC() @ resolve() could throw
2618 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2619 bl dvmResolveInstField @ r0<- resolved InstField ptr
2621 bne .LOP_IGET_CHAR_finish
2622 b common_exceptionThrown
2625 /* ------------------------------ */
2627 .L_OP_IGET_SHORT: /* 0x58 */
2628 /* File: armv5te/OP_IGET_SHORT.S */
2629 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2630 /* File: armv5te/OP_IGET.S */
2632 * General 32-bit instance field get.
2634 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2636 /* op vA, vB, field@CCCC */
2637 mov r0, rINST, lsr #12 @ r0<- B
2638 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2639 FETCH(r1, 1) @ r1<- field ref CCCC
2640 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2641 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2642 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2643 cmp r0, #0 @ is resolved entry null?
2644 bne .LOP_IGET_SHORT_finish @ no, already resolved
2645 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2646 EXPORT_PC() @ resolve() could throw
2647 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2648 bl dvmResolveInstField @ r0<- resolved InstField ptr
2650 bne .LOP_IGET_SHORT_finish
2651 b common_exceptionThrown
2654 /* ------------------------------ */
2656 .L_OP_IPUT: /* 0x59 */
2657 /* File: armv5te/OP_IPUT.S */
2659 * General 32-bit instance field put.
2661 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2663 /* op vA, vB, field@CCCC */
2664 mov r0, rINST, lsr #12 @ r0<- B
2665 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2666 FETCH(r1, 1) @ r1<- field ref CCCC
2667 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2668 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2669 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2670 cmp r0, #0 @ is resolved entry null?
2671 bne .LOP_IPUT_finish @ no, already resolved
2672 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2673 EXPORT_PC() @ resolve() could throw
2674 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2675 bl dvmResolveInstField @ r0<- resolved InstField ptr
2676 cmp r0, #0 @ success?
2677 bne .LOP_IPUT_finish @ yes, finish up
2678 b common_exceptionThrown
2680 /* ------------------------------ */
2682 .L_OP_IPUT_WIDE: /* 0x5a */
2683 /* File: armv5te/OP_IPUT_WIDE.S */
2684 /* iput-wide vA, vB, field@CCCC */
2685 mov r0, rINST, lsr #12 @ r0<- B
2686 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2687 FETCH(r1, 1) @ r1<- field ref CCCC
2688 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2689 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2690 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2691 cmp r0, #0 @ is resolved entry null?
2692 bne .LOP_IPUT_WIDE_finish @ no, already resolved
2693 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2694 EXPORT_PC() @ resolve() could throw
2695 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2696 bl dvmResolveInstField @ r0<- resolved InstField ptr
2697 cmp r0, #0 @ success?
2698 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2699 b common_exceptionThrown
2701 /* ------------------------------ */
2703 .L_OP_IPUT_OBJECT: /* 0x5b */
2704 /* File: armv5te/OP_IPUT_OBJECT.S */
2705 /* File: armv5te/OP_IPUT.S */
2707 * General 32-bit instance field put.
2709 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2711 /* op vA, vB, field@CCCC */
2712 mov r0, rINST, lsr #12 @ r0<- B
2713 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2714 FETCH(r1, 1) @ r1<- field ref CCCC
2715 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2716 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2717 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2718 cmp r0, #0 @ is resolved entry null?
2719 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
2720 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2721 EXPORT_PC() @ resolve() could throw
2722 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2723 bl dvmResolveInstField @ r0<- resolved InstField ptr
2724 cmp r0, #0 @ success?
2725 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2726 b common_exceptionThrown
2729 /* ------------------------------ */
2731 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2732 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2733 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2734 /* File: armv5te/OP_IPUT.S */
2736 * General 32-bit instance field put.
2738 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2740 /* op vA, vB, field@CCCC */
2741 mov r0, rINST, lsr #12 @ r0<- B
2742 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2743 FETCH(r1, 1) @ r1<- field ref CCCC
2744 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2745 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2746 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2747 cmp r0, #0 @ is resolved entry null?
2748 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
2749 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2750 EXPORT_PC() @ resolve() could throw
2751 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2752 bl dvmResolveInstField @ r0<- resolved InstField ptr
2753 cmp r0, #0 @ success?
2754 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2755 b common_exceptionThrown
2758 /* ------------------------------ */
2760 .L_OP_IPUT_BYTE: /* 0x5d */
2761 /* File: armv5te/OP_IPUT_BYTE.S */
2762 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2763 /* File: armv5te/OP_IPUT.S */
2765 * General 32-bit instance field put.
2767 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2769 /* op vA, vB, field@CCCC */
2770 mov r0, rINST, lsr #12 @ r0<- B
2771 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2772 FETCH(r1, 1) @ r1<- field ref CCCC
2773 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2774 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2775 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2776 cmp r0, #0 @ is resolved entry null?
2777 bne .LOP_IPUT_BYTE_finish @ no, already resolved
2778 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2779 EXPORT_PC() @ resolve() could throw
2780 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2781 bl dvmResolveInstField @ r0<- resolved InstField ptr
2782 cmp r0, #0 @ success?
2783 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2784 b common_exceptionThrown
2787 /* ------------------------------ */
2789 .L_OP_IPUT_CHAR: /* 0x5e */
2790 /* File: armv5te/OP_IPUT_CHAR.S */
2791 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2792 /* File: armv5te/OP_IPUT.S */
2794 * General 32-bit instance field put.
2796 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2798 /* op vA, vB, field@CCCC */
2799 mov r0, rINST, lsr #12 @ r0<- B
2800 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2801 FETCH(r1, 1) @ r1<- field ref CCCC
2802 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2803 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2804 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2805 cmp r0, #0 @ is resolved entry null?
2806 bne .LOP_IPUT_CHAR_finish @ no, already resolved
2807 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2808 EXPORT_PC() @ resolve() could throw
2809 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2810 bl dvmResolveInstField @ r0<- resolved InstField ptr
2811 cmp r0, #0 @ success?
2812 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2813 b common_exceptionThrown
2816 /* ------------------------------ */
2818 .L_OP_IPUT_SHORT: /* 0x5f */
2819 /* File: armv5te/OP_IPUT_SHORT.S */
2820 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2821 /* File: armv5te/OP_IPUT.S */
2823 * General 32-bit instance field put.
2825 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2827 /* op vA, vB, field@CCCC */
2828 mov r0, rINST, lsr #12 @ r0<- B
2829 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2830 FETCH(r1, 1) @ r1<- field ref CCCC
2831 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2832 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2833 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2834 cmp r0, #0 @ is resolved entry null?
2835 bne .LOP_IPUT_SHORT_finish @ no, already resolved
2836 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2837 EXPORT_PC() @ resolve() could throw
2838 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2839 bl dvmResolveInstField @ r0<- resolved InstField ptr
2840 cmp r0, #0 @ success?
2841 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2842 b common_exceptionThrown
2845 /* ------------------------------ */
2847 .L_OP_SGET: /* 0x60 */
2848 /* File: armv5te/OP_SGET.S */
2850 * General 32-bit SGET handler.
2852 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2854 /* op vAA, field@BBBB */
2855 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2856 FETCH(r1, 1) @ r1<- field ref BBBB
2857 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2858 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2859 cmp r0, #0 @ is resolved entry null?
2860 beq .LOP_SGET_resolve @ yes, do resolve
2861 .LOP_SGET_finish: @ field ptr in r0
2862 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2863 mov r2, rINST, lsr #8 @ r2<- AA
2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2865 SET_VREG(r1, r2) @ fp[AA]<- r1
2866 GET_INST_OPCODE(ip) @ extract opcode from rINST
2867 GOTO_OPCODE(ip) @ jump to next instruction
2869 /* ------------------------------ */
2871 .L_OP_SGET_WIDE: /* 0x61 */
2872 /* File: armv5te/OP_SGET_WIDE.S */
2874 * 64-bit SGET handler.
2876 /* sget-wide vAA, field@BBBB */
2877 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2878 FETCH(r1, 1) @ r1<- field ref BBBB
2879 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2880 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2881 cmp r0, #0 @ is resolved entry null?
2882 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2883 .LOP_SGET_WIDE_finish:
2884 mov r1, rINST, lsr #8 @ r1<- AA
2885 ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2886 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
2887 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2888 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
2889 GET_INST_OPCODE(ip) @ extract opcode from rINST
2890 GOTO_OPCODE(ip) @ jump to next instruction
2892 /* ------------------------------ */
2894 .L_OP_SGET_OBJECT: /* 0x62 */
2895 /* File: armv5te/OP_SGET_OBJECT.S */
2896 /* File: armv5te/OP_SGET.S */
2898 * General 32-bit SGET handler.
2900 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2902 /* op vAA, field@BBBB */
2903 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2904 FETCH(r1, 1) @ r1<- field ref BBBB
2905 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2906 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2907 cmp r0, #0 @ is resolved entry null?
2908 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2909 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2910 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2911 mov r2, rINST, lsr #8 @ r2<- AA
2912 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2913 SET_VREG(r1, r2) @ fp[AA]<- r1
2914 GET_INST_OPCODE(ip) @ extract opcode from rINST
2915 GOTO_OPCODE(ip) @ jump to next instruction
2918 /* ------------------------------ */
2920 .L_OP_SGET_BOOLEAN: /* 0x63 */
2921 /* File: armv5te/OP_SGET_BOOLEAN.S */
2922 /* File: armv5te/OP_SGET.S */
2924 * General 32-bit SGET handler.
2926 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2928 /* op vAA, field@BBBB */
2929 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2930 FETCH(r1, 1) @ r1<- field ref BBBB
2931 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2932 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2933 cmp r0, #0 @ is resolved entry null?
2934 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2935 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2936 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2937 mov r2, rINST, lsr #8 @ r2<- AA
2938 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2939 SET_VREG(r1, r2) @ fp[AA]<- r1
2940 GET_INST_OPCODE(ip) @ extract opcode from rINST
2941 GOTO_OPCODE(ip) @ jump to next instruction
2944 /* ------------------------------ */
2946 .L_OP_SGET_BYTE: /* 0x64 */
2947 /* File: armv5te/OP_SGET_BYTE.S */
2948 /* File: armv5te/OP_SGET.S */
2950 * General 32-bit SGET handler.
2952 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2954 /* op vAA, field@BBBB */
2955 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2956 FETCH(r1, 1) @ r1<- field ref BBBB
2957 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2958 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2959 cmp r0, #0 @ is resolved entry null?
2960 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2961 .LOP_SGET_BYTE_finish: @ field ptr in r0
2962 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2963 mov r2, rINST, lsr #8 @ r2<- AA
2964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2965 SET_VREG(r1, r2) @ fp[AA]<- r1
2966 GET_INST_OPCODE(ip) @ extract opcode from rINST
2967 GOTO_OPCODE(ip) @ jump to next instruction
2970 /* ------------------------------ */
2972 .L_OP_SGET_CHAR: /* 0x65 */
2973 /* File: armv5te/OP_SGET_CHAR.S */
2974 /* File: armv5te/OP_SGET.S */
2976 * General 32-bit SGET handler.
2978 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2980 /* op vAA, field@BBBB */
2981 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2982 FETCH(r1, 1) @ r1<- field ref BBBB
2983 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2984 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2985 cmp r0, #0 @ is resolved entry null?
2986 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2987 .LOP_SGET_CHAR_finish: @ field ptr in r0
2988 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2989 mov r2, rINST, lsr #8 @ r2<- AA
2990 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2991 SET_VREG(r1, r2) @ fp[AA]<- r1
2992 GET_INST_OPCODE(ip) @ extract opcode from rINST
2993 GOTO_OPCODE(ip) @ jump to next instruction
2996 /* ------------------------------ */
2998 .L_OP_SGET_SHORT: /* 0x66 */
2999 /* File: armv5te/OP_SGET_SHORT.S */
3000 /* File: armv5te/OP_SGET.S */
3002 * General 32-bit SGET handler.
3004 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3006 /* op vAA, field@BBBB */
3007 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3008 FETCH(r1, 1) @ r1<- field ref BBBB
3009 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3010 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3011 cmp r0, #0 @ is resolved entry null?
3012 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
3013 .LOP_SGET_SHORT_finish: @ field ptr in r0
3014 ldr r1, [r0, #offStaticField_value] @ r1<- field value
3015 mov r2, rINST, lsr #8 @ r2<- AA
3016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3017 SET_VREG(r1, r2) @ fp[AA]<- r1
3018 GET_INST_OPCODE(ip) @ extract opcode from rINST
3019 GOTO_OPCODE(ip) @ jump to next instruction
3022 /* ------------------------------ */
3024 .L_OP_SPUT: /* 0x67 */
3025 /* File: armv5te/OP_SPUT.S */
3027 * General 32-bit SPUT handler.
3029 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3031 /* op vAA, field@BBBB */
3032 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3033 FETCH(r1, 1) @ r1<- field ref BBBB
3034 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3035 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3036 cmp r0, #0 @ is resolved entry null?
3037 beq .LOP_SPUT_resolve @ yes, do resolve
3038 .LOP_SPUT_finish: @ field ptr in r0
3039 mov r2, rINST, lsr #8 @ r2<- AA
3040 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3041 GET_VREG(r1, r2) @ r1<- fp[AA]
3042 GET_INST_OPCODE(ip) @ extract opcode from rINST
3043 str r1, [r0, #offStaticField_value] @ field<- vAA
3044 GOTO_OPCODE(ip) @ jump to next instruction
3046 /* ------------------------------ */
3048 .L_OP_SPUT_WIDE: /* 0x68 */
3049 /* File: armv5te/OP_SPUT_WIDE.S */
3051 * 64-bit SPUT handler.
3053 /* sput-wide vAA, field@BBBB */
3054 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3055 FETCH(r1, 1) @ r1<- field ref BBBB
3056 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3057 mov r9, rINST, lsr #8 @ r9<- AA
3058 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3059 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
3060 cmp r0, #0 @ is resolved entry null?
3061 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
3062 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3064 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
3065 GET_INST_OPCODE(ip) @ extract opcode from rINST
3066 strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3067 GOTO_OPCODE(ip) @ jump to next instruction
3069 /* ------------------------------ */
3071 .L_OP_SPUT_OBJECT: /* 0x69 */
3072 /* File: armv5te/OP_SPUT_OBJECT.S */
3073 /* File: armv5te/OP_SPUT.S */
3075 * General 32-bit SPUT handler.
3077 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3079 /* op vAA, field@BBBB */
3080 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3081 FETCH(r1, 1) @ r1<- field ref BBBB
3082 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3083 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3084 cmp r0, #0 @ is resolved entry null?
3085 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
3086 .LOP_SPUT_OBJECT_finish: @ field ptr in r0
3087 mov r2, rINST, lsr #8 @ r2<- AA
3088 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3089 GET_VREG(r1, r2) @ r1<- fp[AA]
3090 GET_INST_OPCODE(ip) @ extract opcode from rINST
3091 str r1, [r0, #offStaticField_value] @ field<- vAA
3092 GOTO_OPCODE(ip) @ jump to next instruction
3095 /* ------------------------------ */
3097 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3098 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3099 /* File: armv5te/OP_SPUT.S */
3101 * General 32-bit SPUT handler.
3103 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3105 /* op vAA, field@BBBB */
3106 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3107 FETCH(r1, 1) @ r1<- field ref BBBB
3108 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3109 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3110 cmp r0, #0 @ is resolved entry null?
3111 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve
3112 .LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
3113 mov r2, rINST, lsr #8 @ r2<- AA
3114 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3115 GET_VREG(r1, r2) @ r1<- fp[AA]
3116 GET_INST_OPCODE(ip) @ extract opcode from rINST
3117 str r1, [r0, #offStaticField_value] @ field<- vAA
3118 GOTO_OPCODE(ip) @ jump to next instruction
3121 /* ------------------------------ */
3123 .L_OP_SPUT_BYTE: /* 0x6b */
3124 /* File: armv5te/OP_SPUT_BYTE.S */
3125 /* File: armv5te/OP_SPUT.S */
3127 * General 32-bit SPUT handler.
3129 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3131 /* op vAA, field@BBBB */
3132 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3133 FETCH(r1, 1) @ r1<- field ref BBBB
3134 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3135 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3136 cmp r0, #0 @ is resolved entry null?
3137 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve
3138 .LOP_SPUT_BYTE_finish: @ field ptr in r0
3139 mov r2, rINST, lsr #8 @ r2<- AA
3140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3141 GET_VREG(r1, r2) @ r1<- fp[AA]
3142 GET_INST_OPCODE(ip) @ extract opcode from rINST
3143 str r1, [r0, #offStaticField_value] @ field<- vAA
3144 GOTO_OPCODE(ip) @ jump to next instruction
3147 /* ------------------------------ */
3149 .L_OP_SPUT_CHAR: /* 0x6c */
3150 /* File: armv5te/OP_SPUT_CHAR.S */
3151 /* File: armv5te/OP_SPUT.S */
3153 * General 32-bit SPUT handler.
3155 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3157 /* op vAA, field@BBBB */
3158 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3159 FETCH(r1, 1) @ r1<- field ref BBBB
3160 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3161 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3162 cmp r0, #0 @ is resolved entry null?
3163 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve
3164 .LOP_SPUT_CHAR_finish: @ field ptr in r0
3165 mov r2, rINST, lsr #8 @ r2<- AA
3166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3167 GET_VREG(r1, r2) @ r1<- fp[AA]
3168 GET_INST_OPCODE(ip) @ extract opcode from rINST
3169 str r1, [r0, #offStaticField_value] @ field<- vAA
3170 GOTO_OPCODE(ip) @ jump to next instruction
3173 /* ------------------------------ */
3175 .L_OP_SPUT_SHORT: /* 0x6d */
3176 /* File: armv5te/OP_SPUT_SHORT.S */
3177 /* File: armv5te/OP_SPUT.S */
3179 * General 32-bit SPUT handler.
3181 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3183 /* op vAA, field@BBBB */
3184 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3185 FETCH(r1, 1) @ r1<- field ref BBBB
3186 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3187 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3188 cmp r0, #0 @ is resolved entry null?
3189 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve
3190 .LOP_SPUT_SHORT_finish: @ field ptr in r0
3191 mov r2, rINST, lsr #8 @ r2<- AA
3192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3193 GET_VREG(r1, r2) @ r1<- fp[AA]
3194 GET_INST_OPCODE(ip) @ extract opcode from rINST
3195 str r1, [r0, #offStaticField_value] @ field<- vAA
3196 GOTO_OPCODE(ip) @ jump to next instruction
3199 /* ------------------------------ */
3201 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3202 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3204 * Handle a virtual method call.
3206 * for: invoke-virtual, invoke-virtual/range
3208 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3209 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3210 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3211 FETCH(r1, 1) @ r1<- BBBB
3212 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3213 FETCH(r10, 2) @ r10<- GFED or CCCC
3214 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3216 and r10, r10, #15 @ r10<- D (or stays CCCC)
3218 cmp r0, #0 @ already resolved?
3219 EXPORT_PC() @ must export for invoke
3220 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3221 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3222 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3223 mov r2, #METHOD_VIRTUAL @ resolver method type
3224 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3225 cmp r0, #0 @ got null?
3226 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3227 b common_exceptionThrown @ yes, handle exception
3229 /* ------------------------------ */
3231 .L_OP_INVOKE_SUPER: /* 0x6f */
3232 /* File: armv5te/OP_INVOKE_SUPER.S */
3234 * Handle a "super" method call.
3236 * for: invoke-super, invoke-super/range
3238 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240 FETCH(r10, 2) @ r10<- GFED or CCCC
3241 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3243 and r10, r10, #15 @ r10<- D (or stays CCCC)
3245 FETCH(r1, 1) @ r1<- BBBB
3246 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3247 GET_VREG(r2, r10) @ r2<- "this" ptr
3248 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3249 cmp r2, #0 @ null "this"?
3250 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3251 beq common_errNullObject @ null "this", throw exception
3252 cmp r0, #0 @ already resolved?
3253 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3254 EXPORT_PC() @ must export for invoke
3255 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3256 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3258 /* ------------------------------ */
3260 .L_OP_INVOKE_DIRECT: /* 0x70 */
3261 /* File: armv5te/OP_INVOKE_DIRECT.S */
3263 * Handle a direct method call.
3265 * (We could defer the "is 'this' pointer null" test to the common
3266 * method invocation code, and use a flag to indicate that static
3267 * calls don't count. If we do this as part of copying the arguments
3268 * out we could avoiding loading the first arg twice.)
3270 * for: invoke-direct, invoke-direct/range
3272 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3273 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3274 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3275 FETCH(r1, 1) @ r1<- BBBB
3276 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3277 FETCH(r10, 2) @ r10<- GFED or CCCC
3278 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3280 and r10, r10, #15 @ r10<- D (or stays CCCC)
3282 cmp r0, #0 @ already resolved?
3283 EXPORT_PC() @ must export for invoke
3284 GET_VREG(r2, r10) @ r2<- "this" ptr
3285 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3286 .LOP_INVOKE_DIRECT_finish:
3287 cmp r2, #0 @ null "this" ref?
3288 bne common_invokeMethodNoRange @ no, continue on
3289 b common_errNullObject @ yes, throw exception
3291 /* ------------------------------ */
3293 .L_OP_INVOKE_STATIC: /* 0x71 */
3294 /* File: armv5te/OP_INVOKE_STATIC.S */
3296 * Handle a static method call.
3298 * for: invoke-static, invoke-static/range
3300 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3301 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3302 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3303 FETCH(r1, 1) @ r1<- BBBB
3304 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3305 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3306 cmp r0, #0 @ already resolved?
3307 EXPORT_PC() @ must export for invoke
3308 bne common_invokeMethodNoRange @ yes, continue on
3309 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3310 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3311 mov r2, #METHOD_STATIC @ resolver method type
3312 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3313 cmp r0, #0 @ got null?
3314 bne common_invokeMethodNoRange @ no, continue
3315 b common_exceptionThrown @ yes, handle exception
3318 /* ------------------------------ */
3320 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3321 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3323 * Handle an interface method call.
3325 * for: invoke-interface, invoke-interface/range
3327 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3328 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3329 FETCH(r2, 2) @ r2<- FEDC or CCCC
3330 FETCH(r1, 1) @ r1<- BBBB
3332 and r2, r2, #15 @ r2<- C (or stays CCCC)
3334 EXPORT_PC() @ must export for invoke
3335 GET_VREG(r0, r2) @ r0<- first arg ("this")
3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3337 cmp r0, #0 @ null obj?
3338 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3339 beq common_errNullObject @ yes, fail
3340 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3341 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3342 cmp r0, #0 @ failed?
3343 beq common_exceptionThrown @ yes, handle exception
3344 b common_invokeMethodNoRange @ jump to common handler
3347 /* ------------------------------ */
3349 .L_OP_UNUSED_73: /* 0x73 */
3350 /* File: armv5te/OP_UNUSED_73.S */
3351 /* File: armv5te/unused.S */
3356 /* ------------------------------ */
3358 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3359 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3360 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3362 * Handle a virtual method call.
3364 * for: invoke-virtual, invoke-virtual/range
3366 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3369 FETCH(r1, 1) @ r1<- BBBB
3370 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3371 FETCH(r10, 2) @ r10<- GFED or CCCC
3372 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3374 and r10, r10, #15 @ r10<- D (or stays CCCC)
3376 cmp r0, #0 @ already resolved?
3377 EXPORT_PC() @ must export for invoke
3378 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3379 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3380 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3381 mov r2, #METHOD_VIRTUAL @ resolver method type
3382 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3383 cmp r0, #0 @ got null?
3384 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3385 b common_exceptionThrown @ yes, handle exception
3388 /* ------------------------------ */
3390 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3391 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3392 /* File: armv5te/OP_INVOKE_SUPER.S */
3394 * Handle a "super" method call.
3396 * for: invoke-super, invoke-super/range
3398 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3399 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3400 FETCH(r10, 2) @ r10<- GFED or CCCC
3401 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3403 and r10, r10, #15 @ r10<- D (or stays CCCC)
3405 FETCH(r1, 1) @ r1<- BBBB
3406 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3407 GET_VREG(r2, r10) @ r2<- "this" ptr
3408 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3409 cmp r2, #0 @ null "this"?
3410 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3411 beq common_errNullObject @ null "this", throw exception
3412 cmp r0, #0 @ already resolved?
3413 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3414 EXPORT_PC() @ must export for invoke
3415 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3416 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3419 /* ------------------------------ */
3421 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3422 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3423 /* File: armv5te/OP_INVOKE_DIRECT.S */
3425 * Handle a direct method call.
3427 * (We could defer the "is 'this' pointer null" test to the common
3428 * method invocation code, and use a flag to indicate that static
3429 * calls don't count. If we do this as part of copying the arguments
3430 * out we could avoiding loading the first arg twice.)
3432 * for: invoke-direct, invoke-direct/range
3434 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3435 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3436 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3437 FETCH(r1, 1) @ r1<- BBBB
3438 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3439 FETCH(r10, 2) @ r10<- GFED or CCCC
3440 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3442 and r10, r10, #15 @ r10<- D (or stays CCCC)
3444 cmp r0, #0 @ already resolved?
3445 EXPORT_PC() @ must export for invoke
3446 GET_VREG(r2, r10) @ r2<- "this" ptr
3447 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3448 .LOP_INVOKE_DIRECT_RANGE_finish:
3449 cmp r2, #0 @ null "this" ref?
3450 bne common_invokeMethodRange @ no, continue on
3451 b common_errNullObject @ yes, throw exception
3454 /* ------------------------------ */
3456 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3457 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3458 /* File: armv5te/OP_INVOKE_STATIC.S */
3460 * Handle a static method call.
3462 * for: invoke-static, invoke-static/range
3464 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3465 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3466 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3467 FETCH(r1, 1) @ r1<- BBBB
3468 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3469 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3470 cmp r0, #0 @ already resolved?
3471 EXPORT_PC() @ must export for invoke
3472 bne common_invokeMethodRange @ yes, continue on
3473 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3474 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3475 mov r2, #METHOD_STATIC @ resolver method type
3476 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3477 cmp r0, #0 @ got null?
3478 bne common_invokeMethodRange @ no, continue
3479 b common_exceptionThrown @ yes, handle exception
3483 /* ------------------------------ */
3485 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3486 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3487 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3489 * Handle an interface method call.
3491 * for: invoke-interface, invoke-interface/range
3493 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3494 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3495 FETCH(r2, 2) @ r2<- FEDC or CCCC
3496 FETCH(r1, 1) @ r1<- BBBB
3498 and r2, r2, #15 @ r2<- C (or stays CCCC)
3500 EXPORT_PC() @ must export for invoke
3501 GET_VREG(r0, r2) @ r0<- first arg ("this")
3502 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3503 cmp r0, #0 @ null obj?
3504 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3505 beq common_errNullObject @ yes, fail
3506 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3507 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3508 cmp r0, #0 @ failed?
3509 beq common_exceptionThrown @ yes, handle exception
3510 b common_invokeMethodRange @ jump to common handler
3514 /* ------------------------------ */
3516 .L_OP_UNUSED_79: /* 0x79 */
3517 /* File: armv5te/OP_UNUSED_79.S */
3518 /* File: armv5te/unused.S */
3523 /* ------------------------------ */
3525 .L_OP_UNUSED_7A: /* 0x7a */
3526 /* File: armv5te/OP_UNUSED_7A.S */
3527 /* File: armv5te/unused.S */
3532 /* ------------------------------ */
3534 .L_OP_NEG_INT: /* 0x7b */
3535 /* File: armv5te/OP_NEG_INT.S */
3536 /* File: armv5te/unop.S */
3538 * Generic 32-bit unary operation. Provide an "instr" line that
3539 * specifies an instruction that performs "result = op r0".
3540 * This could be an ARM instruction or a function call.
3542 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543 * int-to-byte, int-to-char, int-to-short
3546 mov r3, rINST, lsr #12 @ r3<- B
3547 mov r9, rINST, lsr #8 @ r9<- A+
3548 GET_VREG(r0, r3) @ r0<- vB
3550 @ optional op; may set condition codes
3551 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3552 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3553 GET_INST_OPCODE(ip) @ extract opcode from rINST
3554 SET_VREG(r0, r9) @ vAA<- r0
3555 GOTO_OPCODE(ip) @ jump to next instruction
3556 /* 9-10 instructions */
3559 /* ------------------------------ */
3561 .L_OP_NOT_INT: /* 0x7c */
3562 /* File: armv5te/OP_NOT_INT.S */
3563 /* File: armv5te/unop.S */
3565 * Generic 32-bit unary operation. Provide an "instr" line that
3566 * specifies an instruction that performs "result = op r0".
3567 * This could be an ARM instruction or a function call.
3569 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3570 * int-to-byte, int-to-char, int-to-short
3573 mov r3, rINST, lsr #12 @ r3<- B
3574 mov r9, rINST, lsr #8 @ r9<- A+
3575 GET_VREG(r0, r3) @ r0<- vB
3577 @ optional op; may set condition codes
3578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3579 mvn r0, r0 @ r0<- op, r0-r3 changed
3580 GET_INST_OPCODE(ip) @ extract opcode from rINST
3581 SET_VREG(r0, r9) @ vAA<- r0
3582 GOTO_OPCODE(ip) @ jump to next instruction
3583 /* 9-10 instructions */
3586 /* ------------------------------ */
3588 .L_OP_NEG_LONG: /* 0x7d */
3589 /* File: armv5te/OP_NEG_LONG.S */
3590 /* File: armv5te/unopWide.S */
3592 * Generic 64-bit unary operation. Provide an "instr" line that
3593 * specifies an instruction that performs "result = op r0/r1".
3594 * This could be an ARM instruction or a function call.
3596 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3599 mov r9, rINST, lsr #8 @ r9<- A+
3600 mov r3, rINST, lsr #12 @ r3<- B
3602 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3603 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3604 ldmia r3, {r0-r1} @ r0/r1<- vAA
3605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3606 rsbs r0, r0, #0 @ optional op; may set condition codes
3607 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3608 GET_INST_OPCODE(ip) @ extract opcode from rINST
3609 stmia r9, {r0-r1} @ vAA<- r0/r1
3610 GOTO_OPCODE(ip) @ jump to next instruction
3611 /* 12-13 instructions */
3615 /* ------------------------------ */
3617 .L_OP_NOT_LONG: /* 0x7e */
3618 /* File: armv5te/OP_NOT_LONG.S */
3619 /* File: armv5te/unopWide.S */
3621 * Generic 64-bit unary operation. Provide an "instr" line that
3622 * specifies an instruction that performs "result = op r0/r1".
3623 * This could be an ARM instruction or a function call.
3625 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3628 mov r9, rINST, lsr #8 @ r9<- A+
3629 mov r3, rINST, lsr #12 @ r3<- B
3631 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3632 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3633 ldmia r3, {r0-r1} @ r0/r1<- vAA
3634 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3635 mvn r0, r0 @ optional op; may set condition codes
3636 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3637 GET_INST_OPCODE(ip) @ extract opcode from rINST
3638 stmia r9, {r0-r1} @ vAA<- r0/r1
3639 GOTO_OPCODE(ip) @ jump to next instruction
3640 /* 12-13 instructions */
3644 /* ------------------------------ */
3646 .L_OP_NEG_FLOAT: /* 0x7f */
3647 /* File: armv5te/OP_NEG_FLOAT.S */
3648 /* File: armv5te/unop.S */
3650 * Generic 32-bit unary operation. Provide an "instr" line that
3651 * specifies an instruction that performs "result = op r0".
3652 * This could be an ARM instruction or a function call.
3654 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3655 * int-to-byte, int-to-char, int-to-short
3658 mov r3, rINST, lsr #12 @ r3<- B
3659 mov r9, rINST, lsr #8 @ r9<- A+
3660 GET_VREG(r0, r3) @ r0<- vB
3662 @ optional op; may set condition codes
3663 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3664 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3665 GET_INST_OPCODE(ip) @ extract opcode from rINST
3666 SET_VREG(r0, r9) @ vAA<- r0
3667 GOTO_OPCODE(ip) @ jump to next instruction
3668 /* 9-10 instructions */
3671 /* ------------------------------ */
3673 .L_OP_NEG_DOUBLE: /* 0x80 */
3674 /* File: armv5te/OP_NEG_DOUBLE.S */
3675 /* File: armv5te/unopWide.S */
3677 * Generic 64-bit unary operation. Provide an "instr" line that
3678 * specifies an instruction that performs "result = op r0/r1".
3679 * This could be an ARM instruction or a function call.
3681 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3684 mov r9, rINST, lsr #8 @ r9<- A+
3685 mov r3, rINST, lsr #12 @ r3<- B
3687 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3688 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3689 ldmia r3, {r0-r1} @ r0/r1<- vAA
3690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3691 @ optional op; may set condition codes
3692 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed
3693 GET_INST_OPCODE(ip) @ extract opcode from rINST
3694 stmia r9, {r0-r1} @ vAA<- r0/r1
3695 GOTO_OPCODE(ip) @ jump to next instruction
3696 /* 12-13 instructions */
3700 /* ------------------------------ */
3702 .L_OP_INT_TO_LONG: /* 0x81 */
3703 /* File: armv5te/OP_INT_TO_LONG.S */
3704 /* File: armv5te/unopWider.S */
3706 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3707 * that specifies an instruction that performs "result = op r0", where
3708 * "result" is a 64-bit quantity in r0/r1.
3710 * For: int-to-long, int-to-double, float-to-long, float-to-double
3713 mov r9, rINST, lsr #8 @ r9<- A+
3714 mov r3, rINST, lsr #12 @ r3<- B
3716 GET_VREG(r0, r3) @ r0<- vB
3717 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3718 @ optional op; may set condition codes
3719 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3720 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3721 GET_INST_OPCODE(ip) @ extract opcode from rINST
3722 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3723 GOTO_OPCODE(ip) @ jump to next instruction
3724 /* 10-11 instructions */
3727 /* ------------------------------ */
3729 .L_OP_INT_TO_FLOAT: /* 0x82 */
3730 /* File: armv5te/OP_INT_TO_FLOAT.S */
3731 /* File: armv5te/unop.S */
3733 * Generic 32-bit unary operation. Provide an "instr" line that
3734 * specifies an instruction that performs "result = op r0".
3735 * This could be an ARM instruction or a function call.
3737 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3738 * int-to-byte, int-to-char, int-to-short
3741 mov r3, rINST, lsr #12 @ r3<- B
3742 mov r9, rINST, lsr #8 @ r9<- A+
3743 GET_VREG(r0, r3) @ r0<- vB
3745 @ optional op; may set condition codes
3746 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3747 bl __aeabi_i2f @ r0<- op, r0-r3 changed
3748 GET_INST_OPCODE(ip) @ extract opcode from rINST
3749 SET_VREG(r0, r9) @ vAA<- r0
3750 GOTO_OPCODE(ip) @ jump to next instruction
3751 /* 9-10 instructions */
3754 /* ------------------------------ */
3756 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3757 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3758 /* File: armv5te/unopWider.S */
3760 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3761 * that specifies an instruction that performs "result = op r0", where
3762 * "result" is a 64-bit quantity in r0/r1.
3764 * For: int-to-long, int-to-double, float-to-long, float-to-double
3767 mov r9, rINST, lsr #8 @ r9<- A+
3768 mov r3, rINST, lsr #12 @ r3<- B
3770 GET_VREG(r0, r3) @ r0<- vB
3771 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3772 @ optional op; may set condition codes
3773 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3774 bl __aeabi_i2d @ r0<- op, r0-r3 changed
3775 GET_INST_OPCODE(ip) @ extract opcode from rINST
3776 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3777 GOTO_OPCODE(ip) @ jump to next instruction
3778 /* 10-11 instructions */
3781 /* ------------------------------ */
3783 .L_OP_LONG_TO_INT: /* 0x84 */
3784 /* File: armv5te/OP_LONG_TO_INT.S */
3785 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3786 /* File: armv5te/OP_MOVE.S */
3787 /* for move, move-object, long-to-int */
3789 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3790 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3791 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3792 GET_VREG(r2, r1) @ r2<- fp[B]
3794 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3795 SET_VREG(r2, r0) @ fp[A]<- r2
3796 GOTO_OPCODE(ip) @ execute next instruction
3800 /* ------------------------------ */
3802 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3803 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3804 /* File: armv5te/unopNarrower.S */
3806 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3807 * that specifies an instruction that performs "result = op r0/r1", where
3808 * "result" is a 32-bit quantity in r0.
3810 * For: long-to-float, double-to-int, double-to-float
3812 * (This would work for long-to-int, but that instruction is actually
3813 * an exact match for OP_MOVE.)
3816 mov r3, rINST, lsr #12 @ r3<- B
3817 mov r9, rINST, lsr #8 @ r9<- A+
3818 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3820 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3821 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3822 @ optional op; may set condition codes
3823 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3824 GET_INST_OPCODE(ip) @ extract opcode from rINST
3825 SET_VREG(r0, r9) @ vA<- r0
3826 GOTO_OPCODE(ip) @ jump to next instruction
3827 /* 10-11 instructions */
3830 /* ------------------------------ */
3832 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3833 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3834 /* File: armv5te/unopWide.S */
3836 * Generic 64-bit unary operation. Provide an "instr" line that
3837 * specifies an instruction that performs "result = op r0/r1".
3838 * This could be an ARM instruction or a function call.
3840 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3843 mov r9, rINST, lsr #8 @ r9<- A+
3844 mov r3, rINST, lsr #12 @ r3<- B
3846 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3847 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3848 ldmia r3, {r0-r1} @ r0/r1<- vAA
3849 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3850 @ optional op; may set condition codes
3851 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3852 GET_INST_OPCODE(ip) @ extract opcode from rINST
3853 stmia r9, {r0-r1} @ vAA<- r0/r1
3854 GOTO_OPCODE(ip) @ jump to next instruction
3855 /* 12-13 instructions */
3859 /* ------------------------------ */
3861 .L_OP_FLOAT_TO_INT: /* 0x87 */
3862 /* File: armv5te/OP_FLOAT_TO_INT.S */
3863 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3864 /* File: armv5te/unop.S */
3866 * Generic 32-bit unary operation. Provide an "instr" line that
3867 * specifies an instruction that performs "result = op r0".
3868 * This could be an ARM instruction or a function call.
3870 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3871 * int-to-byte, int-to-char, int-to-short
3874 mov r3, rINST, lsr #12 @ r3<- B
3875 mov r9, rINST, lsr #8 @ r9<- A+
3876 GET_VREG(r0, r3) @ r0<- vB
3878 @ optional op; may set condition codes
3879 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3880 bl __aeabi_f2iz @ r0<- op, r0-r3 changed
3881 GET_INST_OPCODE(ip) @ extract opcode from rINST
3882 SET_VREG(r0, r9) @ vAA<- r0
3883 GOTO_OPCODE(ip) @ jump to next instruction
3884 /* 9-10 instructions */
3888 @include "armv5te/unop.S" {"instr":"bl f2i_doconv"}
3891 * Convert the float in r0 to an int in r0.
3893 * We have to clip values to int min/max per the specification. The
3894 * expected common case is a "reasonable" value that converts directly
3895 * to modest integer. The EABI convert function isn't doing this for us.
3899 mov r1, #0x4f000000 @ (float)maxint
3901 bl __aeabi_fcmpge @ is arg >= maxint?
3902 cmp r0, #0 @ nonzero == yes
3903 mvnne r0, #0x80000000 @ return maxint (7fffffff)
3904 ldmnefd sp!, {r4, pc}
3906 mov r0, r4 @ recover arg
3907 mov r1, #0xcf000000 @ (float)minint
3908 bl __aeabi_fcmple @ is arg <= minint?
3909 cmp r0, #0 @ nonzero == yes
3910 movne r0, #0x80000000 @ return minint (80000000)
3911 ldmnefd sp!, {r4, pc}
3913 mov r0, r4 @ recover arg
3915 bl __aeabi_fcmpeq @ is arg == self?
3916 cmp r0, #0 @ zero == no
3917 ldmeqfd sp!, {r4, pc} @ return zero for NaN
3919 mov r0, r4 @ recover arg
3920 bl __aeabi_f2iz @ convert float to int
3925 /* ------------------------------ */
3927 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3928 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3929 @include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3930 /* File: armv5te/unopWider.S */
3932 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3933 * that specifies an instruction that performs "result = op r0", where
3934 * "result" is a 64-bit quantity in r0/r1.
3936 * For: int-to-long, int-to-double, float-to-long, float-to-double
3939 mov r9, rINST, lsr #8 @ r9<- A+
3940 mov r3, rINST, lsr #12 @ r3<- B
3942 GET_VREG(r0, r3) @ r0<- vB
3943 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3944 @ optional op; may set condition codes
3945 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3946 bl f2l_doconv @ r0<- op, r0-r3 changed
3947 GET_INST_OPCODE(ip) @ extract opcode from rINST
3948 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3949 GOTO_OPCODE(ip) @ jump to next instruction
3950 /* 10-11 instructions */
3954 /* ------------------------------ */
3956 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3957 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3958 /* File: armv5te/unopWider.S */
3960 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3961 * that specifies an instruction that performs "result = op r0", where
3962 * "result" is a 64-bit quantity in r0/r1.
3964 * For: int-to-long, int-to-double, float-to-long, float-to-double
3967 mov r9, rINST, lsr #8 @ r9<- A+
3968 mov r3, rINST, lsr #12 @ r3<- B
3970 GET_VREG(r0, r3) @ r0<- vB
3971 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3972 @ optional op; may set condition codes
3973 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3974 bl __aeabi_f2d @ r0<- op, r0-r3 changed
3975 GET_INST_OPCODE(ip) @ extract opcode from rINST
3976 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3977 GOTO_OPCODE(ip) @ jump to next instruction
3978 /* 10-11 instructions */
3981 /* ------------------------------ */
3983 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3984 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3985 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3986 /* File: armv5te/unopNarrower.S */
3988 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3989 * that specifies an instruction that performs "result = op r0/r1", where
3990 * "result" is a 32-bit quantity in r0.
3992 * For: long-to-float, double-to-int, double-to-float
3994 * (This would work for long-to-int, but that instruction is actually
3995 * an exact match for OP_MOVE.)
3998 mov r3, rINST, lsr #12 @ r3<- B
3999 mov r9, rINST, lsr #8 @ r9<- A+
4000 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4002 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
4003 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4004 @ optional op; may set condition codes
4005 bl __aeabi_d2iz @ r0<- op, r0-r3 changed
4006 GET_INST_OPCODE(ip) @ extract opcode from rINST
4007 SET_VREG(r0, r9) @ vA<- r0
4008 GOTO_OPCODE(ip) @ jump to next instruction
4009 /* 10-11 instructions */
4013 @include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"}
4016 * Convert the double in r0/r1 to an int in r0.
4018 * We have to clip values to int min/max per the specification. The
4019 * expected common case is a "reasonable" value that converts directly
4020 * to modest integer. The EABI convert function isn't doing this for us.
4023 stmfd sp!, {r4, r5, lr} @ save regs
4024 mov r2, #0x80000000 @ maxint, as a double (low word)
4025 mov r2, r2, asr #9 @ 0xffc00000
4026 sub sp, sp, #4 @ align for EABI
4027 mvn r3, #0xbe000000 @ maxint, as a double (high word)
4028 sub r3, r3, #0x00200000 @ 0x41dfffff
4029 mov r4, r0 @ save a copy of r0
4031 bl __aeabi_dcmpge @ is arg >= maxint?
4032 cmp r0, #0 @ nonzero == yes
4033 mvnne r0, #0x80000000 @ return maxint (0x7fffffff)
4036 mov r0, r4 @ recover arg
4038 mov r3, #0xc1000000 @ minint, as a double (high word)
4039 add r3, r3, #0x00e00000 @ 0xc1e00000
4040 mov r2, #0 @ minint, as a double (low word)
4041 bl __aeabi_dcmple @ is arg <= minint?
4042 cmp r0, #0 @ nonzero == yes
4043 movne r0, #0x80000000 @ return minint (80000000)
4046 mov r0, r4 @ recover arg
4048 mov r2, r4 @ compare against self
4050 bl __aeabi_dcmpeq @ is arg == self?
4051 cmp r0, #0 @ zero == no
4052 beq 1f @ return zero for NaN
4054 mov r0, r4 @ recover arg
4056 bl __aeabi_d2iz @ convert double to int
4060 ldmfd sp!, {r4, r5, pc}
4064 /* ------------------------------ */
4066 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
4067 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
4068 @include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"}
4069 /* File: armv5te/unopWide.S */
4071 * Generic 64-bit unary operation. Provide an "instr" line that
4072 * specifies an instruction that performs "result = op r0/r1".
4073 * This could be an ARM instruction or a function call.
4075 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4078 mov r9, rINST, lsr #8 @ r9<- A+
4079 mov r3, rINST, lsr #12 @ r3<- B
4081 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4082 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
4083 ldmia r3, {r0-r1} @ r0/r1<- vAA
4084 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4085 @ optional op; may set condition codes
4086 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
4087 GET_INST_OPCODE(ip) @ extract opcode from rINST
4088 stmia r9, {r0-r1} @ vAA<- r0/r1
4089 GOTO_OPCODE(ip) @ jump to next instruction
4090 /* 12-13 instructions */
4095 /* ------------------------------ */
4097 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4098 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4099 /* File: armv5te/unopNarrower.S */
4101 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
4102 * that specifies an instruction that performs "result = op r0/r1", where
4103 * "result" is a 32-bit quantity in r0.
4105 * For: long-to-float, double-to-int, double-to-float
4107 * (This would work for long-to-int, but that instruction is actually
4108 * an exact match for OP_MOVE.)
4111 mov r3, rINST, lsr #12 @ r3<- B
4112 mov r9, rINST, lsr #8 @ r9<- A+
4113 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4115 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
4116 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4117 @ optional op; may set condition codes
4118 bl __aeabi_d2f @ r0<- op, r0-r3 changed
4119 GET_INST_OPCODE(ip) @ extract opcode from rINST
4120 SET_VREG(r0, r9) @ vA<- r0
4121 GOTO_OPCODE(ip) @ jump to next instruction
4122 /* 10-11 instructions */
4125 /* ------------------------------ */
4127 .L_OP_INT_TO_BYTE: /* 0x8d */
4128 /* File: armv5te/OP_INT_TO_BYTE.S */
4129 /* File: armv5te/unop.S */
4131 * Generic 32-bit unary operation. Provide an "instr" line that
4132 * specifies an instruction that performs "result = op r0".
4133 * This could be an ARM instruction or a function call.
4135 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4136 * int-to-byte, int-to-char, int-to-short
4139 mov r3, rINST, lsr #12 @ r3<- B
4140 mov r9, rINST, lsr #8 @ r9<- A+
4141 GET_VREG(r0, r3) @ r0<- vB
4143 mov r0, r0, asl #24 @ optional op; may set condition codes
4144 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4145 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed
4146 GET_INST_OPCODE(ip) @ extract opcode from rINST
4147 SET_VREG(r0, r9) @ vAA<- r0
4148 GOTO_OPCODE(ip) @ jump to next instruction
4149 /* 9-10 instructions */
4152 /* ------------------------------ */
4154 .L_OP_INT_TO_CHAR: /* 0x8e */
4155 /* File: armv5te/OP_INT_TO_CHAR.S */
4156 /* File: armv5te/unop.S */
4158 * Generic 32-bit unary operation. Provide an "instr" line that
4159 * specifies an instruction that performs "result = op r0".
4160 * This could be an ARM instruction or a function call.
4162 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4163 * int-to-byte, int-to-char, int-to-short
4166 mov r3, rINST, lsr #12 @ r3<- B
4167 mov r9, rINST, lsr #8 @ r9<- A+
4168 GET_VREG(r0, r3) @ r0<- vB
4170 mov r0, r0, asl #16 @ optional op; may set condition codes
4171 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4172 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed
4173 GET_INST_OPCODE(ip) @ extract opcode from rINST
4174 SET_VREG(r0, r9) @ vAA<- r0
4175 GOTO_OPCODE(ip) @ jump to next instruction
4176 /* 9-10 instructions */
4179 /* ------------------------------ */
4181 .L_OP_INT_TO_SHORT: /* 0x8f */
4182 /* File: armv5te/OP_INT_TO_SHORT.S */
4183 /* File: armv5te/unop.S */
4185 * Generic 32-bit unary operation. Provide an "instr" line that
4186 * specifies an instruction that performs "result = op r0".
4187 * This could be an ARM instruction or a function call.
4189 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4190 * int-to-byte, int-to-char, int-to-short
4193 mov r3, rINST, lsr #12 @ r3<- B
4194 mov r9, rINST, lsr #8 @ r9<- A+
4195 GET_VREG(r0, r3) @ r0<- vB
4197 mov r0, r0, asl #16 @ optional op; may set condition codes
4198 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4199 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed
4200 GET_INST_OPCODE(ip) @ extract opcode from rINST
4201 SET_VREG(r0, r9) @ vAA<- r0
4202 GOTO_OPCODE(ip) @ jump to next instruction
4203 /* 9-10 instructions */
4206 /* ------------------------------ */
4208 .L_OP_ADD_INT: /* 0x90 */
4209 /* File: armv5te/OP_ADD_INT.S */
4210 /* File: armv5te/binop.S */
4212 * Generic 32-bit binary operation. Provide an "instr" line that
4213 * specifies an instruction that performs "result = r0 op r1".
4214 * This could be an ARM instruction or a function call. (If the result
4215 * comes back in a register other than r0, you can override "result".)
4217 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4218 * vCC (r1). Useful for integer division and modulus. Note that we
4219 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4220 * handles it correctly.
4222 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4223 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4224 * mul-float, div-float, rem-float
4226 /* binop vAA, vBB, vCC */
4227 FETCH(r0, 1) @ r0<- CCBB
4228 mov r9, rINST, lsr #8 @ r9<- AA
4229 mov r3, r0, lsr #8 @ r3<- CC
4230 and r2, r0, #255 @ r2<- BB
4231 GET_VREG(r1, r3) @ r1<- vCC
4232 GET_VREG(r0, r2) @ r0<- vBB
4234 cmp r1, #0 @ is second operand zero?
4235 beq common_errDivideByZero
4238 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4239 @ optional op; may set condition codes
4240 add r0, r0, r1 @ r0<- op, r0-r3 changed
4241 GET_INST_OPCODE(ip) @ extract opcode from rINST
4242 SET_VREG(r0, r9) @ vAA<- r0
4243 GOTO_OPCODE(ip) @ jump to next instruction
4244 /* 11-14 instructions */
4248 /* ------------------------------ */
4250 .L_OP_SUB_INT: /* 0x91 */
4251 /* File: armv5te/OP_SUB_INT.S */
4252 /* File: armv5te/binop.S */
4254 * Generic 32-bit binary operation. Provide an "instr" line that
4255 * specifies an instruction that performs "result = r0 op r1".
4256 * This could be an ARM instruction or a function call. (If the result
4257 * comes back in a register other than r0, you can override "result".)
4259 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4260 * vCC (r1). Useful for integer division and modulus. Note that we
4261 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4262 * handles it correctly.
4264 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4265 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4266 * mul-float, div-float, rem-float
4268 /* binop vAA, vBB, vCC */
4269 FETCH(r0, 1) @ r0<- CCBB
4270 mov r9, rINST, lsr #8 @ r9<- AA
4271 mov r3, r0, lsr #8 @ r3<- CC
4272 and r2, r0, #255 @ r2<- BB
4273 GET_VREG(r1, r3) @ r1<- vCC
4274 GET_VREG(r0, r2) @ r0<- vBB
4276 cmp r1, #0 @ is second operand zero?
4277 beq common_errDivideByZero
4280 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4281 @ optional op; may set condition codes
4282 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4283 GET_INST_OPCODE(ip) @ extract opcode from rINST
4284 SET_VREG(r0, r9) @ vAA<- r0
4285 GOTO_OPCODE(ip) @ jump to next instruction
4286 /* 11-14 instructions */
4290 /* ------------------------------ */
4292 .L_OP_MUL_INT: /* 0x92 */
4293 /* File: armv5te/OP_MUL_INT.S */
4294 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4295 /* File: armv5te/binop.S */
4297 * Generic 32-bit binary operation. Provide an "instr" line that
4298 * specifies an instruction that performs "result = r0 op r1".
4299 * This could be an ARM instruction or a function call. (If the result
4300 * comes back in a register other than r0, you can override "result".)
4302 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4303 * vCC (r1). Useful for integer division and modulus. Note that we
4304 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4305 * handles it correctly.
4307 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4308 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4309 * mul-float, div-float, rem-float
4311 /* binop vAA, vBB, vCC */
4312 FETCH(r0, 1) @ r0<- CCBB
4313 mov r9, rINST, lsr #8 @ r9<- AA
4314 mov r3, r0, lsr #8 @ r3<- CC
4315 and r2, r0, #255 @ r2<- BB
4316 GET_VREG(r1, r3) @ r1<- vCC
4317 GET_VREG(r0, r2) @ r0<- vBB
4319 cmp r1, #0 @ is second operand zero?
4320 beq common_errDivideByZero
4323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4324 @ optional op; may set condition codes
4325 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4326 GET_INST_OPCODE(ip) @ extract opcode from rINST
4327 SET_VREG(r0, r9) @ vAA<- r0
4328 GOTO_OPCODE(ip) @ jump to next instruction
4329 /* 11-14 instructions */
4333 /* ------------------------------ */
4335 .L_OP_DIV_INT: /* 0x93 */
4336 /* File: armv5te/OP_DIV_INT.S */
4337 /* File: armv5te/binop.S */
4339 * Generic 32-bit binary operation. Provide an "instr" line that
4340 * specifies an instruction that performs "result = r0 op r1".
4341 * This could be an ARM instruction or a function call. (If the result
4342 * comes back in a register other than r0, you can override "result".)
4344 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4345 * vCC (r1). Useful for integer division and modulus. Note that we
4346 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4347 * handles it correctly.
4349 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4350 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4351 * mul-float, div-float, rem-float
4353 /* binop vAA, vBB, vCC */
4354 FETCH(r0, 1) @ r0<- CCBB
4355 mov r9, rINST, lsr #8 @ r9<- AA
4356 mov r3, r0, lsr #8 @ r3<- CC
4357 and r2, r0, #255 @ r2<- BB
4358 GET_VREG(r1, r3) @ r1<- vCC
4359 GET_VREG(r0, r2) @ r0<- vBB
4361 cmp r1, #0 @ is second operand zero?
4362 beq common_errDivideByZero
4365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4366 @ optional op; may set condition codes
4367 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4368 GET_INST_OPCODE(ip) @ extract opcode from rINST
4369 SET_VREG(r0, r9) @ vAA<- r0
4370 GOTO_OPCODE(ip) @ jump to next instruction
4371 /* 11-14 instructions */
4375 /* ------------------------------ */
4377 .L_OP_REM_INT: /* 0x94 */
4378 /* File: armv5te/OP_REM_INT.S */
4379 /* idivmod returns quotient in r0 and remainder in r1 */
4380 /* File: armv5te/binop.S */
4382 * Generic 32-bit binary operation. Provide an "instr" line that
4383 * specifies an instruction that performs "result = r0 op r1".
4384 * This could be an ARM instruction or a function call. (If the result
4385 * comes back in a register other than r0, you can override "result".)
4387 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4388 * vCC (r1). Useful for integer division and modulus. Note that we
4389 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4390 * handles it correctly.
4392 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4393 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4394 * mul-float, div-float, rem-float
4396 /* binop vAA, vBB, vCC */
4397 FETCH(r0, 1) @ r0<- CCBB
4398 mov r9, rINST, lsr #8 @ r9<- AA
4399 mov r3, r0, lsr #8 @ r3<- CC
4400 and r2, r0, #255 @ r2<- BB
4401 GET_VREG(r1, r3) @ r1<- vCC
4402 GET_VREG(r0, r2) @ r0<- vBB
4404 cmp r1, #0 @ is second operand zero?
4405 beq common_errDivideByZero
4408 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4409 @ optional op; may set condition codes
4410 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4411 GET_INST_OPCODE(ip) @ extract opcode from rINST
4412 SET_VREG(r1, r9) @ vAA<- r1
4413 GOTO_OPCODE(ip) @ jump to next instruction
4414 /* 11-14 instructions */
4418 /* ------------------------------ */
4420 .L_OP_AND_INT: /* 0x95 */
4421 /* File: armv5te/OP_AND_INT.S */
4422 /* File: armv5te/binop.S */
4424 * Generic 32-bit binary operation. Provide an "instr" line that
4425 * specifies an instruction that performs "result = r0 op r1".
4426 * This could be an ARM instruction or a function call. (If the result
4427 * comes back in a register other than r0, you can override "result".)
4429 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4430 * vCC (r1). Useful for integer division and modulus. Note that we
4431 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4432 * handles it correctly.
4434 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4435 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4436 * mul-float, div-float, rem-float
4438 /* binop vAA, vBB, vCC */
4439 FETCH(r0, 1) @ r0<- CCBB
4440 mov r9, rINST, lsr #8 @ r9<- AA
4441 mov r3, r0, lsr #8 @ r3<- CC
4442 and r2, r0, #255 @ r2<- BB
4443 GET_VREG(r1, r3) @ r1<- vCC
4444 GET_VREG(r0, r2) @ r0<- vBB
4446 cmp r1, #0 @ is second operand zero?
4447 beq common_errDivideByZero
4450 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4451 @ optional op; may set condition codes
4452 and r0, r0, r1 @ r0<- op, r0-r3 changed
4453 GET_INST_OPCODE(ip) @ extract opcode from rINST
4454 SET_VREG(r0, r9) @ vAA<- r0
4455 GOTO_OPCODE(ip) @ jump to next instruction
4456 /* 11-14 instructions */
4460 /* ------------------------------ */
4462 .L_OP_OR_INT: /* 0x96 */
4463 /* File: armv5te/OP_OR_INT.S */
4464 /* File: armv5te/binop.S */
4466 * Generic 32-bit binary operation. Provide an "instr" line that
4467 * specifies an instruction that performs "result = r0 op r1".
4468 * This could be an ARM instruction or a function call. (If the result
4469 * comes back in a register other than r0, you can override "result".)
4471 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4472 * vCC (r1). Useful for integer division and modulus. Note that we
4473 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4474 * handles it correctly.
4476 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4477 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4478 * mul-float, div-float, rem-float
4480 /* binop vAA, vBB, vCC */
4481 FETCH(r0, 1) @ r0<- CCBB
4482 mov r9, rINST, lsr #8 @ r9<- AA
4483 mov r3, r0, lsr #8 @ r3<- CC
4484 and r2, r0, #255 @ r2<- BB
4485 GET_VREG(r1, r3) @ r1<- vCC
4486 GET_VREG(r0, r2) @ r0<- vBB
4488 cmp r1, #0 @ is second operand zero?
4489 beq common_errDivideByZero
4492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4493 @ optional op; may set condition codes
4494 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4495 GET_INST_OPCODE(ip) @ extract opcode from rINST
4496 SET_VREG(r0, r9) @ vAA<- r0
4497 GOTO_OPCODE(ip) @ jump to next instruction
4498 /* 11-14 instructions */
4502 /* ------------------------------ */
4504 .L_OP_XOR_INT: /* 0x97 */
4505 /* File: armv5te/OP_XOR_INT.S */
4506 /* File: armv5te/binop.S */
4508 * Generic 32-bit binary operation. Provide an "instr" line that
4509 * specifies an instruction that performs "result = r0 op r1".
4510 * This could be an ARM instruction or a function call. (If the result
4511 * comes back in a register other than r0, you can override "result".)
4513 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4514 * vCC (r1). Useful for integer division and modulus. Note that we
4515 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4516 * handles it correctly.
4518 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4519 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4520 * mul-float, div-float, rem-float
4522 /* binop vAA, vBB, vCC */
4523 FETCH(r0, 1) @ r0<- CCBB
4524 mov r9, rINST, lsr #8 @ r9<- AA
4525 mov r3, r0, lsr #8 @ r3<- CC
4526 and r2, r0, #255 @ r2<- BB
4527 GET_VREG(r1, r3) @ r1<- vCC
4528 GET_VREG(r0, r2) @ r0<- vBB
4530 cmp r1, #0 @ is second operand zero?
4531 beq common_errDivideByZero
4534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4535 @ optional op; may set condition codes
4536 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4537 GET_INST_OPCODE(ip) @ extract opcode from rINST
4538 SET_VREG(r0, r9) @ vAA<- r0
4539 GOTO_OPCODE(ip) @ jump to next instruction
4540 /* 11-14 instructions */
4544 /* ------------------------------ */
4546 .L_OP_SHL_INT: /* 0x98 */
4547 /* File: armv5te/OP_SHL_INT.S */
4548 /* File: armv5te/binop.S */
4550 * Generic 32-bit binary operation. Provide an "instr" line that
4551 * specifies an instruction that performs "result = r0 op r1".
4552 * This could be an ARM instruction or a function call. (If the result
4553 * comes back in a register other than r0, you can override "result".)
4555 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4556 * vCC (r1). Useful for integer division and modulus. Note that we
4557 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4558 * handles it correctly.
4560 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4561 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4562 * mul-float, div-float, rem-float
4564 /* binop vAA, vBB, vCC */
4565 FETCH(r0, 1) @ r0<- CCBB
4566 mov r9, rINST, lsr #8 @ r9<- AA
4567 mov r3, r0, lsr #8 @ r3<- CC
4568 and r2, r0, #255 @ r2<- BB
4569 GET_VREG(r1, r3) @ r1<- vCC
4570 GET_VREG(r0, r2) @ r0<- vBB
4572 cmp r1, #0 @ is second operand zero?
4573 beq common_errDivideByZero
4576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4577 and r1, r1, #31 @ optional op; may set condition codes
4578 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4579 GET_INST_OPCODE(ip) @ extract opcode from rINST
4580 SET_VREG(r0, r9) @ vAA<- r0
4581 GOTO_OPCODE(ip) @ jump to next instruction
4582 /* 11-14 instructions */
4586 /* ------------------------------ */
4588 .L_OP_SHR_INT: /* 0x99 */
4589 /* File: armv5te/OP_SHR_INT.S */
4590 /* File: armv5te/binop.S */
4592 * Generic 32-bit binary operation. Provide an "instr" line that
4593 * specifies an instruction that performs "result = r0 op r1".
4594 * This could be an ARM instruction or a function call. (If the result
4595 * comes back in a register other than r0, you can override "result".)
4597 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4598 * vCC (r1). Useful for integer division and modulus. Note that we
4599 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4600 * handles it correctly.
4602 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4603 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4604 * mul-float, div-float, rem-float
4606 /* binop vAA, vBB, vCC */
4607 FETCH(r0, 1) @ r0<- CCBB
4608 mov r9, rINST, lsr #8 @ r9<- AA
4609 mov r3, r0, lsr #8 @ r3<- CC
4610 and r2, r0, #255 @ r2<- BB
4611 GET_VREG(r1, r3) @ r1<- vCC
4612 GET_VREG(r0, r2) @ r0<- vBB
4614 cmp r1, #0 @ is second operand zero?
4615 beq common_errDivideByZero
4618 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4619 and r1, r1, #31 @ optional op; may set condition codes
4620 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4621 GET_INST_OPCODE(ip) @ extract opcode from rINST
4622 SET_VREG(r0, r9) @ vAA<- r0
4623 GOTO_OPCODE(ip) @ jump to next instruction
4624 /* 11-14 instructions */
4628 /* ------------------------------ */
4630 .L_OP_USHR_INT: /* 0x9a */
4631 /* File: armv5te/OP_USHR_INT.S */
4632 /* File: armv5te/binop.S */
4634 * Generic 32-bit binary operation. Provide an "instr" line that
4635 * specifies an instruction that performs "result = r0 op r1".
4636 * This could be an ARM instruction or a function call. (If the result
4637 * comes back in a register other than r0, you can override "result".)
4639 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4640 * vCC (r1). Useful for integer division and modulus. Note that we
4641 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4642 * handles it correctly.
4644 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4645 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4646 * mul-float, div-float, rem-float
4648 /* binop vAA, vBB, vCC */
4649 FETCH(r0, 1) @ r0<- CCBB
4650 mov r9, rINST, lsr #8 @ r9<- AA
4651 mov r3, r0, lsr #8 @ r3<- CC
4652 and r2, r0, #255 @ r2<- BB
4653 GET_VREG(r1, r3) @ r1<- vCC
4654 GET_VREG(r0, r2) @ r0<- vBB
4656 cmp r1, #0 @ is second operand zero?
4657 beq common_errDivideByZero
4660 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4661 and r1, r1, #31 @ optional op; may set condition codes
4662 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4663 GET_INST_OPCODE(ip) @ extract opcode from rINST
4664 SET_VREG(r0, r9) @ vAA<- r0
4665 GOTO_OPCODE(ip) @ jump to next instruction
4666 /* 11-14 instructions */
4670 /* ------------------------------ */
4672 .L_OP_ADD_LONG: /* 0x9b */
4673 /* File: armv5te/OP_ADD_LONG.S */
4674 /* File: armv5te/binopWide.S */
4676 * Generic 64-bit binary operation. Provide an "instr" line that
4677 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4678 * This could be an ARM instruction or a function call. (If the result
4679 * comes back in a register other than r0, you can override "result".)
4681 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4682 * vCC (r1). Useful for integer division and modulus.
4684 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4685 * xor-long, add-double, sub-double, mul-double, div-double,
4688 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4690 /* binop vAA, vBB, vCC */
4691 FETCH(r0, 1) @ r0<- CCBB
4692 mov r9, rINST, lsr #8 @ r9<- AA
4693 and r2, r0, #255 @ r2<- BB
4694 mov r3, r0, lsr #8 @ r3<- CC
4695 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4696 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4697 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4698 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4699 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4701 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4702 beq common_errDivideByZero
4704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4706 adds r0, r0, r2 @ optional op; may set condition codes
4707 adc r1, r1, r3 @ result<- op, r0-r3 changed
4708 GET_INST_OPCODE(ip) @ extract opcode from rINST
4709 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4710 GOTO_OPCODE(ip) @ jump to next instruction
4711 /* 14-17 instructions */
4715 /* ------------------------------ */
4717 .L_OP_SUB_LONG: /* 0x9c */
4718 /* File: armv5te/OP_SUB_LONG.S */
4719 /* File: armv5te/binopWide.S */
4721 * Generic 64-bit binary operation. Provide an "instr" line that
4722 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4723 * This could be an ARM instruction or a function call. (If the result
4724 * comes back in a register other than r0, you can override "result".)
4726 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4727 * vCC (r1). Useful for integer division and modulus.
4729 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4730 * xor-long, add-double, sub-double, mul-double, div-double,
4733 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4735 /* binop vAA, vBB, vCC */
4736 FETCH(r0, 1) @ r0<- CCBB
4737 mov r9, rINST, lsr #8 @ r9<- AA
4738 and r2, r0, #255 @ r2<- BB
4739 mov r3, r0, lsr #8 @ r3<- CC
4740 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4741 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4742 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4743 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4744 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4746 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4747 beq common_errDivideByZero
4749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4751 subs r0, r0, r2 @ optional op; may set condition codes
4752 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4753 GET_INST_OPCODE(ip) @ extract opcode from rINST
4754 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4755 GOTO_OPCODE(ip) @ jump to next instruction
4756 /* 14-17 instructions */
4760 /* ------------------------------ */
4762 .L_OP_MUL_LONG: /* 0x9d */
4763 /* File: armv5te/OP_MUL_LONG.S */
4765 * Signed 64-bit integer multiply.
4767 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4774 * The low word of the result holds ZX, the high word holds
4775 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4776 * it doesn't fit in the low 64 bits.
4778 * Unlike most ARM math operations, multiply instructions have
4779 * restrictions on using the same register more than once (Rd and Rm
4780 * cannot be the same).
4782 /* mul-long vAA, vBB, vCC */
4783 FETCH(r0, 1) @ r0<- CCBB
4784 and r2, r0, #255 @ r2<- BB
4785 mov r3, r0, lsr #8 @ r3<- CC
4786 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4787 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4788 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4789 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4790 mul ip, r2, r1 @ ip<- ZxW
4791 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4792 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4793 mov r0, rINST, lsr #8 @ r0<- AA
4794 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4795 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4796 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4797 b .LOP_MUL_LONG_finish
4799 /* ------------------------------ */
4801 .L_OP_DIV_LONG: /* 0x9e */
4802 /* File: armv5te/OP_DIV_LONG.S */
4803 /* File: armv5te/binopWide.S */
4805 * Generic 64-bit binary operation. Provide an "instr" line that
4806 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4807 * This could be an ARM instruction or a function call. (If the result
4808 * comes back in a register other than r0, you can override "result".)
4810 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4811 * vCC (r1). Useful for integer division and modulus.
4813 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4814 * xor-long, add-double, sub-double, mul-double, div-double,
4817 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4819 /* binop vAA, vBB, vCC */
4820 FETCH(r0, 1) @ r0<- CCBB
4821 mov r9, rINST, lsr #8 @ r9<- AA
4822 and r2, r0, #255 @ r2<- BB
4823 mov r3, r0, lsr #8 @ r3<- CC
4824 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4825 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4826 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4827 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4828 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4830 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4831 beq common_errDivideByZero
4833 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4835 @ optional op; may set condition codes
4836 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4837 GET_INST_OPCODE(ip) @ extract opcode from rINST
4838 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4839 GOTO_OPCODE(ip) @ jump to next instruction
4840 /* 14-17 instructions */
4844 /* ------------------------------ */
4846 .L_OP_REM_LONG: /* 0x9f */
4847 /* File: armv5te/OP_REM_LONG.S */
4848 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4849 /* File: armv5te/binopWide.S */
4851 * Generic 64-bit binary operation. Provide an "instr" line that
4852 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4853 * This could be an ARM instruction or a function call. (If the result
4854 * comes back in a register other than r0, you can override "result".)
4856 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4857 * vCC (r1). Useful for integer division and modulus.
4859 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4860 * xor-long, add-double, sub-double, mul-double, div-double,
4863 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4865 /* binop vAA, vBB, vCC */
4866 FETCH(r0, 1) @ r0<- CCBB
4867 mov r9, rINST, lsr #8 @ r9<- AA
4868 and r2, r0, #255 @ r2<- BB
4869 mov r3, r0, lsr #8 @ r3<- CC
4870 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4871 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4872 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4873 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4874 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4876 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4877 beq common_errDivideByZero
4879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4881 @ optional op; may set condition codes
4882 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4883 GET_INST_OPCODE(ip) @ extract opcode from rINST
4884 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4885 GOTO_OPCODE(ip) @ jump to next instruction
4886 /* 14-17 instructions */
4890 /* ------------------------------ */
4892 .L_OP_AND_LONG: /* 0xa0 */
4893 /* File: armv5te/OP_AND_LONG.S */
4894 /* File: armv5te/binopWide.S */
4896 * Generic 64-bit binary operation. Provide an "instr" line that
4897 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4898 * This could be an ARM instruction or a function call. (If the result
4899 * comes back in a register other than r0, you can override "result".)
4901 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4902 * vCC (r1). Useful for integer division and modulus.
4904 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4905 * xor-long, add-double, sub-double, mul-double, div-double,
4908 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4910 /* binop vAA, vBB, vCC */
4911 FETCH(r0, 1) @ r0<- CCBB
4912 mov r9, rINST, lsr #8 @ r9<- AA
4913 and r2, r0, #255 @ r2<- BB
4914 mov r3, r0, lsr #8 @ r3<- CC
4915 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4916 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4917 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4918 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4919 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4921 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4922 beq common_errDivideByZero
4924 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4926 and r0, r0, r2 @ optional op; may set condition codes
4927 and r1, r1, r3 @ result<- op, r0-r3 changed
4928 GET_INST_OPCODE(ip) @ extract opcode from rINST
4929 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4930 GOTO_OPCODE(ip) @ jump to next instruction
4931 /* 14-17 instructions */
4935 /* ------------------------------ */
4937 .L_OP_OR_LONG: /* 0xa1 */
4938 /* File: armv5te/OP_OR_LONG.S */
4939 /* File: armv5te/binopWide.S */
4941 * Generic 64-bit binary operation. Provide an "instr" line that
4942 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4943 * This could be an ARM instruction or a function call. (If the result
4944 * comes back in a register other than r0, you can override "result".)
4946 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4947 * vCC (r1). Useful for integer division and modulus.
4949 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4950 * xor-long, add-double, sub-double, mul-double, div-double,
4953 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4955 /* binop vAA, vBB, vCC */
4956 FETCH(r0, 1) @ r0<- CCBB
4957 mov r9, rINST, lsr #8 @ r9<- AA
4958 and r2, r0, #255 @ r2<- BB
4959 mov r3, r0, lsr #8 @ r3<- CC
4960 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4961 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4962 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4963 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4964 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4966 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4967 beq common_errDivideByZero
4969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4971 orr r0, r0, r2 @ optional op; may set condition codes
4972 orr r1, r1, r3 @ result<- op, r0-r3 changed
4973 GET_INST_OPCODE(ip) @ extract opcode from rINST
4974 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4975 GOTO_OPCODE(ip) @ jump to next instruction
4976 /* 14-17 instructions */
4980 /* ------------------------------ */
4982 .L_OP_XOR_LONG: /* 0xa2 */
4983 /* File: armv5te/OP_XOR_LONG.S */
4984 /* File: armv5te/binopWide.S */
4986 * Generic 64-bit binary operation. Provide an "instr" line that
4987 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4988 * This could be an ARM instruction or a function call. (If the result
4989 * comes back in a register other than r0, you can override "result".)
4991 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4992 * vCC (r1). Useful for integer division and modulus.
4994 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4995 * xor-long, add-double, sub-double, mul-double, div-double,
4998 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5000 /* binop vAA, vBB, vCC */
5001 FETCH(r0, 1) @ r0<- CCBB
5002 mov r9, rINST, lsr #8 @ r9<- AA
5003 and r2, r0, #255 @ r2<- BB
5004 mov r3, r0, lsr #8 @ r3<- CC
5005 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5006 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5007 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5008 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5009 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5011 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5012 beq common_errDivideByZero
5014 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5016 eor r0, r0, r2 @ optional op; may set condition codes
5017 eor r1, r1, r3 @ result<- op, r0-r3 changed
5018 GET_INST_OPCODE(ip) @ extract opcode from rINST
5019 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5020 GOTO_OPCODE(ip) @ jump to next instruction
5021 /* 14-17 instructions */
5025 /* ------------------------------ */
5027 .L_OP_SHL_LONG: /* 0xa3 */
5028 /* File: armv5te/OP_SHL_LONG.S */
5030 * Long integer shift. This is different from the generic 32/64-bit
5031 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5032 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5033 * 6 bits of the shift distance.
5035 /* shl-long vAA, vBB, vCC */
5036 FETCH(r0, 1) @ r0<- CCBB
5037 mov r9, rINST, lsr #8 @ r9<- AA
5038 and r3, r0, #255 @ r3<- BB
5039 mov r0, r0, lsr #8 @ r0<- CC
5040 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5041 GET_VREG(r2, r0) @ r2<- vCC
5042 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5043 and r2, r2, #63 @ r2<- r2 & 0x3f
5044 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5046 mov r1, r1, asl r2 @ r1<- r1 << r2
5047 rsb r3, r2, #32 @ r3<- 32 - r2
5048 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
5049 subs ip, r2, #32 @ ip<- r2 - 32
5050 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
5051 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5052 b .LOP_SHL_LONG_finish
5054 /* ------------------------------ */
5056 .L_OP_SHR_LONG: /* 0xa4 */
5057 /* File: armv5te/OP_SHR_LONG.S */
5059 * Long integer shift. This is different from the generic 32/64-bit
5060 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5061 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5062 * 6 bits of the shift distance.
5064 /* shr-long vAA, vBB, vCC */
5065 FETCH(r0, 1) @ r0<- CCBB
5066 mov r9, rINST, lsr #8 @ r9<- AA
5067 and r3, r0, #255 @ r3<- BB
5068 mov r0, r0, lsr #8 @ r0<- CC
5069 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5070 GET_VREG(r2, r0) @ r2<- vCC
5071 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5072 and r2, r2, #63 @ r0<- r0 & 0x3f
5073 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5075 mov r0, r0, lsr r2 @ r0<- r2 >> r2
5076 rsb r3, r2, #32 @ r3<- 32 - r2
5077 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
5078 subs ip, r2, #32 @ ip<- r2 - 32
5079 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
5080 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5081 b .LOP_SHR_LONG_finish
5083 /* ------------------------------ */
5085 .L_OP_USHR_LONG: /* 0xa5 */
5086 /* File: armv5te/OP_USHR_LONG.S */
5088 * Long integer shift. This is different from the generic 32/64-bit
5089 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5090 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5091 * 6 bits of the shift distance.
5093 /* ushr-long vAA, vBB, vCC */
5094 FETCH(r0, 1) @ r0<- CCBB
5095 mov r9, rINST, lsr #8 @ r9<- AA
5096 and r3, r0, #255 @ r3<- BB
5097 mov r0, r0, lsr #8 @ r0<- CC
5098 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5099 GET_VREG(r2, r0) @ r2<- vCC
5100 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5101 and r2, r2, #63 @ r0<- r0 & 0x3f
5102 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5104 mov r0, r0, lsr r2 @ r0<- r2 >> r2
5105 rsb r3, r2, #32 @ r3<- 32 - r2
5106 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
5107 subs ip, r2, #32 @ ip<- r2 - 32
5108 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
5109 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5110 b .LOP_USHR_LONG_finish
5112 /* ------------------------------ */
5114 .L_OP_ADD_FLOAT: /* 0xa6 */
5115 /* File: armv5te/OP_ADD_FLOAT.S */
5116 /* File: armv5te/binop.S */
5118 * Generic 32-bit binary operation. Provide an "instr" line that
5119 * specifies an instruction that performs "result = r0 op r1".
5120 * This could be an ARM instruction or a function call. (If the result
5121 * comes back in a register other than r0, you can override "result".)
5123 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5124 * vCC (r1). Useful for integer division and modulus. Note that we
5125 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5126 * handles it correctly.
5128 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5129 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5130 * mul-float, div-float, rem-float
5132 /* binop vAA, vBB, vCC */
5133 FETCH(r0, 1) @ r0<- CCBB
5134 mov r9, rINST, lsr #8 @ r9<- AA
5135 mov r3, r0, lsr #8 @ r3<- CC
5136 and r2, r0, #255 @ r2<- BB
5137 GET_VREG(r1, r3) @ r1<- vCC
5138 GET_VREG(r0, r2) @ r0<- vBB
5140 cmp r1, #0 @ is second operand zero?
5141 beq common_errDivideByZero
5144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5145 @ optional op; may set condition codes
5146 bl __aeabi_fadd @ r0<- op, r0-r3 changed
5147 GET_INST_OPCODE(ip) @ extract opcode from rINST
5148 SET_VREG(r0, r9) @ vAA<- r0
5149 GOTO_OPCODE(ip) @ jump to next instruction
5150 /* 11-14 instructions */
5154 /* ------------------------------ */
5156 .L_OP_SUB_FLOAT: /* 0xa7 */
5157 /* File: armv5te/OP_SUB_FLOAT.S */
5158 /* File: armv5te/binop.S */
5160 * Generic 32-bit binary operation. Provide an "instr" line that
5161 * specifies an instruction that performs "result = r0 op r1".
5162 * This could be an ARM instruction or a function call. (If the result
5163 * comes back in a register other than r0, you can override "result".)
5165 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5166 * vCC (r1). Useful for integer division and modulus. Note that we
5167 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5168 * handles it correctly.
5170 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5171 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5172 * mul-float, div-float, rem-float
5174 /* binop vAA, vBB, vCC */
5175 FETCH(r0, 1) @ r0<- CCBB
5176 mov r9, rINST, lsr #8 @ r9<- AA
5177 mov r3, r0, lsr #8 @ r3<- CC
5178 and r2, r0, #255 @ r2<- BB
5179 GET_VREG(r1, r3) @ r1<- vCC
5180 GET_VREG(r0, r2) @ r0<- vBB
5182 cmp r1, #0 @ is second operand zero?
5183 beq common_errDivideByZero
5186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5187 @ optional op; may set condition codes
5188 bl __aeabi_fsub @ r0<- op, r0-r3 changed
5189 GET_INST_OPCODE(ip) @ extract opcode from rINST
5190 SET_VREG(r0, r9) @ vAA<- r0
5191 GOTO_OPCODE(ip) @ jump to next instruction
5192 /* 11-14 instructions */
5196 /* ------------------------------ */
5198 .L_OP_MUL_FLOAT: /* 0xa8 */
5199 /* File: armv5te/OP_MUL_FLOAT.S */
5200 /* File: armv5te/binop.S */
5202 * Generic 32-bit binary operation. Provide an "instr" line that
5203 * specifies an instruction that performs "result = r0 op r1".
5204 * This could be an ARM instruction or a function call. (If the result
5205 * comes back in a register other than r0, you can override "result".)
5207 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5208 * vCC (r1). Useful for integer division and modulus. Note that we
5209 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5210 * handles it correctly.
5212 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5213 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5214 * mul-float, div-float, rem-float
5216 /* binop vAA, vBB, vCC */
5217 FETCH(r0, 1) @ r0<- CCBB
5218 mov r9, rINST, lsr #8 @ r9<- AA
5219 mov r3, r0, lsr #8 @ r3<- CC
5220 and r2, r0, #255 @ r2<- BB
5221 GET_VREG(r1, r3) @ r1<- vCC
5222 GET_VREG(r0, r2) @ r0<- vBB
5224 cmp r1, #0 @ is second operand zero?
5225 beq common_errDivideByZero
5228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5229 @ optional op; may set condition codes
5230 bl __aeabi_fmul @ r0<- op, r0-r3 changed
5231 GET_INST_OPCODE(ip) @ extract opcode from rINST
5232 SET_VREG(r0, r9) @ vAA<- r0
5233 GOTO_OPCODE(ip) @ jump to next instruction
5234 /* 11-14 instructions */
5238 /* ------------------------------ */
5240 .L_OP_DIV_FLOAT: /* 0xa9 */
5241 /* File: armv5te/OP_DIV_FLOAT.S */
5242 /* File: armv5te/binop.S */
5244 * Generic 32-bit binary operation. Provide an "instr" line that
5245 * specifies an instruction that performs "result = r0 op r1".
5246 * This could be an ARM instruction or a function call. (If the result
5247 * comes back in a register other than r0, you can override "result".)
5249 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5250 * vCC (r1). Useful for integer division and modulus. Note that we
5251 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5252 * handles it correctly.
5254 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5255 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5256 * mul-float, div-float, rem-float
5258 /* binop vAA, vBB, vCC */
5259 FETCH(r0, 1) @ r0<- CCBB
5260 mov r9, rINST, lsr #8 @ r9<- AA
5261 mov r3, r0, lsr #8 @ r3<- CC
5262 and r2, r0, #255 @ r2<- BB
5263 GET_VREG(r1, r3) @ r1<- vCC
5264 GET_VREG(r0, r2) @ r0<- vBB
5266 cmp r1, #0 @ is second operand zero?
5267 beq common_errDivideByZero
5270 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5271 @ optional op; may set condition codes
5272 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
5273 GET_INST_OPCODE(ip) @ extract opcode from rINST
5274 SET_VREG(r0, r9) @ vAA<- r0
5275 GOTO_OPCODE(ip) @ jump to next instruction
5276 /* 11-14 instructions */
5280 /* ------------------------------ */
5282 .L_OP_REM_FLOAT: /* 0xaa */
5283 /* File: armv5te/OP_REM_FLOAT.S */
5284 /* EABI doesn't define a float remainder function, but libm does */
5285 /* File: armv5te/binop.S */
5287 * Generic 32-bit binary operation. Provide an "instr" line that
5288 * specifies an instruction that performs "result = r0 op r1".
5289 * This could be an ARM instruction or a function call. (If the result
5290 * comes back in a register other than r0, you can override "result".)
5292 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5293 * vCC (r1). Useful for integer division and modulus. Note that we
5294 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5295 * handles it correctly.
5297 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5298 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5299 * mul-float, div-float, rem-float
5301 /* binop vAA, vBB, vCC */
5302 FETCH(r0, 1) @ r0<- CCBB
5303 mov r9, rINST, lsr #8 @ r9<- AA
5304 mov r3, r0, lsr #8 @ r3<- CC
5305 and r2, r0, #255 @ r2<- BB
5306 GET_VREG(r1, r3) @ r1<- vCC
5307 GET_VREG(r0, r2) @ r0<- vBB
5309 cmp r1, #0 @ is second operand zero?
5310 beq common_errDivideByZero
5313 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5314 @ optional op; may set condition codes
5315 bl fmodf @ r0<- op, r0-r3 changed
5316 GET_INST_OPCODE(ip) @ extract opcode from rINST
5317 SET_VREG(r0, r9) @ vAA<- r0
5318 GOTO_OPCODE(ip) @ jump to next instruction
5319 /* 11-14 instructions */
5323 /* ------------------------------ */
5325 .L_OP_ADD_DOUBLE: /* 0xab */
5326 /* File: armv5te/OP_ADD_DOUBLE.S */
5327 /* File: armv5te/binopWide.S */
5329 * Generic 64-bit binary operation. Provide an "instr" line that
5330 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5331 * This could be an ARM instruction or a function call. (If the result
5332 * comes back in a register other than r0, you can override "result".)
5334 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5335 * vCC (r1). Useful for integer division and modulus.
5337 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5338 * xor-long, add-double, sub-double, mul-double, div-double,
5341 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5343 /* binop vAA, vBB, vCC */
5344 FETCH(r0, 1) @ r0<- CCBB
5345 mov r9, rINST, lsr #8 @ r9<- AA
5346 and r2, r0, #255 @ r2<- BB
5347 mov r3, r0, lsr #8 @ r3<- CC
5348 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5349 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5350 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5351 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5352 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5354 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5355 beq common_errDivideByZero
5357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5359 @ optional op; may set condition codes
5360 bl __aeabi_dadd @ result<- op, r0-r3 changed
5361 GET_INST_OPCODE(ip) @ extract opcode from rINST
5362 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5363 GOTO_OPCODE(ip) @ jump to next instruction
5364 /* 14-17 instructions */
5368 /* ------------------------------ */
5370 .L_OP_SUB_DOUBLE: /* 0xac */
5371 /* File: armv5te/OP_SUB_DOUBLE.S */
5372 /* File: armv5te/binopWide.S */
5374 * Generic 64-bit binary operation. Provide an "instr" line that
5375 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5376 * This could be an ARM instruction or a function call. (If the result
5377 * comes back in a register other than r0, you can override "result".)
5379 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5380 * vCC (r1). Useful for integer division and modulus.
5382 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5383 * xor-long, add-double, sub-double, mul-double, div-double,
5386 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5388 /* binop vAA, vBB, vCC */
5389 FETCH(r0, 1) @ r0<- CCBB
5390 mov r9, rINST, lsr #8 @ r9<- AA
5391 and r2, r0, #255 @ r2<- BB
5392 mov r3, r0, lsr #8 @ r3<- CC
5393 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5394 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5395 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5396 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5397 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5399 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5400 beq common_errDivideByZero
5402 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5404 @ optional op; may set condition codes
5405 bl __aeabi_dsub @ result<- op, r0-r3 changed
5406 GET_INST_OPCODE(ip) @ extract opcode from rINST
5407 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5408 GOTO_OPCODE(ip) @ jump to next instruction
5409 /* 14-17 instructions */
5413 /* ------------------------------ */
5415 .L_OP_MUL_DOUBLE: /* 0xad */
5416 /* File: armv5te/OP_MUL_DOUBLE.S */
5417 /* File: armv5te/binopWide.S */
5419 * Generic 64-bit binary operation. Provide an "instr" line that
5420 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5421 * This could be an ARM instruction or a function call. (If the result
5422 * comes back in a register other than r0, you can override "result".)
5424 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425 * vCC (r1). Useful for integer division and modulus.
5427 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5428 * xor-long, add-double, sub-double, mul-double, div-double,
5431 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5433 /* binop vAA, vBB, vCC */
5434 FETCH(r0, 1) @ r0<- CCBB
5435 mov r9, rINST, lsr #8 @ r9<- AA
5436 and r2, r0, #255 @ r2<- BB
5437 mov r3, r0, lsr #8 @ r3<- CC
5438 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5439 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5440 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5441 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5442 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5444 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5445 beq common_errDivideByZero
5447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5449 @ optional op; may set condition codes
5450 bl __aeabi_dmul @ result<- op, r0-r3 changed
5451 GET_INST_OPCODE(ip) @ extract opcode from rINST
5452 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5453 GOTO_OPCODE(ip) @ jump to next instruction
5454 /* 14-17 instructions */
5458 /* ------------------------------ */
5460 .L_OP_DIV_DOUBLE: /* 0xae */
5461 /* File: armv5te/OP_DIV_DOUBLE.S */
5462 /* File: armv5te/binopWide.S */
5464 * Generic 64-bit binary operation. Provide an "instr" line that
5465 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5466 * This could be an ARM instruction or a function call. (If the result
5467 * comes back in a register other than r0, you can override "result".)
5469 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5470 * vCC (r1). Useful for integer division and modulus.
5472 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5473 * xor-long, add-double, sub-double, mul-double, div-double,
5476 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5478 /* binop vAA, vBB, vCC */
5479 FETCH(r0, 1) @ r0<- CCBB
5480 mov r9, rINST, lsr #8 @ r9<- AA
5481 and r2, r0, #255 @ r2<- BB
5482 mov r3, r0, lsr #8 @ r3<- CC
5483 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5484 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5485 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5486 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5487 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5489 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5490 beq common_errDivideByZero
5492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5494 @ optional op; may set condition codes
5495 bl __aeabi_ddiv @ result<- op, r0-r3 changed
5496 GET_INST_OPCODE(ip) @ extract opcode from rINST
5497 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5498 GOTO_OPCODE(ip) @ jump to next instruction
5499 /* 14-17 instructions */
5503 /* ------------------------------ */
5505 .L_OP_REM_DOUBLE: /* 0xaf */
5506 /* File: armv5te/OP_REM_DOUBLE.S */
5507 /* EABI doesn't define a double remainder function, but libm does */
5508 /* File: armv5te/binopWide.S */
5510 * Generic 64-bit binary operation. Provide an "instr" line that
5511 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5512 * This could be an ARM instruction or a function call. (If the result
5513 * comes back in a register other than r0, you can override "result".)
5515 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5516 * vCC (r1). Useful for integer division and modulus.
5518 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5519 * xor-long, add-double, sub-double, mul-double, div-double,
5522 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5524 /* binop vAA, vBB, vCC */
5525 FETCH(r0, 1) @ r0<- CCBB
5526 mov r9, rINST, lsr #8 @ r9<- AA
5527 and r2, r0, #255 @ r2<- BB
5528 mov r3, r0, lsr #8 @ r3<- CC
5529 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5530 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5531 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5532 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5533 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5535 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5536 beq common_errDivideByZero
5538 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5540 @ optional op; may set condition codes
5541 bl fmod @ result<- op, r0-r3 changed
5542 GET_INST_OPCODE(ip) @ extract opcode from rINST
5543 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5544 GOTO_OPCODE(ip) @ jump to next instruction
5545 /* 14-17 instructions */
5549 /* ------------------------------ */
5551 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5552 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5553 /* File: armv5te/binop2addr.S */
5555 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5556 * that specifies an instruction that performs "result = r0 op r1".
5557 * This could be an ARM instruction or a function call. (If the result
5558 * comes back in a register other than r0, you can override "result".)
5560 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5561 * vCC (r1). Useful for integer division and modulus.
5563 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5564 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5565 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5566 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5568 /* binop/2addr vA, vB */
5569 mov r9, rINST, lsr #8 @ r9<- A+
5570 mov r3, rINST, lsr #12 @ r3<- B
5572 GET_VREG(r1, r3) @ r1<- vB
5573 GET_VREG(r0, r9) @ r0<- vA
5575 cmp r1, #0 @ is second operand zero?
5576 beq common_errDivideByZero
5578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5580 @ optional op; may set condition codes
5581 add r0, r0, r1 @ r0<- op, r0-r3 changed
5582 GET_INST_OPCODE(ip) @ extract opcode from rINST
5583 SET_VREG(r0, r9) @ vAA<- r0
5584 GOTO_OPCODE(ip) @ jump to next instruction
5585 /* 10-13 instructions */
5589 /* ------------------------------ */
5591 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5592 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5593 /* File: armv5te/binop2addr.S */
5595 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5596 * that specifies an instruction that performs "result = r0 op r1".
5597 * This could be an ARM instruction or a function call. (If the result
5598 * comes back in a register other than r0, you can override "result".)
5600 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601 * vCC (r1). Useful for integer division and modulus.
5603 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5608 /* binop/2addr vA, vB */
5609 mov r9, rINST, lsr #8 @ r9<- A+
5610 mov r3, rINST, lsr #12 @ r3<- B
5612 GET_VREG(r1, r3) @ r1<- vB
5613 GET_VREG(r0, r9) @ r0<- vA
5615 cmp r1, #0 @ is second operand zero?
5616 beq common_errDivideByZero
5618 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5620 @ optional op; may set condition codes
5621 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5622 GET_INST_OPCODE(ip) @ extract opcode from rINST
5623 SET_VREG(r0, r9) @ vAA<- r0
5624 GOTO_OPCODE(ip) @ jump to next instruction
5625 /* 10-13 instructions */
5629 /* ------------------------------ */
5631 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5632 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5633 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5634 /* File: armv5te/binop2addr.S */
5636 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5637 * that specifies an instruction that performs "result = r0 op r1".
5638 * This could be an ARM instruction or a function call. (If the result
5639 * comes back in a register other than r0, you can override "result".)
5641 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5642 * vCC (r1). Useful for integer division and modulus.
5644 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5645 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5646 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5647 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5649 /* binop/2addr vA, vB */
5650 mov r9, rINST, lsr #8 @ r9<- A+
5651 mov r3, rINST, lsr #12 @ r3<- B
5653 GET_VREG(r1, r3) @ r1<- vB
5654 GET_VREG(r0, r9) @ r0<- vA
5656 cmp r1, #0 @ is second operand zero?
5657 beq common_errDivideByZero
5659 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5661 @ optional op; may set condition codes
5662 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5663 GET_INST_OPCODE(ip) @ extract opcode from rINST
5664 SET_VREG(r0, r9) @ vAA<- r0
5665 GOTO_OPCODE(ip) @ jump to next instruction
5666 /* 10-13 instructions */
5670 /* ------------------------------ */
5672 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5673 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5674 /* File: armv5te/binop2addr.S */
5676 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5677 * that specifies an instruction that performs "result = r0 op r1".
5678 * This could be an ARM instruction or a function call. (If the result
5679 * comes back in a register other than r0, you can override "result".)
5681 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5682 * vCC (r1). Useful for integer division and modulus.
5684 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5685 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5686 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5687 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5689 /* binop/2addr vA, vB */
5690 mov r9, rINST, lsr #8 @ r9<- A+
5691 mov r3, rINST, lsr #12 @ r3<- B
5693 GET_VREG(r1, r3) @ r1<- vB
5694 GET_VREG(r0, r9) @ r0<- vA
5696 cmp r1, #0 @ is second operand zero?
5697 beq common_errDivideByZero
5699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5701 @ optional op; may set condition codes
5702 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5703 GET_INST_OPCODE(ip) @ extract opcode from rINST
5704 SET_VREG(r0, r9) @ vAA<- r0
5705 GOTO_OPCODE(ip) @ jump to next instruction
5706 /* 10-13 instructions */
5710 /* ------------------------------ */
5712 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5713 /* File: armv5te/OP_REM_INT_2ADDR.S */
5714 /* idivmod returns quotient in r0 and remainder in r1 */
5715 /* File: armv5te/binop2addr.S */
5717 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5718 * that specifies an instruction that performs "result = r0 op r1".
5719 * This could be an ARM instruction or a function call. (If the result
5720 * comes back in a register other than r0, you can override "result".)
5722 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5723 * vCC (r1). Useful for integer division and modulus.
5725 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5726 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5727 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5728 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5730 /* binop/2addr vA, vB */
5731 mov r9, rINST, lsr #8 @ r9<- A+
5732 mov r3, rINST, lsr #12 @ r3<- B
5734 GET_VREG(r1, r3) @ r1<- vB
5735 GET_VREG(r0, r9) @ r0<- vA
5737 cmp r1, #0 @ is second operand zero?
5738 beq common_errDivideByZero
5740 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5742 @ optional op; may set condition codes
5743 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5744 GET_INST_OPCODE(ip) @ extract opcode from rINST
5745 SET_VREG(r1, r9) @ vAA<- r1
5746 GOTO_OPCODE(ip) @ jump to next instruction
5747 /* 10-13 instructions */
5751 /* ------------------------------ */
5753 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5754 /* File: armv5te/OP_AND_INT_2ADDR.S */
5755 /* File: armv5te/binop2addr.S */
5757 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5758 * that specifies an instruction that performs "result = r0 op r1".
5759 * This could be an ARM instruction or a function call. (If the result
5760 * comes back in a register other than r0, you can override "result".)
5762 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5763 * vCC (r1). Useful for integer division and modulus.
5765 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5766 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5767 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5768 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5770 /* binop/2addr vA, vB */
5771 mov r9, rINST, lsr #8 @ r9<- A+
5772 mov r3, rINST, lsr #12 @ r3<- B
5774 GET_VREG(r1, r3) @ r1<- vB
5775 GET_VREG(r0, r9) @ r0<- vA
5777 cmp r1, #0 @ is second operand zero?
5778 beq common_errDivideByZero
5780 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5782 @ optional op; may set condition codes
5783 and r0, r0, r1 @ r0<- op, r0-r3 changed
5784 GET_INST_OPCODE(ip) @ extract opcode from rINST
5785 SET_VREG(r0, r9) @ vAA<- r0
5786 GOTO_OPCODE(ip) @ jump to next instruction
5787 /* 10-13 instructions */
5791 /* ------------------------------ */
5793 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5794 /* File: armv5te/OP_OR_INT_2ADDR.S */
5795 /* File: armv5te/binop2addr.S */
5797 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5798 * that specifies an instruction that performs "result = r0 op r1".
5799 * This could be an ARM instruction or a function call. (If the result
5800 * comes back in a register other than r0, you can override "result".)
5802 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5803 * vCC (r1). Useful for integer division and modulus.
5805 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5806 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5807 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5808 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5810 /* binop/2addr vA, vB */
5811 mov r9, rINST, lsr #8 @ r9<- A+
5812 mov r3, rINST, lsr #12 @ r3<- B
5814 GET_VREG(r1, r3) @ r1<- vB
5815 GET_VREG(r0, r9) @ r0<- vA
5817 cmp r1, #0 @ is second operand zero?
5818 beq common_errDivideByZero
5820 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5822 @ optional op; may set condition codes
5823 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5824 GET_INST_OPCODE(ip) @ extract opcode from rINST
5825 SET_VREG(r0, r9) @ vAA<- r0
5826 GOTO_OPCODE(ip) @ jump to next instruction
5827 /* 10-13 instructions */
5831 /* ------------------------------ */
5833 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5834 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5835 /* File: armv5te/binop2addr.S */
5837 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5838 * that specifies an instruction that performs "result = r0 op r1".
5839 * This could be an ARM instruction or a function call. (If the result
5840 * comes back in a register other than r0, you can override "result".)
5842 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5843 * vCC (r1). Useful for integer division and modulus.
5845 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5846 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5847 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5848 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5850 /* binop/2addr vA, vB */
5851 mov r9, rINST, lsr #8 @ r9<- A+
5852 mov r3, rINST, lsr #12 @ r3<- B
5854 GET_VREG(r1, r3) @ r1<- vB
5855 GET_VREG(r0, r9) @ r0<- vA
5857 cmp r1, #0 @ is second operand zero?
5858 beq common_errDivideByZero
5860 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5862 @ optional op; may set condition codes
5863 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5864 GET_INST_OPCODE(ip) @ extract opcode from rINST
5865 SET_VREG(r0, r9) @ vAA<- r0
5866 GOTO_OPCODE(ip) @ jump to next instruction
5867 /* 10-13 instructions */
5871 /* ------------------------------ */
5873 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5874 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5875 /* File: armv5te/binop2addr.S */
5877 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5878 * that specifies an instruction that performs "result = r0 op r1".
5879 * This could be an ARM instruction or a function call. (If the result
5880 * comes back in a register other than r0, you can override "result".)
5882 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5883 * vCC (r1). Useful for integer division and modulus.
5885 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5886 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5887 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5888 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5890 /* binop/2addr vA, vB */
5891 mov r9, rINST, lsr #8 @ r9<- A+
5892 mov r3, rINST, lsr #12 @ r3<- B
5894 GET_VREG(r1, r3) @ r1<- vB
5895 GET_VREG(r0, r9) @ r0<- vA
5897 cmp r1, #0 @ is second operand zero?
5898 beq common_errDivideByZero
5900 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5902 and r1, r1, #31 @ optional op; may set condition codes
5903 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
5904 GET_INST_OPCODE(ip) @ extract opcode from rINST
5905 SET_VREG(r0, r9) @ vAA<- r0
5906 GOTO_OPCODE(ip) @ jump to next instruction
5907 /* 10-13 instructions */
5911 /* ------------------------------ */
5913 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5914 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5915 /* File: armv5te/binop2addr.S */
5917 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5918 * that specifies an instruction that performs "result = r0 op r1".
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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5926 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5927 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5928 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5930 /* binop/2addr vA, vB */
5931 mov r9, rINST, lsr #8 @ r9<- A+
5932 mov r3, rINST, lsr #12 @ r3<- B
5934 GET_VREG(r1, r3) @ r1<- vB
5935 GET_VREG(r0, r9) @ r0<- vA
5937 cmp r1, #0 @ is second operand zero?
5938 beq common_errDivideByZero
5940 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5942 and r1, r1, #31 @ optional op; may set condition codes
5943 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
5944 GET_INST_OPCODE(ip) @ extract opcode from rINST
5945 SET_VREG(r0, r9) @ vAA<- r0
5946 GOTO_OPCODE(ip) @ jump to next instruction
5947 /* 10-13 instructions */
5951 /* ------------------------------ */
5953 .L_OP_USHR_INT_2ADDR: /* 0xba */
5954 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5955 /* File: armv5te/binop2addr.S */
5957 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5958 * that specifies an instruction that performs "result = r0 op r1".
5959 * This could be an ARM instruction or a function call. (If the result
5960 * comes back in a register other than r0, you can override "result".)
5962 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5963 * vCC (r1). Useful for integer division and modulus.
5965 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5966 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5967 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5968 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5970 /* binop/2addr vA, vB */
5971 mov r9, rINST, lsr #8 @ r9<- A+
5972 mov r3, rINST, lsr #12 @ r3<- B
5974 GET_VREG(r1, r3) @ r1<- vB
5975 GET_VREG(r0, r9) @ r0<- vA
5977 cmp r1, #0 @ is second operand zero?
5978 beq common_errDivideByZero
5980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5982 and r1, r1, #31 @ optional op; may set condition codes
5983 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
5984 GET_INST_OPCODE(ip) @ extract opcode from rINST
5985 SET_VREG(r0, r9) @ vAA<- r0
5986 GOTO_OPCODE(ip) @ jump to next instruction
5987 /* 10-13 instructions */
5991 /* ------------------------------ */
5993 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5994 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5995 /* File: armv5te/binopWide2addr.S */
5997 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5998 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5999 * This could be an ARM instruction or a function call. (If the result
6000 * comes back in a register other than r0, you can override "result".)
6002 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6003 * vCC (r1). Useful for integer division and modulus.
6005 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6006 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6007 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6010 /* binop/2addr vA, vB */
6011 mov r9, rINST, lsr #8 @ r9<- A+
6012 mov r1, rINST, lsr #12 @ r1<- B
6014 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6015 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6016 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6017 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6019 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6020 beq common_errDivideByZero
6022 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6024 adds r0, r0, r2 @ optional op; may set condition codes
6025 adc r1, r1, r3 @ result<- op, r0-r3 changed
6026 GET_INST_OPCODE(ip) @ extract opcode from rINST
6027 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6028 GOTO_OPCODE(ip) @ jump to next instruction
6029 /* 12-15 instructions */
6033 /* ------------------------------ */
6035 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
6036 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
6037 /* File: armv5te/binopWide2addr.S */
6039 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6040 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6041 * This could be an ARM instruction or a function call. (If the result
6042 * comes back in a register other than r0, you can override "result".)
6044 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6045 * vCC (r1). Useful for integer division and modulus.
6047 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6048 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6049 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6052 /* binop/2addr vA, vB */
6053 mov r9, rINST, lsr #8 @ r9<- A+
6054 mov r1, rINST, lsr #12 @ r1<- B
6056 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6057 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6058 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6059 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6061 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6062 beq common_errDivideByZero
6064 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6066 subs r0, r0, r2 @ optional op; may set condition codes
6067 sbc r1, r1, r3 @ result<- op, r0-r3 changed
6068 GET_INST_OPCODE(ip) @ extract opcode from rINST
6069 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6070 GOTO_OPCODE(ip) @ jump to next instruction
6071 /* 12-15 instructions */
6075 /* ------------------------------ */
6077 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
6078 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
6080 * Signed 64-bit integer multiply, "/2addr" version.
6082 * See OP_MUL_LONG for an explanation.
6084 * We get a little tight on registers, so to avoid looking up &fp[A]
6085 * again we stuff it into rINST.
6087 /* mul-long/2addr vA, vB */
6088 mov r9, rINST, lsr #8 @ r9<- A+
6089 mov r1, rINST, lsr #12 @ r1<- B
6091 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6092 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
6093 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6094 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
6095 mul ip, r2, r1 @ ip<- ZxW
6096 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
6097 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
6098 mov r0, rINST @ r0<- &fp[A] (free up rINST)
6099 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6100 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
6101 GET_INST_OPCODE(ip) @ extract opcode from rINST
6102 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
6103 GOTO_OPCODE(ip) @ jump to next instruction
6106 /* ------------------------------ */
6108 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
6109 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
6110 /* File: armv5te/binopWide2addr.S */
6112 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6113 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6114 * This could be an ARM instruction or a function call. (If the result
6115 * comes back in a register other than r0, you can override "result".)
6117 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6118 * vCC (r1). Useful for integer division and modulus.
6120 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6121 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6122 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6125 /* binop/2addr vA, vB */
6126 mov r9, rINST, lsr #8 @ r9<- A+
6127 mov r1, rINST, lsr #12 @ r1<- B
6129 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6130 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6131 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6132 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6134 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6135 beq common_errDivideByZero
6137 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6139 @ optional op; may set condition codes
6140 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
6141 GET_INST_OPCODE(ip) @ extract opcode from rINST
6142 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6143 GOTO_OPCODE(ip) @ jump to next instruction
6144 /* 12-15 instructions */
6148 /* ------------------------------ */
6150 .L_OP_REM_LONG_2ADDR: /* 0xbf */
6151 /* File: armv5te/OP_REM_LONG_2ADDR.S */
6152 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6153 /* File: armv5te/binopWide2addr.S */
6155 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6156 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6157 * This could be an ARM instruction or a function call. (If the result
6158 * comes back in a register other than r0, you can override "result".)
6160 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6161 * vCC (r1). Useful for integer division and modulus.
6163 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6164 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6165 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6168 /* binop/2addr vA, vB */
6169 mov r9, rINST, lsr #8 @ r9<- A+
6170 mov r1, rINST, lsr #12 @ r1<- B
6172 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6173 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6174 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6175 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6177 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6178 beq common_errDivideByZero
6180 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6182 @ optional op; may set condition codes
6183 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
6184 GET_INST_OPCODE(ip) @ extract opcode from rINST
6185 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
6186 GOTO_OPCODE(ip) @ jump to next instruction
6187 /* 12-15 instructions */
6191 /* ------------------------------ */
6193 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6194 /* File: armv5te/OP_AND_LONG_2ADDR.S */
6195 /* File: armv5te/binopWide2addr.S */
6197 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6198 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6199 * This could be an ARM instruction or a function call. (If the result
6200 * comes back in a register other than r0, you can override "result".)
6202 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6203 * vCC (r1). Useful for integer division and modulus.
6205 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6206 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6207 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6210 /* binop/2addr vA, vB */
6211 mov r9, rINST, lsr #8 @ r9<- A+
6212 mov r1, rINST, lsr #12 @ r1<- B
6214 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6215 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6216 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6217 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6219 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6220 beq common_errDivideByZero
6222 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6224 and r0, r0, r2 @ optional op; may set condition codes
6225 and r1, r1, r3 @ result<- op, r0-r3 changed
6226 GET_INST_OPCODE(ip) @ extract opcode from rINST
6227 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6228 GOTO_OPCODE(ip) @ jump to next instruction
6229 /* 12-15 instructions */
6233 /* ------------------------------ */
6235 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
6236 /* File: armv5te/OP_OR_LONG_2ADDR.S */
6237 /* File: armv5te/binopWide2addr.S */
6239 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6240 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6241 * This could be an ARM instruction or a function call. (If the result
6242 * comes back in a register other than r0, you can override "result".)
6244 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6245 * vCC (r1). Useful for integer division and modulus.
6247 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6248 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6249 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6252 /* binop/2addr vA, vB */
6253 mov r9, rINST, lsr #8 @ r9<- A+
6254 mov r1, rINST, lsr #12 @ r1<- B
6256 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6257 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6258 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6259 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6261 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6262 beq common_errDivideByZero
6264 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6266 orr r0, r0, r2 @ optional op; may set condition codes
6267 orr r1, r1, r3 @ result<- op, r0-r3 changed
6268 GET_INST_OPCODE(ip) @ extract opcode from rINST
6269 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6270 GOTO_OPCODE(ip) @ jump to next instruction
6271 /* 12-15 instructions */
6275 /* ------------------------------ */
6277 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6278 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6279 /* File: armv5te/binopWide2addr.S */
6281 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6282 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6283 * This could be an ARM instruction or a function call. (If the result
6284 * comes back in a register other than r0, you can override "result".)
6286 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6287 * vCC (r1). Useful for integer division and modulus.
6289 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6290 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6291 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6294 /* binop/2addr vA, vB */
6295 mov r9, rINST, lsr #8 @ r9<- A+
6296 mov r1, rINST, lsr #12 @ r1<- B
6298 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6299 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6300 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6301 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6303 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6304 beq common_errDivideByZero
6306 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6308 eor r0, r0, r2 @ optional op; may set condition codes
6309 eor r1, r1, r3 @ result<- op, r0-r3 changed
6310 GET_INST_OPCODE(ip) @ extract opcode from rINST
6311 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6312 GOTO_OPCODE(ip) @ jump to next instruction
6313 /* 12-15 instructions */
6317 /* ------------------------------ */
6319 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6320 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6322 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6323 * 32-bit shift distance.
6325 /* shl-long/2addr vA, vB */
6326 mov r9, rINST, lsr #8 @ r9<- A+
6327 mov r3, rINST, lsr #12 @ r3<- B
6329 GET_VREG(r2, r3) @ r2<- vB
6330 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6331 and r2, r2, #63 @ r2<- r2 & 0x3f
6332 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6334 mov r1, r1, asl r2 @ r1<- r1 << r2
6335 rsb r3, r2, #32 @ r3<- 32 - r2
6336 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6337 subs ip, r2, #32 @ ip<- r2 - 32
6338 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6339 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6340 mov r0, r0, asl r2 @ r0<- r0 << r2
6341 b .LOP_SHL_LONG_2ADDR_finish
6343 /* ------------------------------ */
6345 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6346 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6348 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6349 * 32-bit shift distance.
6351 /* shr-long/2addr vA, vB */
6352 mov r9, rINST, lsr #8 @ r9<- A+
6353 mov r3, rINST, lsr #12 @ r3<- B
6355 GET_VREG(r2, r3) @ r2<- vB
6356 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6357 and r2, r2, #63 @ r2<- r2 & 0x3f
6358 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6360 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6361 rsb r3, r2, #32 @ r3<- 32 - r2
6362 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6363 subs ip, r2, #32 @ ip<- r2 - 32
6364 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6365 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6366 mov r1, r1, asr r2 @ r1<- r1 >> r2
6367 b .LOP_SHR_LONG_2ADDR_finish
6369 /* ------------------------------ */
6371 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6372 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6374 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6375 * 32-bit shift distance.
6377 /* ushr-long/2addr vA, vB */
6378 mov r9, rINST, lsr #8 @ r9<- A+
6379 mov r3, rINST, lsr #12 @ r3<- B
6381 GET_VREG(r2, r3) @ r2<- vB
6382 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6383 and r2, r2, #63 @ r2<- r2 & 0x3f
6384 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6386 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6387 rsb r3, r2, #32 @ r3<- 32 - r2
6388 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6389 subs ip, r2, #32 @ ip<- r2 - 32
6390 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6391 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6392 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6393 b .LOP_USHR_LONG_2ADDR_finish
6395 /* ------------------------------ */
6397 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6398 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6399 /* File: armv5te/binop2addr.S */
6401 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6402 * that specifies an instruction that performs "result = r0 op r1".
6403 * This could be an ARM instruction or a function call. (If the result
6404 * comes back in a register other than r0, you can override "result".)
6406 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6407 * vCC (r1). Useful for integer division and modulus.
6409 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6410 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6411 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6412 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6414 /* binop/2addr vA, vB */
6415 mov r9, rINST, lsr #8 @ r9<- A+
6416 mov r3, rINST, lsr #12 @ r3<- B
6418 GET_VREG(r1, r3) @ r1<- vB
6419 GET_VREG(r0, r9) @ r0<- vA
6421 cmp r1, #0 @ is second operand zero?
6422 beq common_errDivideByZero
6424 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6426 @ optional op; may set condition codes
6427 bl __aeabi_fadd @ r0<- op, r0-r3 changed
6428 GET_INST_OPCODE(ip) @ extract opcode from rINST
6429 SET_VREG(r0, r9) @ vAA<- r0
6430 GOTO_OPCODE(ip) @ jump to next instruction
6431 /* 10-13 instructions */
6435 /* ------------------------------ */
6437 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6438 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6439 /* File: armv5te/binop2addr.S */
6441 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6442 * that specifies an instruction that performs "result = r0 op r1".
6443 * This could be an ARM instruction or a function call. (If the result
6444 * comes back in a register other than r0, you can override "result".)
6446 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6447 * vCC (r1). Useful for integer division and modulus.
6449 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6450 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6451 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6452 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6454 /* binop/2addr vA, vB */
6455 mov r9, rINST, lsr #8 @ r9<- A+
6456 mov r3, rINST, lsr #12 @ r3<- B
6458 GET_VREG(r1, r3) @ r1<- vB
6459 GET_VREG(r0, r9) @ r0<- vA
6461 cmp r1, #0 @ is second operand zero?
6462 beq common_errDivideByZero
6464 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6466 @ optional op; may set condition codes
6467 bl __aeabi_fsub @ r0<- op, r0-r3 changed
6468 GET_INST_OPCODE(ip) @ extract opcode from rINST
6469 SET_VREG(r0, r9) @ vAA<- r0
6470 GOTO_OPCODE(ip) @ jump to next instruction
6471 /* 10-13 instructions */
6475 /* ------------------------------ */
6477 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6478 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6479 /* File: armv5te/binop2addr.S */
6481 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6482 * that specifies an instruction that performs "result = r0 op r1".
6483 * This could be an ARM instruction or a function call. (If the result
6484 * comes back in a register other than r0, you can override "result".)
6486 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6487 * vCC (r1). Useful for integer division and modulus.
6489 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6490 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6491 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6492 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6494 /* binop/2addr vA, vB */
6495 mov r9, rINST, lsr #8 @ r9<- A+
6496 mov r3, rINST, lsr #12 @ r3<- B
6498 GET_VREG(r1, r3) @ r1<- vB
6499 GET_VREG(r0, r9) @ r0<- vA
6501 cmp r1, #0 @ is second operand zero?
6502 beq common_errDivideByZero
6504 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6506 @ optional op; may set condition codes
6507 bl __aeabi_fmul @ r0<- op, r0-r3 changed
6508 GET_INST_OPCODE(ip) @ extract opcode from rINST
6509 SET_VREG(r0, r9) @ vAA<- r0
6510 GOTO_OPCODE(ip) @ jump to next instruction
6511 /* 10-13 instructions */
6515 /* ------------------------------ */
6517 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6518 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6519 /* File: armv5te/binop2addr.S */
6521 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6522 * that specifies an instruction that performs "result = r0 op r1".
6523 * This could be an ARM instruction or a function call. (If the result
6524 * comes back in a register other than r0, you can override "result".)
6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527 * vCC (r1). Useful for integer division and modulus.
6529 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6530 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6531 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6532 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6534 /* binop/2addr vA, vB */
6535 mov r9, rINST, lsr #8 @ r9<- A+
6536 mov r3, rINST, lsr #12 @ r3<- B
6538 GET_VREG(r1, r3) @ r1<- vB
6539 GET_VREG(r0, r9) @ r0<- vA
6541 cmp r1, #0 @ is second operand zero?
6542 beq common_errDivideByZero
6544 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6546 @ optional op; may set condition codes
6547 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
6548 GET_INST_OPCODE(ip) @ extract opcode from rINST
6549 SET_VREG(r0, r9) @ vAA<- r0
6550 GOTO_OPCODE(ip) @ jump to next instruction
6551 /* 10-13 instructions */
6555 /* ------------------------------ */
6557 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6558 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6559 /* EABI doesn't define a float remainder function, but libm does */
6560 /* File: armv5te/binop2addr.S */
6562 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6563 * that specifies an instruction that performs "result = r0 op r1".
6564 * This could be an ARM instruction or a function call. (If the result
6565 * comes back in a register other than r0, you can override "result".)
6567 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568 * vCC (r1). Useful for integer division and modulus.
6570 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6571 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6572 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6573 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6575 /* binop/2addr vA, vB */
6576 mov r9, rINST, lsr #8 @ r9<- A+
6577 mov r3, rINST, lsr #12 @ r3<- B
6579 GET_VREG(r1, r3) @ r1<- vB
6580 GET_VREG(r0, r9) @ r0<- vA
6582 cmp r1, #0 @ is second operand zero?
6583 beq common_errDivideByZero
6585 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6587 @ optional op; may set condition codes
6588 bl fmodf @ r0<- op, r0-r3 changed
6589 GET_INST_OPCODE(ip) @ extract opcode from rINST
6590 SET_VREG(r0, r9) @ vAA<- r0
6591 GOTO_OPCODE(ip) @ jump to next instruction
6592 /* 10-13 instructions */
6596 /* ------------------------------ */
6598 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6599 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6600 /* File: armv5te/binopWide2addr.S */
6602 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6603 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6604 * This could be an ARM instruction or a function call. (If the result
6605 * comes back in a register other than r0, you can override "result".)
6607 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6608 * vCC (r1). Useful for integer division and modulus.
6610 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6611 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6612 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6615 /* binop/2addr vA, vB */
6616 mov r9, rINST, lsr #8 @ r9<- A+
6617 mov r1, rINST, lsr #12 @ r1<- B
6619 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6620 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6621 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6622 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6624 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6625 beq common_errDivideByZero
6627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6629 @ optional op; may set condition codes
6630 bl __aeabi_dadd @ result<- op, r0-r3 changed
6631 GET_INST_OPCODE(ip) @ extract opcode from rINST
6632 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6633 GOTO_OPCODE(ip) @ jump to next instruction
6634 /* 12-15 instructions */
6638 /* ------------------------------ */
6640 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6641 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6642 /* File: armv5te/binopWide2addr.S */
6644 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6645 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6653 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6654 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6657 /* binop/2addr vA, vB */
6658 mov r9, rINST, lsr #8 @ r9<- A+
6659 mov r1, rINST, lsr #12 @ r1<- B
6661 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6662 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6663 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6664 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6666 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6667 beq common_errDivideByZero
6669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6671 @ optional op; may set condition codes
6672 bl __aeabi_dsub @ result<- op, r0-r3 changed
6673 GET_INST_OPCODE(ip) @ extract opcode from rINST
6674 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6675 GOTO_OPCODE(ip) @ jump to next instruction
6676 /* 12-15 instructions */
6680 /* ------------------------------ */
6682 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6683 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6684 /* File: armv5te/binopWide2addr.S */
6686 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6687 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6688 * This could be an ARM instruction or a function call. (If the result
6689 * comes back in a register other than r0, you can override "result".)
6691 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6692 * vCC (r1). Useful for integer division and modulus.
6694 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6695 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6696 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6699 /* binop/2addr vA, vB */
6700 mov r9, rINST, lsr #8 @ r9<- A+
6701 mov r1, rINST, lsr #12 @ r1<- B
6703 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6704 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6705 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6706 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6708 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6709 beq common_errDivideByZero
6711 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6713 @ optional op; may set condition codes
6714 bl __aeabi_dmul @ result<- op, r0-r3 changed
6715 GET_INST_OPCODE(ip) @ extract opcode from rINST
6716 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6717 GOTO_OPCODE(ip) @ jump to next instruction
6718 /* 12-15 instructions */
6722 /* ------------------------------ */
6724 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6725 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6726 /* File: armv5te/binopWide2addr.S */
6728 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6729 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6730 * This could be an ARM instruction or a function call. (If the result
6731 * comes back in a register other than r0, you can override "result".)
6733 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6734 * vCC (r1). Useful for integer division and modulus.
6736 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6737 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6738 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6741 /* binop/2addr vA, vB */
6742 mov r9, rINST, lsr #8 @ r9<- A+
6743 mov r1, rINST, lsr #12 @ r1<- B
6745 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6746 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6747 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6748 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6750 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6751 beq common_errDivideByZero
6753 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6755 @ optional op; may set condition codes
6756 bl __aeabi_ddiv @ result<- op, r0-r3 changed
6757 GET_INST_OPCODE(ip) @ extract opcode from rINST
6758 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6759 GOTO_OPCODE(ip) @ jump to next instruction
6760 /* 12-15 instructions */
6764 /* ------------------------------ */
6766 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6767 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6768 /* EABI doesn't define a double remainder function, but libm does */
6769 /* File: armv5te/binopWide2addr.S */
6771 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6772 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6773 * This could be an ARM instruction or a function call. (If the result
6774 * comes back in a register other than r0, you can override "result".)
6776 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6777 * vCC (r1). Useful for integer division and modulus.
6779 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6780 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6781 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6784 /* binop/2addr vA, vB */
6785 mov r9, rINST, lsr #8 @ r9<- A+
6786 mov r1, rINST, lsr #12 @ r1<- B
6788 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6789 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6790 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6791 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6793 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6794 beq common_errDivideByZero
6796 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6798 @ optional op; may set condition codes
6799 bl fmod @ result<- op, r0-r3 changed
6800 GET_INST_OPCODE(ip) @ extract opcode from rINST
6801 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6802 GOTO_OPCODE(ip) @ jump to next instruction
6803 /* 12-15 instructions */
6807 /* ------------------------------ */
6809 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6810 /* File: armv5te/OP_ADD_INT_LIT16.S */
6811 /* File: armv5te/binopLit16.S */
6813 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6814 * that specifies an instruction that performs "result = r0 op r1".
6815 * This could be an ARM instruction or a function call. (If the result
6816 * comes back in a register other than r0, you can override "result".)
6818 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6819 * vCC (r1). Useful for integer division and modulus.
6821 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6822 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6824 /* binop/lit16 vA, vB, #+CCCC */
6825 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6826 mov r2, rINST, lsr #12 @ r2<- B
6827 mov r9, rINST, lsr #8 @ r9<- A+
6828 GET_VREG(r0, r2) @ r0<- vB
6831 cmp r1, #0 @ is second operand zero?
6832 beq common_errDivideByZero
6834 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6836 add r0, r0, r1 @ r0<- op, r0-r3 changed
6837 GET_INST_OPCODE(ip) @ extract opcode from rINST
6838 SET_VREG(r0, r9) @ vAA<- r0
6839 GOTO_OPCODE(ip) @ jump to next instruction
6840 /* 10-13 instructions */
6844 /* ------------------------------ */
6846 .L_OP_RSUB_INT: /* 0xd1 */
6847 /* File: armv5te/OP_RSUB_INT.S */
6848 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6849 /* File: armv5te/binopLit16.S */
6851 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6852 * that specifies an instruction that performs "result = r0 op r1".
6853 * This could be an ARM instruction or a function call. (If the result
6854 * comes back in a register other than r0, you can override "result".)
6856 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6857 * vCC (r1). Useful for integer division and modulus.
6859 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6860 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6862 /* binop/lit16 vA, vB, #+CCCC */
6863 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6864 mov r2, rINST, lsr #12 @ r2<- B
6865 mov r9, rINST, lsr #8 @ r9<- A+
6866 GET_VREG(r0, r2) @ r0<- vB
6869 cmp r1, #0 @ is second operand zero?
6870 beq common_errDivideByZero
6872 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6874 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6875 GET_INST_OPCODE(ip) @ extract opcode from rINST
6876 SET_VREG(r0, r9) @ vAA<- r0
6877 GOTO_OPCODE(ip) @ jump to next instruction
6878 /* 10-13 instructions */
6882 /* ------------------------------ */
6884 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6885 /* File: armv5te/OP_MUL_INT_LIT16.S */
6886 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6887 /* File: armv5te/binopLit16.S */
6889 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6890 * that specifies an instruction that performs "result = r0 op r1".
6891 * This could be an ARM instruction or a function call. (If the result
6892 * comes back in a register other than r0, you can override "result".)
6894 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6895 * vCC (r1). Useful for integer division and modulus.
6897 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6898 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6900 /* binop/lit16 vA, vB, #+CCCC */
6901 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6902 mov r2, rINST, lsr #12 @ r2<- B
6903 mov r9, rINST, lsr #8 @ r9<- A+
6904 GET_VREG(r0, r2) @ r0<- vB
6907 cmp r1, #0 @ is second operand zero?
6908 beq common_errDivideByZero
6910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6912 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6913 GET_INST_OPCODE(ip) @ extract opcode from rINST
6914 SET_VREG(r0, r9) @ vAA<- r0
6915 GOTO_OPCODE(ip) @ jump to next instruction
6916 /* 10-13 instructions */
6920 /* ------------------------------ */
6922 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6923 /* File: armv5te/OP_DIV_INT_LIT16.S */
6924 /* File: armv5te/binopLit16.S */
6926 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6927 * that specifies an instruction that performs "result = r0 op r1".
6928 * This could be an ARM instruction or a function call. (If the result
6929 * comes back in a register other than r0, you can override "result".)
6931 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6932 * vCC (r1). Useful for integer division and modulus.
6934 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6935 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6937 /* binop/lit16 vA, vB, #+CCCC */
6938 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6939 mov r2, rINST, lsr #12 @ r2<- B
6940 mov r9, rINST, lsr #8 @ r9<- A+
6941 GET_VREG(r0, r2) @ r0<- vB
6944 cmp r1, #0 @ is second operand zero?
6945 beq common_errDivideByZero
6947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6949 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6950 GET_INST_OPCODE(ip) @ extract opcode from rINST
6951 SET_VREG(r0, r9) @ vAA<- r0
6952 GOTO_OPCODE(ip) @ jump to next instruction
6953 /* 10-13 instructions */
6957 /* ------------------------------ */
6959 .L_OP_REM_INT_LIT16: /* 0xd4 */
6960 /* File: armv5te/OP_REM_INT_LIT16.S */
6961 /* idivmod returns quotient in r0 and remainder in r1 */
6962 /* File: armv5te/binopLit16.S */
6964 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6965 * that specifies an instruction that performs "result = r0 op r1".
6966 * This could be an ARM instruction or a function call. (If the result
6967 * comes back in a register other than r0, you can override "result".)
6969 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6970 * vCC (r1). Useful for integer division and modulus.
6972 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6973 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6975 /* binop/lit16 vA, vB, #+CCCC */
6976 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6977 mov r2, rINST, lsr #12 @ r2<- B
6978 mov r9, rINST, lsr #8 @ r9<- A+
6979 GET_VREG(r0, r2) @ r0<- vB
6982 cmp r1, #0 @ is second operand zero?
6983 beq common_errDivideByZero
6985 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6987 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6988 GET_INST_OPCODE(ip) @ extract opcode from rINST
6989 SET_VREG(r1, r9) @ vAA<- r1
6990 GOTO_OPCODE(ip) @ jump to next instruction
6991 /* 10-13 instructions */
6995 /* ------------------------------ */
6997 .L_OP_AND_INT_LIT16: /* 0xd5 */
6998 /* File: armv5te/OP_AND_INT_LIT16.S */
6999 /* File: armv5te/binopLit16.S */
7001 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7002 * that specifies an instruction that performs "result = r0 op r1".
7003 * This could be an ARM instruction or a function call. (If the result
7004 * comes back in a register other than r0, you can override "result".)
7006 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7007 * vCC (r1). Useful for integer division and modulus.
7009 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7010 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7012 /* binop/lit16 vA, vB, #+CCCC */
7013 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7014 mov r2, rINST, lsr #12 @ r2<- B
7015 mov r9, rINST, lsr #8 @ r9<- A+
7016 GET_VREG(r0, r2) @ r0<- vB
7019 cmp r1, #0 @ is second operand zero?
7020 beq common_errDivideByZero
7022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7024 and r0, r0, r1 @ r0<- op, r0-r3 changed
7025 GET_INST_OPCODE(ip) @ extract opcode from rINST
7026 SET_VREG(r0, r9) @ vAA<- r0
7027 GOTO_OPCODE(ip) @ jump to next instruction
7028 /* 10-13 instructions */
7032 /* ------------------------------ */
7034 .L_OP_OR_INT_LIT16: /* 0xd6 */
7035 /* File: armv5te/OP_OR_INT_LIT16.S */
7036 /* File: armv5te/binopLit16.S */
7038 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7039 * that specifies an instruction that performs "result = r0 op r1".
7040 * This could be an ARM instruction or a function call. (If the result
7041 * comes back in a register other than r0, you can override "result".)
7043 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7044 * vCC (r1). Useful for integer division and modulus.
7046 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7047 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7049 /* binop/lit16 vA, vB, #+CCCC */
7050 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7051 mov r2, rINST, lsr #12 @ r2<- B
7052 mov r9, rINST, lsr #8 @ r9<- A+
7053 GET_VREG(r0, r2) @ r0<- vB
7056 cmp r1, #0 @ is second operand zero?
7057 beq common_errDivideByZero
7059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7061 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7062 GET_INST_OPCODE(ip) @ extract opcode from rINST
7063 SET_VREG(r0, r9) @ vAA<- r0
7064 GOTO_OPCODE(ip) @ jump to next instruction
7065 /* 10-13 instructions */
7069 /* ------------------------------ */
7071 .L_OP_XOR_INT_LIT16: /* 0xd7 */
7072 /* File: armv5te/OP_XOR_INT_LIT16.S */
7073 /* File: armv5te/binopLit16.S */
7075 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7076 * that specifies an instruction that performs "result = r0 op r1".
7077 * This could be an ARM instruction or a function call. (If the result
7078 * comes back in a register other than r0, you can override "result".)
7080 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7081 * vCC (r1). Useful for integer division and modulus.
7083 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7084 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7086 /* binop/lit16 vA, vB, #+CCCC */
7087 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7088 mov r2, rINST, lsr #12 @ r2<- B
7089 mov r9, rINST, lsr #8 @ r9<- A+
7090 GET_VREG(r0, r2) @ r0<- vB
7093 cmp r1, #0 @ is second operand zero?
7094 beq common_errDivideByZero
7096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7098 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7099 GET_INST_OPCODE(ip) @ extract opcode from rINST
7100 SET_VREG(r0, r9) @ vAA<- r0
7101 GOTO_OPCODE(ip) @ jump to next instruction
7102 /* 10-13 instructions */
7106 /* ------------------------------ */
7108 .L_OP_ADD_INT_LIT8: /* 0xd8 */
7109 /* File: armv5te/OP_ADD_INT_LIT8.S */
7110 /* File: armv5te/binopLit8.S */
7112 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7113 * that specifies an instruction that performs "result = r0 op r1".
7114 * This could be an ARM instruction or a function call. (If the result
7115 * comes back in a register other than r0, you can override "result".)
7117 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7118 * vCC (r1). Useful for integer division and modulus.
7120 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7121 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7122 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7124 /* binop/lit8 vAA, vBB, #+CC */
7125 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7126 mov r9, rINST, lsr #8 @ r9<- AA
7127 and r2, r3, #255 @ r2<- BB
7128 GET_VREG(r0, r2) @ r0<- vBB
7129 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7131 @cmp r1, #0 @ is second operand zero?
7132 beq common_errDivideByZero
7134 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7136 @ optional op; may set condition codes
7137 add r0, r0, r1 @ r0<- op, r0-r3 changed
7138 GET_INST_OPCODE(ip) @ extract opcode from rINST
7139 SET_VREG(r0, r9) @ vAA<- r0
7140 GOTO_OPCODE(ip) @ jump to next instruction
7141 /* 10-12 instructions */
7145 /* ------------------------------ */
7147 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
7148 /* File: armv5te/OP_RSUB_INT_LIT8.S */
7149 /* File: armv5te/binopLit8.S */
7151 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7152 * that specifies an instruction that performs "result = r0 op r1".
7153 * This could be an ARM instruction or a function call. (If the result
7154 * comes back in a register other than r0, you can override "result".)
7156 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7157 * vCC (r1). Useful for integer division and modulus.
7159 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7160 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7161 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7163 /* binop/lit8 vAA, vBB, #+CC */
7164 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7165 mov r9, rINST, lsr #8 @ r9<- AA
7166 and r2, r3, #255 @ r2<- BB
7167 GET_VREG(r0, r2) @ r0<- vBB
7168 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7170 @cmp r1, #0 @ is second operand zero?
7171 beq common_errDivideByZero
7173 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7175 @ optional op; may set condition codes
7176 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
7177 GET_INST_OPCODE(ip) @ extract opcode from rINST
7178 SET_VREG(r0, r9) @ vAA<- r0
7179 GOTO_OPCODE(ip) @ jump to next instruction
7180 /* 10-12 instructions */
7184 /* ------------------------------ */
7186 .L_OP_MUL_INT_LIT8: /* 0xda */
7187 /* File: armv5te/OP_MUL_INT_LIT8.S */
7188 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7189 /* File: armv5te/binopLit8.S */
7191 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7192 * that specifies an instruction that performs "result = r0 op r1".
7193 * This could be an ARM instruction or a function call. (If the result
7194 * comes back in a register other than r0, you can override "result".)
7196 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7197 * vCC (r1). Useful for integer division and modulus.
7199 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7200 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7201 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7203 /* binop/lit8 vAA, vBB, #+CC */
7204 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7205 mov r9, rINST, lsr #8 @ r9<- AA
7206 and r2, r3, #255 @ r2<- BB
7207 GET_VREG(r0, r2) @ r0<- vBB
7208 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7210 @cmp r1, #0 @ is second operand zero?
7211 beq common_errDivideByZero
7213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7215 @ optional op; may set condition codes
7216 mul r0, r1, r0 @ r0<- op, r0-r3 changed
7217 GET_INST_OPCODE(ip) @ extract opcode from rINST
7218 SET_VREG(r0, r9) @ vAA<- r0
7219 GOTO_OPCODE(ip) @ jump to next instruction
7220 /* 10-12 instructions */
7224 /* ------------------------------ */
7226 .L_OP_DIV_INT_LIT8: /* 0xdb */
7227 /* File: armv5te/OP_DIV_INT_LIT8.S */
7228 /* File: armv5te/binopLit8.S */
7230 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7231 * that specifies an instruction that performs "result = r0 op r1".
7232 * This could be an ARM instruction or a function call. (If the result
7233 * comes back in a register other than r0, you can override "result".)
7235 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7236 * vCC (r1). Useful for integer division and modulus.
7238 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7239 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7240 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7242 /* binop/lit8 vAA, vBB, #+CC */
7243 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7244 mov r9, rINST, lsr #8 @ r9<- AA
7245 and r2, r3, #255 @ r2<- BB
7246 GET_VREG(r0, r2) @ r0<- vBB
7247 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7249 @cmp r1, #0 @ is second operand zero?
7250 beq common_errDivideByZero
7252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7254 @ optional op; may set condition codes
7255 bl __aeabi_idiv @ r0<- op, r0-r3 changed
7256 GET_INST_OPCODE(ip) @ extract opcode from rINST
7257 SET_VREG(r0, r9) @ vAA<- r0
7258 GOTO_OPCODE(ip) @ jump to next instruction
7259 /* 10-12 instructions */
7263 /* ------------------------------ */
7265 .L_OP_REM_INT_LIT8: /* 0xdc */
7266 /* File: armv5te/OP_REM_INT_LIT8.S */
7267 /* idivmod returns quotient in r0 and remainder in r1 */
7268 /* File: armv5te/binopLit8.S */
7270 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7271 * that specifies an instruction that performs "result = r0 op r1".
7272 * This could be an ARM instruction or a function call. (If the result
7273 * comes back in a register other than r0, you can override "result".)
7275 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7276 * vCC (r1). Useful for integer division and modulus.
7278 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7279 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7280 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7282 /* binop/lit8 vAA, vBB, #+CC */
7283 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7284 mov r9, rINST, lsr #8 @ r9<- AA
7285 and r2, r3, #255 @ r2<- BB
7286 GET_VREG(r0, r2) @ r0<- vBB
7287 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7289 @cmp r1, #0 @ is second operand zero?
7290 beq common_errDivideByZero
7292 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7294 @ optional op; may set condition codes
7295 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
7296 GET_INST_OPCODE(ip) @ extract opcode from rINST
7297 SET_VREG(r1, r9) @ vAA<- r1
7298 GOTO_OPCODE(ip) @ jump to next instruction
7299 /* 10-12 instructions */
7303 /* ------------------------------ */
7305 .L_OP_AND_INT_LIT8: /* 0xdd */
7306 /* File: armv5te/OP_AND_INT_LIT8.S */
7307 /* File: armv5te/binopLit8.S */
7309 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7310 * that specifies an instruction that performs "result = r0 op r1".
7311 * This could be an ARM instruction or a function call. (If the result
7312 * comes back in a register other than r0, you can override "result".)
7314 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7315 * vCC (r1). Useful for integer division and modulus.
7317 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7318 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7319 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7321 /* binop/lit8 vAA, vBB, #+CC */
7322 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7323 mov r9, rINST, lsr #8 @ r9<- AA
7324 and r2, r3, #255 @ r2<- BB
7325 GET_VREG(r0, r2) @ r0<- vBB
7326 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7328 @cmp r1, #0 @ is second operand zero?
7329 beq common_errDivideByZero
7331 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7333 @ optional op; may set condition codes
7334 and r0, r0, r1 @ r0<- op, r0-r3 changed
7335 GET_INST_OPCODE(ip) @ extract opcode from rINST
7336 SET_VREG(r0, r9) @ vAA<- r0
7337 GOTO_OPCODE(ip) @ jump to next instruction
7338 /* 10-12 instructions */
7342 /* ------------------------------ */
7344 .L_OP_OR_INT_LIT8: /* 0xde */
7345 /* File: armv5te/OP_OR_INT_LIT8.S */
7346 /* File: armv5te/binopLit8.S */
7348 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7349 * that specifies an instruction that performs "result = r0 op r1".
7350 * This could be an ARM instruction or a function call. (If the result
7351 * comes back in a register other than r0, you can override "result".)
7353 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7354 * vCC (r1). Useful for integer division and modulus.
7356 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7357 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7358 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7360 /* binop/lit8 vAA, vBB, #+CC */
7361 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7362 mov r9, rINST, lsr #8 @ r9<- AA
7363 and r2, r3, #255 @ r2<- BB
7364 GET_VREG(r0, r2) @ r0<- vBB
7365 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7367 @cmp r1, #0 @ is second operand zero?
7368 beq common_errDivideByZero
7370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7372 @ optional op; may set condition codes
7373 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7374 GET_INST_OPCODE(ip) @ extract opcode from rINST
7375 SET_VREG(r0, r9) @ vAA<- r0
7376 GOTO_OPCODE(ip) @ jump to next instruction
7377 /* 10-12 instructions */
7381 /* ------------------------------ */
7383 .L_OP_XOR_INT_LIT8: /* 0xdf */
7384 /* File: armv5te/OP_XOR_INT_LIT8.S */
7385 /* File: armv5te/binopLit8.S */
7387 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7388 * that specifies an instruction that performs "result = r0 op r1".
7389 * This could be an ARM instruction or a function call. (If the result
7390 * comes back in a register other than r0, you can override "result".)
7392 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7393 * vCC (r1). Useful for integer division and modulus.
7395 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7396 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7397 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7399 /* binop/lit8 vAA, vBB, #+CC */
7400 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7401 mov r9, rINST, lsr #8 @ r9<- AA
7402 and r2, r3, #255 @ r2<- BB
7403 GET_VREG(r0, r2) @ r0<- vBB
7404 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7406 @cmp r1, #0 @ is second operand zero?
7407 beq common_errDivideByZero
7409 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7411 @ optional op; may set condition codes
7412 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7413 GET_INST_OPCODE(ip) @ extract opcode from rINST
7414 SET_VREG(r0, r9) @ vAA<- r0
7415 GOTO_OPCODE(ip) @ jump to next instruction
7416 /* 10-12 instructions */
7420 /* ------------------------------ */
7422 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7423 /* File: armv5te/OP_SHL_INT_LIT8.S */
7424 /* File: armv5te/binopLit8.S */
7426 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7427 * that specifies an instruction that performs "result = r0 op r1".
7428 * This could be an ARM instruction or a function call. (If the result
7429 * comes back in a register other than r0, you can override "result".)
7431 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7432 * vCC (r1). Useful for integer division and modulus.
7434 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7435 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7436 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7438 /* binop/lit8 vAA, vBB, #+CC */
7439 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7440 mov r9, rINST, lsr #8 @ r9<- AA
7441 and r2, r3, #255 @ r2<- BB
7442 GET_VREG(r0, r2) @ r0<- vBB
7443 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7445 @cmp r1, #0 @ is second operand zero?
7446 beq common_errDivideByZero
7448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7450 and r1, r1, #31 @ optional op; may set condition codes
7451 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7452 GET_INST_OPCODE(ip) @ extract opcode from rINST
7453 SET_VREG(r0, r9) @ vAA<- r0
7454 GOTO_OPCODE(ip) @ jump to next instruction
7455 /* 10-12 instructions */
7459 /* ------------------------------ */
7461 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7462 /* File: armv5te/OP_SHR_INT_LIT8.S */
7463 /* File: armv5te/binopLit8.S */
7465 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7466 * that specifies an instruction that performs "result = r0 op r1".
7467 * This could be an ARM instruction or a function call. (If the result
7468 * comes back in a register other than r0, you can override "result".)
7470 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7471 * vCC (r1). Useful for integer division and modulus.
7473 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7474 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7475 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7477 /* binop/lit8 vAA, vBB, #+CC */
7478 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7479 mov r9, rINST, lsr #8 @ r9<- AA
7480 and r2, r3, #255 @ r2<- BB
7481 GET_VREG(r0, r2) @ r0<- vBB
7482 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7484 @cmp r1, #0 @ is second operand zero?
7485 beq common_errDivideByZero
7487 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7489 and r1, r1, #31 @ optional op; may set condition codes
7490 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7491 GET_INST_OPCODE(ip) @ extract opcode from rINST
7492 SET_VREG(r0, r9) @ vAA<- r0
7493 GOTO_OPCODE(ip) @ jump to next instruction
7494 /* 10-12 instructions */
7498 /* ------------------------------ */
7500 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7501 /* File: armv5te/OP_USHR_INT_LIT8.S */
7502 /* File: armv5te/binopLit8.S */
7504 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7505 * that specifies an instruction that performs "result = r0 op r1".
7506 * This could be an ARM instruction or a function call. (If the result
7507 * comes back in a register other than r0, you can override "result".)
7509 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7510 * vCC (r1). Useful for integer division and modulus.
7512 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7513 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7514 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7516 /* binop/lit8 vAA, vBB, #+CC */
7517 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7518 mov r9, rINST, lsr #8 @ r9<- AA
7519 and r2, r3, #255 @ r2<- BB
7520 GET_VREG(r0, r2) @ r0<- vBB
7521 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7523 @cmp r1, #0 @ is second operand zero?
7524 beq common_errDivideByZero
7526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7528 and r1, r1, #31 @ optional op; may set condition codes
7529 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7530 GET_INST_OPCODE(ip) @ extract opcode from rINST
7531 SET_VREG(r0, r9) @ vAA<- r0
7532 GOTO_OPCODE(ip) @ jump to next instruction
7533 /* 10-12 instructions */
7537 /* ------------------------------ */
7539 .L_OP_UNUSED_E3: /* 0xe3 */
7540 /* File: armv5te/OP_UNUSED_E3.S */
7541 /* File: armv5te/unused.S */
7546 /* ------------------------------ */
7548 .L_OP_UNUSED_E4: /* 0xe4 */
7549 /* File: armv5te/OP_UNUSED_E4.S */
7550 /* File: armv5te/unused.S */
7555 /* ------------------------------ */
7557 .L_OP_UNUSED_E5: /* 0xe5 */
7558 /* File: armv5te/OP_UNUSED_E5.S */
7559 /* File: armv5te/unused.S */
7564 /* ------------------------------ */
7566 .L_OP_UNUSED_E6: /* 0xe6 */
7567 /* File: armv5te/OP_UNUSED_E6.S */
7568 /* File: armv5te/unused.S */
7573 /* ------------------------------ */
7575 .L_OP_UNUSED_E7: /* 0xe7 */
7576 /* File: armv5te/OP_UNUSED_E7.S */
7577 /* File: armv5te/unused.S */
7582 /* ------------------------------ */
7584 .L_OP_UNUSED_E8: /* 0xe8 */
7585 /* File: armv5te/OP_UNUSED_E8.S */
7586 /* File: armv5te/unused.S */
7591 /* ------------------------------ */
7593 .L_OP_UNUSED_E9: /* 0xe9 */
7594 /* File: armv5te/OP_UNUSED_E9.S */
7595 /* File: armv5te/unused.S */
7600 /* ------------------------------ */
7602 .L_OP_UNUSED_EA: /* 0xea */
7603 /* File: armv5te/OP_UNUSED_EA.S */
7604 /* File: armv5te/unused.S */
7609 /* ------------------------------ */
7611 .L_OP_UNUSED_EB: /* 0xeb */
7612 /* File: armv5te/OP_UNUSED_EB.S */
7613 /* File: armv5te/unused.S */
7618 /* ------------------------------ */
7620 .L_OP_UNUSED_EC: /* 0xec */
7621 /* File: armv5te/OP_UNUSED_EC.S */
7622 /* File: armv5te/unused.S */
7627 /* ------------------------------ */
7629 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7630 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7632 * Handle a throw-verification-error instruction. This throws an
7633 * exception for an error discovered during verification. The
7634 * exception is indicated by AA, with some detail provided by BBBB.
7636 /* op AA, ref@BBBB */
7637 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7638 FETCH(r2, 1) @ r2<- BBBB
7639 EXPORT_PC() @ export the PC
7640 mov r1, rINST, lsr #8 @ r1<- AA
7641 bl dvmThrowVerificationError @ always throws
7642 b common_exceptionThrown @ handle exception
7645 /* ------------------------------ */
7647 .L_OP_EXECUTE_INLINE: /* 0xee */
7648 /* File: armv5te/OP_EXECUTE_INLINE.S */
7650 * Execute a "native inline" instruction.
7653 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7655 * The first four args are in r0-r3, but the last two must be pushed
7658 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7659 FETCH(r10, 1) @ r10<- BBBB
7660 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7661 EXPORT_PC() @ can throw
7662 sub sp, sp, #8 @ make room for arg(s)
7663 mov r0, rINST, lsr #12 @ r0<- B
7664 str r1, [sp] @ push &glue->retval
7665 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7666 add sp, sp, #8 @ pop stack
7667 cmp r0, #0 @ test boolean result of inline
7668 beq common_exceptionThrown @ returned false, handle exception
7669 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7670 GET_INST_OPCODE(ip) @ extract opcode from rINST
7671 GOTO_OPCODE(ip) @ jump to next instruction
7673 /* ------------------------------ */
7675 .L_OP_UNUSED_EF: /* 0xef */
7676 /* File: armv5te/OP_UNUSED_EF.S */
7677 /* File: armv5te/unused.S */
7682 /* ------------------------------ */
7684 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7685 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7687 * invoke-direct-empty is a no-op in a "standard" interpreter.
7689 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7690 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7691 GOTO_OPCODE(ip) @ execute it
7693 /* ------------------------------ */
7695 .L_OP_UNUSED_F1: /* 0xf1 */
7696 /* File: armv5te/OP_UNUSED_F1.S */
7697 /* File: armv5te/unused.S */
7702 /* ------------------------------ */
7704 .L_OP_IGET_QUICK: /* 0xf2 */
7705 /* File: armv5te/OP_IGET_QUICK.S */
7706 /* For: iget-quick, iget-object-quick */
7707 /* op vA, vB, offset@CCCC */
7708 mov r2, rINST, lsr #12 @ r2<- B
7709 GET_VREG(r3, r2) @ r3<- object we're operating on
7710 FETCH(r1, 1) @ r1<- field byte offset
7711 cmp r3, #0 @ check object for null
7712 mov r2, rINST, lsr #8 @ r2<- A(+)
7713 beq common_errNullObject @ object was null
7714 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7715 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7717 GET_INST_OPCODE(ip) @ extract opcode from rINST
7718 SET_VREG(r0, r2) @ fp[A]<- r0
7719 GOTO_OPCODE(ip) @ jump to next instruction
7722 /* ------------------------------ */
7724 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7725 /* File: armv5te/OP_IGET_WIDE_QUICK.S */
7726 /* iget-wide-quick vA, vB, offset@CCCC */
7727 mov r2, rINST, lsr #12 @ r2<- B
7728 GET_VREG(r3, r2) @ r3<- object we're operating on
7729 FETCH(r1, 1) @ r1<- field byte offset
7730 cmp r3, #0 @ check object for null
7731 mov r2, rINST, lsr #8 @ r2<- A(+)
7732 beq common_errNullObject @ object was null
7733 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned)
7735 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7736 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7737 GET_INST_OPCODE(ip) @ extract opcode from rINST
7738 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7739 GOTO_OPCODE(ip) @ jump to next instruction
7742 /* ------------------------------ */
7744 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7745 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7746 /* File: armv5te/OP_IGET_QUICK.S */
7747 /* For: iget-quick, iget-object-quick */
7748 /* op vA, vB, offset@CCCC */
7749 mov r2, rINST, lsr #12 @ r2<- B
7750 GET_VREG(r3, r2) @ r3<- object we're operating on
7751 FETCH(r1, 1) @ r1<- field byte offset
7752 cmp r3, #0 @ check object for null
7753 mov r2, rINST, lsr #8 @ r2<- A(+)
7754 beq common_errNullObject @ object was null
7755 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7758 GET_INST_OPCODE(ip) @ extract opcode from rINST
7759 SET_VREG(r0, r2) @ fp[A]<- r0
7760 GOTO_OPCODE(ip) @ jump to next instruction
7764 /* ------------------------------ */
7766 .L_OP_IPUT_QUICK: /* 0xf5 */
7767 /* File: armv5te/OP_IPUT_QUICK.S */
7768 /* For: iput-quick, iput-object-quick */
7769 /* op vA, vB, offset@CCCC */
7770 mov r2, rINST, lsr #12 @ r2<- B
7771 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7772 FETCH(r1, 1) @ r1<- field byte offset
7773 cmp r3, #0 @ check object for null
7774 mov r2, rINST, lsr #8 @ r2<- A(+)
7775 beq common_errNullObject @ object was null
7777 GET_VREG(r0, r2) @ r0<- fp[A]
7778 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7779 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7780 GET_INST_OPCODE(ip) @ extract opcode from rINST
7781 GOTO_OPCODE(ip) @ jump to next instruction
7784 /* ------------------------------ */
7786 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7787 /* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7788 /* iput-wide-quick vA, vB, offset@CCCC */
7789 mov r0, rINST, lsr #8 @ r0<- A(+)
7790 mov r1, rINST, lsr #12 @ r1<- B
7792 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7793 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7794 cmp r2, #0 @ check object for null
7795 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7796 beq common_errNullObject @ object was null
7797 FETCH(r3, 1) @ r3<- field byte offset
7798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7799 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1
7800 GET_INST_OPCODE(ip) @ extract opcode from rINST
7801 GOTO_OPCODE(ip) @ jump to next instruction
7804 /* ------------------------------ */
7806 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7807 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7808 /* File: armv5te/OP_IPUT_QUICK.S */
7809 /* For: iput-quick, iput-object-quick */
7810 /* op vA, vB, offset@CCCC */
7811 mov r2, rINST, lsr #12 @ r2<- B
7812 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7813 FETCH(r1, 1) @ r1<- field byte offset
7814 cmp r3, #0 @ check object for null
7815 mov r2, rINST, lsr #8 @ r2<- A(+)
7816 beq common_errNullObject @ object was null
7818 GET_VREG(r0, r2) @ r0<- fp[A]
7819 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7820 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7821 GET_INST_OPCODE(ip) @ extract opcode from rINST
7822 GOTO_OPCODE(ip) @ jump to next instruction
7826 /* ------------------------------ */
7828 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7829 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7831 * Handle an optimized virtual method call.
7833 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7835 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7836 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7837 FETCH(r3, 2) @ r3<- FEDC or CCCC
7838 FETCH(r1, 1) @ r1<- BBBB
7840 and r3, r3, #15 @ r3<- C (or stays CCCC)
7842 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7843 cmp r2, #0 @ is "this" null?
7844 beq common_errNullObject @ null "this", throw exception
7845 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7846 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7847 EXPORT_PC() @ invoke must export
7848 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7849 bl common_invokeMethodNoRange @ continue on
7851 /* ------------------------------ */
7853 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7854 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7855 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7857 * Handle an optimized virtual method call.
7859 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7861 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7862 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7863 FETCH(r3, 2) @ r3<- FEDC or CCCC
7864 FETCH(r1, 1) @ r1<- BBBB
7866 and r3, r3, #15 @ r3<- C (or stays CCCC)
7868 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7869 cmp r2, #0 @ is "this" null?
7870 beq common_errNullObject @ null "this", throw exception
7871 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7872 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7873 EXPORT_PC() @ invoke must export
7874 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7875 bl common_invokeMethodRange @ continue on
7878 /* ------------------------------ */
7880 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7881 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7883 * Handle an optimized "super" method call.
7885 * for: [opt] invoke-super-quick, invoke-super-quick/range
7887 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7888 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7889 FETCH(r10, 2) @ r10<- GFED or CCCC
7890 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7892 and r10, r10, #15 @ r10<- D (or stays CCCC)
7894 FETCH(r1, 1) @ r1<- BBBB
7895 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7896 EXPORT_PC() @ must export for invoke
7897 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7898 GET_VREG(r3, r10) @ r3<- "this"
7899 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7900 cmp r3, #0 @ null "this" ref?
7901 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7902 beq common_errNullObject @ "this" is null, throw exception
7903 bl common_invokeMethodNoRange @ continue on
7906 /* ------------------------------ */
7908 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7909 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7910 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7912 * Handle an optimized "super" method call.
7914 * for: [opt] invoke-super-quick, invoke-super-quick/range
7916 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7917 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7918 FETCH(r10, 2) @ r10<- GFED or CCCC
7919 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7921 and r10, r10, #15 @ r10<- D (or stays CCCC)
7923 FETCH(r1, 1) @ r1<- BBBB
7924 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7925 EXPORT_PC() @ must export for invoke
7926 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7927 GET_VREG(r3, r10) @ r3<- "this"
7928 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7929 cmp r3, #0 @ null "this" ref?
7930 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7931 beq common_errNullObject @ "this" is null, throw exception
7932 bl common_invokeMethodRange @ continue on
7936 /* ------------------------------ */
7938 .L_OP_UNUSED_FC: /* 0xfc */
7939 /* File: armv5te/OP_UNUSED_FC.S */
7940 /* File: armv5te/unused.S */
7945 /* ------------------------------ */
7947 .L_OP_UNUSED_FD: /* 0xfd */
7948 /* File: armv5te/OP_UNUSED_FD.S */
7949 /* File: armv5te/unused.S */
7954 /* ------------------------------ */
7956 .L_OP_UNUSED_FE: /* 0xfe */
7957 /* File: armv5te/OP_UNUSED_FE.S */
7958 /* File: armv5te/unused.S */
7963 /* ------------------------------ */
7965 .L_OP_UNUSED_FF: /* 0xff */
7966 /* File: armv5te/OP_UNUSED_FF.S */
7967 /* File: armv5te/unused.S */
7974 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
7975 .global dvmAsmInstructionEnd
7976 dvmAsmInstructionEnd:
7979 * ===========================================================================
7980 * Sister implementations
7981 * ===========================================================================
7983 .global dvmAsmSisterStart
7984 .type dvmAsmSisterStart, %function
7989 /* continuation for OP_CONST_STRING */
7992 * Continuation if the String has not yet been resolved.
7993 * r1: BBBB (String ref)
7994 * r9: target register
7996 .LOP_CONST_STRING_resolve:
7998 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7999 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8000 bl dvmResolveString @ r0<- String reference
8001 cmp r0, #0 @ failed?
8002 beq common_exceptionThrown @ yup, handle the exception
8003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8004 GET_INST_OPCODE(ip) @ extract opcode from rINST
8005 SET_VREG(r0, r9) @ vAA<- r0
8006 GOTO_OPCODE(ip) @ jump to next instruction
8009 /* continuation for OP_CONST_STRING_JUMBO */
8012 * Continuation if the String has not yet been resolved.
8013 * r1: BBBBBBBB (String ref)
8014 * r9: target register
8016 .LOP_CONST_STRING_JUMBO_resolve:
8018 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8019 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8020 bl dvmResolveString @ r0<- String reference
8021 cmp r0, #0 @ failed?
8022 beq common_exceptionThrown @ yup, handle the exception
8023 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
8024 GET_INST_OPCODE(ip) @ extract opcode from rINST
8025 SET_VREG(r0, r9) @ vAA<- r0
8026 GOTO_OPCODE(ip) @ jump to next instruction
8029 /* continuation for OP_CONST_CLASS */
8032 * Continuation if the Class has not yet been resolved.
8033 * r1: BBBB (Class ref)
8034 * r9: target register
8036 .LOP_CONST_CLASS_resolve:
8038 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8039 mov r2, #1 @ r2<- true
8040 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8041 bl dvmResolveClass @ r0<- Class reference
8042 cmp r0, #0 @ failed?
8043 beq common_exceptionThrown @ yup, handle the exception
8044 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8045 GET_INST_OPCODE(ip) @ extract opcode from rINST
8046 SET_VREG(r0, r9) @ vAA<- r0
8047 GOTO_OPCODE(ip) @ jump to next instruction
8050 /* continuation for OP_CHECK_CAST */
8053 * Trivial test failed, need to perform full check. This is common.
8054 * r0 holds obj->clazz
8055 * r1 holds class resolved from BBBB
8058 .LOP_CHECK_CAST_fullcheck:
8059 bl dvmInstanceofNonTrivial @ r0<- boolean result
8060 cmp r0, #0 @ failed?
8061 bne .LOP_CHECK_CAST_okay @ no, success
8063 @ A cast has failed. We need to throw a ClassCastException with the
8064 @ class of the object that failed to be cast.
8065 EXPORT_PC() @ about to throw
8066 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz
8067 ldr r0, .LstrClassCastExceptionPtr
8068 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8069 bl dvmThrowExceptionWithClassMessage
8070 b common_exceptionThrown
8073 * Resolution required. This is the least-likely path.
8078 .LOP_CHECK_CAST_resolve:
8079 EXPORT_PC() @ resolve() could throw
8080 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8081 mov r1, r2 @ r1<- BBBB
8082 mov r2, #0 @ r2<- false
8083 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8084 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8085 cmp r0, #0 @ got null?
8086 beq common_exceptionThrown @ yes, handle exception
8087 mov r1, r0 @ r1<- class resolved from BBB
8088 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8089 b .LOP_CHECK_CAST_resolved @ pick up where we left off
8091 .LstrClassCastExceptionPtr:
8092 .word .LstrClassCastException
8095 /* continuation for OP_INSTANCE_OF */
8098 * Trivial test failed, need to perform full check. This is common.
8099 * r0 holds obj->clazz
8100 * r1 holds class resolved from BBBB
8103 .LOP_INSTANCE_OF_fullcheck:
8104 bl dvmInstanceofNonTrivial @ r0<- boolean result
8105 @ fall through to OP_INSTANCE_OF_store
8108 * r0 holds boolean result
8111 .LOP_INSTANCE_OF_store:
8112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8113 SET_VREG(r0, r9) @ vA<- r0
8114 GET_INST_OPCODE(ip) @ extract opcode from rINST
8115 GOTO_OPCODE(ip) @ jump to next instruction
8118 * Trivial test succeeded, save and bail.
8121 .LOP_INSTANCE_OF_trivial:
8122 mov r0, #1 @ indicate success
8123 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8125 SET_VREG(r0, r9) @ vA<- r0
8126 GET_INST_OPCODE(ip) @ extract opcode from rINST
8127 GOTO_OPCODE(ip) @ jump to next instruction
8130 * Resolution required. This is the least-likely path.
8135 .LOP_INSTANCE_OF_resolve:
8136 EXPORT_PC() @ resolve() could throw
8137 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8138 mov r1, r3 @ r1<- BBBB
8139 mov r2, #1 @ r2<- true
8140 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8141 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8142 cmp r0, #0 @ got null?
8143 beq common_exceptionThrown @ yes, handle exception
8144 mov r1, r0 @ r1<- class resolved from BBB
8145 mov r3, rINST, lsr #12 @ r3<- B
8146 GET_VREG(r0, r3) @ r0<- vB (object)
8147 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
8148 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
8151 /* continuation for OP_NEW_INSTANCE */
8153 .balign 32 @ minimize cache lines
8154 .LOP_NEW_INSTANCE_finish: @ r0=new object
8155 mov r3, rINST, lsr #8 @ r3<- AA
8156 cmp r0, #0 @ failed?
8157 beq common_exceptionThrown @ yes, handle the exception
8158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8159 GET_INST_OPCODE(ip) @ extract opcode from rINST
8160 SET_VREG(r0, r3) @ vAA<- r0
8161 GOTO_OPCODE(ip) @ jump to next instruction
8164 * Class initialization required.
8166 * r0 holds class object
8168 .LOP_NEW_INSTANCE_needinit:
8169 mov r9, r0 @ save r0
8170 bl dvmInitClass @ initialize class
8171 cmp r0, #0 @ check boolean result
8172 mov r0, r9 @ restore r0
8173 bne .LOP_NEW_INSTANCE_initialized @ success, continue
8174 b common_exceptionThrown @ failed, deal with init exception
8177 * Resolution required. This is the least-likely path.
8181 .LOP_NEW_INSTANCE_resolve:
8182 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8183 mov r2, #0 @ r2<- false
8184 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8185 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8186 cmp r0, #0 @ got null?
8187 bne .LOP_NEW_INSTANCE_resolved @ no, continue
8188 b common_exceptionThrown @ yes, handle exception
8190 .LstrInstantiationErrorPtr:
8191 .word .LstrInstantiationError
8194 /* continuation for OP_NEW_ARRAY */
8198 * Resolve class. (This is an uncommon case.)
8200 * r1 holds array length
8201 * r2 holds class ref CCCC
8203 .LOP_NEW_ARRAY_resolve:
8204 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8205 mov r9, r1 @ r9<- length (save)
8206 mov r1, r2 @ r1<- CCCC
8207 mov r2, #0 @ r2<- false
8208 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8209 bl dvmResolveClass @ r0<- call(clazz, ref)
8210 cmp r0, #0 @ got null?
8211 mov r1, r9 @ r1<- length (restore)
8212 beq common_exceptionThrown @ yes, handle exception
8213 @ fall through to OP_NEW_ARRAY_finish
8216 * Finish allocation.
8219 * r1 holds array length
8221 .LOP_NEW_ARRAY_finish:
8222 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
8223 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
8224 cmp r0, #0 @ failed?
8225 mov r2, rINST, lsr #8 @ r2<- A+
8226 beq common_exceptionThrown @ yes, handle the exception
8227 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8228 and r2, r2, #15 @ r2<- A
8229 GET_INST_OPCODE(ip) @ extract opcode from rINST
8230 SET_VREG(r0, r2) @ vA<- r0
8231 GOTO_OPCODE(ip) @ jump to next instruction
8234 /* continuation for OP_FILLED_NEW_ARRAY */
8238 * r0 holds array class
8239 * r10 holds AA or BA
8241 .LOP_FILLED_NEW_ARRAY_continue:
8242 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8243 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8244 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8246 mov r1, r10 @ r1<- AA (length)
8248 mov r1, r10, lsr #4 @ r1<- B (length)
8250 cmp r3, #'I' @ array of ints?
8251 cmpne r3, #'L' @ array of objects?
8252 cmpne r3, #'[' @ array of arrays?
8253 mov r9, r1 @ save length in r9
8254 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
8255 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8256 cmp r0, #0 @ null return?
8257 beq common_exceptionThrown @ alloc failed, handle exception
8259 FETCH(r1, 2) @ r1<- FEDC or CCCC
8260 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8261 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8262 subs r9, r9, #1 @ length--, check for neg
8263 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8264 bmi 2f @ was zero, bail
8266 @ copy values from registers into the array
8267 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8269 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8270 1: ldr r3, [r2], #4 @ r3<- *r2++
8271 subs r9, r9, #1 @ count--
8272 str r3, [r0], #4 @ *contents++ = vX
8276 cmp r9, #4 @ length was initially 5?
8277 and r2, r10, #15 @ r2<- A
8278 bne 1f @ <= 4 args, branch
8279 GET_VREG(r3, r2) @ r3<- vA
8280 sub r9, r9, #1 @ count--
8281 str r3, [r0, #16] @ contents[4] = vA
8282 1: and r2, r1, #15 @ r2<- F/E/D/C
8283 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8284 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8285 subs r9, r9, #1 @ count--
8286 str r3, [r0], #4 @ *contents++ = vX
8292 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8293 GOTO_OPCODE(ip) @ execute it
8296 * Throw an exception indicating that we have not implemented this
8297 * mode of filled-new-array.
8299 .LOP_FILLED_NEW_ARRAY_notimpl:
8300 ldr r0, .L_strInternalError
8301 ldr r1, .L_strFilledNewArrayNotImpl
8302 bl dvmThrowException
8303 b common_exceptionThrown
8305 .if (!0) @ define in one or the other, not both
8306 .L_strFilledNewArrayNotImpl:
8307 .word .LstrFilledNewArrayNotImpl
8308 .L_strInternalError:
8309 .word .LstrInternalError
8313 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8317 * r0 holds array class
8318 * r10 holds AA or BA
8320 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8321 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8322 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8323 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8325 mov r1, r10 @ r1<- AA (length)
8327 mov r1, r10, lsr #4 @ r1<- B (length)
8329 cmp r3, #'I' @ array of ints?
8330 cmpne r3, #'L' @ array of objects?
8331 cmpne r3, #'[' @ array of arrays?
8332 mov r9, r1 @ save length in r9
8333 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
8334 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8335 cmp r0, #0 @ null return?
8336 beq common_exceptionThrown @ alloc failed, handle exception
8338 FETCH(r1, 2) @ r1<- FEDC or CCCC
8339 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8340 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8341 subs r9, r9, #1 @ length--, check for neg
8342 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8343 bmi 2f @ was zero, bail
8345 @ copy values from registers into the array
8346 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8348 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8349 1: ldr r3, [r2], #4 @ r3<- *r2++
8350 subs r9, r9, #1 @ count--
8351 str r3, [r0], #4 @ *contents++ = vX
8355 cmp r9, #4 @ length was initially 5?
8356 and r2, r10, #15 @ r2<- A
8357 bne 1f @ <= 4 args, branch
8358 GET_VREG(r3, r2) @ r3<- vA
8359 sub r9, r9, #1 @ count--
8360 str r3, [r0, #16] @ contents[4] = vA
8361 1: and r2, r1, #15 @ r2<- F/E/D/C
8362 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8363 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8364 subs r9, r9, #1 @ count--
8365 str r3, [r0], #4 @ *contents++ = vX
8371 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8372 GOTO_OPCODE(ip) @ execute it
8375 * Throw an exception indicating that we have not implemented this
8376 * mode of filled-new-array.
8378 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8379 ldr r0, .L_strInternalError
8380 ldr r1, .L_strFilledNewArrayNotImpl
8381 bl dvmThrowException
8382 b common_exceptionThrown
8384 .if (!1) @ define in one or the other, not both
8385 .L_strFilledNewArrayNotImpl:
8386 .word .LstrFilledNewArrayNotImpl
8387 .L_strInternalError:
8388 .word .LstrInternalError
8392 /* continuation for OP_CMPL_FLOAT */
8394 @ Test for NaN with a second comparison. EABI forbids testing bit
8395 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8396 @ make the library call.
8397 .LOP_CMPL_FLOAT_gt_or_nan:
8398 mov r1, r9 @ reverse order
8400 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8402 movcc r1, #1 @ (greater than) r1<- 1
8403 bcc .LOP_CMPL_FLOAT_finish
8404 mvn r1, #0 @ r1<- 1 or -1 for NaN
8405 b .LOP_CMPL_FLOAT_finish
8408 #if 0 /* "clasic" form */
8409 FETCH(r0, 1) @ r0<- CCBB
8410 and r2, r0, #255 @ r2<- BB
8411 mov r3, r0, lsr #8 @ r3<- CC
8412 GET_VREG(r9, r2) @ r9<- vBB
8413 GET_VREG(r10, r3) @ r10<- vCC
8414 mov r0, r9 @ r0<- vBB
8415 mov r1, r10 @ r1<- vCC
8416 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8418 movne r1, #0 @ yes, result is 0
8419 bne OP_CMPL_FLOAT_finish
8420 mov r0, r9 @ r0<- vBB
8421 mov r1, r10 @ r1<- vCC
8422 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8423 cmp r0, #0 @ less than?
8424 b OP_CMPL_FLOAT_continue
8427 OP_CMPL_FLOAT_continue:
8428 mvnne r1, #0 @ yes, result is -1
8429 bne OP_CMPL_FLOAT_finish
8430 mov r0, r9 @ r0<- vBB
8431 mov r1, r10 @ r1<- vCC
8432 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8433 cmp r0, #0 @ greater than?
8434 beq OP_CMPL_FLOAT_nan @ no, must be NaN
8435 mov r1, #1 @ yes, result is 1
8436 @ fall through to _finish
8438 OP_CMPL_FLOAT_finish:
8439 mov r3, rINST, lsr #8 @ r3<- AA
8440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8441 SET_VREG(r1, r3) @ vAA<- r1
8442 GET_INST_OPCODE(ip) @ extract opcode from rINST
8443 GOTO_OPCODE(ip) @ jump to next instruction
8446 * This is expected to be uncommon, so we double-branch (once to here,
8447 * again back to _finish).
8450 mvn r1, #0 @ r1<- 1 or -1 for NaN
8451 b OP_CMPL_FLOAT_finish
8456 /* continuation for OP_CMPG_FLOAT */
8458 @ Test for NaN with a second comparison. EABI forbids testing bit
8459 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8460 @ make the library call.
8461 .LOP_CMPG_FLOAT_gt_or_nan:
8462 mov r1, r9 @ reverse order
8464 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8466 movcc r1, #1 @ (greater than) r1<- 1
8467 bcc .LOP_CMPG_FLOAT_finish
8468 mov r1, #1 @ r1<- 1 or -1 for NaN
8469 b .LOP_CMPG_FLOAT_finish
8472 #if 0 /* "clasic" form */
8473 FETCH(r0, 1) @ r0<- CCBB
8474 and r2, r0, #255 @ r2<- BB
8475 mov r3, r0, lsr #8 @ r3<- CC
8476 GET_VREG(r9, r2) @ r9<- vBB
8477 GET_VREG(r10, r3) @ r10<- vCC
8478 mov r0, r9 @ r0<- vBB
8479 mov r1, r10 @ r1<- vCC
8480 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8482 movne r1, #0 @ yes, result is 0
8483 bne OP_CMPG_FLOAT_finish
8484 mov r0, r9 @ r0<- vBB
8485 mov r1, r10 @ r1<- vCC
8486 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8487 cmp r0, #0 @ less than?
8488 b OP_CMPG_FLOAT_continue
8491 OP_CMPG_FLOAT_continue:
8492 mvnne r1, #0 @ yes, result is -1
8493 bne OP_CMPG_FLOAT_finish
8494 mov r0, r9 @ r0<- vBB
8495 mov r1, r10 @ r1<- vCC
8496 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8497 cmp r0, #0 @ greater than?
8498 beq OP_CMPG_FLOAT_nan @ no, must be NaN
8499 mov r1, #1 @ yes, result is 1
8500 @ fall through to _finish
8502 OP_CMPG_FLOAT_finish:
8503 mov r3, rINST, lsr #8 @ r3<- AA
8504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8505 SET_VREG(r1, r3) @ vAA<- r1
8506 GET_INST_OPCODE(ip) @ extract opcode from rINST
8507 GOTO_OPCODE(ip) @ jump to next instruction
8510 * This is expected to be uncommon, so we double-branch (once to here,
8511 * again back to _finish).
8514 mov r1, #1 @ r1<- 1 or -1 for NaN
8515 b OP_CMPG_FLOAT_finish
8520 /* continuation for OP_CMPL_DOUBLE */
8522 @ Test for NaN with a second comparison. EABI forbids testing bit
8523 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8524 @ make the library call.
8525 .LOP_CMPL_DOUBLE_gt_or_nan:
8526 ldmia r10, {r0-r1} @ reverse order
8528 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8530 movcc r1, #1 @ (greater than) r1<- 1
8531 bcc .LOP_CMPL_DOUBLE_finish
8532 mvn r1, #0 @ r1<- 1 or -1 for NaN
8533 b .LOP_CMPL_DOUBLE_finish
8536 /* continuation for OP_CMPG_DOUBLE */
8538 @ Test for NaN with a second comparison. EABI forbids testing bit
8539 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8540 @ make the library call.
8541 .LOP_CMPG_DOUBLE_gt_or_nan:
8542 ldmia r10, {r0-r1} @ reverse order
8544 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8546 movcc r1, #1 @ (greater than) r1<- 1
8547 bcc .LOP_CMPG_DOUBLE_finish
8548 mov r1, #1 @ r1<- 1 or -1 for NaN
8549 b .LOP_CMPG_DOUBLE_finish
8552 /* continuation for OP_CMP_LONG */
8555 mvn r1, #0 @ r1<- -1
8556 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8557 @ instead, we just replicate the tail end.
8558 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8559 SET_VREG(r1, r9) @ vAA<- r1
8560 GET_INST_OPCODE(ip) @ extract opcode from rINST
8561 GOTO_OPCODE(ip) @ jump to next instruction
8563 .LOP_CMP_LONG_greater:
8565 @ fall through to _finish
8567 .LOP_CMP_LONG_finish:
8568 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8569 SET_VREG(r1, r9) @ vAA<- r1
8570 GET_INST_OPCODE(ip) @ extract opcode from rINST
8571 GOTO_OPCODE(ip) @ jump to next instruction
8574 /* continuation for OP_AGET_WIDE */
8576 .LOP_AGET_WIDE_finish:
8577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8578 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8579 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8580 GET_INST_OPCODE(ip) @ extract opcode from rINST
8581 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8582 GOTO_OPCODE(ip) @ jump to next instruction
8585 /* continuation for OP_APUT_WIDE */
8587 .LOP_APUT_WIDE_finish:
8588 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8589 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8590 GET_INST_OPCODE(ip) @ extract opcode from rINST
8591 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8592 GOTO_OPCODE(ip) @ jump to next instruction
8595 /* continuation for OP_APUT_OBJECT */
8598 * r1 = vBB (arrayObj)
8600 * r10 = offset into array (vBB + vCC * width)
8602 .LOP_APUT_OBJECT_finish:
8603 cmp r9, #0 @ storing null reference?
8604 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8605 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8606 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz
8607 bl dvmCanPutArrayElement @ test object type vs. array type
8609 beq common_errArrayStore @ no
8610 .LOP_APUT_OBJECT_skip_check:
8611 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8612 GET_INST_OPCODE(ip) @ extract opcode from rINST
8613 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8614 GOTO_OPCODE(ip) @ jump to next instruction
8617 /* continuation for OP_IGET */
8621 * r0 holds resolved field
8626 cmp r9, #0 @ check object for null
8627 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8628 beq common_errNullObject @ object was null
8629 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8630 mov r2, rINST, lsr #8 @ r2<- A+
8631 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8632 and r2, r2, #15 @ r2<- A
8633 GET_INST_OPCODE(ip) @ extract opcode from rINST
8634 SET_VREG(r0, r2) @ fp[A]<- r0
8635 GOTO_OPCODE(ip) @ jump to next instruction
8638 /* continuation for OP_IGET_WIDE */
8642 * r0 holds resolved field
8645 .LOP_IGET_WIDE_finish:
8646 cmp r9, #0 @ check object for null
8647 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8648 beq common_errNullObject @ object was null
8649 mov r2, rINST, lsr #8 @ r2<- A+
8650 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
8651 and r2, r2, #15 @ r2<- A
8652 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8653 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8654 GET_INST_OPCODE(ip) @ extract opcode from rINST
8655 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8656 GOTO_OPCODE(ip) @ jump to next instruction
8659 /* continuation for OP_IGET_OBJECT */
8663 * r0 holds resolved field
8666 .LOP_IGET_OBJECT_finish:
8668 cmp r9, #0 @ check object for null
8669 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8670 beq common_errNullObject @ object was null
8671 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8672 mov r2, rINST, lsr #8 @ r2<- A+
8673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8674 and r2, r2, #15 @ r2<- A
8675 GET_INST_OPCODE(ip) @ extract opcode from rINST
8676 SET_VREG(r0, r2) @ fp[A]<- r0
8677 GOTO_OPCODE(ip) @ jump to next instruction
8680 /* continuation for OP_IGET_BOOLEAN */
8684 * r0 holds resolved field
8687 .LOP_IGET_BOOLEAN_finish:
8689 cmp r9, #0 @ check object for null
8690 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8691 beq common_errNullObject @ object was null
8692 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8693 mov r2, rINST, lsr #8 @ r2<- A+
8694 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8695 and r2, r2, #15 @ r2<- A
8696 GET_INST_OPCODE(ip) @ extract opcode from rINST
8697 SET_VREG(r0, r2) @ fp[A]<- r0
8698 GOTO_OPCODE(ip) @ jump to next instruction
8701 /* continuation for OP_IGET_BYTE */
8705 * r0 holds resolved field
8708 .LOP_IGET_BYTE_finish:
8710 cmp r9, #0 @ check object for null
8711 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8712 beq common_errNullObject @ object was null
8713 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8714 mov r2, rINST, lsr #8 @ r2<- A+
8715 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8716 and r2, r2, #15 @ r2<- A
8717 GET_INST_OPCODE(ip) @ extract opcode from rINST
8718 SET_VREG(r0, r2) @ fp[A]<- r0
8719 GOTO_OPCODE(ip) @ jump to next instruction
8722 /* continuation for OP_IGET_CHAR */
8726 * r0 holds resolved field
8729 .LOP_IGET_CHAR_finish:
8731 cmp r9, #0 @ check object for null
8732 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8733 beq common_errNullObject @ object was null
8734 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8735 mov r2, rINST, lsr #8 @ r2<- A+
8736 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8737 and r2, r2, #15 @ r2<- A
8738 GET_INST_OPCODE(ip) @ extract opcode from rINST
8739 SET_VREG(r0, r2) @ fp[A]<- r0
8740 GOTO_OPCODE(ip) @ jump to next instruction
8743 /* continuation for OP_IGET_SHORT */
8747 * r0 holds resolved field
8750 .LOP_IGET_SHORT_finish:
8752 cmp r9, #0 @ check object for null
8753 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8754 beq common_errNullObject @ object was null
8755 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8756 mov r2, rINST, lsr #8 @ r2<- A+
8757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8758 and r2, r2, #15 @ r2<- A
8759 GET_INST_OPCODE(ip) @ extract opcode from rINST
8760 SET_VREG(r0, r2) @ fp[A]<- r0
8761 GOTO_OPCODE(ip) @ jump to next instruction
8764 /* continuation for OP_IPUT */
8768 * r0 holds resolved field
8773 mov r1, rINST, lsr #8 @ r1<- A+
8774 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8775 and r1, r1, #15 @ r1<- A
8776 cmp r9, #0 @ check object for null
8777 GET_VREG(r0, r1) @ r0<- fp[A]
8778 beq common_errNullObject @ object was null
8779 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8780 GET_INST_OPCODE(ip) @ extract opcode from rINST
8781 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8782 GOTO_OPCODE(ip) @ jump to next instruction
8785 /* continuation for OP_IPUT_WIDE */
8789 * r0 holds resolved field
8792 .LOP_IPUT_WIDE_finish:
8793 mov r2, rINST, lsr #8 @ r2<- A+
8794 cmp r9, #0 @ check object for null
8795 and r2, r2, #15 @ r2<- A
8796 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8797 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8798 beq common_errNullObject @ object was null
8799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8800 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8801 GET_INST_OPCODE(ip) @ extract opcode from rINST
8802 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
8803 GOTO_OPCODE(ip) @ jump to next instruction
8806 /* continuation for OP_IPUT_OBJECT */
8810 * r0 holds resolved field
8813 .LOP_IPUT_OBJECT_finish:
8815 mov r1, rINST, lsr #8 @ r1<- A+
8816 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8817 and r1, r1, #15 @ r1<- A
8818 cmp r9, #0 @ check object for null
8819 GET_VREG(r0, r1) @ r0<- fp[A]
8820 beq common_errNullObject @ object was null
8821 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8822 GET_INST_OPCODE(ip) @ extract opcode from rINST
8823 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8824 GOTO_OPCODE(ip) @ jump to next instruction
8827 /* continuation for OP_IPUT_BOOLEAN */
8831 * r0 holds resolved field
8834 .LOP_IPUT_BOOLEAN_finish:
8836 mov r1, rINST, lsr #8 @ r1<- A+
8837 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8838 and r1, r1, #15 @ r1<- A
8839 cmp r9, #0 @ check object for null
8840 GET_VREG(r0, r1) @ r0<- fp[A]
8841 beq common_errNullObject @ object was null
8842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8843 GET_INST_OPCODE(ip) @ extract opcode from rINST
8844 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8845 GOTO_OPCODE(ip) @ jump to next instruction
8848 /* continuation for OP_IPUT_BYTE */
8852 * r0 holds resolved field
8855 .LOP_IPUT_BYTE_finish:
8857 mov r1, rINST, lsr #8 @ r1<- A+
8858 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8859 and r1, r1, #15 @ r1<- A
8860 cmp r9, #0 @ check object for null
8861 GET_VREG(r0, r1) @ r0<- fp[A]
8862 beq common_errNullObject @ object was null
8863 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8864 GET_INST_OPCODE(ip) @ extract opcode from rINST
8865 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8866 GOTO_OPCODE(ip) @ jump to next instruction
8869 /* continuation for OP_IPUT_CHAR */
8873 * r0 holds resolved field
8876 .LOP_IPUT_CHAR_finish:
8878 mov r1, rINST, lsr #8 @ r1<- A+
8879 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8880 and r1, r1, #15 @ r1<- A
8881 cmp r9, #0 @ check object for null
8882 GET_VREG(r0, r1) @ r0<- fp[A]
8883 beq common_errNullObject @ object was null
8884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8885 GET_INST_OPCODE(ip) @ extract opcode from rINST
8886 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8887 GOTO_OPCODE(ip) @ jump to next instruction
8890 /* continuation for OP_IPUT_SHORT */
8894 * r0 holds resolved field
8897 .LOP_IPUT_SHORT_finish:
8899 mov r1, rINST, lsr #8 @ r1<- A+
8900 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8901 and r1, r1, #15 @ r1<- A
8902 cmp r9, #0 @ check object for null
8903 GET_VREG(r0, r1) @ r0<- fp[A]
8904 beq common_errNullObject @ object was null
8905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8906 GET_INST_OPCODE(ip) @ extract opcode from rINST
8907 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8908 GOTO_OPCODE(ip) @ jump to next instruction
8911 /* continuation for OP_SGET */
8914 * Continuation if the field has not yet been resolved.
8915 * r1: BBBB field ref
8918 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8919 EXPORT_PC() @ resolve() could throw, so export now
8920 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8921 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8922 cmp r0, #0 @ success?
8923 bne .LOP_SGET_finish @ yes, finish
8924 b common_exceptionThrown @ no, handle exception
8927 /* continuation for OP_SGET_WIDE */
8930 * Continuation if the field has not yet been resolved.
8931 * r1: BBBB field ref
8933 .LOP_SGET_WIDE_resolve:
8934 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8935 EXPORT_PC() @ resolve() could throw, so export now
8936 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8937 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8938 cmp r0, #0 @ success?
8939 bne .LOP_SGET_WIDE_finish @ yes, finish
8940 b common_exceptionThrown @ no, handle exception
8943 /* continuation for OP_SGET_OBJECT */
8946 * Continuation if the field has not yet been resolved.
8947 * r1: BBBB field ref
8949 .LOP_SGET_OBJECT_resolve:
8950 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8951 EXPORT_PC() @ resolve() could throw, so export now
8952 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8953 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8954 cmp r0, #0 @ success?
8955 bne .LOP_SGET_OBJECT_finish @ yes, finish
8956 b common_exceptionThrown @ no, handle exception
8959 /* continuation for OP_SGET_BOOLEAN */
8962 * Continuation if the field has not yet been resolved.
8963 * r1: BBBB field ref
8965 .LOP_SGET_BOOLEAN_resolve:
8966 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8967 EXPORT_PC() @ resolve() could throw, so export now
8968 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8969 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8970 cmp r0, #0 @ success?
8971 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
8972 b common_exceptionThrown @ no, handle exception
8975 /* continuation for OP_SGET_BYTE */
8978 * Continuation if the field has not yet been resolved.
8979 * r1: BBBB field ref
8981 .LOP_SGET_BYTE_resolve:
8982 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8983 EXPORT_PC() @ resolve() could throw, so export now
8984 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8985 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8986 cmp r0, #0 @ success?
8987 bne .LOP_SGET_BYTE_finish @ yes, finish
8988 b common_exceptionThrown @ no, handle exception
8991 /* continuation for OP_SGET_CHAR */
8994 * Continuation if the field has not yet been resolved.
8995 * r1: BBBB field ref
8997 .LOP_SGET_CHAR_resolve:
8998 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8999 EXPORT_PC() @ resolve() could throw, so export now
9000 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9001 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9002 cmp r0, #0 @ success?
9003 bne .LOP_SGET_CHAR_finish @ yes, finish
9004 b common_exceptionThrown @ no, handle exception
9007 /* continuation for OP_SGET_SHORT */
9010 * Continuation if the field has not yet been resolved.
9011 * r1: BBBB field ref
9013 .LOP_SGET_SHORT_resolve:
9014 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9015 EXPORT_PC() @ resolve() could throw, so export now
9016 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9017 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9018 cmp r0, #0 @ success?
9019 bne .LOP_SGET_SHORT_finish @ yes, finish
9020 b common_exceptionThrown @ no, handle exception
9023 /* continuation for OP_SPUT */
9026 * Continuation if the field has not yet been resolved.
9027 * r1: BBBB field ref
9030 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9031 EXPORT_PC() @ resolve() could throw, so export now
9032 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9033 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9034 cmp r0, #0 @ success?
9035 bne .LOP_SPUT_finish @ yes, finish
9036 b common_exceptionThrown @ no, handle exception
9039 /* continuation for OP_SPUT_WIDE */
9042 * Continuation if the field has not yet been resolved.
9043 * r1: BBBB field ref
9046 .LOP_SPUT_WIDE_resolve:
9047 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9048 EXPORT_PC() @ resolve() could throw, so export now
9049 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9050 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9051 cmp r0, #0 @ success?
9052 bne .LOP_SPUT_WIDE_finish @ yes, finish
9053 b common_exceptionThrown @ no, handle exception
9056 /* continuation for OP_SPUT_OBJECT */
9059 * Continuation if the field has not yet been resolved.
9060 * r1: BBBB field ref
9062 .LOP_SPUT_OBJECT_resolve:
9063 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9064 EXPORT_PC() @ resolve() could throw, so export now
9065 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9066 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9067 cmp r0, #0 @ success?
9068 bne .LOP_SPUT_OBJECT_finish @ yes, finish
9069 b common_exceptionThrown @ no, handle exception
9072 /* continuation for OP_SPUT_BOOLEAN */
9075 * Continuation if the field has not yet been resolved.
9076 * r1: BBBB field ref
9078 .LOP_SPUT_BOOLEAN_resolve:
9079 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9080 EXPORT_PC() @ resolve() could throw, so export now
9081 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9082 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9083 cmp r0, #0 @ success?
9084 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
9085 b common_exceptionThrown @ no, handle exception
9088 /* continuation for OP_SPUT_BYTE */
9091 * Continuation if the field has not yet been resolved.
9092 * r1: BBBB field ref
9094 .LOP_SPUT_BYTE_resolve:
9095 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9096 EXPORT_PC() @ resolve() could throw, so export now
9097 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9098 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9099 cmp r0, #0 @ success?
9100 bne .LOP_SPUT_BYTE_finish @ yes, finish
9101 b common_exceptionThrown @ no, handle exception
9104 /* continuation for OP_SPUT_CHAR */
9107 * Continuation if the field has not yet been resolved.
9108 * r1: BBBB field ref
9110 .LOP_SPUT_CHAR_resolve:
9111 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9112 EXPORT_PC() @ resolve() could throw, so export now
9113 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9114 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9115 cmp r0, #0 @ success?
9116 bne .LOP_SPUT_CHAR_finish @ yes, finish
9117 b common_exceptionThrown @ no, handle exception
9120 /* continuation for OP_SPUT_SHORT */
9123 * Continuation if the field has not yet been resolved.
9124 * r1: BBBB field ref
9126 .LOP_SPUT_SHORT_resolve:
9127 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9128 EXPORT_PC() @ resolve() could throw, so export now
9129 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9130 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9131 cmp r0, #0 @ success?
9132 bne .LOP_SPUT_SHORT_finish @ yes, finish
9133 b common_exceptionThrown @ no, handle exception
9136 /* continuation for OP_INVOKE_VIRTUAL */
9140 * r0 = resolved base method
9141 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
9143 .LOP_INVOKE_VIRTUAL_continue:
9144 GET_VREG(r1, r10) @ r1<- "this" ptr
9145 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9146 cmp r1, #0 @ is "this" null?
9147 beq common_errNullObject @ null "this", throw exception
9148 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
9149 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
9150 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
9151 bl common_invokeMethodNoRange @ continue on
9154 /* continuation for OP_INVOKE_SUPER */
9158 * r0 = resolved base method
9159 * r9 = method->clazz
9161 .LOP_INVOKE_SUPER_continue:
9162 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
9163 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9164 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
9165 EXPORT_PC() @ must export for invoke
9166 cmp r2, r3 @ compare (methodIndex, vtableCount)
9167 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
9168 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
9169 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
9170 bl common_invokeMethodNoRange @ continue on
9172 .LOP_INVOKE_SUPER_resolve:
9173 mov r0, r9 @ r0<- method->clazz
9174 mov r2, #METHOD_VIRTUAL @ resolver method type
9175 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9176 cmp r0, #0 @ got null?
9177 bne .LOP_INVOKE_SUPER_continue @ no, continue
9178 b common_exceptionThrown @ yes, handle exception
9181 * Throw a NoSuchMethodError with the method name as the message.
9182 * r0 = resolved base method
9184 .LOP_INVOKE_SUPER_nsm:
9185 ldr r1, [r0, #offMethod_name] @ r1<- method name
9186 b common_errNoSuchMethod
9189 /* continuation for OP_INVOKE_DIRECT */
9193 * r1 = reference (BBBB or CCCC)
9194 * r10 = "this" register
9196 .LOP_INVOKE_DIRECT_resolve:
9197 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9198 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9199 mov r2, #METHOD_DIRECT @ resolver method type
9200 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9201 cmp r0, #0 @ got null?
9202 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9203 bne .LOP_INVOKE_DIRECT_finish @ no, continue
9204 b common_exceptionThrown @ yes, handle exception
9207 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9211 * r0 = resolved base method
9212 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
9214 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9215 GET_VREG(r1, r10) @ r1<- "this" ptr
9216 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9217 cmp r1, #0 @ is "this" null?
9218 beq common_errNullObject @ null "this", throw exception
9219 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
9220 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
9221 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
9222 bl common_invokeMethodRange @ continue on
9225 /* continuation for OP_INVOKE_SUPER_RANGE */
9229 * r0 = resolved base method
9230 * r9 = method->clazz
9232 .LOP_INVOKE_SUPER_RANGE_continue:
9233 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
9234 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9235 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
9236 EXPORT_PC() @ must export for invoke
9237 cmp r2, r3 @ compare (methodIndex, vtableCount)
9238 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
9239 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
9240 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
9241 bl common_invokeMethodRange @ continue on
9243 .LOP_INVOKE_SUPER_RANGE_resolve:
9244 mov r0, r9 @ r0<- method->clazz
9245 mov r2, #METHOD_VIRTUAL @ resolver method type
9246 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9247 cmp r0, #0 @ got null?
9248 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
9249 b common_exceptionThrown @ yes, handle exception
9252 * Throw a NoSuchMethodError with the method name as the message.
9253 * r0 = resolved base method
9255 .LOP_INVOKE_SUPER_RANGE_nsm:
9256 ldr r1, [r0, #offMethod_name] @ r1<- method name
9257 b common_errNoSuchMethod
9260 /* continuation for OP_INVOKE_DIRECT_RANGE */
9264 * r1 = reference (BBBB or CCCC)
9265 * r10 = "this" register
9267 .LOP_INVOKE_DIRECT_RANGE_resolve:
9268 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9269 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9270 mov r2, #METHOD_DIRECT @ resolver method type
9271 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9272 cmp r0, #0 @ got null?
9273 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9274 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
9275 b common_exceptionThrown @ yes, handle exception
9278 /* continuation for OP_FLOAT_TO_LONG */
9280 * Convert the float in r0 to a long in r0/r1.
9282 * We have to clip values to long min/max per the specification. The
9283 * expected common case is a "reasonable" value that converts directly
9284 * to modest integer. The EABI convert function isn't doing this for us.
9288 mov r1, #0x5f000000 @ (float)maxlong
9290 bl __aeabi_fcmpge @ is arg >= maxlong?
9291 cmp r0, #0 @ nonzero == yes
9292 mvnne r0, #0 @ return maxlong (7fffffff)
9293 mvnne r1, #0x80000000
9294 ldmnefd sp!, {r4, pc}
9296 mov r0, r4 @ recover arg
9297 mov r1, #0xdf000000 @ (float)minlong
9298 bl __aeabi_fcmple @ is arg <= minlong?
9299 cmp r0, #0 @ nonzero == yes
9300 movne r0, #0 @ return minlong (80000000)
9301 movne r1, #0x80000000
9302 ldmnefd sp!, {r4, pc}
9304 mov r0, r4 @ recover arg
9306 bl __aeabi_fcmpeq @ is arg == self?
9307 cmp r0, #0 @ zero == no
9308 moveq r1, #0 @ return zero for NaN
9309 ldmeqfd sp!, {r4, pc}
9311 mov r0, r4 @ recover arg
9312 bl __aeabi_f2lz @ convert float to long
9316 /* continuation for OP_DOUBLE_TO_LONG */
9318 * Convert the double in r0/r1 to a long in r0/r1.
9320 * We have to clip values to long min/max per the specification. The
9321 * expected common case is a "reasonable" value that converts directly
9322 * to modest integer. The EABI convert function isn't doing this for us.
9325 stmfd sp!, {r4, r5, lr} @ save regs
9326 mov r3, #0x43000000 @ maxlong, as a double (high word)
9327 add r3, #0x00e00000 @ 0x43e00000
9328 mov r2, #0 @ maxlong, as a double (low word)
9329 sub sp, sp, #4 @ align for EABI
9330 mov r4, r0 @ save a copy of r0
9332 bl __aeabi_dcmpge @ is arg >= maxlong?
9333 cmp r0, #0 @ nonzero == yes
9334 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
9335 mvnne r1, #0x80000000
9338 mov r0, r4 @ recover arg
9340 mov r3, #0xc3000000 @ minlong, as a double (high word)
9341 add r3, #0x00e00000 @ 0xc3e00000
9342 mov r2, #0 @ minlong, as a double (low word)
9343 bl __aeabi_dcmple @ is arg <= minlong?
9344 cmp r0, #0 @ nonzero == yes
9345 movne r0, #0 @ return minlong (8000000000000000)
9346 movne r1, #0x80000000
9349 mov r0, r4 @ recover arg
9351 mov r2, r4 @ compare against self
9353 bl __aeabi_dcmpeq @ is arg == self?
9354 cmp r0, #0 @ zero == no
9355 moveq r1, #0 @ return zero for NaN
9358 mov r0, r4 @ recover arg
9360 bl __aeabi_d2lz @ convert double to long
9364 ldmfd sp!, {r4, r5, pc}
9367 /* continuation for OP_MUL_LONG */
9369 .LOP_MUL_LONG_finish:
9370 GET_INST_OPCODE(ip) @ extract opcode from rINST
9371 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
9372 GOTO_OPCODE(ip) @ jump to next instruction
9375 /* continuation for OP_SHL_LONG */
9377 .LOP_SHL_LONG_finish:
9378 mov r0, r0, asl r2 @ r0<- r0 << r2
9379 GET_INST_OPCODE(ip) @ extract opcode from rINST
9380 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9381 GOTO_OPCODE(ip) @ jump to next instruction
9384 /* continuation for OP_SHR_LONG */
9386 .LOP_SHR_LONG_finish:
9387 mov r1, r1, asr r2 @ r1<- r1 >> r2
9388 GET_INST_OPCODE(ip) @ extract opcode from rINST
9389 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9390 GOTO_OPCODE(ip) @ jump to next instruction
9393 /* continuation for OP_USHR_LONG */
9395 .LOP_USHR_LONG_finish:
9396 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
9397 GET_INST_OPCODE(ip) @ extract opcode from rINST
9398 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9399 GOTO_OPCODE(ip) @ jump to next instruction
9402 /* continuation for OP_SHL_LONG_2ADDR */
9404 .LOP_SHL_LONG_2ADDR_finish:
9405 GET_INST_OPCODE(ip) @ extract opcode from rINST
9406 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9407 GOTO_OPCODE(ip) @ jump to next instruction
9410 /* continuation for OP_SHR_LONG_2ADDR */
9412 .LOP_SHR_LONG_2ADDR_finish:
9413 GET_INST_OPCODE(ip) @ extract opcode from rINST
9414 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9415 GOTO_OPCODE(ip) @ jump to next instruction
9418 /* continuation for OP_USHR_LONG_2ADDR */
9420 .LOP_USHR_LONG_2ADDR_finish:
9421 GET_INST_OPCODE(ip) @ extract opcode from rINST
9422 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9423 GOTO_OPCODE(ip) @ jump to next instruction
9426 /* continuation for OP_EXECUTE_INLINE */
9429 * Extract args, call function.
9430 * r0 = #of args (0-4)
9432 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9435 * - Use a jump table from the main piece to jump directly into the
9436 * AND/LDR pairs. Costs a data load, saves a branch.
9437 * - Have five separate pieces that do the loading, so we can work the
9438 * interleave a little better. Increases code size.
9440 .LOP_EXECUTE_INLINE_continue:
9441 rsb r0, r0, #4 @ r0<- 4-r0
9442 FETCH(r9, 2) @ r9<- FEDC
9443 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9444 bl common_abort @ (skipped due to ARM prefetch)
9445 4: and ip, r9, #0xf000 @ isolate F
9446 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
9447 3: and ip, r9, #0x0f00 @ isolate E
9448 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
9449 2: and ip, r9, #0x00f0 @ isolate D
9450 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
9451 1: and ip, r9, #0x000f @ isolate C
9452 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
9454 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
9455 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9458 .LOP_EXECUTE_INLINE_table:
9459 .word gDvmInlineOpsTable
9462 .size dvmAsmSisterStart, .-dvmAsmSisterStart
9463 .global dvmAsmSisterEnd
9466 /* File: armv5te/footer.S */
9469 * ===========================================================================
9470 * Common subroutines and data
9471 * ===========================================================================
9479 #if defined(WITH_JIT)
9480 #if defined(WITH_SELF_VERIFICATION)
9481 .global dvmJitToInterpPunt
9483 mov r2,#kSVSPunt @ r2<- interpreter entry point
9484 b dvmJitSelfVerificationEnd @ doesn't return
9486 .global dvmJitToInterpSingleStep
9487 dvmJitToInterpSingleStep:
9488 mov r2,#kSVSSingleStep @ r2<- interpreter entry point
9489 b dvmJitSelfVerificationEnd @ doesn't return
9491 .global dvmJitToTraceSelect
9492 dvmJitToTraceSelect:
9493 ldr r0,[r14, #-1] @ pass our target PC
9494 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
9495 b dvmJitSelfVerificationEnd @ doesn't return
9497 .global dvmJitToBackwardBranch
9498 dvmJitToBackwardBranch:
9499 ldr r0,[r14, #-1] @ pass our target PC
9500 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
9501 b dvmJitSelfVerificationEnd @ doesn't return
9503 .global dvmJitToInterpNormal
9504 dvmJitToInterpNormal:
9505 ldr r0,[r14, #-1] @ pass our target PC
9506 mov r2,#kSVSNormal @ r2<- interpreter entry point
9507 b dvmJitSelfVerificationEnd @ doesn't return
9509 .global dvmJitToInterpNoChain
9510 dvmJitToInterpNoChain:
9511 mov r0,rPC @ pass our target PC
9512 mov r2,#kSVSNoChain @ r2<- interpreter entry point
9513 b dvmJitSelfVerificationEnd @ doesn't return
9516 * Return from the translation cache to the interpreter when the compiler is
9517 * having issues translating/executing a Dalvik instruction. We have to skip
9518 * the code cache lookup otherwise it is possible to indefinitely bouce
9519 * between the interpreter and the code cache if the instruction that fails
9520 * to be compiled happens to be at a trace start.
9522 .global dvmJitToInterpPunt
9530 adrl rIBASE, dvmAsmInstructionStart
9536 * Return to the interpreter to handle a single instruction.
9539 * r1 <= PC of resume instruction
9540 * lr <= resume point in translation
9542 .global dvmJitToInterpSingleStep
9543 dvmJitToInterpSingleStep:
9544 str lr,[rGLUE,#offGlue_jitResume]
9545 str r1,[rGLUE,#offGlue_jitResumePC]
9546 mov r1,#kInterpEntryInstr
9547 @ enum is 4 byte in aapcs-EABI
9548 str r1, [rGLUE, #offGlue_entryPoint]
9551 adrl rIBASE, dvmAsmInstructionStart
9552 mov r2,#kJitSingleStep @ Ask for single step and then revert
9553 str r2,[rGLUE,#offGlue_jitState]
9554 mov r1,#1 @ set changeInterp to bail to debug interp
9559 * Return from the translation cache and immediately request
9560 * a translation for the exit target. Commonly used following
9563 .global dvmJitToTraceSelect
9564 dvmJitToTraceSelect:
9565 ldr rPC,[r14, #-1] @ get our target PC
9566 add rINST,r14,#-5 @ save start of chain branch
9568 bl dvmJitGetCodeAddr @ Is there a translation?
9572 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9573 cmp r0,#0 @ successful chain?
9574 bxne r0 @ continue native execution
9575 b toInterpreter @ didn't chain - resume with interpreter
9577 /* No translation, so request one if profiling isn't disabled*/
9579 adrl rIBASE, dvmAsmInstructionStart
9580 GET_JIT_PROF_TABLE(r0)
9583 bne common_selectTrace
9588 * Return from the translation cache to the interpreter.
9589 * The return was done with a BLX from thumb mode, and
9590 * the following 32-bit word contains the target rPC value.
9591 * Note that lr (r14) will have its low-order bit set to denote
9592 * its thumb-mode origin.
9594 * We'll need to stash our lr origin away, recover the new
9595 * target and then check to see if there is a translation available
9596 * for our new target. If so, we do a translation chain and
9597 * go back to native execution. Otherwise, it's back to the
9598 * interpreter (after treating this entry as a potential
9601 .global dvmJitToInterpNormal
9602 dvmJitToInterpNormal:
9603 ldr rPC,[r14, #-1] @ get our target PC
9604 add rINST,r14,#-5 @ save start of chain branch
9609 bl dvmJitGetCodeAddr @ Is there a translation?
9611 beq toInterpreter @ go if not, otherwise do chain
9613 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9614 cmp r0,#0 @ successful chain?
9615 bxne r0 @ continue native execution
9616 b toInterpreter @ didn't chain - resume with interpreter
9619 * Return from the translation cache to the interpreter to do method invocation.
9620 * Check if translation exists for the callee, but don't chain to it.
9622 .global dvmJitToInterpNoChain
9623 dvmJitToInterpNoChain:
9628 bl dvmJitGetCodeAddr @ Is there a translation?
9630 bxne r0 @ continue native execution if so
9634 * No translation, restore interpreter regs and start interpreting.
9635 * rGLUE & rFP were preserved in the translated code, and rPC has
9636 * already been restored by the time we get here. We'll need to set
9637 * up rIBASE & rINST, and load the address of the JitTable into r0.
9641 adrl rIBASE, dvmAsmInstructionStart
9643 GET_JIT_PROF_TABLE(r0)
9644 @ NOTE: intended fallthrough
9646 * Common code to update potential trace start counter, and initiate
9647 * a trace-build if appropriate. On entry, rPC should point to the
9648 * next instruction to execute, and rINST should be already loaded with
9649 * the next opcode word, and r0 holds a pointer to the jit profile
9650 * table (pJitProfTable).
9652 common_testUpdateProfile:
9655 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */
9657 common_updateProfile:
9658 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9659 lsl r3,r3,#23 @ shift out excess 511
9660 ldrb r1,[r0,r3,lsr #23] @ get counter
9662 subs r1,r1,#1 @ decrement counter
9663 strb r1,[r0,r3,lsr #23] @ and store it
9664 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
9667 * Here, we switch to the debug interpreter to request
9668 * trace selection. First, though, check to see if there
9669 * is already a native translation in place (and, if so,
9673 strb r1,[r0,r3,lsr #23] @ reset counter
9676 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
9678 beq common_selectTrace
9679 #if !defined(WITH_SELF_VERIFICATION)
9680 bxne r0 @ jump to the translation
9682 bne dvmJitSelfVerificationStart @ set up self verification
9685 mov r2,#kJitTSelectRequest @ ask for trace selection
9686 str r2,[rGLUE,#offGlue_jitState]
9687 mov r2,#kInterpEntryInstr @ normal entry reason
9688 str r2,[rGLUE,#offGlue_entryPoint]
9689 mov r1,#1 @ set changeInterp
9692 #if defined(WITH_SELF_VERIFICATION)
9694 * Save PC and registers to shadow memory for self verification mode
9695 * before jumping to native translation.
9697 dvmJitSelfVerificationStart:
9698 sub sp,sp,#4 @ allocate stack space
9699 str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
9700 mov r0,rPC @ r0<- program counter
9701 mov r1,rFP @ r1<- frame pointer
9702 mov r2,rGLUE @ r2<- InterpState pointer
9703 bl dvmSelfVerificationSaveState @ save registers to shadow space
9704 ldr rFP,[r0,#20] @ rFP<- fp in shadow space
9705 add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
9706 ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
9707 add sp,sp,#4 @ restore stack
9708 bx r0 @ jump to the translation
9711 * Restore PC, registers, and interpState to original values
9712 * before jumping back to the interpreter.
9714 dvmJitSelfVerificationEnd:
9715 mov r1,rFP @ pass ending fp
9716 bl dvmSelfVerificationRestoreState @ restore pc and fp values
9717 ldr rPC,[r0,#0] @ restore PC
9718 ldr rFP,[r0,#4] @ restore FP
9719 ldr rGLUE,[r0,#8] @ restore InterpState
9720 ldr r1,[r0,#12] @ get exitPoint
9721 cmp r1,#0 @ check for punt condition
9723 mov r2,#kJitSelfVerification @ ask for self verification
9724 str r2,[rGLUE,#offGlue_jitState]
9725 mov r2,#kInterpEntryInstr @ normal entry reason
9726 str r2,[rGLUE,#offGlue_entryPoint]
9727 mov r1,#1 @ set changeInterp
9730 1: @ exit to interpreter without check
9732 adrl rIBASE, dvmAsmInstructionStart
9741 * Common code when a backward branch is taken.
9744 * r9 is PC adjustment *in bytes*
9746 common_backwardBranch:
9747 mov r0, #kInterpEntryInstr
9748 bl common_periodicChecks
9749 #if defined(WITH_JIT)
9750 GET_JIT_PROF_TABLE(r0)
9751 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9753 bne common_updateProfile
9757 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9758 GET_INST_OPCODE(ip) @ extract opcode from rINST
9759 GOTO_OPCODE(ip) @ jump to next instruction
9764 * Need to see if the thread needs to be suspended or debugger/profiler
9765 * activity has begun.
9767 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9768 * have to do the second ldr.
9770 * TODO: reduce this so we're just checking a single location.
9773 * r0 is reentry type, e.g. kInterpEntryInstr
9774 * r9 is trampoline PC adjustment *in bytes*
9776 common_periodicChecks:
9777 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9779 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9780 str r0, [rGLUE, #offGlue_entryPoint]
9782 #if defined(WITH_DEBUGGER)
9783 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9785 #if defined(WITH_PROFILER)
9786 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9789 ldr r3, [r3] @ r3<- suspendCount (int)
9791 #if defined(WITH_DEBUGGER)
9792 ldrb r1, [r1] @ r1<- debuggerActive (boolean)
9794 #if defined (WITH_PROFILER)
9795 ldr r2, [r2] @ r2<- activeProfilers (int)
9798 cmp r3, #0 @ suspend pending?
9799 bne 2f @ yes, do full suspension check
9801 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9802 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9803 orrs r1, r1, r2 @ r1<- r1 | r2
9804 cmp r1, #0 @ debugger attached or profiler started?
9805 # elif defined(WITH_DEBUGGER)
9806 cmp r1, #0 @ debugger attached?
9807 # elif defined(WITH_PROFILER)
9808 cmp r2, #0 @ profiler started?
9810 bne 3f @ debugger/profiler, switch interp
9813 bx lr @ nothing to do, return
9816 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9817 EXPORT_PC() @ need for precise GC
9818 b dvmCheckSuspendPending @ suspend if necessary, then return
9820 3: @ debugger/profiler enabled, bail out
9821 add rPC, rPC, r9 @ update rPC
9822 mov r1, #1 @ "want switch" = true
9827 * The equivalent of "goto bail", this calls through the "bail handler".
9829 * State registers will be saved to the "glue" area before bailing.
9832 * r1 is "bool changeInterp", indicating if we want to switch to the
9833 * other interpreter or just bail all the way out
9836 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9837 mov r0, rGLUE @ r0<- glue ptr
9838 b dvmMterpStdBail @ call(glue, changeInterp)
9840 @add r1, r1, #1 @ using (boolean+1)
9841 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9842 @bl _longjmp @ does not return
9847 * Common code for method invocation with range.
9850 * r0 is "Method* methodToCall", the method we're trying to call
9852 common_invokeMethodRange:
9854 @ prepare to copy args to "outs" area of current frame
9855 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9856 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9857 beq .LinvokeArgsDone @ if no args, skip the rest
9858 FETCH(r1, 2) @ r1<- CCCC
9860 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9861 @ (very few methods have > 10 args; could unroll for common cases)
9862 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9863 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9864 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9865 1: ldr r1, [r3], #4 @ val = *fp++
9866 subs r2, r2, #1 @ count--
9867 str r1, [r10], #4 @ *outs++ = val
9868 bne 1b @ ...while count != 0
9869 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9873 * Common code for method invocation without range.
9876 * r0 is "Method* methodToCall", the method we're trying to call
9878 common_invokeMethodNoRange:
9880 @ prepare to copy args to "outs" area of current frame
9881 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9882 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9883 FETCH(r1, 2) @ r1<- GFED (load here to hide latency)
9884 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9885 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9886 beq .LinvokeArgsDone
9888 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9890 rsb r2, r2, #5 @ r2<- 5-r2
9891 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
9892 bl common_abort @ (skipped due to ARM prefetch)
9893 5: and ip, rINST, #0x0f00 @ isolate A
9894 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2)
9896 str r2, [r10, #-4]! @ *--outs = vA
9897 4: and ip, r1, #0xf000 @ isolate G
9898 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2)
9900 str r2, [r10, #-4]! @ *--outs = vG
9901 3: and ip, r1, #0x0f00 @ isolate F
9902 ldr r2, [rFP, ip, lsr #6] @ r2<- vF
9904 str r2, [r10, #-4]! @ *--outs = vF
9905 2: and ip, r1, #0x00f0 @ isolate E
9906 ldr r2, [rFP, ip, lsr #2] @ r2<- vE
9908 str r2, [r10, #-4]! @ *--outs = vE
9909 1: and ip, r1, #0x000f @ isolate D
9910 ldr r2, [rFP, ip, lsl #2] @ r2<- vD
9912 str r2, [r10, #-4]! @ *--outs = vD
9913 0: @ fall through to .LinvokeArgsDone
9915 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9916 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns
9917 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz
9918 @ find space for the new stack frame, check for overflow
9919 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
9920 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize)
9921 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
9922 @ bl common_dumpRegs
9923 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
9924 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
9925 cmp r3, r9 @ bottom < interpStackEnd?
9926 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9927 blt .LstackOverflow @ yes, this frame will overflow stack
9929 @ set up newSaveArea
9931 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
9932 str ip, [r10, #offStackSaveArea_prevSave]
9934 str rFP, [r10, #offStackSaveArea_prevFrame]
9935 str rPC, [r10, #offStackSaveArea_savedPc]
9936 #if defined(WITH_JIT)
9938 str r9, [r10, #offStackSaveArea_returnAddr]
9940 str r0, [r10, #offStackSaveArea_method]
9946 bl common_printNewline
9955 bl common_printNewline
9959 ldrh r9, [r2] @ r9 <- load INST from new PC
9960 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9961 mov rPC, r2 @ publish new rPC
9962 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
9964 @ Update "glue" values for the new method
9965 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9966 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
9967 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9968 #if defined(WITH_JIT)
9969 GET_JIT_PROF_TABLE(r0)
9970 mov rFP, r1 @ fp = newFp
9971 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9972 mov rINST, r9 @ publish new rINST
9973 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9975 bne common_updateProfile
9976 GOTO_OPCODE(ip) @ jump to next instruction
9978 mov rFP, r1 @ fp = newFp
9979 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9980 mov rINST, r9 @ publish new rINST
9981 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9982 GOTO_OPCODE(ip) @ jump to next instruction
9986 @ Prep for the native call
9987 @ r0=methodToCall, r1=newFp, r10=newSaveArea
9988 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9989 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9990 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
9991 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9992 mov r9, r3 @ r9<- glue->self (preserve)
9994 mov r2, r0 @ r2<- methodToCall
9995 mov r0, r1 @ r0<- newFp (points to args)
9996 add r1, rGLUE, #offGlue_retval @ r1<- &retval
9998 #ifdef ASSIST_DEBUGGER
9999 /* insert fake function header to help gdb find the stack frame */
10001 .type dalvik_mterp, %function
10009 @mov lr, pc @ set return addr
10010 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10011 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10013 @ native return; r9=self, r10=newSaveArea
10014 @ equivalent to dvmPopJniLocals
10015 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10016 ldr r1, [r9, #offThread_exception] @ check for exception
10017 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
10019 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10020 bne common_exceptionThrown @ no, handle exception
10022 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
10023 GET_INST_OPCODE(ip) @ extract opcode from rINST
10024 GOTO_OPCODE(ip) @ jump to next instruction
10026 .LstackOverflow: @ r0=methodToCall
10027 mov r1, r0 @ r1<- methodToCall
10028 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
10029 bl dvmHandleStackOverflow
10030 b common_exceptionThrown
10031 #ifdef ASSIST_DEBUGGER
10037 * Common code for method invocation, calling through "glue code".
10039 * TODO: now that we have range and non-range invoke handlers, this
10040 * needs to be split into two. Maybe just create entry points
10041 * that set r9 and jump here?
10044 * r0 is "Method* methodToCall", the method we're trying to call
10045 * r9 is "bool methodCallRange", indicating if this is a /range variant
10049 sub sp, sp, #8 @ space for args + pad
10050 FETCH(ip, 2) @ ip<- FEDC or CCCC
10051 mov r2, r0 @ A2<- methodToCall
10052 mov r0, rGLUE @ A0<- glue
10053 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
10054 mov r1, r9 @ A1<- methodCallRange
10055 mov r3, rINST, lsr #8 @ A3<- AA
10056 str ip, [sp, #0] @ A4<- ip
10057 bl dvmMterp_invokeMethod @ call the C invokeMethod
10058 add sp, sp, #8 @ remove arg area
10059 b common_resumeAfterGlueCall @ continue to next instruction
10065 * Common code for handling a return instruction.
10067 * This does not return.
10069 common_returnFromMethod:
10071 mov r0, #kInterpEntryReturn
10073 bl common_periodicChecks
10075 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
10076 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10077 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10078 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10079 @ r2<- method we're returning to
10080 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
10081 cmp r2, #0 @ is this a break frame?
10082 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10083 mov r1, #0 @ "want switch" = false
10084 beq common_gotoBail @ break frame, bail out completely
10086 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10087 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10088 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
10089 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
10090 #if defined(WITH_JIT)
10091 ldr r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
10092 GET_JIT_PROF_TABLE(r0)
10093 mov rPC, r9 @ publish new rPC
10094 str r1, [rGLUE, #offGlue_methodClassDex]
10095 cmp r3, #0 @ caller is compiled code
10097 GET_INST_OPCODE(ip) @ extract opcode from rINST
10099 bne common_updateProfile
10100 GOTO_OPCODE(ip) @ jump to next instruction
10102 GET_INST_OPCODE(ip) @ extract opcode from rINST
10103 mov rPC, r9 @ publish new rPC
10104 str r1, [rGLUE, #offGlue_methodClassDex]
10105 GOTO_OPCODE(ip) @ jump to next instruction
10109 * Return handling, calls through "glue code".
10113 SAVE_PC_FP_TO_GLUE() @ export state
10114 mov r0, rGLUE @ arg to function
10115 bl dvmMterp_returnFromMethod
10116 b common_resumeAfterGlueCall
10121 * Somebody has thrown an exception. Handle it.
10123 * If the exception processing code returns to us (instead of falling
10124 * out of the interpreter), continue with whatever the next instruction
10125 * now happens to be.
10127 * This does not return.
10129 .global dvmMterpCommonExceptionThrown
10130 dvmMterpCommonExceptionThrown:
10131 common_exceptionThrown:
10133 mov r0, #kInterpEntryThrow
10135 bl common_periodicChecks
10137 #if defined(WITH_JIT)
10138 mov r2,#kJitTSelectAbort @ abandon trace selection in progress
10139 str r2,[rGLUE,#offGlue_jitState]
10142 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10143 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
10144 mov r1, r10 @ r1<- self
10145 mov r0, r9 @ r0<- exception
10146 bl dvmAddTrackedAlloc @ don't let the exception be GCed
10147 mov r3, #0 @ r3<- NULL
10148 str r3, [r10, #offThread_exception] @ self->exception = NULL
10150 /* set up args and a local for "&fp" */
10151 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
10152 str rFP, [sp, #-4]! @ *--sp = fp
10153 mov ip, sp @ ip<- &fp
10154 mov r3, #0 @ r3<- false
10155 str ip, [sp, #-4]! @ *--sp = &fp
10156 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10157 mov r0, r10 @ r0<- self
10158 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
10159 mov r2, r9 @ r2<- exception
10160 sub r1, rPC, r1 @ r1<- pc - method->insns
10161 mov r1, r1, asr #1 @ r1<- offset in code units
10163 /* call, r0 gets catchRelPc (a code-unit offset) */
10164 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
10166 /* fix earlier stack overflow if necessary; may trash rFP */
10167 ldrb r1, [r10, #offThread_stackOverflowed]
10168 cmp r1, #0 @ did we overflow earlier?
10169 beq 1f @ no, skip ahead
10170 mov rFP, r0 @ save relPc result in rFP
10171 mov r0, r10 @ r0<- self
10172 bl dvmCleanupStackOverflow @ call(self)
10173 mov r0, rFP @ restore result
10176 /* update frame pointer and check result from dvmFindCatchBlock */
10177 ldr rFP, [sp, #4] @ retrieve the updated rFP
10178 cmp r0, #0 @ is catchRelPc < 0?
10179 add sp, sp, #8 @ restore stack
10180 bmi .LnotCaughtLocally
10182 /* adjust locals to match self->curFrame and updated PC */
10183 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
10184 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
10185 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
10186 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
10187 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
10188 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10189 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
10190 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10192 /* release the tracked alloc on the exception */
10193 mov r0, r9 @ r0<- exception
10194 mov r1, r10 @ r1<- self
10195 bl dvmReleaseTrackedAlloc @ release the exception
10197 /* restore the exception if the handler wants it */
10198 FETCH_INST() @ load rINST from rPC
10199 GET_INST_OPCODE(ip) @ extract opcode from rINST
10200 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
10201 streq r9, [r10, #offThread_exception] @ yes, restore the exception
10202 GOTO_OPCODE(ip) @ jump to next instruction
10204 .LnotCaughtLocally: @ r9=exception, r10=self
10205 /* fix stack overflow if necessary */
10206 ldrb r1, [r10, #offThread_stackOverflowed]
10207 cmp r1, #0 @ did we overflow earlier?
10208 movne r0, r10 @ if yes: r0<- self
10209 blne dvmCleanupStackOverflow @ if yes: call(self)
10211 @ may want to show "not caught locally" debug messages here
10212 #if DVM_SHOW_EXCEPTION >= 2
10213 /* call __android_log_print(prio, tag, format, ...) */
10214 /* "Exception %s from %s:%d not caught locally" */
10215 @ dvmLineNumFromPC(method, pc - method->insns)
10216 ldr r0, [rGLUE, #offGlue_method]
10217 ldr r1, [r0, #offMethod_insns]
10220 bl dvmLineNumFromPC
10222 @ dvmGetMethodSourceFile(method)
10223 ldr r0, [rGLUE, #offGlue_method]
10224 bl dvmGetMethodSourceFile
10226 @ exception->clazz->descriptor
10227 ldr r3, [r9, #offObject_clazz]
10228 ldr r3, [r3, #offClassObject_descriptor]
10230 ldr r2, strExceptionNotCaughtLocally
10232 mov r0, #3 @ LOG_DEBUG
10233 bl __android_log_print
10235 str r9, [r10, #offThread_exception] @ restore exception
10236 mov r0, r9 @ r0<- exception
10237 mov r1, r10 @ r1<- self
10238 bl dvmReleaseTrackedAlloc @ release the exception
10239 mov r1, #0 @ "want switch" = false
10240 b common_gotoBail @ bail out
10244 * Exception handling, calls through "glue code".
10248 SAVE_PC_FP_TO_GLUE() @ export state
10249 mov r0, rGLUE @ arg to function
10250 bl dvmMterp_exceptionThrown
10251 b common_resumeAfterGlueCall
10256 * After returning from a "glued" function, pull out the updated
10257 * values and start executing at the next instruction.
10259 common_resumeAfterGlueCall:
10260 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
10261 FETCH_INST() @ load rINST from rPC
10262 GET_INST_OPCODE(ip) @ extract opcode from rINST
10263 GOTO_OPCODE(ip) @ jump to next instruction
10266 * Invalid array index.
10268 common_errArrayIndex:
10270 ldr r0, strArrayIndexException
10272 bl dvmThrowException
10273 b common_exceptionThrown
10276 * Invalid array value.
10278 common_errArrayStore:
10280 ldr r0, strArrayStoreException
10282 bl dvmThrowException
10283 b common_exceptionThrown
10286 * Integer divide or mod by zero.
10288 common_errDivideByZero:
10290 ldr r0, strArithmeticException
10291 ldr r1, strDivideByZero
10292 bl dvmThrowException
10293 b common_exceptionThrown
10296 * Attempt to allocate an array with a negative size.
10298 common_errNegativeArraySize:
10300 ldr r0, strNegativeArraySizeException
10302 bl dvmThrowException
10303 b common_exceptionThrown
10306 * Invocation of a non-existent method.
10308 common_errNoSuchMethod:
10310 ldr r0, strNoSuchMethodError
10312 bl dvmThrowException
10313 b common_exceptionThrown
10316 * We encountered a null object when we weren't expecting one. We
10317 * export the PC, throw a NullPointerException, and goto the exception
10320 common_errNullObject:
10322 ldr r0, strNullPointerException
10324 bl dvmThrowException
10325 b common_exceptionThrown
10328 * For debugging, cause an immediate fault. The source address will
10329 * be in lr (use a bl instruction to jump here).
10337 * Spit out a "we were here", preserving all registers. (The attempt
10338 * to save ip won't work, but we need to save an even number of
10339 * registers for EABI 64-bit stack alignment.)
10343 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10347 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10359 * Spit out the number in r0, preserving registers.
10362 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10366 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10370 * Print a newline, preserving registers.
10372 common_printNewline:
10373 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10376 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10380 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10383 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10385 ldr r0, strPrintHex
10387 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10391 * Print the 64-bit quantity in r0-r1, preserving registers.
10394 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10397 ldr r0, strPrintLong
10399 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10403 * Print full method info. Pass the Method* in r0. Preserves regs.
10405 common_printMethod:
10406 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10407 bl dvmMterpPrintMethod
10408 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10412 * Call a C helper function that dumps regs and possibly some
10413 * additional info. Requires the C function to be compiled in.
10417 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10418 bl dvmMterpDumpArmRegs
10419 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10425 * Experiment on VFP mode.
10427 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10429 * Updates the bits specified by "mask", setting them to the values in "val".
10432 and r0, r0, r1 @ make sure no stray bits are set
10433 fmrx r2, fpscr @ get VFP reg
10434 mvn r1, r1 @ bit-invert mask
10435 and r2, r2, r1 @ clear masked bits
10436 orr r2, r2, r0 @ set specified bits
10437 fmxr fpscr, r2 @ set VFP reg
10438 mov r0, r2 @ return new value
10442 .global dvmConfigureFP
10443 .type dvmConfigureFP, %function
10445 stmfd sp!, {ip, lr}
10446 /* 0x03000000 sets DN/FZ */
10447 /* 0x00009f00 clears the six exception enable flags */
10449 mov r0, #0x03000000 @ r0<- 0x03000000
10450 add r1, r0, #0x9f00 @ r1<- 0x03009f00
10452 ldmfd sp!, {ip, pc}
10457 * String references, must be close to the code that uses them.
10460 strArithmeticException:
10461 .word .LstrArithmeticException
10462 strArrayIndexException:
10463 .word .LstrArrayIndexException
10464 strArrayStoreException:
10465 .word .LstrArrayStoreException
10467 .word .LstrDivideByZero
10468 strNegativeArraySizeException:
10469 .word .LstrNegativeArraySizeException
10470 strNoSuchMethodError:
10471 .word .LstrNoSuchMethodError
10472 strNullPointerException:
10473 .word .LstrNullPointerException
10477 strExceptionNotCaughtLocally:
10478 .word .LstrExceptionNotCaughtLocally
10485 .word .LstrPrintHex
10487 .word .LstrPrintLong
10490 * Zero-terminated ASCII string data.
10492 * On ARM we have two choices: do like gcc does, and LDR from a .word
10493 * with the address, or use an ADR pseudo-op to get the address
10494 * directly. ADR saves 4 bytes and an indirection, but it's using a
10495 * PC-relative addressing mode and hence has a limited range, which
10496 * makes it not work well with mergeable string sections.
10498 .section .rodata.str1.4,"aMS",%progbits,1
10500 .LstrBadEntryPoint:
10501 .asciz "Bad entry point %d\n"
10502 .LstrArithmeticException:
10503 .asciz "Ljava/lang/ArithmeticException;"
10504 .LstrArrayIndexException:
10505 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
10506 .LstrArrayStoreException:
10507 .asciz "Ljava/lang/ArrayStoreException;"
10508 .LstrClassCastException:
10509 .asciz "Ljava/lang/ClassCastException;"
10511 .asciz "divide by zero"
10512 .LstrFilledNewArrayNotImpl:
10513 .asciz "filled-new-array only implemented for objects and 'int'"
10514 .LstrInternalError:
10515 .asciz "Ljava/lang/InternalError;"
10516 .LstrInstantiationError:
10517 .asciz "Ljava/lang/InstantiationError;"
10518 .LstrNegativeArraySizeException:
10519 .asciz "Ljava/lang/NegativeArraySizeException;"
10520 .LstrNoSuchMethodError:
10521 .asciz "Ljava/lang/NoSuchMethodError;"
10522 .LstrNullPointerException:
10523 .asciz "Ljava/lang/NullPointerException;"
10527 .LstrExceptionNotCaughtLocally:
10528 .asciz "Exception %s from %s:%d not caught locally\n"