2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
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.
25 * ARMv5 definitions and declarations.
29 ARM EABI general notes:
31 r0-r3 hold first 4 args to a method; they are not preserved across method calls
32 r4-r8 are available for general use
33 r9 is given special treatment in some situations, but not for us
34 r10 (sl) seems to be generally available
35 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36 r12 (ip) is scratch -- not preserved across method calls
37 r13 (sp) should be managed carefully in case a signal arrives
38 r14 (lr) must be preserved
39 r15 (pc) can be tinkered with directly
41 r0 holds returns of <= 4 bytes
42 r0-r1 hold returns of 8 bytes, low word in r0
44 Callee must save/restore r4+ (except r12) if it modifies them. If VFP
45 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46 s0-s15 (d0-d7, q0-a3) do not need to be.
48 Stack is "full descending". Only the arguments that don't fit in the first 4
49 registers are placed on the stack. "sp" points at the first stacked argument
52 VFP: single-precision results in s0, double-precision results in d0.
54 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
55 64-bit quantities (long long, double) must be 64-bit aligned.
61 The following registers have fixed assignments:
64 r4 rPC interpreted program counter, used for fetching instructions
65 r5 rFP interpreted frame pointer, used for accessing locals and args
66 r6 rGLUE MterpGlue pointer
67 r7 rINST first 16-bit code unit of current instruction
68 r8 rIBASE interpreted instruction base pointer, used for computed goto
70 Macros are provided for common operations. Each macro MUST emit only
71 one instruction to make instruction-counting easier. They MUST NOT alter
72 unspecified registers or condition codes.
75 /* single-purpose registers, given names for clarity */
82 /* save/restore the PC and/or FP from the glue struct */
83 #define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc]
84 #define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc]
85 #define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp]
86 #define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp]
87 #define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP}
88 #define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP}
91 * "export" the PC to the stack frame, f/b/o future exception objects. Must
92 * be done *before* something calls dvmThrowException.
94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
97 * It's okay to do this more than once.
100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
103 * Given a frame pointer, find the stack save area.
105 * In C this is "((StackSaveArea*)(_fp) -1)".
107 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
108 sub _reg, _fpreg, #sizeofStackSaveArea
111 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
113 #define FETCH_INST() ldrh rINST, [rPC]
116 * Fetch the next instruction from the specified offset. Advances rPC
117 * to point to the next instruction. "_count" is in 16-bit code units.
119 * Because of the limited size of immediate constants on ARM, this is only
120 * suitable for small forward movements (i.e. don't try to implement "goto"
123 * This must come AFTER anything that can throw an exception, or the
124 * exception catch may miss. (This also implies that it must come after
127 #define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]!
130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
133 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134 ldrh _dreg, [_sreg, #(_count*2)]!
137 * Fetch the next instruction from an offset specified by _reg. Updates
138 * rPC to point to the next instruction. "_reg" must specify the distance
139 * in bytes, *not* 16-bit code units, and may be a signed value.
141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142 * bits that hold the shift distance are used for the half/byte/sign flags.
143 * In some cases we can pre-double _reg for free, so we require a byte offset
146 #define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]!
149 * Fetch a half-word code unit from an offset past the current PC. The
150 * "_count" value is in 16-bit code units. Does not advance rPC.
152 * The "_S" variant works the same but treats the value as signed.
154 #define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)]
155 #define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)]
158 * Fetch one byte from an offset past the current PC. Pass in the same
159 * "_count" as you would for FETCH, and an additional 0/1 indicating which
160 * byte of the halfword you want (lo/hi).
162 #define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)]
165 * Put the instruction's opcode field into the specified register.
167 #define GET_INST_OPCODE(_reg) and _reg, rINST, #255
170 * Put the prefetched instruction's opcode field into the specified register.
172 #define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255
175 * Begin executing the opcode in _reg. Because this only jumps within the
176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
178 #define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6
179 #define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6
180 #define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6
183 * Get/set the 32-bit value from a Dalvik register.
185 #define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2]
186 #define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2]
188 #if defined(WITH_JIT)
189 #define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable]
190 #define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold]
194 * Convert a virtual register index into an address.
196 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197 add _reg, rFP, _vreg, lsl #2
200 * This is a #include, not a %include, because we want the C pre-processor
201 * to expand the macros into assembler assignment statements.
203 #include "../common/asm-constants.h"
205 #if defined(WITH_JIT)
206 #include "../common/jit-config.h"
209 /* File: armv5te/platform.S */
211 * ===========================================================================
212 * CPU-version-specific defines
213 * ===========================================================================
217 * Macro for data memory barrier; not meaningful pre-ARMv6K.
223 * Macro for data memory barrier; not meaningful pre-ARMv6K.
228 /* File: armv5te/entry.S */
230 * Copyright (C) 2008 The Android Open Source Project
232 * Licensed under the Apache License, Version 2.0 (the "License");
233 * you may not use this file except in compliance with the License.
234 * You may obtain a copy of the License at
236 * http://www.apache.org/licenses/LICENSE-2.0
238 * Unless required by applicable law or agreed to in writing, software
239 * distributed under the License is distributed on an "AS IS" BASIS,
240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241 * See the License for the specific language governing permissions and
242 * limitations under the License.
245 * Interpreter entry point.
249 * We don't have formal stack frames, so gdb scans upward in the code
250 * to find the start of the function (a label with the %function type),
251 * and then looks at the next few instructions to figure out what
252 * got pushed onto the stack. From this it figures out how to restore
253 * the registers, including PC, for the previous stack frame. If gdb
254 * sees a non-function label, it stops scanning, so either we need to
255 * have nothing but assembler-local labels between the entry point and
256 * the break, or we need to fake it out.
258 * When this is defined, we add some stuff to make gdb less confused.
260 #define ASSIST_DEBUGGER 1
264 .global dvmMterpStdRun
265 .type dvmMterpStdRun, %function
271 * This function returns a boolean "changeInterp" value. The return comes
272 * via a call to dvmMterpStdBail().
275 #define MTERP_ENTRY1 \
276 .save {r4-r10,fp,lr}; \
277 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs
278 #define MTERP_ENTRY2 \
280 sub sp, sp, #4 @ align 64
286 /* save stack pointer, add magic word for debuggerd */
287 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return
289 /* set up "named" registers, figure out entry point */
290 mov rGLUE, r0 @ set rGLUE
291 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI
292 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue"
293 adr rIBASE, dvmAsmInstructionStart @ set rIBASE
294 cmp r1, #kInterpEntryInstr @ usual case?
295 bne .Lnot_instr @ no, handle it
297 #if defined(WITH_JIT)
299 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
300 /* Entry is always a possible trace start */
301 GET_JIT_PROF_TABLE(r0)
303 mov r1, #0 @ prepare the value for the new state
304 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
305 cmp r0,#0 @ is profiling disabled?
306 #if !defined(WITH_SELF_VERIFICATION)
307 bne common_updateProfile @ profiling is enabled
309 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state
310 beq 1f @ profiling is disabled
311 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state
312 cmp r3, #kSVSTraceSelect @ hot trace following?
313 moveq r2,#kJitTSelectRequestHot @ ask for trace selection
314 beq common_selectTrace @ go build the trace
315 cmp r3, #kSVSNoProfile @ don't profile the next instruction?
316 beq 1f @ intrepret the next instruction
317 b common_updateProfile @ collect profiles
323 /* start executing the instruction at rPC */
324 FETCH_INST() @ load rINST from rPC
325 GET_INST_OPCODE(ip) @ extract opcode from rINST
326 GOTO_OPCODE(ip) @ jump to next instruction
330 cmp r1, #kInterpEntryReturn @ were we returning from a method?
331 beq common_returnFromMethod
334 cmp r1, #kInterpEntryThrow @ were we throwing an exception?
335 beq common_exceptionThrown
337 #if defined(WITH_JIT)
339 ldr r10,[rGLUE, #offGlue_jitResumeNPC]
340 ldr r2,[rGLUE, #offGlue_jitResumeDPC]
341 cmp r1, #kInterpEntryResume @ resuming after Jit single-step?
344 bne .LentryInstr @ must have branched, don't resume
345 #if defined(WITH_SELF_VERIFICATION)
346 @ glue->entryPoint will be set in dvmSelfVerificationSaveState
347 b jitSVShadowRunStart @ re-enter the translation after the
348 @ single-stepped instruction
351 mov r1, #kInterpEntryInstr
352 str r1, [rGLUE, #offGlue_entryPoint]
353 bx r10 @ re-enter the translation
357 ldr r0, strBadEntryPoint
358 @ r1 holds value of entryPoint
364 .global dvmMterpStdBail
365 .type dvmMterpStdBail, %function
368 * Restore the stack pointer and PC from the save point established on entry.
369 * This is essentially the same as a longjmp, but should be cheaper. The
370 * last instruction causes us to return to whoever called dvmMterpStdRun.
372 * We pushed some registers on the stack in dvmMterpStdRun, then saved
373 * SP and LR. Here we restore SP, restore the registers, and then restore
378 * r1 bool changeInterp
381 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP
382 mov r0, r1 @ return the changeInterp value
383 add sp, sp, #4 @ un-align 64
384 ldmfd sp!, {r4-r10,fp,pc} @ restore 9 regs and return
391 .word .LstrBadEntryPoint
394 .global dvmAsmInstructionStart
395 .type dvmAsmInstructionStart, %function
396 dvmAsmInstructionStart = .L_OP_NOP
399 /* ------------------------------ */
401 .L_OP_NOP: /* 0x00 */
402 /* File: armv5te/OP_NOP.S */
403 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST
404 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
405 GOTO_OPCODE(ip) @ execute it
407 #ifdef ASSIST_DEBUGGER
408 /* insert fake function header to help gdb find the stack frame */
409 .type dalvik_inst, %function
417 /* ------------------------------ */
419 .L_OP_MOVE: /* 0x01 */
420 /* File: armv5te/OP_MOVE.S */
421 /* for move, move-object, long-to-int */
423 mov r1, rINST, lsr #12 @ r1<- B from 15:12
424 mov r0, rINST, lsr #8 @ r0<- A from 11:8
425 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
426 GET_VREG(r2, r1) @ r2<- fp[B]
428 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
429 SET_VREG(r2, r0) @ fp[A]<- r2
430 GOTO_OPCODE(ip) @ execute next instruction
432 /* ------------------------------ */
434 .L_OP_MOVE_FROM16: /* 0x02 */
435 /* File: armv5te/OP_MOVE_FROM16.S */
436 /* for: move/from16, move-object/from16 */
438 FETCH(r1, 1) @ r1<- BBBB
439 mov r0, rINST, lsr #8 @ r0<- AA
440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
441 GET_VREG(r2, r1) @ r2<- fp[BBBB]
442 GET_INST_OPCODE(ip) @ extract opcode from rINST
443 SET_VREG(r2, r0) @ fp[AA]<- r2
444 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
460 /* ------------------------------ */
462 .L_OP_MOVE_WIDE: /* 0x04 */
463 /* File: armv5te/OP_MOVE_WIDE.S */
464 /* move-wide vA, vB */
465 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466 mov r2, rINST, lsr #8 @ r2<- A(+)
467 mov r3, rINST, lsr #12 @ r3<- B
469 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
470 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
471 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
472 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
473 GET_INST_OPCODE(ip) @ extract opcode from rINST
474 stmia r2, {r0-r1} @ fp[A]<- r0/r1
475 GOTO_OPCODE(ip) @ jump to next instruction
477 /* ------------------------------ */
479 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481 /* move-wide/from16 vAA, vBBBB */
482 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483 FETCH(r3, 1) @ r3<- BBBB
484 mov r2, rINST, lsr #8 @ r2<- AA
485 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
486 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
487 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
488 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
489 GET_INST_OPCODE(ip) @ extract opcode from rINST
490 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
491 GOTO_OPCODE(ip) @ jump to next instruction
493 /* ------------------------------ */
495 .L_OP_MOVE_WIDE_16: /* 0x06 */
496 /* File: armv5te/OP_MOVE_WIDE_16.S */
497 /* move-wide/16 vAAAA, vBBBB */
498 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
499 FETCH(r3, 2) @ r3<- BBBB
500 FETCH(r2, 1) @ r2<- AAAA
501 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
502 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
503 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
504 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
505 GET_INST_OPCODE(ip) @ extract opcode from rINST
506 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
507 GOTO_OPCODE(ip) @ jump to next instruction
509 /* ------------------------------ */
511 .L_OP_MOVE_OBJECT: /* 0x07 */
512 /* File: armv5te/OP_MOVE_OBJECT.S */
513 /* File: armv5te/OP_MOVE.S */
514 /* for move, move-object, long-to-int */
516 mov r1, rINST, lsr #12 @ r1<- B from 15:12
517 mov r0, rINST, lsr #8 @ r0<- A from 11:8
518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
519 GET_VREG(r2, r1) @ r2<- fp[B]
521 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
522 SET_VREG(r2, r0) @ fp[A]<- r2
523 GOTO_OPCODE(ip) @ execute next instruction
526 /* ------------------------------ */
528 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
529 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
530 /* File: armv5te/OP_MOVE_FROM16.S */
531 /* for: move/from16, move-object/from16 */
533 FETCH(r1, 1) @ r1<- BBBB
534 mov r0, rINST, lsr #8 @ r0<- AA
535 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
536 GET_VREG(r2, r1) @ r2<- fp[BBBB]
537 GET_INST_OPCODE(ip) @ extract opcode from rINST
538 SET_VREG(r2, r0) @ fp[AA]<- r2
539 GOTO_OPCODE(ip) @ jump to next instruction
542 /* ------------------------------ */
544 .L_OP_MOVE_OBJECT_16: /* 0x09 */
545 /* File: armv5te/OP_MOVE_OBJECT_16.S */
546 /* File: armv5te/OP_MOVE_16.S */
547 /* for: move/16, move-object/16 */
548 /* op vAAAA, vBBBB */
549 FETCH(r1, 2) @ r1<- BBBB
550 FETCH(r0, 1) @ r0<- AAAA
551 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
552 GET_VREG(r2, r1) @ r2<- fp[BBBB]
553 GET_INST_OPCODE(ip) @ extract opcode from rINST
554 SET_VREG(r2, r0) @ fp[AAAA]<- r2
555 GOTO_OPCODE(ip) @ jump to next instruction
558 /* ------------------------------ */
560 .L_OP_MOVE_RESULT: /* 0x0a */
561 /* File: armv5te/OP_MOVE_RESULT.S */
562 /* for: move-result, move-result-object */
564 mov r2, rINST, lsr #8 @ r2<- AA
565 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
566 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
567 GET_INST_OPCODE(ip) @ extract opcode from rINST
568 SET_VREG(r0, r2) @ fp[AA]<- r0
569 GOTO_OPCODE(ip) @ jump to next instruction
571 /* ------------------------------ */
573 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
574 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
575 /* move-result-wide vAA */
576 mov r2, rINST, lsr #8 @ r2<- AA
577 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
578 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
579 ldmia r3, {r0-r1} @ r0/r1<- retval.j
580 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
581 GET_INST_OPCODE(ip) @ extract opcode from rINST
582 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
583 GOTO_OPCODE(ip) @ jump to next instruction
585 /* ------------------------------ */
587 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
588 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
589 /* File: armv5te/OP_MOVE_RESULT.S */
590 /* for: move-result, move-result-object */
592 mov r2, rINST, lsr #8 @ r2<- AA
593 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
594 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
595 GET_INST_OPCODE(ip) @ extract opcode from rINST
596 SET_VREG(r0, r2) @ fp[AA]<- r0
597 GOTO_OPCODE(ip) @ jump to next instruction
600 /* ------------------------------ */
602 .L_OP_MOVE_EXCEPTION: /* 0x0d */
603 /* File: armv5te/OP_MOVE_EXCEPTION.S */
604 /* move-exception vAA */
605 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
606 mov r2, rINST, lsr #8 @ r2<- AA
607 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
609 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
610 SET_VREG(r3, r2) @ fp[AA]<- exception obj
611 GET_INST_OPCODE(ip) @ extract opcode from rINST
612 str r1, [r0, #offThread_exception] @ dvmClearException bypass
613 GOTO_OPCODE(ip) @ jump to next instruction
615 /* ------------------------------ */
617 .L_OP_RETURN_VOID: /* 0x0e */
618 /* File: armv5te/OP_RETURN_VOID.S */
619 b common_returnFromMethod
621 /* ------------------------------ */
623 .L_OP_RETURN: /* 0x0f */
624 /* File: armv5te/OP_RETURN.S */
626 * Return a 32-bit value. Copies the return value into the "glue"
627 * structure, then jumps to the return handler.
629 * for: return, return-object
632 mov r2, rINST, lsr #8 @ r2<- AA
633 GET_VREG(r0, r2) @ r0<- vAA
634 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
635 b common_returnFromMethod
637 /* ------------------------------ */
639 .L_OP_RETURN_WIDE: /* 0x10 */
640 /* File: armv5te/OP_RETURN_WIDE.S */
642 * Return a 64-bit value. Copies the return value into the "glue"
643 * structure, then jumps to the return handler.
645 /* return-wide vAA */
646 mov r2, rINST, lsr #8 @ r2<- AA
647 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
648 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
649 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
650 stmia r3, {r0-r1} @ retval<- r0/r1
651 b common_returnFromMethod
653 /* ------------------------------ */
655 .L_OP_RETURN_OBJECT: /* 0x11 */
656 /* File: armv5te/OP_RETURN_OBJECT.S */
657 /* File: armv5te/OP_RETURN.S */
659 * Return a 32-bit value. Copies the return value into the "glue"
660 * structure, then jumps to the return handler.
662 * for: return, return-object
665 mov r2, rINST, lsr #8 @ r2<- AA
666 GET_VREG(r0, r2) @ r0<- vAA
667 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
668 b common_returnFromMethod
671 /* ------------------------------ */
673 .L_OP_CONST_4: /* 0x12 */
674 /* File: armv5te/OP_CONST_4.S */
675 /* const/4 vA, #+B */
676 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
677 mov r0, rINST, lsr #8 @ r0<- A+
678 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
679 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
681 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
682 SET_VREG(r1, r0) @ fp[A]<- r1
683 GOTO_OPCODE(ip) @ execute next instruction
685 /* ------------------------------ */
687 .L_OP_CONST_16: /* 0x13 */
688 /* File: armv5te/OP_CONST_16.S */
689 /* const/16 vAA, #+BBBB */
690 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
691 mov r3, rINST, lsr #8 @ r3<- AA
692 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
693 SET_VREG(r0, r3) @ vAA<- r0
694 GET_INST_OPCODE(ip) @ extract opcode from rINST
695 GOTO_OPCODE(ip) @ jump to next instruction
697 /* ------------------------------ */
699 .L_OP_CONST: /* 0x14 */
700 /* File: armv5te/OP_CONST.S */
701 /* const vAA, #+BBBBbbbb */
702 mov r3, rINST, lsr #8 @ r3<- AA
703 FETCH(r0, 1) @ r0<- bbbb (low)
704 FETCH(r1, 2) @ r1<- BBBB (high)
705 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
706 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
707 GET_INST_OPCODE(ip) @ extract opcode from rINST
708 SET_VREG(r0, r3) @ vAA<- r0
709 GOTO_OPCODE(ip) @ jump to next instruction
711 /* ------------------------------ */
713 .L_OP_CONST_HIGH16: /* 0x15 */
714 /* File: armv5te/OP_CONST_HIGH16.S */
715 /* const/high16 vAA, #+BBBB0000 */
716 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
717 mov r3, rINST, lsr #8 @ r3<- AA
718 mov r0, r0, lsl #16 @ r0<- BBBB0000
719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
720 SET_VREG(r0, r3) @ vAA<- r0
721 GET_INST_OPCODE(ip) @ extract opcode from rINST
722 GOTO_OPCODE(ip) @ jump to next instruction
724 /* ------------------------------ */
726 .L_OP_CONST_WIDE_16: /* 0x16 */
727 /* File: armv5te/OP_CONST_WIDE_16.S */
728 /* const-wide/16 vAA, #+BBBB */
729 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
730 mov r3, rINST, lsr #8 @ r3<- AA
731 mov r1, r0, asr #31 @ r1<- ssssssss
732 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
733 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
734 GET_INST_OPCODE(ip) @ extract opcode from rINST
735 stmia r3, {r0-r1} @ vAA<- r0/r1
736 GOTO_OPCODE(ip) @ jump to next instruction
738 /* ------------------------------ */
740 .L_OP_CONST_WIDE_32: /* 0x17 */
741 /* File: armv5te/OP_CONST_WIDE_32.S */
742 /* const-wide/32 vAA, #+BBBBbbbb */
743 FETCH(r0, 1) @ r0<- 0000bbbb (low)
744 mov r3, rINST, lsr #8 @ r3<- AA
745 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
746 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
747 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
748 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
749 mov r1, r0, asr #31 @ r1<- ssssssss
750 GET_INST_OPCODE(ip) @ extract opcode from rINST
751 stmia r3, {r0-r1} @ vAA<- r0/r1
752 GOTO_OPCODE(ip) @ jump to next instruction
754 /* ------------------------------ */
756 .L_OP_CONST_WIDE: /* 0x18 */
757 /* File: armv5te/OP_CONST_WIDE.S */
758 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
759 FETCH(r0, 1) @ r0<- bbbb (low)
760 FETCH(r1, 2) @ r1<- BBBB (low middle)
761 FETCH(r2, 3) @ r2<- hhhh (high middle)
762 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
763 FETCH(r3, 4) @ r3<- HHHH (high)
764 mov r9, rINST, lsr #8 @ r9<- AA
765 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
766 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
767 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
768 GET_INST_OPCODE(ip) @ extract opcode from rINST
769 stmia r9, {r0-r1} @ vAA<- r0/r1
770 GOTO_OPCODE(ip) @ jump to next instruction
772 /* ------------------------------ */
774 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
775 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
776 /* const-wide/high16 vAA, #+BBBB000000000000 */
777 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
778 mov r3, rINST, lsr #8 @ r3<- AA
779 mov r0, #0 @ r0<- 00000000
780 mov r1, r1, lsl #16 @ r1<- BBBB0000
781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
782 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
783 GET_INST_OPCODE(ip) @ extract opcode from rINST
784 stmia r3, {r0-r1} @ vAA<- r0/r1
785 GOTO_OPCODE(ip) @ jump to next instruction
787 /* ------------------------------ */
789 .L_OP_CONST_STRING: /* 0x1a */
790 /* File: armv5te/OP_CONST_STRING.S */
791 /* const/string vAA, String@BBBB */
792 FETCH(r1, 1) @ r1<- BBBB
793 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
794 mov r9, rINST, lsr #8 @ r9<- AA
795 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
796 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
797 cmp r0, #0 @ not yet resolved?
798 beq .LOP_CONST_STRING_resolve
799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
800 GET_INST_OPCODE(ip) @ extract opcode from rINST
801 SET_VREG(r0, r9) @ vAA<- r0
802 GOTO_OPCODE(ip) @ jump to next instruction
804 /* ------------------------------ */
806 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
807 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
808 /* const/string vAA, String@BBBBBBBB */
809 FETCH(r0, 1) @ r0<- bbbb (low)
810 FETCH(r1, 2) @ r1<- BBBB (high)
811 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
812 mov r9, rINST, lsr #8 @ r9<- AA
813 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
814 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
815 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
817 beq .LOP_CONST_STRING_JUMBO_resolve
818 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
819 GET_INST_OPCODE(ip) @ extract opcode from rINST
820 SET_VREG(r0, r9) @ vAA<- r0
821 GOTO_OPCODE(ip) @ jump to next instruction
823 /* ------------------------------ */
825 .L_OP_CONST_CLASS: /* 0x1c */
826 /* File: armv5te/OP_CONST_CLASS.S */
827 /* const/class vAA, Class@BBBB */
828 FETCH(r1, 1) @ r1<- BBBB
829 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
830 mov r9, rINST, lsr #8 @ r9<- AA
831 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
832 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
833 cmp r0, #0 @ not yet resolved?
834 beq .LOP_CONST_CLASS_resolve
835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
836 GET_INST_OPCODE(ip) @ extract opcode from rINST
837 SET_VREG(r0, r9) @ vAA<- r0
838 GOTO_OPCODE(ip) @ jump to next instruction
840 /* ------------------------------ */
842 .L_OP_MONITOR_ENTER: /* 0x1d */
843 /* File: armv5te/OP_MONITOR_ENTER.S */
845 * Synchronize on an object.
847 /* monitor-enter vAA */
848 mov r2, rINST, lsr #8 @ r2<- AA
849 GET_VREG(r1, r2) @ r1<- vAA (object)
850 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
851 cmp r1, #0 @ null object?
852 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING
853 beq common_errNullObject @ null object, throw an exception
854 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
855 bl dvmLockObject @ call(self, obj)
856 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
857 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
858 ldr r1, [r0, #offThread_exception] @ check for exception
860 bne common_exceptionThrown @ exception raised, bail out
862 GET_INST_OPCODE(ip) @ extract opcode from rINST
863 GOTO_OPCODE(ip) @ jump to next instruction
865 /* ------------------------------ */
867 .L_OP_MONITOR_EXIT: /* 0x1e */
868 /* File: armv5te/OP_MONITOR_EXIT.S */
872 * Exceptions that occur when unlocking a monitor need to appear as
873 * if they happened at the following instruction. See the Dalvik
876 /* monitor-exit vAA */
877 mov r2, rINST, lsr #8 @ r2<- AA
878 EXPORT_PC() @ before fetch: export the PC
879 GET_VREG(r1, r2) @ r1<- vAA (object)
880 cmp r1, #0 @ null object?
882 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
883 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
885 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
886 beq common_exceptionThrown @ yes, exception is pending
887 GET_INST_OPCODE(ip) @ extract opcode from rINST
888 GOTO_OPCODE(ip) @ jump to next instruction
890 FETCH_ADVANCE_INST(1) @ advance before throw
891 b common_errNullObject
893 /* ------------------------------ */
895 .L_OP_CHECK_CAST: /* 0x1f */
896 /* File: armv5te/OP_CHECK_CAST.S */
898 * Check to see if a cast from one class to another is allowed.
900 /* check-cast vAA, class@BBBB */
901 mov r3, rINST, lsr #8 @ r3<- AA
902 FETCH(r2, 1) @ r2<- BBBB
903 GET_VREG(r9, r3) @ r9<- object
904 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
905 cmp r9, #0 @ is object null?
906 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
907 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
908 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
909 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
910 cmp r1, #0 @ have we resolved this before?
911 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
912 .LOP_CHECK_CAST_resolved:
913 cmp r0, r1 @ same class (trivial success)?
914 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
915 .LOP_CHECK_CAST_okay:
916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
917 GET_INST_OPCODE(ip) @ extract opcode from rINST
918 GOTO_OPCODE(ip) @ jump to next instruction
920 /* ------------------------------ */
922 .L_OP_INSTANCE_OF: /* 0x20 */
923 /* File: armv5te/OP_INSTANCE_OF.S */
925 * Check to see if an object reference is an instance of a class.
927 * Most common situation is a non-null object, being compared against
928 * an already-resolved class.
930 /* instance-of vA, vB, class@CCCC */
931 mov r3, rINST, lsr #12 @ r3<- B
932 mov r9, rINST, lsr #8 @ r9<- A+
933 GET_VREG(r0, r3) @ r0<- vB (object)
934 and r9, r9, #15 @ r9<- A
935 cmp r0, #0 @ is object null?
936 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
937 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
938 FETCH(r3, 1) @ r3<- CCCC
939 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
940 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
941 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
942 cmp r1, #0 @ have we resolved this before?
943 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
944 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
945 cmp r0, r1 @ same class (trivial success)?
946 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
947 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
949 /* ------------------------------ */
951 .L_OP_ARRAY_LENGTH: /* 0x21 */
952 /* File: armv5te/OP_ARRAY_LENGTH.S */
954 * Return the length of an array.
956 mov r1, rINST, lsr #12 @ r1<- B
957 mov r2, rINST, lsr #8 @ r2<- A+
958 GET_VREG(r0, r1) @ r0<- vB (object ref)
959 and r2, r2, #15 @ r2<- A
960 cmp r0, #0 @ is object null?
961 beq common_errNullObject @ yup, fail
962 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
963 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
964 GET_INST_OPCODE(ip) @ extract opcode from rINST
965 SET_VREG(r3, r2) @ vB<- length
966 GOTO_OPCODE(ip) @ jump to next instruction
968 /* ------------------------------ */
970 .L_OP_NEW_INSTANCE: /* 0x22 */
971 /* File: armv5te/OP_NEW_INSTANCE.S */
973 * Create a new instance of a class.
975 /* new-instance vAA, class@BBBB */
976 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
977 FETCH(r1, 1) @ r1<- BBBB
978 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
979 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
980 EXPORT_PC() @ req'd for init, resolve, alloc
981 cmp r0, #0 @ already resolved?
982 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
983 .LOP_NEW_INSTANCE_resolved: @ r0=class
984 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
985 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
986 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
987 .LOP_NEW_INSTANCE_initialized: @ r0=class
988 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
989 bl dvmAllocObject @ r0<- new object
990 b .LOP_NEW_INSTANCE_finish @ continue
992 /* ------------------------------ */
994 .L_OP_NEW_ARRAY: /* 0x23 */
995 /* File: armv5te/OP_NEW_ARRAY.S */
997 * Allocate an array of objects, specified with the array class
1000 * The verifier guarantees that this is an array class, so we don't
1001 * check for it here.
1003 /* new-array vA, vB, class@CCCC */
1004 mov r0, rINST, lsr #12 @ r0<- B
1005 FETCH(r2, 1) @ r2<- CCCC
1006 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1007 GET_VREG(r1, r0) @ r1<- vB (array length)
1008 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1009 cmp r1, #0 @ check length
1010 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
1011 bmi common_errNegativeArraySize @ negative length, bail
1012 cmp r0, #0 @ already resolved?
1013 EXPORT_PC() @ req'd for resolve, alloc
1014 bne .LOP_NEW_ARRAY_finish @ resolved, continue
1015 b .LOP_NEW_ARRAY_resolve @ do resolve now
1017 /* ------------------------------ */
1019 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1020 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1022 * Create a new array with elements filled from registers.
1024 * for: filled-new-array, filled-new-array/range
1026 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1027 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1028 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1029 FETCH(r1, 1) @ r1<- BBBB
1030 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1031 EXPORT_PC() @ need for resolve and alloc
1032 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1033 mov r10, rINST, lsr #8 @ r10<- AA or BA
1034 cmp r0, #0 @ already resolved?
1035 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
1036 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1037 mov r2, #0 @ r2<- false
1038 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1039 bl dvmResolveClass @ r0<- call(clazz, ref)
1040 cmp r0, #0 @ got null?
1041 beq common_exceptionThrown @ yes, handle exception
1042 b .LOP_FILLED_NEW_ARRAY_continue
1044 /* ------------------------------ */
1046 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1047 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1048 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1050 * Create a new array with elements filled from registers.
1052 * for: filled-new-array, filled-new-array/range
1054 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1055 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1056 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1057 FETCH(r1, 1) @ r1<- BBBB
1058 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1059 EXPORT_PC() @ need for resolve and alloc
1060 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1061 mov r10, rINST, lsr #8 @ r10<- AA or BA
1062 cmp r0, #0 @ already resolved?
1063 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
1064 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1065 mov r2, #0 @ r2<- false
1066 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1067 bl dvmResolveClass @ r0<- call(clazz, ref)
1068 cmp r0, #0 @ got null?
1069 beq common_exceptionThrown @ yes, handle exception
1070 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1073 /* ------------------------------ */
1075 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1076 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1077 /* fill-array-data vAA, +BBBBBBBB */
1078 FETCH(r0, 1) @ r0<- bbbb (lo)
1079 FETCH(r1, 2) @ r1<- BBBB (hi)
1080 mov r3, rINST, lsr #8 @ r3<- AA
1081 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1082 GET_VREG(r0, r3) @ r0<- vAA (array object)
1083 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1085 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1086 cmp r0, #0 @ 0 means an exception is thrown
1087 beq common_exceptionThrown @ has exception
1088 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1089 GET_INST_OPCODE(ip) @ extract opcode from rINST
1090 GOTO_OPCODE(ip) @ jump to next instruction
1092 /* ------------------------------ */
1094 .L_OP_THROW: /* 0x27 */
1095 /* File: armv5te/OP_THROW.S */
1097 * Throw an exception object in the current thread.
1100 mov r2, rINST, lsr #8 @ r2<- AA
1101 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1102 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1103 EXPORT_PC() @ exception handler can throw
1104 cmp r1, #0 @ null object?
1105 beq common_errNullObject @ yes, throw an NPE instead
1106 @ bypass dvmSetException, just store it
1107 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1108 b common_exceptionThrown
1110 /* ------------------------------ */
1112 .L_OP_GOTO: /* 0x28 */
1113 /* File: armv5te/OP_GOTO.S */
1115 * Unconditional branch, 8-bit offset.
1117 * The branch distance is a signed code-unit offset, which we need to
1118 * double to get a byte offset.
1121 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1122 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1123 mov r9, r9, lsl #1 @ r9<- byte offset
1124 bmi common_backwardBranch @ backward branch, do periodic checks
1125 #if defined(WITH_JIT)
1126 GET_JIT_PROF_TABLE(r0)
1127 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1129 bne common_updateProfile
1130 GET_INST_OPCODE(ip) @ extract opcode from rINST
1131 GOTO_OPCODE(ip) @ jump to next instruction
1133 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1134 GET_INST_OPCODE(ip) @ extract opcode from rINST
1135 GOTO_OPCODE(ip) @ jump to next instruction
1138 /* ------------------------------ */
1140 .L_OP_GOTO_16: /* 0x29 */
1141 /* File: armv5te/OP_GOTO_16.S */
1143 * Unconditional branch, 16-bit offset.
1145 * The branch distance is a signed code-unit offset, which we need to
1146 * double to get a byte offset.
1149 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1150 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1151 bmi common_backwardBranch @ backward branch, do periodic checks
1152 #if defined(WITH_JIT)
1153 GET_JIT_PROF_TABLE(r0)
1154 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1156 bne common_updateProfile
1157 GET_INST_OPCODE(ip) @ extract opcode from rINST
1158 GOTO_OPCODE(ip) @ jump to next instruction
1160 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1161 GET_INST_OPCODE(ip) @ extract opcode from rINST
1162 GOTO_OPCODE(ip) @ jump to next instruction
1165 /* ------------------------------ */
1167 .L_OP_GOTO_32: /* 0x2a */
1168 /* File: armv5te/OP_GOTO_32.S */
1170 * Unconditional branch, 32-bit offset.
1172 * The branch distance is a signed code-unit offset, which we need to
1173 * double to get a byte offset.
1175 * Unlike most opcodes, this one is allowed to branch to itself, so
1176 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1177 * instruction doesn't affect the V flag, so we need to clear it
1180 /* goto/32 +AAAAAAAA */
1181 FETCH(r0, 1) @ r0<- aaaa (lo)
1182 FETCH(r1, 2) @ r1<- AAAA (hi)
1183 cmp ip, ip @ (clear V flag during stall)
1184 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1185 mov r9, r0, asl #1 @ r9<- byte offset
1186 ble common_backwardBranch @ backward branch, do periodic checks
1187 #if defined(WITH_JIT)
1188 GET_JIT_PROF_TABLE(r0)
1189 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1191 bne common_updateProfile
1192 GET_INST_OPCODE(ip) @ extract opcode from rINST
1193 GOTO_OPCODE(ip) @ jump to next instruction
1195 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1196 GET_INST_OPCODE(ip) @ extract opcode from rINST
1197 GOTO_OPCODE(ip) @ jump to next instruction
1200 /* ------------------------------ */
1202 .L_OP_PACKED_SWITCH: /* 0x2b */
1203 /* File: armv5te/OP_PACKED_SWITCH.S */
1205 * Handle a packed-switch or sparse-switch instruction. In both cases
1206 * we decode it and hand it off to a helper function.
1208 * We don't really expect backward branches in a switch statement, but
1209 * they're perfectly legal, so we check for them here.
1211 * for: packed-switch, sparse-switch
1214 FETCH(r0, 1) @ r0<- bbbb (lo)
1215 FETCH(r1, 2) @ r1<- BBBB (hi)
1216 mov r3, rINST, lsr #8 @ r3<- AA
1217 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1218 GET_VREG(r1, r3) @ r1<- vAA
1219 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1220 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1221 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1222 bmi common_backwardBranch @ backward branch, do periodic checks
1223 beq common_backwardBranch @ (want to use BLE but V is unknown)
1224 #if defined(WITH_JIT)
1225 GET_JIT_PROF_TABLE(r0)
1226 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1228 bne common_updateProfile
1229 GET_INST_OPCODE(ip) @ extract opcode from rINST
1230 GOTO_OPCODE(ip) @ jump to next instruction
1232 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1233 GET_INST_OPCODE(ip) @ extract opcode from rINST
1234 GOTO_OPCODE(ip) @ jump to next instruction
1237 /* ------------------------------ */
1239 .L_OP_SPARSE_SWITCH: /* 0x2c */
1240 /* File: armv5te/OP_SPARSE_SWITCH.S */
1241 /* File: armv5te/OP_PACKED_SWITCH.S */
1243 * Handle a packed-switch or sparse-switch instruction. In both cases
1244 * we decode it and hand it off to a helper function.
1246 * We don't really expect backward branches in a switch statement, but
1247 * they're perfectly legal, so we check for them here.
1249 * for: packed-switch, sparse-switch
1252 FETCH(r0, 1) @ r0<- bbbb (lo)
1253 FETCH(r1, 2) @ r1<- BBBB (hi)
1254 mov r3, rINST, lsr #8 @ r3<- AA
1255 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1256 GET_VREG(r1, r3) @ r1<- vAA
1257 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1258 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1259 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1260 bmi common_backwardBranch @ backward branch, do periodic checks
1261 beq common_backwardBranch @ (want to use BLE but V is unknown)
1262 #if defined(WITH_JIT)
1263 GET_JIT_PROF_TABLE(r0)
1264 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1266 bne common_updateProfile
1267 GET_INST_OPCODE(ip) @ extract opcode from rINST
1268 GOTO_OPCODE(ip) @ jump to next instruction
1270 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1271 GET_INST_OPCODE(ip) @ extract opcode from rINST
1272 GOTO_OPCODE(ip) @ jump to next instruction
1276 /* ------------------------------ */
1278 .L_OP_CMPL_FLOAT: /* 0x2d */
1279 /* File: arm-vfp/OP_CMPL_FLOAT.S */
1281 * Compare two floating-point values. Puts 0, 1, or -1 into the
1282 * destination register based on the results of the comparison.
1284 * int compare(x, y) {
1287 * } else if (x > y) {
1289 * } else if (x < y) {
1296 /* op vAA, vBB, vCC */
1297 FETCH(r0, 1) @ r0<- CCBB
1298 mov r9, rINST, lsr #8 @ r9<- AA
1299 and r2, r0, #255 @ r2<- BB
1300 mov r3, r0, lsr #8 @ r3<- CC
1301 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1302 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1303 flds s0, [r2] @ s0<- vBB
1304 flds s1, [r3] @ s1<- vCC
1305 fcmpes s0, s1 @ compare (vBB, vCC)
1306 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1307 mvn r0, #0 @ r0<- -1 (default)
1308 GET_INST_OPCODE(ip) @ extract opcode from rINST
1309 fmstat @ export status flags
1310 movgt r0, #1 @ (greater than) r1<- 1
1311 moveq r0, #0 @ (equal) r1<- 0
1312 b .LOP_CMPL_FLOAT_finish @ argh
1315 /* ------------------------------ */
1317 .L_OP_CMPG_FLOAT: /* 0x2e */
1318 /* File: arm-vfp/OP_CMPG_FLOAT.S */
1320 * Compare two floating-point values. Puts 0, 1, or -1 into the
1321 * destination register based on the results of the comparison.
1323 * int compare(x, y) {
1326 * } else if (x < y) {
1328 * } else if (x > y) {
1335 /* op vAA, vBB, vCC */
1336 FETCH(r0, 1) @ r0<- CCBB
1337 mov r9, rINST, lsr #8 @ r9<- AA
1338 and r2, r0, #255 @ r2<- BB
1339 mov r3, r0, lsr #8 @ r3<- CC
1340 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1341 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1342 flds s0, [r2] @ s0<- vBB
1343 flds s1, [r3] @ s1<- vCC
1344 fcmpes s0, s1 @ compare (vBB, vCC)
1345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1346 mov r0, #1 @ r0<- 1 (default)
1347 GET_INST_OPCODE(ip) @ extract opcode from rINST
1348 fmstat @ export status flags
1349 mvnmi r0, #0 @ (less than) r1<- -1
1350 moveq r0, #0 @ (equal) r1<- 0
1351 b .LOP_CMPG_FLOAT_finish @ argh
1354 /* ------------------------------ */
1356 .L_OP_CMPL_DOUBLE: /* 0x2f */
1357 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
1359 * Compare two floating-point values. Puts 0, 1, or -1 into the
1360 * destination register based on the results of the comparison.
1362 * int compare(x, y) {
1365 * } else if (x > y) {
1367 * } else if (x < y) {
1374 /* op vAA, vBB, vCC */
1375 FETCH(r0, 1) @ r0<- CCBB
1376 mov r9, rINST, lsr #8 @ r9<- AA
1377 and r2, r0, #255 @ r2<- BB
1378 mov r3, r0, lsr #8 @ r3<- CC
1379 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1380 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1381 fldd d0, [r2] @ d0<- vBB
1382 fldd d1, [r3] @ d1<- vCC
1383 fcmped d0, d1 @ compare (vBB, vCC)
1384 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1385 mvn r0, #0 @ r0<- -1 (default)
1386 GET_INST_OPCODE(ip) @ extract opcode from rINST
1387 fmstat @ export status flags
1388 movgt r0, #1 @ (greater than) r1<- 1
1389 moveq r0, #0 @ (equal) r1<- 0
1390 b .LOP_CMPL_DOUBLE_finish @ argh
1393 /* ------------------------------ */
1395 .L_OP_CMPG_DOUBLE: /* 0x30 */
1396 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
1398 * Compare two floating-point values. Puts 0, 1, or -1 into the
1399 * destination register based on the results of the comparison.
1401 * int compare(x, y) {
1404 * } else if (x < y) {
1406 * } else if (x > y) {
1413 /* op vAA, vBB, vCC */
1414 FETCH(r0, 1) @ r0<- CCBB
1415 mov r9, rINST, lsr #8 @ r9<- AA
1416 and r2, r0, #255 @ r2<- BB
1417 mov r3, r0, lsr #8 @ r3<- CC
1418 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1419 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1420 fldd d0, [r2] @ d0<- vBB
1421 fldd d1, [r3] @ d1<- vCC
1422 fcmped d0, d1 @ compare (vBB, vCC)
1423 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1424 mov r0, #1 @ r0<- 1 (default)
1425 GET_INST_OPCODE(ip) @ extract opcode from rINST
1426 fmstat @ export status flags
1427 mvnmi r0, #0 @ (less than) r1<- -1
1428 moveq r0, #0 @ (equal) r1<- 0
1429 b .LOP_CMPG_DOUBLE_finish @ argh
1432 /* ------------------------------ */
1434 .L_OP_CMP_LONG: /* 0x31 */
1435 /* File: armv5te/OP_CMP_LONG.S */
1437 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1438 * register based on the results of the comparison.
1440 * We load the full values with LDM, but in practice many values could
1441 * be resolved by only looking at the high word. This could be made
1442 * faster or slower by splitting the LDM into a pair of LDRs.
1444 * If we just wanted to set condition flags, we could do this:
1448 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1449 * integer value, which we can do with 2 conditional mov/mvn instructions
1450 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1451 * us a constant 5-cycle path plus a branch at the end to the
1452 * instruction epilogue code. The multi-compare approach below needs
1453 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1454 * in the worst case (the 64-bit values are equal).
1456 /* cmp-long vAA, vBB, vCC */
1457 FETCH(r0, 1) @ r0<- CCBB
1458 mov r9, rINST, lsr #8 @ r9<- AA
1459 and r2, r0, #255 @ r2<- BB
1460 mov r3, r0, lsr #8 @ r3<- CC
1461 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1462 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1463 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1464 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1465 cmp r1, r3 @ compare (vBB+1, vCC+1)
1466 blt .LOP_CMP_LONG_less @ signed compare on high part
1467 bgt .LOP_CMP_LONG_greater
1468 subs r1, r0, r2 @ r1<- r0 - r2
1469 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1470 bne .LOP_CMP_LONG_less
1471 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1473 /* ------------------------------ */
1475 .L_OP_IF_EQ: /* 0x32 */
1476 /* File: armv5te/OP_IF_EQ.S */
1477 /* File: armv5te/bincmp.S */
1479 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1480 * fragment that specifies the *reverse* comparison to perform, e.g.
1481 * for "if-le" you would use "gt".
1483 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1485 /* if-cmp vA, vB, +CCCC */
1486 mov r0, rINST, lsr #8 @ r0<- A+
1487 mov r1, rINST, lsr #12 @ r1<- B
1489 GET_VREG(r3, r1) @ r3<- vB
1490 GET_VREG(r2, r0) @ r2<- vA
1491 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1492 cmp r2, r3 @ compare (vA, vB)
1493 bne 1f @ branch to 1 if comparison failed
1494 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1495 movs r9, r9, asl #1 @ convert to bytes, check sign
1496 bmi common_backwardBranch @ yes, do periodic checks
1498 #if defined(WITH_JIT)
1499 GET_JIT_PROF_TABLE(r0)
1500 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1501 b common_testUpdateProfile
1503 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1504 GET_INST_OPCODE(ip) @ extract opcode from rINST
1505 GOTO_OPCODE(ip) @ jump to next instruction
1509 /* ------------------------------ */
1511 .L_OP_IF_NE: /* 0x33 */
1512 /* File: armv5te/OP_IF_NE.S */
1513 /* File: armv5te/bincmp.S */
1515 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1516 * fragment that specifies the *reverse* comparison to perform, e.g.
1517 * for "if-le" you would use "gt".
1519 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1521 /* if-cmp vA, vB, +CCCC */
1522 mov r0, rINST, lsr #8 @ r0<- A+
1523 mov r1, rINST, lsr #12 @ r1<- B
1525 GET_VREG(r3, r1) @ r3<- vB
1526 GET_VREG(r2, r0) @ r2<- vA
1527 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1528 cmp r2, r3 @ compare (vA, vB)
1529 beq 1f @ branch to 1 if comparison failed
1530 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1531 movs r9, r9, asl #1 @ convert to bytes, check sign
1532 bmi common_backwardBranch @ yes, do periodic checks
1534 #if defined(WITH_JIT)
1535 GET_JIT_PROF_TABLE(r0)
1536 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1537 b common_testUpdateProfile
1539 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1540 GET_INST_OPCODE(ip) @ extract opcode from rINST
1541 GOTO_OPCODE(ip) @ jump to next instruction
1545 /* ------------------------------ */
1547 .L_OP_IF_LT: /* 0x34 */
1548 /* File: armv5te/OP_IF_LT.S */
1549 /* File: armv5te/bincmp.S */
1551 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1552 * fragment that specifies the *reverse* comparison to perform, e.g.
1553 * for "if-le" you would use "gt".
1555 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1557 /* if-cmp vA, vB, +CCCC */
1558 mov r0, rINST, lsr #8 @ r0<- A+
1559 mov r1, rINST, lsr #12 @ r1<- B
1561 GET_VREG(r3, r1) @ r3<- vB
1562 GET_VREG(r2, r0) @ r2<- vA
1563 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1564 cmp r2, r3 @ compare (vA, vB)
1565 bge 1f @ branch to 1 if comparison failed
1566 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1567 movs r9, r9, asl #1 @ convert to bytes, check sign
1568 bmi common_backwardBranch @ yes, do periodic checks
1570 #if defined(WITH_JIT)
1571 GET_JIT_PROF_TABLE(r0)
1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1573 b common_testUpdateProfile
1575 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1576 GET_INST_OPCODE(ip) @ extract opcode from rINST
1577 GOTO_OPCODE(ip) @ jump to next instruction
1581 /* ------------------------------ */
1583 .L_OP_IF_GE: /* 0x35 */
1584 /* File: armv5te/OP_IF_GE.S */
1585 /* File: armv5te/bincmp.S */
1587 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1588 * fragment that specifies the *reverse* comparison to perform, e.g.
1589 * for "if-le" you would use "gt".
1591 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1593 /* if-cmp vA, vB, +CCCC */
1594 mov r0, rINST, lsr #8 @ r0<- A+
1595 mov r1, rINST, lsr #12 @ r1<- B
1597 GET_VREG(r3, r1) @ r3<- vB
1598 GET_VREG(r2, r0) @ r2<- vA
1599 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1600 cmp r2, r3 @ compare (vA, vB)
1601 blt 1f @ branch to 1 if comparison failed
1602 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1603 movs r9, r9, asl #1 @ convert to bytes, check sign
1604 bmi common_backwardBranch @ yes, do periodic checks
1606 #if defined(WITH_JIT)
1607 GET_JIT_PROF_TABLE(r0)
1608 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1609 b common_testUpdateProfile
1611 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1612 GET_INST_OPCODE(ip) @ extract opcode from rINST
1613 GOTO_OPCODE(ip) @ jump to next instruction
1617 /* ------------------------------ */
1619 .L_OP_IF_GT: /* 0x36 */
1620 /* File: armv5te/OP_IF_GT.S */
1621 /* File: armv5te/bincmp.S */
1623 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1624 * fragment that specifies the *reverse* comparison to perform, e.g.
1625 * for "if-le" you would use "gt".
1627 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1629 /* if-cmp vA, vB, +CCCC */
1630 mov r0, rINST, lsr #8 @ r0<- A+
1631 mov r1, rINST, lsr #12 @ r1<- B
1633 GET_VREG(r3, r1) @ r3<- vB
1634 GET_VREG(r2, r0) @ r2<- vA
1635 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1636 cmp r2, r3 @ compare (vA, vB)
1637 ble 1f @ branch to 1 if comparison failed
1638 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1639 movs r9, r9, asl #1 @ convert to bytes, check sign
1640 bmi common_backwardBranch @ yes, do periodic checks
1642 #if defined(WITH_JIT)
1643 GET_JIT_PROF_TABLE(r0)
1644 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1645 b common_testUpdateProfile
1647 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1648 GET_INST_OPCODE(ip) @ extract opcode from rINST
1649 GOTO_OPCODE(ip) @ jump to next instruction
1653 /* ------------------------------ */
1655 .L_OP_IF_LE: /* 0x37 */
1656 /* File: armv5te/OP_IF_LE.S */
1657 /* File: armv5te/bincmp.S */
1659 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1660 * fragment that specifies the *reverse* comparison to perform, e.g.
1661 * for "if-le" you would use "gt".
1663 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1665 /* if-cmp vA, vB, +CCCC */
1666 mov r0, rINST, lsr #8 @ r0<- A+
1667 mov r1, rINST, lsr #12 @ r1<- B
1669 GET_VREG(r3, r1) @ r3<- vB
1670 GET_VREG(r2, r0) @ r2<- vA
1671 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1672 cmp r2, r3 @ compare (vA, vB)
1673 bgt 1f @ branch to 1 if comparison failed
1674 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1675 movs r9, r9, asl #1 @ convert to bytes, check sign
1676 bmi common_backwardBranch @ yes, do periodic checks
1678 #if defined(WITH_JIT)
1679 GET_JIT_PROF_TABLE(r0)
1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1681 b common_testUpdateProfile
1683 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1684 GET_INST_OPCODE(ip) @ extract opcode from rINST
1685 GOTO_OPCODE(ip) @ jump to next instruction
1689 /* ------------------------------ */
1691 .L_OP_IF_EQZ: /* 0x38 */
1692 /* File: armv5te/OP_IF_EQZ.S */
1693 /* File: armv5te/zcmp.S */
1695 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1696 * fragment that specifies the *reverse* comparison to perform, e.g.
1697 * for "if-le" you would use "gt".
1699 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1701 /* if-cmp vAA, +BBBB */
1702 mov r0, rINST, lsr #8 @ r0<- AA
1703 GET_VREG(r2, r0) @ r2<- vAA
1704 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1705 cmp r2, #0 @ compare (vA, 0)
1706 bne 1f @ branch to 1 if comparison failed
1707 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1708 movs r9, r9, asl #1 @ convert to bytes, check sign
1709 bmi common_backwardBranch @ backward branch, do periodic checks
1711 #if defined(WITH_JIT)
1712 GET_JIT_PROF_TABLE(r0)
1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1715 bne common_updateProfile
1716 GET_INST_OPCODE(ip) @ extract opcode from rINST
1717 GOTO_OPCODE(ip) @ jump to next instruction
1719 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1720 GET_INST_OPCODE(ip) @ extract opcode from rINST
1721 GOTO_OPCODE(ip) @ jump to next instruction
1725 /* ------------------------------ */
1727 .L_OP_IF_NEZ: /* 0x39 */
1728 /* File: armv5te/OP_IF_NEZ.S */
1729 /* File: armv5te/zcmp.S */
1731 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1732 * fragment that specifies the *reverse* comparison to perform, e.g.
1733 * for "if-le" you would use "gt".
1735 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1737 /* if-cmp vAA, +BBBB */
1738 mov r0, rINST, lsr #8 @ r0<- AA
1739 GET_VREG(r2, r0) @ r2<- vAA
1740 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1741 cmp r2, #0 @ compare (vA, 0)
1742 beq 1f @ branch to 1 if comparison failed
1743 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1744 movs r9, r9, asl #1 @ convert to bytes, check sign
1745 bmi common_backwardBranch @ backward branch, do periodic checks
1747 #if defined(WITH_JIT)
1748 GET_JIT_PROF_TABLE(r0)
1749 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1751 bne common_updateProfile
1752 GET_INST_OPCODE(ip) @ extract opcode from rINST
1753 GOTO_OPCODE(ip) @ jump to next instruction
1755 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1756 GET_INST_OPCODE(ip) @ extract opcode from rINST
1757 GOTO_OPCODE(ip) @ jump to next instruction
1761 /* ------------------------------ */
1763 .L_OP_IF_LTZ: /* 0x3a */
1764 /* File: armv5te/OP_IF_LTZ.S */
1765 /* File: armv5te/zcmp.S */
1767 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1768 * fragment that specifies the *reverse* comparison to perform, e.g.
1769 * for "if-le" you would use "gt".
1771 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1773 /* if-cmp vAA, +BBBB */
1774 mov r0, rINST, lsr #8 @ r0<- AA
1775 GET_VREG(r2, r0) @ r2<- vAA
1776 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1777 cmp r2, #0 @ compare (vA, 0)
1778 bge 1f @ branch to 1 if comparison failed
1779 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1780 movs r9, r9, asl #1 @ convert to bytes, check sign
1781 bmi common_backwardBranch @ backward branch, do periodic checks
1783 #if defined(WITH_JIT)
1784 GET_JIT_PROF_TABLE(r0)
1785 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1787 bne common_updateProfile
1788 GET_INST_OPCODE(ip) @ extract opcode from rINST
1789 GOTO_OPCODE(ip) @ jump to next instruction
1791 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1792 GET_INST_OPCODE(ip) @ extract opcode from rINST
1793 GOTO_OPCODE(ip) @ jump to next instruction
1797 /* ------------------------------ */
1799 .L_OP_IF_GEZ: /* 0x3b */
1800 /* File: armv5te/OP_IF_GEZ.S */
1801 /* File: armv5te/zcmp.S */
1803 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1804 * fragment that specifies the *reverse* comparison to perform, e.g.
1805 * for "if-le" you would use "gt".
1807 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1809 /* if-cmp vAA, +BBBB */
1810 mov r0, rINST, lsr #8 @ r0<- AA
1811 GET_VREG(r2, r0) @ r2<- vAA
1812 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1813 cmp r2, #0 @ compare (vA, 0)
1814 blt 1f @ branch to 1 if comparison failed
1815 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1816 movs r9, r9, asl #1 @ convert to bytes, check sign
1817 bmi common_backwardBranch @ backward branch, do periodic checks
1819 #if defined(WITH_JIT)
1820 GET_JIT_PROF_TABLE(r0)
1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1823 bne common_updateProfile
1824 GET_INST_OPCODE(ip) @ extract opcode from rINST
1825 GOTO_OPCODE(ip) @ jump to next instruction
1827 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1828 GET_INST_OPCODE(ip) @ extract opcode from rINST
1829 GOTO_OPCODE(ip) @ jump to next instruction
1833 /* ------------------------------ */
1835 .L_OP_IF_GTZ: /* 0x3c */
1836 /* File: armv5te/OP_IF_GTZ.S */
1837 /* File: armv5te/zcmp.S */
1839 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1840 * fragment that specifies the *reverse* comparison to perform, e.g.
1841 * for "if-le" you would use "gt".
1843 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1845 /* if-cmp vAA, +BBBB */
1846 mov r0, rINST, lsr #8 @ r0<- AA
1847 GET_VREG(r2, r0) @ r2<- vAA
1848 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1849 cmp r2, #0 @ compare (vA, 0)
1850 ble 1f @ branch to 1 if comparison failed
1851 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1852 movs r9, r9, asl #1 @ convert to bytes, check sign
1853 bmi common_backwardBranch @ backward branch, do periodic checks
1855 #if defined(WITH_JIT)
1856 GET_JIT_PROF_TABLE(r0)
1857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1859 bne common_updateProfile
1860 GET_INST_OPCODE(ip) @ extract opcode from rINST
1861 GOTO_OPCODE(ip) @ jump to next instruction
1863 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1864 GET_INST_OPCODE(ip) @ extract opcode from rINST
1865 GOTO_OPCODE(ip) @ jump to next instruction
1869 /* ------------------------------ */
1871 .L_OP_IF_LEZ: /* 0x3d */
1872 /* File: armv5te/OP_IF_LEZ.S */
1873 /* File: armv5te/zcmp.S */
1875 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1876 * fragment that specifies the *reverse* comparison to perform, e.g.
1877 * for "if-le" you would use "gt".
1879 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1881 /* if-cmp vAA, +BBBB */
1882 mov r0, rINST, lsr #8 @ r0<- AA
1883 GET_VREG(r2, r0) @ r2<- vAA
1884 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1885 cmp r2, #0 @ compare (vA, 0)
1886 bgt 1f @ branch to 1 if comparison failed
1887 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1888 movs r9, r9, asl #1 @ convert to bytes, check sign
1889 bmi common_backwardBranch @ backward branch, do periodic checks
1891 #if defined(WITH_JIT)
1892 GET_JIT_PROF_TABLE(r0)
1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1895 bne common_updateProfile
1896 GET_INST_OPCODE(ip) @ extract opcode from rINST
1897 GOTO_OPCODE(ip) @ jump to next instruction
1899 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1900 GET_INST_OPCODE(ip) @ extract opcode from rINST
1901 GOTO_OPCODE(ip) @ jump to next instruction
1905 /* ------------------------------ */
1907 .L_OP_UNUSED_3E: /* 0x3e */
1908 /* File: armv5te/OP_UNUSED_3E.S */
1909 /* File: armv5te/unused.S */
1913 /* ------------------------------ */
1915 .L_OP_UNUSED_3F: /* 0x3f */
1916 /* File: armv5te/OP_UNUSED_3F.S */
1917 /* File: armv5te/unused.S */
1921 /* ------------------------------ */
1923 .L_OP_UNUSED_40: /* 0x40 */
1924 /* File: armv5te/OP_UNUSED_40.S */
1925 /* File: armv5te/unused.S */
1929 /* ------------------------------ */
1931 .L_OP_UNUSED_41: /* 0x41 */
1932 /* File: armv5te/OP_UNUSED_41.S */
1933 /* File: armv5te/unused.S */
1937 /* ------------------------------ */
1939 .L_OP_UNUSED_42: /* 0x42 */
1940 /* File: armv5te/OP_UNUSED_42.S */
1941 /* File: armv5te/unused.S */
1945 /* ------------------------------ */
1947 .L_OP_UNUSED_43: /* 0x43 */
1948 /* File: armv5te/OP_UNUSED_43.S */
1949 /* File: armv5te/unused.S */
1953 /* ------------------------------ */
1955 .L_OP_AGET: /* 0x44 */
1956 /* File: armv5te/OP_AGET.S */
1958 * Array get, 32 bits or less. vAA <- vBB[vCC].
1960 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1961 * instructions. We use a pair of FETCH_Bs instead.
1963 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1965 /* op vAA, vBB, vCC */
1966 FETCH_B(r2, 1, 0) @ r2<- BB
1967 mov r9, rINST, lsr #8 @ r9<- AA
1968 FETCH_B(r3, 1, 1) @ r3<- CC
1969 GET_VREG(r0, r2) @ r0<- vBB (array object)
1970 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1971 cmp r0, #0 @ null array object?
1972 beq common_errNullObject @ yes, bail
1973 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1974 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
1975 cmp r1, r3 @ compare unsigned index, length
1976 bcs common_errArrayIndex @ index >= length, bail
1977 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1978 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
1979 GET_INST_OPCODE(ip) @ extract opcode from rINST
1980 SET_VREG(r2, r9) @ vAA<- r2
1981 GOTO_OPCODE(ip) @ jump to next instruction
1983 /* ------------------------------ */
1985 .L_OP_AGET_WIDE: /* 0x45 */
1986 /* File: armv5te/OP_AGET_WIDE.S */
1988 * Array get, 64 bits. vAA <- vBB[vCC].
1990 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1992 /* aget-wide vAA, vBB, vCC */
1993 FETCH(r0, 1) @ r0<- CCBB
1994 mov r9, rINST, lsr #8 @ r9<- AA
1995 and r2, r0, #255 @ r2<- BB
1996 mov r3, r0, lsr #8 @ r3<- CC
1997 GET_VREG(r0, r2) @ r0<- vBB (array object)
1998 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1999 cmp r0, #0 @ null array object?
2000 beq common_errNullObject @ yes, bail
2001 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2002 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2003 cmp r1, r3 @ compare unsigned index, length
2004 bcc .LOP_AGET_WIDE_finish @ okay, continue below
2005 b common_errArrayIndex @ index >= length, bail
2006 @ May want to swap the order of these two branches depending on how the
2007 @ branch prediction (if any) handles conditional forward branches vs.
2008 @ unconditional forward branches.
2010 /* ------------------------------ */
2012 .L_OP_AGET_OBJECT: /* 0x46 */
2013 /* File: armv5te/OP_AGET_OBJECT.S */
2014 /* File: armv5te/OP_AGET.S */
2016 * Array get, 32 bits or less. vAA <- vBB[vCC].
2018 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2019 * instructions. We use a pair of FETCH_Bs instead.
2021 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2023 /* op vAA, vBB, vCC */
2024 FETCH_B(r2, 1, 0) @ r2<- BB
2025 mov r9, rINST, lsr #8 @ r9<- AA
2026 FETCH_B(r3, 1, 1) @ r3<- CC
2027 GET_VREG(r0, r2) @ r0<- vBB (array object)
2028 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2029 cmp r0, #0 @ null array object?
2030 beq common_errNullObject @ yes, bail
2031 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2032 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2033 cmp r1, r3 @ compare unsigned index, length
2034 bcs common_errArrayIndex @ index >= length, bail
2035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2036 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2037 GET_INST_OPCODE(ip) @ extract opcode from rINST
2038 SET_VREG(r2, r9) @ vAA<- r2
2039 GOTO_OPCODE(ip) @ jump to next instruction
2042 /* ------------------------------ */
2044 .L_OP_AGET_BOOLEAN: /* 0x47 */
2045 /* File: armv5te/OP_AGET_BOOLEAN.S */
2046 /* File: armv5te/OP_AGET.S */
2048 * Array get, 32 bits or less. vAA <- vBB[vCC].
2050 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2051 * instructions. We use a pair of FETCH_Bs instead.
2053 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2055 /* op vAA, vBB, vCC */
2056 FETCH_B(r2, 1, 0) @ r2<- BB
2057 mov r9, rINST, lsr #8 @ r9<- AA
2058 FETCH_B(r3, 1, 1) @ r3<- CC
2059 GET_VREG(r0, r2) @ r0<- vBB (array object)
2060 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2061 cmp r0, #0 @ null array object?
2062 beq common_errNullObject @ yes, bail
2063 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2064 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2065 cmp r1, r3 @ compare unsigned index, length
2066 bcs common_errArrayIndex @ index >= length, bail
2067 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2068 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2069 GET_INST_OPCODE(ip) @ extract opcode from rINST
2070 SET_VREG(r2, r9) @ vAA<- r2
2071 GOTO_OPCODE(ip) @ jump to next instruction
2074 /* ------------------------------ */
2076 .L_OP_AGET_BYTE: /* 0x48 */
2077 /* File: armv5te/OP_AGET_BYTE.S */
2078 /* File: armv5te/OP_AGET.S */
2080 * Array get, 32 bits or less. vAA <- vBB[vCC].
2082 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2083 * instructions. We use a pair of FETCH_Bs instead.
2085 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2087 /* op vAA, vBB, vCC */
2088 FETCH_B(r2, 1, 0) @ r2<- BB
2089 mov r9, rINST, lsr #8 @ r9<- AA
2090 FETCH_B(r3, 1, 1) @ r3<- CC
2091 GET_VREG(r0, r2) @ r0<- vBB (array object)
2092 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2093 cmp r0, #0 @ null array object?
2094 beq common_errNullObject @ yes, bail
2095 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2096 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2097 cmp r1, r3 @ compare unsigned index, length
2098 bcs common_errArrayIndex @ index >= length, bail
2099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2100 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2101 GET_INST_OPCODE(ip) @ extract opcode from rINST
2102 SET_VREG(r2, r9) @ vAA<- r2
2103 GOTO_OPCODE(ip) @ jump to next instruction
2106 /* ------------------------------ */
2108 .L_OP_AGET_CHAR: /* 0x49 */
2109 /* File: armv5te/OP_AGET_CHAR.S */
2110 /* File: armv5te/OP_AGET.S */
2112 * Array get, 32 bits or less. vAA <- vBB[vCC].
2114 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2115 * instructions. We use a pair of FETCH_Bs instead.
2117 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2119 /* op vAA, vBB, vCC */
2120 FETCH_B(r2, 1, 0) @ r2<- BB
2121 mov r9, rINST, lsr #8 @ r9<- AA
2122 FETCH_B(r3, 1, 1) @ r3<- CC
2123 GET_VREG(r0, r2) @ r0<- vBB (array object)
2124 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2125 cmp r0, #0 @ null array object?
2126 beq common_errNullObject @ yes, bail
2127 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2128 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2129 cmp r1, r3 @ compare unsigned index, length
2130 bcs common_errArrayIndex @ index >= length, bail
2131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2132 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2133 GET_INST_OPCODE(ip) @ extract opcode from rINST
2134 SET_VREG(r2, r9) @ vAA<- r2
2135 GOTO_OPCODE(ip) @ jump to next instruction
2138 /* ------------------------------ */
2140 .L_OP_AGET_SHORT: /* 0x4a */
2141 /* File: armv5te/OP_AGET_SHORT.S */
2142 /* File: armv5te/OP_AGET.S */
2144 * Array get, 32 bits or less. vAA <- vBB[vCC].
2146 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2147 * instructions. We use a pair of FETCH_Bs instead.
2149 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2151 /* op vAA, vBB, vCC */
2152 FETCH_B(r2, 1, 0) @ r2<- BB
2153 mov r9, rINST, lsr #8 @ r9<- AA
2154 FETCH_B(r3, 1, 1) @ r3<- CC
2155 GET_VREG(r0, r2) @ r0<- vBB (array object)
2156 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2157 cmp r0, #0 @ null array object?
2158 beq common_errNullObject @ yes, bail
2159 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2160 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2161 cmp r1, r3 @ compare unsigned index, length
2162 bcs common_errArrayIndex @ index >= length, bail
2163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2164 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2165 GET_INST_OPCODE(ip) @ extract opcode from rINST
2166 SET_VREG(r2, r9) @ vAA<- r2
2167 GOTO_OPCODE(ip) @ jump to next instruction
2170 /* ------------------------------ */
2172 .L_OP_APUT: /* 0x4b */
2173 /* File: armv5te/OP_APUT.S */
2175 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2177 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2178 * instructions. We use a pair of FETCH_Bs instead.
2180 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2182 /* op vAA, vBB, vCC */
2183 FETCH_B(r2, 1, 0) @ r2<- BB
2184 mov r9, rINST, lsr #8 @ r9<- AA
2185 FETCH_B(r3, 1, 1) @ r3<- CC
2186 GET_VREG(r0, r2) @ r0<- vBB (array object)
2187 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2188 cmp r0, #0 @ null array object?
2189 beq common_errNullObject @ yes, bail
2190 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2191 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2192 cmp r1, r3 @ compare unsigned index, length
2193 bcs common_errArrayIndex @ index >= length, bail
2194 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2195 GET_VREG(r2, r9) @ r2<- vAA
2196 GET_INST_OPCODE(ip) @ extract opcode from rINST
2197 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2198 GOTO_OPCODE(ip) @ jump to next instruction
2200 /* ------------------------------ */
2202 .L_OP_APUT_WIDE: /* 0x4c */
2203 /* File: armv5te/OP_APUT_WIDE.S */
2205 * Array put, 64 bits. vBB[vCC] <- vAA.
2207 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2209 /* aput-wide vAA, vBB, vCC */
2210 FETCH(r0, 1) @ r0<- CCBB
2211 mov r9, rINST, lsr #8 @ r9<- AA
2212 and r2, r0, #255 @ r2<- BB
2213 mov r3, r0, lsr #8 @ r3<- CC
2214 GET_VREG(r0, r2) @ r0<- vBB (array object)
2215 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2216 cmp r0, #0 @ null array object?
2217 beq common_errNullObject @ yes, bail
2218 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2219 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2220 cmp r1, r3 @ compare unsigned index, length
2221 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2222 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2223 b common_errArrayIndex @ index >= length, bail
2224 @ May want to swap the order of these two branches depending on how the
2225 @ branch prediction (if any) handles conditional forward branches vs.
2226 @ unconditional forward branches.
2228 /* ------------------------------ */
2230 .L_OP_APUT_OBJECT: /* 0x4d */
2231 /* File: armv5te/OP_APUT_OBJECT.S */
2233 * Store an object into an array. vBB[vCC] <- vAA.
2235 /* op vAA, vBB, vCC */
2236 FETCH(r0, 1) @ r0<- CCBB
2237 mov r9, rINST, lsr #8 @ r9<- AA
2238 and r2, r0, #255 @ r2<- BB
2239 mov r3, r0, lsr #8 @ r3<- CC
2240 GET_VREG(rINST, r2) @ rINST<- vBB (array object)
2241 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2242 cmp rINST, #0 @ null array object?
2243 GET_VREG(r9, r9) @ r9<- vAA
2244 beq common_errNullObject @ yes, bail
2245 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length
2246 add r10, rINST, r1, lsl #2 @ r10<- arrayObj + index*width
2247 cmp r1, r3 @ compare unsigned index, length
2248 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2249 b common_errArrayIndex @ index >= length, bail
2252 /* ------------------------------ */
2254 .L_OP_APUT_BOOLEAN: /* 0x4e */
2255 /* File: armv5te/OP_APUT_BOOLEAN.S */
2256 /* File: armv5te/OP_APUT.S */
2258 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2260 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2261 * instructions. We use a pair of FETCH_Bs instead.
2263 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2265 /* op vAA, vBB, vCC */
2266 FETCH_B(r2, 1, 0) @ r2<- BB
2267 mov r9, rINST, lsr #8 @ r9<- AA
2268 FETCH_B(r3, 1, 1) @ r3<- CC
2269 GET_VREG(r0, r2) @ r0<- vBB (array object)
2270 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2271 cmp r0, #0 @ null array object?
2272 beq common_errNullObject @ yes, bail
2273 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2274 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2275 cmp r1, r3 @ compare unsigned index, length
2276 bcs common_errArrayIndex @ index >= length, bail
2277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2278 GET_VREG(r2, r9) @ r2<- vAA
2279 GET_INST_OPCODE(ip) @ extract opcode from rINST
2280 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2281 GOTO_OPCODE(ip) @ jump to next instruction
2284 /* ------------------------------ */
2286 .L_OP_APUT_BYTE: /* 0x4f */
2287 /* File: armv5te/OP_APUT_BYTE.S */
2288 /* File: armv5te/OP_APUT.S */
2290 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2292 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2293 * instructions. We use a pair of FETCH_Bs instead.
2295 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2297 /* op vAA, vBB, vCC */
2298 FETCH_B(r2, 1, 0) @ r2<- BB
2299 mov r9, rINST, lsr #8 @ r9<- AA
2300 FETCH_B(r3, 1, 1) @ r3<- CC
2301 GET_VREG(r0, r2) @ r0<- vBB (array object)
2302 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2303 cmp r0, #0 @ null array object?
2304 beq common_errNullObject @ yes, bail
2305 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2306 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2307 cmp r1, r3 @ compare unsigned index, length
2308 bcs common_errArrayIndex @ index >= length, bail
2309 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2310 GET_VREG(r2, r9) @ r2<- vAA
2311 GET_INST_OPCODE(ip) @ extract opcode from rINST
2312 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2313 GOTO_OPCODE(ip) @ jump to next instruction
2316 /* ------------------------------ */
2318 .L_OP_APUT_CHAR: /* 0x50 */
2319 /* File: armv5te/OP_APUT_CHAR.S */
2320 /* File: armv5te/OP_APUT.S */
2322 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2324 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2325 * instructions. We use a pair of FETCH_Bs instead.
2327 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2329 /* op vAA, vBB, vCC */
2330 FETCH_B(r2, 1, 0) @ r2<- BB
2331 mov r9, rINST, lsr #8 @ r9<- AA
2332 FETCH_B(r3, 1, 1) @ r3<- CC
2333 GET_VREG(r0, r2) @ r0<- vBB (array object)
2334 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2335 cmp r0, #0 @ null array object?
2336 beq common_errNullObject @ yes, bail
2337 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2338 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2339 cmp r1, r3 @ compare unsigned index, length
2340 bcs common_errArrayIndex @ index >= length, bail
2341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2342 GET_VREG(r2, r9) @ r2<- vAA
2343 GET_INST_OPCODE(ip) @ extract opcode from rINST
2344 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2345 GOTO_OPCODE(ip) @ jump to next instruction
2348 /* ------------------------------ */
2350 .L_OP_APUT_SHORT: /* 0x51 */
2351 /* File: armv5te/OP_APUT_SHORT.S */
2352 /* File: armv5te/OP_APUT.S */
2354 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2356 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2357 * instructions. We use a pair of FETCH_Bs instead.
2359 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2361 /* op vAA, vBB, vCC */
2362 FETCH_B(r2, 1, 0) @ r2<- BB
2363 mov r9, rINST, lsr #8 @ r9<- AA
2364 FETCH_B(r3, 1, 1) @ r3<- CC
2365 GET_VREG(r0, r2) @ r0<- vBB (array object)
2366 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2367 cmp r0, #0 @ null array object?
2368 beq common_errNullObject @ yes, bail
2369 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2370 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2371 cmp r1, r3 @ compare unsigned index, length
2372 bcs common_errArrayIndex @ index >= length, bail
2373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2374 GET_VREG(r2, r9) @ r2<- vAA
2375 GET_INST_OPCODE(ip) @ extract opcode from rINST
2376 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2377 GOTO_OPCODE(ip) @ jump to next instruction
2380 /* ------------------------------ */
2382 .L_OP_IGET: /* 0x52 */
2383 /* File: armv5te/OP_IGET.S */
2385 * General 32-bit instance field get.
2387 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2389 /* op vA, vB, field@CCCC */
2390 mov r0, rINST, lsr #12 @ r0<- B
2391 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2392 FETCH(r1, 1) @ r1<- field ref CCCC
2393 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2394 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2395 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2396 cmp r0, #0 @ is resolved entry null?
2397 bne .LOP_IGET_finish @ no, already resolved
2398 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2399 EXPORT_PC() @ resolve() could throw
2400 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2401 bl dvmResolveInstField @ r0<- resolved InstField ptr
2403 bne .LOP_IGET_finish
2404 b common_exceptionThrown
2406 /* ------------------------------ */
2408 .L_OP_IGET_WIDE: /* 0x53 */
2409 /* File: armv5te/OP_IGET_WIDE.S */
2411 * Wide 32-bit instance field get.
2413 /* iget-wide vA, vB, field@CCCC */
2414 mov r0, rINST, lsr #12 @ r0<- B
2415 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2416 FETCH(r1, 1) @ r1<- field ref CCCC
2417 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2418 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2419 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2420 cmp r0, #0 @ is resolved entry null?
2421 bne .LOP_IGET_WIDE_finish @ no, already resolved
2422 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2423 EXPORT_PC() @ resolve() could throw
2424 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2425 bl dvmResolveInstField @ r0<- resolved InstField ptr
2427 bne .LOP_IGET_WIDE_finish
2428 b common_exceptionThrown
2430 /* ------------------------------ */
2432 .L_OP_IGET_OBJECT: /* 0x54 */
2433 /* File: armv5te/OP_IGET_OBJECT.S */
2434 /* File: armv5te/OP_IGET.S */
2436 * General 32-bit instance field get.
2438 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2440 /* op vA, vB, field@CCCC */
2441 mov r0, rINST, lsr #12 @ r0<- B
2442 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2443 FETCH(r1, 1) @ r1<- field ref CCCC
2444 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2445 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2446 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2447 cmp r0, #0 @ is resolved entry null?
2448 bne .LOP_IGET_OBJECT_finish @ no, already resolved
2449 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2450 EXPORT_PC() @ resolve() could throw
2451 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2452 bl dvmResolveInstField @ r0<- resolved InstField ptr
2454 bne .LOP_IGET_OBJECT_finish
2455 b common_exceptionThrown
2458 /* ------------------------------ */
2460 .L_OP_IGET_BOOLEAN: /* 0x55 */
2461 /* File: armv5te/OP_IGET_BOOLEAN.S */
2462 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
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_BOOLEAN_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_BOOLEAN_finish
2484 b common_exceptionThrown
2487 /* ------------------------------ */
2489 .L_OP_IGET_BYTE: /* 0x56 */
2490 /* File: armv5te/OP_IGET_BYTE.S */
2491 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2492 /* File: armv5te/OP_IGET.S */
2494 * General 32-bit instance field get.
2496 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2498 /* op vA, vB, field@CCCC */
2499 mov r0, rINST, lsr #12 @ r0<- B
2500 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2501 FETCH(r1, 1) @ r1<- field ref CCCC
2502 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2503 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2504 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2505 cmp r0, #0 @ is resolved entry null?
2506 bne .LOP_IGET_BYTE_finish @ no, already resolved
2507 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2508 EXPORT_PC() @ resolve() could throw
2509 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2510 bl dvmResolveInstField @ r0<- resolved InstField ptr
2512 bne .LOP_IGET_BYTE_finish
2513 b common_exceptionThrown
2516 /* ------------------------------ */
2518 .L_OP_IGET_CHAR: /* 0x57 */
2519 /* File: armv5te/OP_IGET_CHAR.S */
2520 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2521 /* File: armv5te/OP_IGET.S */
2523 * General 32-bit instance field get.
2525 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2527 /* op vA, vB, field@CCCC */
2528 mov r0, rINST, lsr #12 @ r0<- B
2529 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2530 FETCH(r1, 1) @ r1<- field ref CCCC
2531 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2533 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2534 cmp r0, #0 @ is resolved entry null?
2535 bne .LOP_IGET_CHAR_finish @ no, already resolved
2536 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2537 EXPORT_PC() @ resolve() could throw
2538 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2539 bl dvmResolveInstField @ r0<- resolved InstField ptr
2541 bne .LOP_IGET_CHAR_finish
2542 b common_exceptionThrown
2545 /* ------------------------------ */
2547 .L_OP_IGET_SHORT: /* 0x58 */
2548 /* File: armv5te/OP_IGET_SHORT.S */
2549 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2550 /* File: armv5te/OP_IGET.S */
2552 * General 32-bit instance field get.
2554 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2556 /* op vA, vB, field@CCCC */
2557 mov r0, rINST, lsr #12 @ r0<- B
2558 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2559 FETCH(r1, 1) @ r1<- field ref CCCC
2560 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2562 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2563 cmp r0, #0 @ is resolved entry null?
2564 bne .LOP_IGET_SHORT_finish @ no, already resolved
2565 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2566 EXPORT_PC() @ resolve() could throw
2567 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2568 bl dvmResolveInstField @ r0<- resolved InstField ptr
2570 bne .LOP_IGET_SHORT_finish
2571 b common_exceptionThrown
2574 /* ------------------------------ */
2576 .L_OP_IPUT: /* 0x59 */
2577 /* File: armv5te/OP_IPUT.S */
2579 * General 32-bit instance field put.
2581 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2583 /* op vA, vB, field@CCCC */
2584 mov r0, rINST, lsr #12 @ r0<- B
2585 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2586 FETCH(r1, 1) @ r1<- field ref CCCC
2587 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2589 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2590 cmp r0, #0 @ is resolved entry null?
2591 bne .LOP_IPUT_finish @ no, already resolved
2592 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2593 EXPORT_PC() @ resolve() could throw
2594 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2595 bl dvmResolveInstField @ r0<- resolved InstField ptr
2596 cmp r0, #0 @ success?
2597 bne .LOP_IPUT_finish @ yes, finish up
2598 b common_exceptionThrown
2600 /* ------------------------------ */
2602 .L_OP_IPUT_WIDE: /* 0x5a */
2603 /* File: armv5te/OP_IPUT_WIDE.S */
2604 /* iput-wide vA, vB, field@CCCC */
2605 mov r0, rINST, lsr #12 @ r0<- B
2606 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2607 FETCH(r1, 1) @ r1<- field ref CCCC
2608 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2609 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2610 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2611 cmp r0, #0 @ is resolved entry null?
2612 bne .LOP_IPUT_WIDE_finish @ no, already resolved
2613 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2614 EXPORT_PC() @ resolve() could throw
2615 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2616 bl dvmResolveInstField @ r0<- resolved InstField ptr
2617 cmp r0, #0 @ success?
2618 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2619 b common_exceptionThrown
2621 /* ------------------------------ */
2623 .L_OP_IPUT_OBJECT: /* 0x5b */
2624 /* File: armv5te/OP_IPUT_OBJECT.S */
2626 * 32-bit instance field put.
2628 * for: iput-object, iput-object-volatile
2630 /* op vA, vB, field@CCCC */
2631 mov r0, rINST, lsr #12 @ r0<- B
2632 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2633 FETCH(r1, 1) @ r1<- field ref CCCC
2634 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2636 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2637 cmp r0, #0 @ is resolved entry null?
2638 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
2639 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2640 EXPORT_PC() @ resolve() could throw
2641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2642 bl dvmResolveInstField @ r0<- resolved InstField ptr
2643 cmp r0, #0 @ success?
2644 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2645 b common_exceptionThrown
2647 /* ------------------------------ */
2649 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2650 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2651 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2652 /* File: armv5te/OP_IPUT.S */
2654 * General 32-bit instance field put.
2656 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2658 /* op vA, vB, field@CCCC */
2659 mov r0, rINST, lsr #12 @ r0<- B
2660 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2661 FETCH(r1, 1) @ r1<- field ref CCCC
2662 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2663 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2664 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2665 cmp r0, #0 @ is resolved entry null?
2666 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
2667 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2668 EXPORT_PC() @ resolve() could throw
2669 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2670 bl dvmResolveInstField @ r0<- resolved InstField ptr
2671 cmp r0, #0 @ success?
2672 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2673 b common_exceptionThrown
2676 /* ------------------------------ */
2678 .L_OP_IPUT_BYTE: /* 0x5d */
2679 /* File: armv5te/OP_IPUT_BYTE.S */
2680 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2681 /* File: armv5te/OP_IPUT.S */
2683 * General 32-bit instance field put.
2685 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2687 /* op vA, vB, field@CCCC */
2688 mov r0, rINST, lsr #12 @ r0<- B
2689 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2690 FETCH(r1, 1) @ r1<- field ref CCCC
2691 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2692 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2693 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2694 cmp r0, #0 @ is resolved entry null?
2695 bne .LOP_IPUT_BYTE_finish @ no, already resolved
2696 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2697 EXPORT_PC() @ resolve() could throw
2698 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2699 bl dvmResolveInstField @ r0<- resolved InstField ptr
2700 cmp r0, #0 @ success?
2701 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2702 b common_exceptionThrown
2705 /* ------------------------------ */
2707 .L_OP_IPUT_CHAR: /* 0x5e */
2708 /* File: armv5te/OP_IPUT_CHAR.S */
2709 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2710 /* File: armv5te/OP_IPUT.S */
2712 * General 32-bit instance field put.
2714 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2716 /* op vA, vB, field@CCCC */
2717 mov r0, rINST, lsr #12 @ r0<- B
2718 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2719 FETCH(r1, 1) @ r1<- field ref CCCC
2720 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2721 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2722 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2723 cmp r0, #0 @ is resolved entry null?
2724 bne .LOP_IPUT_CHAR_finish @ no, already resolved
2725 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2726 EXPORT_PC() @ resolve() could throw
2727 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2728 bl dvmResolveInstField @ r0<- resolved InstField ptr
2729 cmp r0, #0 @ success?
2730 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2731 b common_exceptionThrown
2734 /* ------------------------------ */
2736 .L_OP_IPUT_SHORT: /* 0x5f */
2737 /* File: armv5te/OP_IPUT_SHORT.S */
2738 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2739 /* File: armv5te/OP_IPUT.S */
2741 * General 32-bit instance field put.
2743 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2745 /* op vA, vB, field@CCCC */
2746 mov r0, rINST, lsr #12 @ r0<- B
2747 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2748 FETCH(r1, 1) @ r1<- field ref CCCC
2749 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2750 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2751 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2752 cmp r0, #0 @ is resolved entry null?
2753 bne .LOP_IPUT_SHORT_finish @ no, already resolved
2754 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2755 EXPORT_PC() @ resolve() could throw
2756 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2757 bl dvmResolveInstField @ r0<- resolved InstField ptr
2758 cmp r0, #0 @ success?
2759 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2760 b common_exceptionThrown
2763 /* ------------------------------ */
2765 .L_OP_SGET: /* 0x60 */
2766 /* File: armv5te/OP_SGET.S */
2768 * General 32-bit SGET handler.
2770 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2772 /* op vAA, field@BBBB */
2773 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2774 FETCH(r1, 1) @ r1<- field ref BBBB
2775 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2776 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2777 cmp r0, #0 @ is resolved entry null?
2778 beq .LOP_SGET_resolve @ yes, do resolve
2779 .LOP_SGET_finish: @ field ptr in r0
2780 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2781 @ no-op @ acquiring load
2782 mov r2, rINST, lsr #8 @ r2<- AA
2783 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2784 SET_VREG(r1, r2) @ fp[AA]<- r1
2785 GET_INST_OPCODE(ip) @ extract opcode from rINST
2786 GOTO_OPCODE(ip) @ jump to next instruction
2788 /* ------------------------------ */
2790 .L_OP_SGET_WIDE: /* 0x61 */
2791 /* File: armv5te/OP_SGET_WIDE.S */
2793 * 64-bit SGET handler.
2795 /* sget-wide vAA, field@BBBB */
2796 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2797 FETCH(r1, 1) @ r1<- field ref BBBB
2798 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2799 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2800 cmp r0, #0 @ is resolved entry null?
2801 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2802 .LOP_SGET_WIDE_finish:
2803 mov r9, rINST, lsr #8 @ r9<- AA
2805 add r0, r0, #offStaticField_value @ r0<- pointer to data
2806 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field
2808 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2810 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2811 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2812 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
2813 GET_INST_OPCODE(ip) @ extract opcode from rINST
2814 GOTO_OPCODE(ip) @ jump to next instruction
2816 /* ------------------------------ */
2818 .L_OP_SGET_OBJECT: /* 0x62 */
2819 /* File: armv5te/OP_SGET_OBJECT.S */
2820 /* File: armv5te/OP_SGET.S */
2822 * General 32-bit SGET handler.
2824 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2826 /* op vAA, field@BBBB */
2827 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2828 FETCH(r1, 1) @ r1<- field ref BBBB
2829 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2830 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2831 cmp r0, #0 @ is resolved entry null?
2832 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2833 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2834 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2835 @ no-op @ acquiring load
2836 mov r2, rINST, lsr #8 @ r2<- AA
2837 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2838 SET_VREG(r1, r2) @ fp[AA]<- r1
2839 GET_INST_OPCODE(ip) @ extract opcode from rINST
2840 GOTO_OPCODE(ip) @ jump to next instruction
2843 /* ------------------------------ */
2845 .L_OP_SGET_BOOLEAN: /* 0x63 */
2846 /* File: armv5te/OP_SGET_BOOLEAN.S */
2847 /* File: armv5te/OP_SGET.S */
2849 * General 32-bit SGET handler.
2851 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2853 /* op vAA, field@BBBB */
2854 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2855 FETCH(r1, 1) @ r1<- field ref BBBB
2856 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2858 cmp r0, #0 @ is resolved entry null?
2859 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2860 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2861 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2862 @ no-op @ acquiring load
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
2870 /* ------------------------------ */
2872 .L_OP_SGET_BYTE: /* 0x64 */
2873 /* File: armv5te/OP_SGET_BYTE.S */
2874 /* File: armv5te/OP_SGET.S */
2876 * General 32-bit SGET handler.
2878 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2880 /* op vAA, field@BBBB */
2881 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2882 FETCH(r1, 1) @ r1<- field ref BBBB
2883 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2885 cmp r0, #0 @ is resolved entry null?
2886 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2887 .LOP_SGET_BYTE_finish: @ field ptr in r0
2888 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2889 @ no-op @ acquiring load
2890 mov r2, rINST, lsr #8 @ r2<- AA
2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2892 SET_VREG(r1, r2) @ fp[AA]<- r1
2893 GET_INST_OPCODE(ip) @ extract opcode from rINST
2894 GOTO_OPCODE(ip) @ jump to next instruction
2897 /* ------------------------------ */
2899 .L_OP_SGET_CHAR: /* 0x65 */
2900 /* File: armv5te/OP_SGET_CHAR.S */
2901 /* File: armv5te/OP_SGET.S */
2903 * General 32-bit SGET handler.
2905 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2907 /* op vAA, field@BBBB */
2908 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2909 FETCH(r1, 1) @ r1<- field ref BBBB
2910 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2912 cmp r0, #0 @ is resolved entry null?
2913 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2914 .LOP_SGET_CHAR_finish: @ field ptr in r0
2915 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2916 @ no-op @ acquiring load
2917 mov r2, rINST, lsr #8 @ r2<- AA
2918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2919 SET_VREG(r1, r2) @ fp[AA]<- r1
2920 GET_INST_OPCODE(ip) @ extract opcode from rINST
2921 GOTO_OPCODE(ip) @ jump to next instruction
2924 /* ------------------------------ */
2926 .L_OP_SGET_SHORT: /* 0x66 */
2927 /* File: armv5te/OP_SGET_SHORT.S */
2928 /* File: armv5te/OP_SGET.S */
2930 * General 32-bit SGET handler.
2932 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2934 /* op vAA, field@BBBB */
2935 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2936 FETCH(r1, 1) @ r1<- field ref BBBB
2937 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2939 cmp r0, #0 @ is resolved entry null?
2940 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
2941 .LOP_SGET_SHORT_finish: @ field ptr in r0
2942 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2943 @ no-op @ acquiring load
2944 mov r2, rINST, lsr #8 @ r2<- AA
2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2946 SET_VREG(r1, r2) @ fp[AA]<- r1
2947 GET_INST_OPCODE(ip) @ extract opcode from rINST
2948 GOTO_OPCODE(ip) @ jump to next instruction
2951 /* ------------------------------ */
2953 .L_OP_SPUT: /* 0x67 */
2954 /* File: armv5te/OP_SPUT.S */
2956 * General 32-bit SPUT handler.
2958 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2960 /* op vAA, field@BBBB */
2961 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2962 FETCH(r1, 1) @ r1<- field ref BBBB
2963 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2964 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2965 cmp r0, #0 @ is resolved entry null?
2966 beq .LOP_SPUT_resolve @ yes, do resolve
2967 .LOP_SPUT_finish: @ field ptr in r0
2968 mov r2, rINST, lsr #8 @ r2<- AA
2969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2970 GET_VREG(r1, r2) @ r1<- fp[AA]
2971 GET_INST_OPCODE(ip) @ extract opcode from rINST
2972 @ no-op @ releasing store
2973 str r1, [r0, #offStaticField_value] @ field<- vAA
2974 GOTO_OPCODE(ip) @ jump to next instruction
2976 /* ------------------------------ */
2978 .L_OP_SPUT_WIDE: /* 0x68 */
2979 /* File: armv5te/OP_SPUT_WIDE.S */
2981 * 64-bit SPUT handler.
2983 /* sput-wide vAA, field@BBBB */
2984 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
2985 FETCH(r1, 1) @ r1<- field ref BBBB
2986 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2987 mov r9, rINST, lsr #8 @ r9<- AA
2988 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
2989 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2990 cmp r2, #0 @ is resolved entry null?
2991 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
2992 .LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2994 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
2995 GET_INST_OPCODE(r10) @ extract opcode from rINST
2997 add r2, r2, #offStaticField_value @ r2<- pointer to data
2998 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2
3000 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3002 GOTO_OPCODE(r10) @ jump to next instruction
3004 /* ------------------------------ */
3006 .L_OP_SPUT_OBJECT: /* 0x69 */
3007 /* File: armv5te/OP_SPUT_OBJECT.S */
3009 * 32-bit SPUT handler for objects
3011 * for: sput-object, sput-object-volatile
3013 /* op vAA, field@BBBB */
3014 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3015 FETCH(r1, 1) @ r1<- field ref BBBB
3016 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3017 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3018 cmp r0, #0 @ is resolved entry null?
3019 bne .LOP_SPUT_OBJECT_finish @ no, continue
3020 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3021 EXPORT_PC() @ resolve() could throw, so export now
3022 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz
3023 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
3024 cmp r0, #0 @ success?
3025 bne .LOP_SPUT_OBJECT_finish @ yes, finish
3026 b common_exceptionThrown @ no, handle exception
3029 /* ------------------------------ */
3031 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3032 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3033 /* File: armv5te/OP_SPUT.S */
3035 * General 32-bit SPUT handler.
3037 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3039 /* op vAA, field@BBBB */
3040 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3041 FETCH(r1, 1) @ r1<- field ref BBBB
3042 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3043 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3044 cmp r0, #0 @ is resolved entry null?
3045 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve
3046 .LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
3047 mov r2, rINST, lsr #8 @ r2<- AA
3048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3049 GET_VREG(r1, r2) @ r1<- fp[AA]
3050 GET_INST_OPCODE(ip) @ extract opcode from rINST
3051 @ no-op @ releasing store
3052 str r1, [r0, #offStaticField_value] @ field<- vAA
3053 GOTO_OPCODE(ip) @ jump to next instruction
3056 /* ------------------------------ */
3058 .L_OP_SPUT_BYTE: /* 0x6b */
3059 /* File: armv5te/OP_SPUT_BYTE.S */
3060 /* File: armv5te/OP_SPUT.S */
3062 * General 32-bit SPUT handler.
3064 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3066 /* op vAA, field@BBBB */
3067 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3068 FETCH(r1, 1) @ r1<- field ref BBBB
3069 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3071 cmp r0, #0 @ is resolved entry null?
3072 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve
3073 .LOP_SPUT_BYTE_finish: @ field ptr in r0
3074 mov r2, rINST, lsr #8 @ r2<- AA
3075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3076 GET_VREG(r1, r2) @ r1<- fp[AA]
3077 GET_INST_OPCODE(ip) @ extract opcode from rINST
3078 @ no-op @ releasing store
3079 str r1, [r0, #offStaticField_value] @ field<- vAA
3080 GOTO_OPCODE(ip) @ jump to next instruction
3083 /* ------------------------------ */
3085 .L_OP_SPUT_CHAR: /* 0x6c */
3086 /* File: armv5te/OP_SPUT_CHAR.S */
3087 /* File: armv5te/OP_SPUT.S */
3089 * General 32-bit SPUT handler.
3091 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3093 /* op vAA, field@BBBB */
3094 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3095 FETCH(r1, 1) @ r1<- field ref BBBB
3096 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3098 cmp r0, #0 @ is resolved entry null?
3099 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve
3100 .LOP_SPUT_CHAR_finish: @ field ptr in r0
3101 mov r2, rINST, lsr #8 @ r2<- AA
3102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3103 GET_VREG(r1, r2) @ r1<- fp[AA]
3104 GET_INST_OPCODE(ip) @ extract opcode from rINST
3105 @ no-op @ releasing store
3106 str r1, [r0, #offStaticField_value] @ field<- vAA
3107 GOTO_OPCODE(ip) @ jump to next instruction
3110 /* ------------------------------ */
3112 .L_OP_SPUT_SHORT: /* 0x6d */
3113 /* File: armv5te/OP_SPUT_SHORT.S */
3114 /* File: armv5te/OP_SPUT.S */
3116 * General 32-bit SPUT handler.
3118 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3120 /* op vAA, field@BBBB */
3121 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3122 FETCH(r1, 1) @ r1<- field ref BBBB
3123 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3125 cmp r0, #0 @ is resolved entry null?
3126 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve
3127 .LOP_SPUT_SHORT_finish: @ field ptr in r0
3128 mov r2, rINST, lsr #8 @ r2<- AA
3129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3130 GET_VREG(r1, r2) @ r1<- fp[AA]
3131 GET_INST_OPCODE(ip) @ extract opcode from rINST
3132 @ no-op @ releasing store
3133 str r1, [r0, #offStaticField_value] @ field<- vAA
3134 GOTO_OPCODE(ip) @ jump to next instruction
3137 /* ------------------------------ */
3139 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3140 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3142 * Handle a virtual method call.
3144 * for: invoke-virtual, invoke-virtual/range
3146 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3147 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3148 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3149 FETCH(r1, 1) @ r1<- BBBB
3150 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3151 FETCH(r10, 2) @ r10<- GFED or CCCC
3152 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3154 and r10, r10, #15 @ r10<- D (or stays CCCC)
3156 cmp r0, #0 @ already resolved?
3157 EXPORT_PC() @ must export for invoke
3158 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3159 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3160 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3161 mov r2, #METHOD_VIRTUAL @ resolver method type
3162 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3163 cmp r0, #0 @ got null?
3164 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3165 b common_exceptionThrown @ yes, handle exception
3167 /* ------------------------------ */
3169 .L_OP_INVOKE_SUPER: /* 0x6f */
3170 /* File: armv5te/OP_INVOKE_SUPER.S */
3172 * Handle a "super" method call.
3174 * for: invoke-super, invoke-super/range
3176 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178 FETCH(r10, 2) @ r10<- GFED or CCCC
3179 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3181 and r10, r10, #15 @ r10<- D (or stays CCCC)
3183 FETCH(r1, 1) @ r1<- BBBB
3184 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3185 GET_VREG(r2, r10) @ r2<- "this" ptr
3186 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3187 cmp r2, #0 @ null "this"?
3188 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3189 beq common_errNullObject @ null "this", throw exception
3190 cmp r0, #0 @ already resolved?
3191 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3192 EXPORT_PC() @ must export for invoke
3193 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3194 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3196 /* ------------------------------ */
3198 .L_OP_INVOKE_DIRECT: /* 0x70 */
3199 /* File: armv5te/OP_INVOKE_DIRECT.S */
3201 * Handle a direct method call.
3203 * (We could defer the "is 'this' pointer null" test to the common
3204 * method invocation code, and use a flag to indicate that static
3205 * calls don't count. If we do this as part of copying the arguments
3206 * out we could avoiding loading the first arg twice.)
3208 * for: invoke-direct, invoke-direct/range
3210 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3211 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3212 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3213 FETCH(r1, 1) @ r1<- BBBB
3214 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3215 FETCH(r10, 2) @ r10<- GFED or CCCC
3216 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3218 and r10, r10, #15 @ r10<- D (or stays CCCC)
3220 cmp r0, #0 @ already resolved?
3221 EXPORT_PC() @ must export for invoke
3222 GET_VREG(r2, r10) @ r2<- "this" ptr
3223 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3224 .LOP_INVOKE_DIRECT_finish:
3225 cmp r2, #0 @ null "this" ref?
3226 bne common_invokeMethodNoRange @ no, continue on
3227 b common_errNullObject @ yes, throw exception
3229 /* ------------------------------ */
3231 .L_OP_INVOKE_STATIC: /* 0x71 */
3232 /* File: armv5te/OP_INVOKE_STATIC.S */
3234 * Handle a static method call.
3236 * for: invoke-static, invoke-static/range
3238 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3241 FETCH(r1, 1) @ r1<- BBBB
3242 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3243 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3244 cmp r0, #0 @ already resolved?
3245 EXPORT_PC() @ must export for invoke
3246 bne common_invokeMethodNoRange @ yes, continue on
3247 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3248 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3249 mov r2, #METHOD_STATIC @ resolver method type
3250 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3251 cmp r0, #0 @ got null?
3252 bne common_invokeMethodNoRange @ no, continue
3253 b common_exceptionThrown @ yes, handle exception
3255 /* ------------------------------ */
3257 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3258 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3260 * Handle an interface method call.
3262 * for: invoke-interface, invoke-interface/range
3264 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3265 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3266 FETCH(r2, 2) @ r2<- FEDC or CCCC
3267 FETCH(r1, 1) @ r1<- BBBB
3269 and r2, r2, #15 @ r2<- C (or stays CCCC)
3271 EXPORT_PC() @ must export for invoke
3272 GET_VREG(r0, r2) @ r0<- first arg ("this")
3273 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3274 cmp r0, #0 @ null obj?
3275 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3276 beq common_errNullObject @ yes, fail
3277 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3278 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3279 cmp r0, #0 @ failed?
3280 beq common_exceptionThrown @ yes, handle exception
3281 b common_invokeMethodNoRange @ jump to common handler
3283 /* ------------------------------ */
3285 .L_OP_UNUSED_73: /* 0x73 */
3286 /* File: armv5te/OP_UNUSED_73.S */
3287 /* File: armv5te/unused.S */
3291 /* ------------------------------ */
3293 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3294 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3295 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3297 * Handle a virtual method call.
3299 * for: invoke-virtual, invoke-virtual/range
3301 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3304 FETCH(r1, 1) @ r1<- BBBB
3305 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3306 FETCH(r10, 2) @ r10<- GFED or CCCC
3307 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3309 and r10, r10, #15 @ r10<- D (or stays CCCC)
3311 cmp r0, #0 @ already resolved?
3312 EXPORT_PC() @ must export for invoke
3313 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3314 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3315 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3316 mov r2, #METHOD_VIRTUAL @ resolver method type
3317 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3318 cmp r0, #0 @ got null?
3319 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3320 b common_exceptionThrown @ yes, handle exception
3323 /* ------------------------------ */
3325 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3326 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3327 /* File: armv5te/OP_INVOKE_SUPER.S */
3329 * Handle a "super" method call.
3331 * for: invoke-super, invoke-super/range
3333 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3334 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3335 FETCH(r10, 2) @ r10<- GFED or CCCC
3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3338 and r10, r10, #15 @ r10<- D (or stays CCCC)
3340 FETCH(r1, 1) @ r1<- BBBB
3341 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3342 GET_VREG(r2, r10) @ r2<- "this" ptr
3343 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3344 cmp r2, #0 @ null "this"?
3345 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3346 beq common_errNullObject @ null "this", throw exception
3347 cmp r0, #0 @ already resolved?
3348 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3349 EXPORT_PC() @ must export for invoke
3350 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3351 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3354 /* ------------------------------ */
3356 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3357 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3358 /* File: armv5te/OP_INVOKE_DIRECT.S */
3360 * Handle a direct method call.
3362 * (We could defer the "is 'this' pointer null" test to the common
3363 * method invocation code, and use a flag to indicate that static
3364 * calls don't count. If we do this as part of copying the arguments
3365 * out we could avoiding loading the first arg twice.)
3367 * for: invoke-direct, invoke-direct/range
3369 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3370 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3371 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3372 FETCH(r1, 1) @ r1<- BBBB
3373 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3374 FETCH(r10, 2) @ r10<- GFED or CCCC
3375 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3377 and r10, r10, #15 @ r10<- D (or stays CCCC)
3379 cmp r0, #0 @ already resolved?
3380 EXPORT_PC() @ must export for invoke
3381 GET_VREG(r2, r10) @ r2<- "this" ptr
3382 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3383 .LOP_INVOKE_DIRECT_RANGE_finish:
3384 cmp r2, #0 @ null "this" ref?
3385 bne common_invokeMethodRange @ no, continue on
3386 b common_errNullObject @ yes, throw exception
3389 /* ------------------------------ */
3391 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3392 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3393 /* File: armv5te/OP_INVOKE_STATIC.S */
3395 * Handle a static method call.
3397 * for: invoke-static, invoke-static/range
3399 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3400 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3401 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3402 FETCH(r1, 1) @ r1<- BBBB
3403 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3404 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3405 cmp r0, #0 @ already resolved?
3406 EXPORT_PC() @ must export for invoke
3407 bne common_invokeMethodRange @ yes, continue on
3408 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3409 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3410 mov r2, #METHOD_STATIC @ resolver method type
3411 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3412 cmp r0, #0 @ got null?
3413 bne common_invokeMethodRange @ no, continue
3414 b common_exceptionThrown @ yes, handle exception
3417 /* ------------------------------ */
3419 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3420 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3421 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3423 * Handle an interface method call.
3425 * for: invoke-interface, invoke-interface/range
3427 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3428 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3429 FETCH(r2, 2) @ r2<- FEDC or CCCC
3430 FETCH(r1, 1) @ r1<- BBBB
3432 and r2, r2, #15 @ r2<- C (or stays CCCC)
3434 EXPORT_PC() @ must export for invoke
3435 GET_VREG(r0, r2) @ r0<- first arg ("this")
3436 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3437 cmp r0, #0 @ null obj?
3438 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3439 beq common_errNullObject @ yes, fail
3440 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3441 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3442 cmp r0, #0 @ failed?
3443 beq common_exceptionThrown @ yes, handle exception
3444 b common_invokeMethodRange @ jump to common handler
3447 /* ------------------------------ */
3449 .L_OP_UNUSED_79: /* 0x79 */
3450 /* File: armv5te/OP_UNUSED_79.S */
3451 /* File: armv5te/unused.S */
3455 /* ------------------------------ */
3457 .L_OP_UNUSED_7A: /* 0x7a */
3458 /* File: armv5te/OP_UNUSED_7A.S */
3459 /* File: armv5te/unused.S */
3463 /* ------------------------------ */
3465 .L_OP_NEG_INT: /* 0x7b */
3466 /* File: armv5te/OP_NEG_INT.S */
3467 /* File: armv5te/unop.S */
3469 * Generic 32-bit unary operation. Provide an "instr" line that
3470 * specifies an instruction that performs "result = op r0".
3471 * This could be an ARM instruction or a function call.
3473 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3474 * int-to-byte, int-to-char, int-to-short
3477 mov r3, rINST, lsr #12 @ r3<- B
3478 mov r9, rINST, lsr #8 @ r9<- A+
3479 GET_VREG(r0, r3) @ r0<- vB
3481 @ optional op; may set condition codes
3482 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3483 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3484 GET_INST_OPCODE(ip) @ extract opcode from rINST
3485 SET_VREG(r0, r9) @ vAA<- r0
3486 GOTO_OPCODE(ip) @ jump to next instruction
3487 /* 9-10 instructions */
3490 /* ------------------------------ */
3492 .L_OP_NOT_INT: /* 0x7c */
3493 /* File: armv5te/OP_NOT_INT.S */
3494 /* File: armv5te/unop.S */
3496 * Generic 32-bit unary operation. Provide an "instr" line that
3497 * specifies an instruction that performs "result = op r0".
3498 * This could be an ARM instruction or a function call.
3500 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3501 * int-to-byte, int-to-char, int-to-short
3504 mov r3, rINST, lsr #12 @ r3<- B
3505 mov r9, rINST, lsr #8 @ r9<- A+
3506 GET_VREG(r0, r3) @ r0<- vB
3508 @ optional op; may set condition codes
3509 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3510 mvn r0, r0 @ r0<- op, r0-r3 changed
3511 GET_INST_OPCODE(ip) @ extract opcode from rINST
3512 SET_VREG(r0, r9) @ vAA<- r0
3513 GOTO_OPCODE(ip) @ jump to next instruction
3514 /* 9-10 instructions */
3517 /* ------------------------------ */
3519 .L_OP_NEG_LONG: /* 0x7d */
3520 /* File: armv5te/OP_NEG_LONG.S */
3521 /* File: armv5te/unopWide.S */
3523 * Generic 64-bit unary operation. Provide an "instr" line that
3524 * specifies an instruction that performs "result = op r0/r1".
3525 * This could be an ARM instruction or a function call.
3527 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3530 mov r9, rINST, lsr #8 @ r9<- A+
3531 mov r3, rINST, lsr #12 @ r3<- B
3533 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3534 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3535 ldmia r3, {r0-r1} @ r0/r1<- vAA
3536 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3537 rsbs r0, r0, #0 @ optional op; may set condition codes
3538 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3539 GET_INST_OPCODE(ip) @ extract opcode from rINST
3540 stmia r9, {r0-r1} @ vAA<- r0/r1
3541 GOTO_OPCODE(ip) @ jump to next instruction
3542 /* 12-13 instructions */
3545 /* ------------------------------ */
3547 .L_OP_NOT_LONG: /* 0x7e */
3548 /* File: armv5te/OP_NOT_LONG.S */
3549 /* File: armv5te/unopWide.S */
3551 * Generic 64-bit unary operation. Provide an "instr" line that
3552 * specifies an instruction that performs "result = op r0/r1".
3553 * This could be an ARM instruction or a function call.
3555 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3558 mov r9, rINST, lsr #8 @ r9<- A+
3559 mov r3, rINST, lsr #12 @ r3<- B
3561 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3562 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3563 ldmia r3, {r0-r1} @ r0/r1<- vAA
3564 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3565 mvn r0, r0 @ optional op; may set condition codes
3566 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3567 GET_INST_OPCODE(ip) @ extract opcode from rINST
3568 stmia r9, {r0-r1} @ vAA<- r0/r1
3569 GOTO_OPCODE(ip) @ jump to next instruction
3570 /* 12-13 instructions */
3573 /* ------------------------------ */
3575 .L_OP_NEG_FLOAT: /* 0x7f */
3576 /* File: armv5te/OP_NEG_FLOAT.S */
3577 /* File: armv5te/unop.S */
3579 * Generic 32-bit unary operation. Provide an "instr" line that
3580 * specifies an instruction that performs "result = op r0".
3581 * This could be an ARM instruction or a function call.
3583 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3584 * int-to-byte, int-to-char, int-to-short
3587 mov r3, rINST, lsr #12 @ r3<- B
3588 mov r9, rINST, lsr #8 @ r9<- A+
3589 GET_VREG(r0, r3) @ r0<- vB
3591 @ optional op; may set condition codes
3592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3593 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3594 GET_INST_OPCODE(ip) @ extract opcode from rINST
3595 SET_VREG(r0, r9) @ vAA<- r0
3596 GOTO_OPCODE(ip) @ jump to next instruction
3597 /* 9-10 instructions */
3600 /* ------------------------------ */
3602 .L_OP_NEG_DOUBLE: /* 0x80 */
3603 /* File: armv5te/OP_NEG_DOUBLE.S */
3604 /* File: armv5te/unopWide.S */
3606 * Generic 64-bit unary operation. Provide an "instr" line that
3607 * specifies an instruction that performs "result = op r0/r1".
3608 * This could be an ARM instruction or a function call.
3610 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3613 mov r9, rINST, lsr #8 @ r9<- A+
3614 mov r3, rINST, lsr #12 @ r3<- B
3616 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3617 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3618 ldmia r3, {r0-r1} @ r0/r1<- vAA
3619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3620 @ optional op; may set condition codes
3621 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed
3622 GET_INST_OPCODE(ip) @ extract opcode from rINST
3623 stmia r9, {r0-r1} @ vAA<- r0/r1
3624 GOTO_OPCODE(ip) @ jump to next instruction
3625 /* 12-13 instructions */
3628 /* ------------------------------ */
3630 .L_OP_INT_TO_LONG: /* 0x81 */
3631 /* File: armv5te/OP_INT_TO_LONG.S */
3632 /* File: armv5te/unopWider.S */
3634 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3635 * that specifies an instruction that performs "result = op r0", where
3636 * "result" is a 64-bit quantity in r0/r1.
3638 * For: int-to-long, int-to-double, float-to-long, float-to-double
3641 mov r9, rINST, lsr #8 @ r9<- A+
3642 mov r3, rINST, lsr #12 @ r3<- B
3644 GET_VREG(r0, r3) @ r0<- vB
3645 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3646 @ optional op; may set condition codes
3647 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3648 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3649 GET_INST_OPCODE(ip) @ extract opcode from rINST
3650 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3651 GOTO_OPCODE(ip) @ jump to next instruction
3652 /* 10-11 instructions */
3655 /* ------------------------------ */
3657 .L_OP_INT_TO_FLOAT: /* 0x82 */
3658 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
3659 /* File: arm-vfp/funop.S */
3661 * Generic 32-bit unary floating-point operation. Provide an "instr"
3662 * line that specifies an instruction that performs "s1 = op s0".
3664 * for: int-to-float, float-to-int
3667 mov r3, rINST, lsr #12 @ r3<- B
3668 mov r9, rINST, lsr #8 @ r9<- A+
3669 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3670 flds s0, [r3] @ s0<- vB
3671 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3672 and r9, r9, #15 @ r9<- A
3673 fsitos s1, s0 @ s1<- op
3674 GET_INST_OPCODE(ip) @ extract opcode from rINST
3675 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3676 fsts s1, [r9] @ vA<- s1
3677 GOTO_OPCODE(ip) @ jump to next instruction
3680 /* ------------------------------ */
3682 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3683 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3684 /* File: arm-vfp/funopWider.S */
3686 * Generic 32bit-to-64bit floating point unary operation. Provide an
3687 * "instr" line that specifies an instruction that performs "d0 = op s0".
3689 * For: int-to-double, float-to-double
3692 mov r3, rINST, lsr #12 @ r3<- B
3693 mov r9, rINST, lsr #8 @ r9<- A+
3694 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3695 flds s0, [r3] @ s0<- vB
3696 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3697 and r9, r9, #15 @ r9<- A
3698 fsitod d0, s0 @ d0<- op
3699 GET_INST_OPCODE(ip) @ extract opcode from rINST
3700 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3701 fstd d0, [r9] @ vA<- d0
3702 GOTO_OPCODE(ip) @ jump to next instruction
3705 /* ------------------------------ */
3707 .L_OP_LONG_TO_INT: /* 0x84 */
3708 /* File: armv5te/OP_LONG_TO_INT.S */
3709 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3710 /* File: armv5te/OP_MOVE.S */
3711 /* for move, move-object, long-to-int */
3713 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3714 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3715 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3716 GET_VREG(r2, r1) @ r2<- fp[B]
3718 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3719 SET_VREG(r2, r0) @ fp[A]<- r2
3720 GOTO_OPCODE(ip) @ execute next instruction
3723 /* ------------------------------ */
3725 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3726 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3727 /* File: armv5te/unopNarrower.S */
3729 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3730 * that specifies an instruction that performs "result = op r0/r1", where
3731 * "result" is a 32-bit quantity in r0.
3733 * For: long-to-float, double-to-int, double-to-float
3735 * (This would work for long-to-int, but that instruction is actually
3736 * an exact match for OP_MOVE.)
3739 mov r3, rINST, lsr #12 @ r3<- B
3740 mov r9, rINST, lsr #8 @ r9<- A+
3741 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3743 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3744 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3745 @ optional op; may set condition codes
3746 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3747 GET_INST_OPCODE(ip) @ extract opcode from rINST
3748 SET_VREG(r0, r9) @ vA<- r0
3749 GOTO_OPCODE(ip) @ jump to next instruction
3750 /* 10-11 instructions */
3753 /* ------------------------------ */
3755 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3756 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3757 /* File: armv5te/unopWide.S */
3759 * Generic 64-bit unary operation. Provide an "instr" line that
3760 * specifies an instruction that performs "result = op r0/r1".
3761 * This could be an ARM instruction or a function call.
3763 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3766 mov r9, rINST, lsr #8 @ r9<- A+
3767 mov r3, rINST, lsr #12 @ r3<- B
3769 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3770 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3771 ldmia r3, {r0-r1} @ r0/r1<- vAA
3772 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3773 @ optional op; may set condition codes
3774 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3775 GET_INST_OPCODE(ip) @ extract opcode from rINST
3776 stmia r9, {r0-r1} @ vAA<- r0/r1
3777 GOTO_OPCODE(ip) @ jump to next instruction
3778 /* 12-13 instructions */
3781 /* ------------------------------ */
3783 .L_OP_FLOAT_TO_INT: /* 0x87 */
3784 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
3785 /* File: arm-vfp/funop.S */
3787 * Generic 32-bit unary floating-point operation. Provide an "instr"
3788 * line that specifies an instruction that performs "s1 = op s0".
3790 * for: int-to-float, float-to-int
3793 mov r3, rINST, lsr #12 @ r3<- B
3794 mov r9, rINST, lsr #8 @ r9<- A+
3795 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3796 flds s0, [r3] @ s0<- vB
3797 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3798 and r9, r9, #15 @ r9<- A
3799 ftosizs s1, s0 @ s1<- op
3800 GET_INST_OPCODE(ip) @ extract opcode from rINST
3801 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3802 fsts s1, [r9] @ vA<- s1
3803 GOTO_OPCODE(ip) @ jump to next instruction
3806 /* ------------------------------ */
3808 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3809 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3810 @include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3811 /* File: armv5te/unopWider.S */
3813 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3814 * that specifies an instruction that performs "result = op r0", where
3815 * "result" is a 64-bit quantity in r0/r1.
3817 * For: int-to-long, int-to-double, float-to-long, float-to-double
3820 mov r9, rINST, lsr #8 @ r9<- A+
3821 mov r3, rINST, lsr #12 @ r3<- B
3823 GET_VREG(r0, r3) @ r0<- vB
3824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3825 @ optional op; may set condition codes
3826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3827 bl f2l_doconv @ r0<- op, r0-r3 changed
3828 GET_INST_OPCODE(ip) @ extract opcode from rINST
3829 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3830 GOTO_OPCODE(ip) @ jump to next instruction
3831 /* 10-11 instructions */
3835 /* ------------------------------ */
3837 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3838 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3839 /* File: arm-vfp/funopWider.S */
3841 * Generic 32bit-to-64bit floating point unary operation. Provide an
3842 * "instr" line that specifies an instruction that performs "d0 = op s0".
3844 * For: int-to-double, float-to-double
3847 mov r3, rINST, lsr #12 @ r3<- B
3848 mov r9, rINST, lsr #8 @ r9<- A+
3849 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3850 flds s0, [r3] @ s0<- vB
3851 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3852 and r9, r9, #15 @ r9<- A
3853 fcvtds d0, s0 @ d0<- op
3854 GET_INST_OPCODE(ip) @ extract opcode from rINST
3855 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3856 fstd d0, [r9] @ vA<- d0
3857 GOTO_OPCODE(ip) @ jump to next instruction
3860 /* ------------------------------ */
3862 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3863 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3864 /* File: arm-vfp/funopNarrower.S */
3866 * Generic 64bit-to-32bit unary floating point operation. Provide an
3867 * "instr" line that specifies an instruction that performs "s0 = op d0".
3869 * For: double-to-int, double-to-float
3872 mov r3, rINST, lsr #12 @ r3<- B
3873 mov r9, rINST, lsr #8 @ r9<- A+
3874 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3875 fldd d0, [r3] @ d0<- vB
3876 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3877 and r9, r9, #15 @ r9<- A
3878 ftosizd s0, d0 @ s0<- op
3879 GET_INST_OPCODE(ip) @ extract opcode from rINST
3880 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3881 fsts s0, [r9] @ vA<- s0
3882 GOTO_OPCODE(ip) @ jump to next instruction
3885 /* ------------------------------ */
3887 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3888 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
3889 @include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"}
3890 /* File: armv5te/unopWide.S */
3892 * Generic 64-bit unary operation. Provide an "instr" line that
3893 * specifies an instruction that performs "result = op r0/r1".
3894 * This could be an ARM instruction or a function call.
3896 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3899 mov r9, rINST, lsr #8 @ r9<- A+
3900 mov r3, rINST, lsr #12 @ r3<- B
3902 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3903 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3904 ldmia r3, {r0-r1} @ r0/r1<- vAA
3905 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3906 @ optional op; may set condition codes
3907 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
3908 GET_INST_OPCODE(ip) @ extract opcode from rINST
3909 stmia r9, {r0-r1} @ vAA<- r0/r1
3910 GOTO_OPCODE(ip) @ jump to next instruction
3911 /* 12-13 instructions */
3915 /* ------------------------------ */
3917 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3918 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3919 /* File: arm-vfp/funopNarrower.S */
3921 * Generic 64bit-to-32bit unary floating point operation. Provide an
3922 * "instr" line that specifies an instruction that performs "s0 = op d0".
3924 * For: double-to-int, double-to-float
3927 mov r3, rINST, lsr #12 @ r3<- B
3928 mov r9, rINST, lsr #8 @ r9<- A+
3929 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3930 fldd d0, [r3] @ d0<- vB
3931 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3932 and r9, r9, #15 @ r9<- A
3933 fcvtsd s0, d0 @ s0<- op
3934 GET_INST_OPCODE(ip) @ extract opcode from rINST
3935 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3936 fsts s0, [r9] @ vA<- s0
3937 GOTO_OPCODE(ip) @ jump to next instruction
3940 /* ------------------------------ */
3942 .L_OP_INT_TO_BYTE: /* 0x8d */
3943 /* File: armv5te/OP_INT_TO_BYTE.S */
3944 /* File: armv5te/unop.S */
3946 * Generic 32-bit unary operation. Provide an "instr" line that
3947 * specifies an instruction that performs "result = op r0".
3948 * This could be an ARM instruction or a function call.
3950 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3951 * int-to-byte, int-to-char, int-to-short
3954 mov r3, rINST, lsr #12 @ r3<- B
3955 mov r9, rINST, lsr #8 @ r9<- A+
3956 GET_VREG(r0, r3) @ r0<- vB
3958 mov r0, r0, asl #24 @ optional op; may set condition codes
3959 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3960 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed
3961 GET_INST_OPCODE(ip) @ extract opcode from rINST
3962 SET_VREG(r0, r9) @ vAA<- r0
3963 GOTO_OPCODE(ip) @ jump to next instruction
3964 /* 9-10 instructions */
3967 /* ------------------------------ */
3969 .L_OP_INT_TO_CHAR: /* 0x8e */
3970 /* File: armv5te/OP_INT_TO_CHAR.S */
3971 /* File: armv5te/unop.S */
3973 * Generic 32-bit unary operation. Provide an "instr" line that
3974 * specifies an instruction that performs "result = op r0".
3975 * This could be an ARM instruction or a function call.
3977 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3978 * int-to-byte, int-to-char, int-to-short
3981 mov r3, rINST, lsr #12 @ r3<- B
3982 mov r9, rINST, lsr #8 @ r9<- A+
3983 GET_VREG(r0, r3) @ r0<- vB
3985 mov r0, r0, asl #16 @ optional op; may set condition codes
3986 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3987 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed
3988 GET_INST_OPCODE(ip) @ extract opcode from rINST
3989 SET_VREG(r0, r9) @ vAA<- r0
3990 GOTO_OPCODE(ip) @ jump to next instruction
3991 /* 9-10 instructions */
3994 /* ------------------------------ */
3996 .L_OP_INT_TO_SHORT: /* 0x8f */
3997 /* File: armv5te/OP_INT_TO_SHORT.S */
3998 /* File: armv5te/unop.S */
4000 * Generic 32-bit unary operation. Provide an "instr" line that
4001 * specifies an instruction that performs "result = op r0".
4002 * This could be an ARM instruction or a function call.
4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005 * int-to-byte, int-to-char, int-to-short
4008 mov r3, rINST, lsr #12 @ r3<- B
4009 mov r9, rINST, lsr #8 @ r9<- A+
4010 GET_VREG(r0, r3) @ r0<- vB
4012 mov r0, r0, asl #16 @ optional op; may set condition codes
4013 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4014 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed
4015 GET_INST_OPCODE(ip) @ extract opcode from rINST
4016 SET_VREG(r0, r9) @ vAA<- r0
4017 GOTO_OPCODE(ip) @ jump to next instruction
4018 /* 9-10 instructions */
4021 /* ------------------------------ */
4023 .L_OP_ADD_INT: /* 0x90 */
4024 /* File: armv5te/OP_ADD_INT.S */
4025 /* File: armv5te/binop.S */
4027 * Generic 32-bit binary operation. Provide an "instr" line that
4028 * specifies an instruction that performs "result = r0 op r1".
4029 * This could be an ARM instruction or a function call. (If the result
4030 * comes back in a register other than r0, you can override "result".)
4032 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4033 * vCC (r1). Useful for integer division and modulus. Note that we
4034 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4035 * handles it correctly.
4037 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4038 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4039 * mul-float, div-float, rem-float
4041 /* binop vAA, vBB, vCC */
4042 FETCH(r0, 1) @ r0<- CCBB
4043 mov r9, rINST, lsr #8 @ r9<- AA
4044 mov r3, r0, lsr #8 @ r3<- CC
4045 and r2, r0, #255 @ r2<- BB
4046 GET_VREG(r1, r3) @ r1<- vCC
4047 GET_VREG(r0, r2) @ r0<- vBB
4049 cmp r1, #0 @ is second operand zero?
4050 beq common_errDivideByZero
4053 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4054 @ optional op; may set condition codes
4055 add r0, r0, r1 @ r0<- op, r0-r3 changed
4056 GET_INST_OPCODE(ip) @ extract opcode from rINST
4057 SET_VREG(r0, r9) @ vAA<- r0
4058 GOTO_OPCODE(ip) @ jump to next instruction
4059 /* 11-14 instructions */
4062 /* ------------------------------ */
4064 .L_OP_SUB_INT: /* 0x91 */
4065 /* File: armv5te/OP_SUB_INT.S */
4066 /* File: armv5te/binop.S */
4068 * Generic 32-bit binary operation. Provide an "instr" line that
4069 * specifies an instruction that performs "result = r0 op r1".
4070 * This could be an ARM instruction or a function call. (If the result
4071 * comes back in a register other than r0, you can override "result".)
4073 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4074 * vCC (r1). Useful for integer division and modulus. Note that we
4075 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4076 * handles it correctly.
4078 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4079 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4080 * mul-float, div-float, rem-float
4082 /* binop vAA, vBB, vCC */
4083 FETCH(r0, 1) @ r0<- CCBB
4084 mov r9, rINST, lsr #8 @ r9<- AA
4085 mov r3, r0, lsr #8 @ r3<- CC
4086 and r2, r0, #255 @ r2<- BB
4087 GET_VREG(r1, r3) @ r1<- vCC
4088 GET_VREG(r0, r2) @ r0<- vBB
4090 cmp r1, #0 @ is second operand zero?
4091 beq common_errDivideByZero
4094 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4095 @ optional op; may set condition codes
4096 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4097 GET_INST_OPCODE(ip) @ extract opcode from rINST
4098 SET_VREG(r0, r9) @ vAA<- r0
4099 GOTO_OPCODE(ip) @ jump to next instruction
4100 /* 11-14 instructions */
4103 /* ------------------------------ */
4105 .L_OP_MUL_INT: /* 0x92 */
4106 /* File: armv5te/OP_MUL_INT.S */
4107 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4108 /* File: armv5te/binop.S */
4110 * Generic 32-bit binary operation. Provide an "instr" line that
4111 * specifies an instruction that performs "result = r0 op r1".
4112 * This could be an ARM instruction or a function call. (If the result
4113 * comes back in a register other than r0, you can override "result".)
4115 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4116 * vCC (r1). Useful for integer division and modulus. Note that we
4117 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4118 * handles it correctly.
4120 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4121 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4122 * mul-float, div-float, rem-float
4124 /* binop vAA, vBB, vCC */
4125 FETCH(r0, 1) @ r0<- CCBB
4126 mov r9, rINST, lsr #8 @ r9<- AA
4127 mov r3, r0, lsr #8 @ r3<- CC
4128 and r2, r0, #255 @ r2<- BB
4129 GET_VREG(r1, r3) @ r1<- vCC
4130 GET_VREG(r0, r2) @ r0<- vBB
4132 cmp r1, #0 @ is second operand zero?
4133 beq common_errDivideByZero
4136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4137 @ optional op; may set condition codes
4138 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4139 GET_INST_OPCODE(ip) @ extract opcode from rINST
4140 SET_VREG(r0, r9) @ vAA<- r0
4141 GOTO_OPCODE(ip) @ jump to next instruction
4142 /* 11-14 instructions */
4145 /* ------------------------------ */
4147 .L_OP_DIV_INT: /* 0x93 */
4148 /* File: armv5te/OP_DIV_INT.S */
4149 /* File: armv5te/binop.S */
4151 * Generic 32-bit binary operation. Provide an "instr" line that
4152 * specifies an instruction that performs "result = r0 op r1".
4153 * This could be an ARM instruction or a function call. (If the result
4154 * comes back in a register other than r0, you can override "result".)
4156 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4157 * vCC (r1). Useful for integer division and modulus. Note that we
4158 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4159 * handles it correctly.
4161 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4162 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4163 * mul-float, div-float, rem-float
4165 /* binop vAA, vBB, vCC */
4166 FETCH(r0, 1) @ r0<- CCBB
4167 mov r9, rINST, lsr #8 @ r9<- AA
4168 mov r3, r0, lsr #8 @ r3<- CC
4169 and r2, r0, #255 @ r2<- BB
4170 GET_VREG(r1, r3) @ r1<- vCC
4171 GET_VREG(r0, r2) @ r0<- vBB
4173 cmp r1, #0 @ is second operand zero?
4174 beq common_errDivideByZero
4177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4178 @ optional op; may set condition codes
4179 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4180 GET_INST_OPCODE(ip) @ extract opcode from rINST
4181 SET_VREG(r0, r9) @ vAA<- r0
4182 GOTO_OPCODE(ip) @ jump to next instruction
4183 /* 11-14 instructions */
4186 /* ------------------------------ */
4188 .L_OP_REM_INT: /* 0x94 */
4189 /* File: armv5te/OP_REM_INT.S */
4190 /* idivmod returns quotient in r0 and remainder in r1 */
4191 /* File: armv5te/binop.S */
4193 * Generic 32-bit binary operation. Provide an "instr" line that
4194 * specifies an instruction that performs "result = r0 op r1".
4195 * This could be an ARM instruction or a function call. (If the result
4196 * comes back in a register other than r0, you can override "result".)
4198 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4199 * vCC (r1). Useful for integer division and modulus. Note that we
4200 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4201 * handles it correctly.
4203 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4204 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4205 * mul-float, div-float, rem-float
4207 /* binop vAA, vBB, vCC */
4208 FETCH(r0, 1) @ r0<- CCBB
4209 mov r9, rINST, lsr #8 @ r9<- AA
4210 mov r3, r0, lsr #8 @ r3<- CC
4211 and r2, r0, #255 @ r2<- BB
4212 GET_VREG(r1, r3) @ r1<- vCC
4213 GET_VREG(r0, r2) @ r0<- vBB
4215 cmp r1, #0 @ is second operand zero?
4216 beq common_errDivideByZero
4219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4220 @ optional op; may set condition codes
4221 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4222 GET_INST_OPCODE(ip) @ extract opcode from rINST
4223 SET_VREG(r1, r9) @ vAA<- r1
4224 GOTO_OPCODE(ip) @ jump to next instruction
4225 /* 11-14 instructions */
4228 /* ------------------------------ */
4230 .L_OP_AND_INT: /* 0x95 */
4231 /* File: armv5te/OP_AND_INT.S */
4232 /* File: armv5te/binop.S */
4234 * Generic 32-bit binary operation. Provide an "instr" line that
4235 * specifies an instruction that performs "result = r0 op r1".
4236 * This could be an ARM instruction or a function call. (If the result
4237 * comes back in a register other than r0, you can override "result".)
4239 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4240 * vCC (r1). Useful for integer division and modulus. Note that we
4241 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4242 * handles it correctly.
4244 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4245 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4246 * mul-float, div-float, rem-float
4248 /* binop vAA, vBB, vCC */
4249 FETCH(r0, 1) @ r0<- CCBB
4250 mov r9, rINST, lsr #8 @ r9<- AA
4251 mov r3, r0, lsr #8 @ r3<- CC
4252 and r2, r0, #255 @ r2<- BB
4253 GET_VREG(r1, r3) @ r1<- vCC
4254 GET_VREG(r0, r2) @ r0<- vBB
4256 cmp r1, #0 @ is second operand zero?
4257 beq common_errDivideByZero
4260 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4261 @ optional op; may set condition codes
4262 and r0, r0, r1 @ r0<- op, r0-r3 changed
4263 GET_INST_OPCODE(ip) @ extract opcode from rINST
4264 SET_VREG(r0, r9) @ vAA<- r0
4265 GOTO_OPCODE(ip) @ jump to next instruction
4266 /* 11-14 instructions */
4269 /* ------------------------------ */
4271 .L_OP_OR_INT: /* 0x96 */
4272 /* File: armv5te/OP_OR_INT.S */
4273 /* File: armv5te/binop.S */
4275 * Generic 32-bit binary operation. Provide an "instr" line that
4276 * specifies an instruction that performs "result = r0 op r1".
4277 * This could be an ARM instruction or a function call. (If the result
4278 * comes back in a register other than r0, you can override "result".)
4280 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281 * vCC (r1). Useful for integer division and modulus. Note that we
4282 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283 * handles it correctly.
4285 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287 * mul-float, div-float, rem-float
4289 /* binop vAA, vBB, vCC */
4290 FETCH(r0, 1) @ r0<- CCBB
4291 mov r9, rINST, lsr #8 @ r9<- AA
4292 mov r3, r0, lsr #8 @ r3<- CC
4293 and r2, r0, #255 @ r2<- BB
4294 GET_VREG(r1, r3) @ r1<- vCC
4295 GET_VREG(r0, r2) @ r0<- vBB
4297 cmp r1, #0 @ is second operand zero?
4298 beq common_errDivideByZero
4301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4302 @ optional op; may set condition codes
4303 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4304 GET_INST_OPCODE(ip) @ extract opcode from rINST
4305 SET_VREG(r0, r9) @ vAA<- r0
4306 GOTO_OPCODE(ip) @ jump to next instruction
4307 /* 11-14 instructions */
4310 /* ------------------------------ */
4312 .L_OP_XOR_INT: /* 0x97 */
4313 /* File: armv5te/OP_XOR_INT.S */
4314 /* File: armv5te/binop.S */
4316 * Generic 32-bit binary operation. Provide an "instr" line that
4317 * specifies an instruction that performs "result = r0 op r1".
4318 * This could be an ARM instruction or a function call. (If the result
4319 * comes back in a register other than r0, you can override "result".)
4321 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4322 * vCC (r1). Useful for integer division and modulus. Note that we
4323 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4324 * handles it correctly.
4326 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4327 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4328 * mul-float, div-float, rem-float
4330 /* binop vAA, vBB, vCC */
4331 FETCH(r0, 1) @ r0<- CCBB
4332 mov r9, rINST, lsr #8 @ r9<- AA
4333 mov r3, r0, lsr #8 @ r3<- CC
4334 and r2, r0, #255 @ r2<- BB
4335 GET_VREG(r1, r3) @ r1<- vCC
4336 GET_VREG(r0, r2) @ r0<- vBB
4338 cmp r1, #0 @ is second operand zero?
4339 beq common_errDivideByZero
4342 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4343 @ optional op; may set condition codes
4344 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4345 GET_INST_OPCODE(ip) @ extract opcode from rINST
4346 SET_VREG(r0, r9) @ vAA<- r0
4347 GOTO_OPCODE(ip) @ jump to next instruction
4348 /* 11-14 instructions */
4351 /* ------------------------------ */
4353 .L_OP_SHL_INT: /* 0x98 */
4354 /* File: armv5te/OP_SHL_INT.S */
4355 /* File: armv5te/binop.S */
4357 * Generic 32-bit binary operation. Provide an "instr" line that
4358 * specifies an instruction that performs "result = r0 op r1".
4359 * This could be an ARM instruction or a function call. (If the result
4360 * comes back in a register other than r0, you can override "result".)
4362 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363 * vCC (r1). Useful for integer division and modulus. Note that we
4364 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365 * handles it correctly.
4367 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369 * mul-float, div-float, rem-float
4371 /* binop vAA, vBB, vCC */
4372 FETCH(r0, 1) @ r0<- CCBB
4373 mov r9, rINST, lsr #8 @ r9<- AA
4374 mov r3, r0, lsr #8 @ r3<- CC
4375 and r2, r0, #255 @ r2<- BB
4376 GET_VREG(r1, r3) @ r1<- vCC
4377 GET_VREG(r0, r2) @ r0<- vBB
4379 cmp r1, #0 @ is second operand zero?
4380 beq common_errDivideByZero
4383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4384 and r1, r1, #31 @ optional op; may set condition codes
4385 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4386 GET_INST_OPCODE(ip) @ extract opcode from rINST
4387 SET_VREG(r0, r9) @ vAA<- r0
4388 GOTO_OPCODE(ip) @ jump to next instruction
4389 /* 11-14 instructions */
4392 /* ------------------------------ */
4394 .L_OP_SHR_INT: /* 0x99 */
4395 /* File: armv5te/OP_SHR_INT.S */
4396 /* File: armv5te/binop.S */
4398 * Generic 32-bit binary operation. Provide an "instr" line that
4399 * specifies an instruction that performs "result = r0 op r1".
4400 * This could be an ARM instruction or a function call. (If the result
4401 * comes back in a register other than r0, you can override "result".)
4403 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4404 * vCC (r1). Useful for integer division and modulus. Note that we
4405 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4406 * handles it correctly.
4408 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4409 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4410 * mul-float, div-float, rem-float
4412 /* binop vAA, vBB, vCC */
4413 FETCH(r0, 1) @ r0<- CCBB
4414 mov r9, rINST, lsr #8 @ r9<- AA
4415 mov r3, r0, lsr #8 @ r3<- CC
4416 and r2, r0, #255 @ r2<- BB
4417 GET_VREG(r1, r3) @ r1<- vCC
4418 GET_VREG(r0, r2) @ r0<- vBB
4420 cmp r1, #0 @ is second operand zero?
4421 beq common_errDivideByZero
4424 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4425 and r1, r1, #31 @ optional op; may set condition codes
4426 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4427 GET_INST_OPCODE(ip) @ extract opcode from rINST
4428 SET_VREG(r0, r9) @ vAA<- r0
4429 GOTO_OPCODE(ip) @ jump to next instruction
4430 /* 11-14 instructions */
4433 /* ------------------------------ */
4435 .L_OP_USHR_INT: /* 0x9a */
4436 /* File: armv5te/OP_USHR_INT.S */
4437 /* File: armv5te/binop.S */
4439 * Generic 32-bit binary operation. Provide an "instr" line that
4440 * specifies an instruction that performs "result = r0 op r1".
4441 * This could be an ARM instruction or a function call. (If the result
4442 * comes back in a register other than r0, you can override "result".)
4444 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4445 * vCC (r1). Useful for integer division and modulus. Note that we
4446 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4447 * handles it correctly.
4449 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4450 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4451 * mul-float, div-float, rem-float
4453 /* binop vAA, vBB, vCC */
4454 FETCH(r0, 1) @ r0<- CCBB
4455 mov r9, rINST, lsr #8 @ r9<- AA
4456 mov r3, r0, lsr #8 @ r3<- CC
4457 and r2, r0, #255 @ r2<- BB
4458 GET_VREG(r1, r3) @ r1<- vCC
4459 GET_VREG(r0, r2) @ r0<- vBB
4461 cmp r1, #0 @ is second operand zero?
4462 beq common_errDivideByZero
4465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4466 and r1, r1, #31 @ optional op; may set condition codes
4467 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4468 GET_INST_OPCODE(ip) @ extract opcode from rINST
4469 SET_VREG(r0, r9) @ vAA<- r0
4470 GOTO_OPCODE(ip) @ jump to next instruction
4471 /* 11-14 instructions */
4474 /* ------------------------------ */
4476 .L_OP_ADD_LONG: /* 0x9b */
4477 /* File: armv5te/OP_ADD_LONG.S */
4478 /* File: armv5te/binopWide.S */
4480 * Generic 64-bit binary operation. Provide an "instr" line that
4481 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4482 * This could be an ARM instruction or a function call. (If the result
4483 * comes back in a register other than r0, you can override "result".)
4485 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4486 * vCC (r1). Useful for integer division and modulus.
4488 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4489 * xor-long, add-double, sub-double, mul-double, div-double,
4492 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4494 /* binop vAA, vBB, vCC */
4495 FETCH(r0, 1) @ r0<- CCBB
4496 mov r9, rINST, lsr #8 @ r9<- AA
4497 and r2, r0, #255 @ r2<- BB
4498 mov r3, r0, lsr #8 @ r3<- CC
4499 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4500 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4501 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4502 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4503 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4505 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4506 beq common_errDivideByZero
4508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4510 adds r0, r0, r2 @ optional op; may set condition codes
4511 adc r1, r1, r3 @ result<- op, r0-r3 changed
4512 GET_INST_OPCODE(ip) @ extract opcode from rINST
4513 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4514 GOTO_OPCODE(ip) @ jump to next instruction
4515 /* 14-17 instructions */
4518 /* ------------------------------ */
4520 .L_OP_SUB_LONG: /* 0x9c */
4521 /* File: armv5te/OP_SUB_LONG.S */
4522 /* File: armv5te/binopWide.S */
4524 * Generic 64-bit binary operation. Provide an "instr" line that
4525 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4526 * This could be an ARM instruction or a function call. (If the result
4527 * comes back in a register other than r0, you can override "result".)
4529 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4530 * vCC (r1). Useful for integer division and modulus.
4532 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4533 * xor-long, add-double, sub-double, mul-double, div-double,
4536 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4538 /* binop vAA, vBB, vCC */
4539 FETCH(r0, 1) @ r0<- CCBB
4540 mov r9, rINST, lsr #8 @ r9<- AA
4541 and r2, r0, #255 @ r2<- BB
4542 mov r3, r0, lsr #8 @ r3<- CC
4543 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4544 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4545 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4546 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4547 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4549 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4550 beq common_errDivideByZero
4552 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4554 subs r0, r0, r2 @ optional op; may set condition codes
4555 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4556 GET_INST_OPCODE(ip) @ extract opcode from rINST
4557 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4558 GOTO_OPCODE(ip) @ jump to next instruction
4559 /* 14-17 instructions */
4562 /* ------------------------------ */
4564 .L_OP_MUL_LONG: /* 0x9d */
4565 /* File: armv5te/OP_MUL_LONG.S */
4567 * Signed 64-bit integer multiply.
4569 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4576 * The low word of the result holds ZX, the high word holds
4577 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4578 * it doesn't fit in the low 64 bits.
4580 * Unlike most ARM math operations, multiply instructions have
4581 * restrictions on using the same register more than once (Rd and Rm
4582 * cannot be the same).
4584 /* mul-long vAA, vBB, vCC */
4585 FETCH(r0, 1) @ r0<- CCBB
4586 and r2, r0, #255 @ r2<- BB
4587 mov r3, r0, lsr #8 @ r3<- CC
4588 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4589 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4590 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4591 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4592 mul ip, r2, r1 @ ip<- ZxW
4593 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4594 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4595 mov r0, rINST, lsr #8 @ r0<- AA
4596 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4597 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4598 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4599 b .LOP_MUL_LONG_finish
4601 /* ------------------------------ */
4603 .L_OP_DIV_LONG: /* 0x9e */
4604 /* File: armv5te/OP_DIV_LONG.S */
4605 /* File: armv5te/binopWide.S */
4607 * Generic 64-bit binary operation. Provide an "instr" line that
4608 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4609 * This could be an ARM instruction or a function call. (If the result
4610 * comes back in a register other than r0, you can override "result".)
4612 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4613 * vCC (r1). Useful for integer division and modulus.
4615 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4616 * xor-long, add-double, sub-double, mul-double, div-double,
4619 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4621 /* binop vAA, vBB, vCC */
4622 FETCH(r0, 1) @ r0<- CCBB
4623 mov r9, rINST, lsr #8 @ r9<- AA
4624 and r2, r0, #255 @ r2<- BB
4625 mov r3, r0, lsr #8 @ r3<- CC
4626 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4627 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4628 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4629 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4630 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4632 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4633 beq common_errDivideByZero
4635 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4637 @ optional op; may set condition codes
4638 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4639 GET_INST_OPCODE(ip) @ extract opcode from rINST
4640 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4641 GOTO_OPCODE(ip) @ jump to next instruction
4642 /* 14-17 instructions */
4645 /* ------------------------------ */
4647 .L_OP_REM_LONG: /* 0x9f */
4648 /* File: armv5te/OP_REM_LONG.S */
4649 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4650 /* File: armv5te/binopWide.S */
4652 * Generic 64-bit binary operation. Provide an "instr" line that
4653 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4654 * This could be an ARM instruction or a function call. (If the result
4655 * comes back in a register other than r0, you can override "result".)
4657 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4658 * vCC (r1). Useful for integer division and modulus.
4660 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4661 * xor-long, add-double, sub-double, mul-double, div-double,
4664 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4666 /* binop vAA, vBB, vCC */
4667 FETCH(r0, 1) @ r0<- CCBB
4668 mov r9, rINST, lsr #8 @ r9<- AA
4669 and r2, r0, #255 @ r2<- BB
4670 mov r3, r0, lsr #8 @ r3<- CC
4671 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4672 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4673 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4674 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4675 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4677 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4678 beq common_errDivideByZero
4680 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4682 @ optional op; may set condition codes
4683 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4684 GET_INST_OPCODE(ip) @ extract opcode from rINST
4685 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4686 GOTO_OPCODE(ip) @ jump to next instruction
4687 /* 14-17 instructions */
4690 /* ------------------------------ */
4692 .L_OP_AND_LONG: /* 0xa0 */
4693 /* File: armv5te/OP_AND_LONG.S */
4694 /* File: armv5te/binopWide.S */
4696 * Generic 64-bit binary operation. Provide an "instr" line that
4697 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4698 * This could be an ARM instruction or a function call. (If the result
4699 * comes back in a register other than r0, you can override "result".)
4701 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4702 * vCC (r1). Useful for integer division and modulus.
4704 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4705 * xor-long, add-double, sub-double, mul-double, div-double,
4708 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4710 /* binop vAA, vBB, vCC */
4711 FETCH(r0, 1) @ r0<- CCBB
4712 mov r9, rINST, lsr #8 @ r9<- AA
4713 and r2, r0, #255 @ r2<- BB
4714 mov r3, r0, lsr #8 @ r3<- CC
4715 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4716 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4717 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4718 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4719 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4721 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4722 beq common_errDivideByZero
4724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4726 and r0, r0, r2 @ optional op; may set condition codes
4727 and r1, r1, r3 @ result<- op, r0-r3 changed
4728 GET_INST_OPCODE(ip) @ extract opcode from rINST
4729 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4730 GOTO_OPCODE(ip) @ jump to next instruction
4731 /* 14-17 instructions */
4734 /* ------------------------------ */
4736 .L_OP_OR_LONG: /* 0xa1 */
4737 /* File: armv5te/OP_OR_LONG.S */
4738 /* File: armv5te/binopWide.S */
4740 * Generic 64-bit binary operation. Provide an "instr" line that
4741 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742 * This could be an ARM instruction or a function call. (If the result
4743 * comes back in a register other than r0, you can override "result".)
4745 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746 * vCC (r1). Useful for integer division and modulus.
4748 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749 * xor-long, add-double, sub-double, mul-double, div-double,
4752 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4754 /* binop vAA, vBB, vCC */
4755 FETCH(r0, 1) @ r0<- CCBB
4756 mov r9, rINST, lsr #8 @ r9<- AA
4757 and r2, r0, #255 @ r2<- BB
4758 mov r3, r0, lsr #8 @ r3<- CC
4759 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4760 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4761 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4762 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4763 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4765 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4766 beq common_errDivideByZero
4768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4770 orr r0, r0, r2 @ optional op; may set condition codes
4771 orr r1, r1, r3 @ result<- op, r0-r3 changed
4772 GET_INST_OPCODE(ip) @ extract opcode from rINST
4773 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4774 GOTO_OPCODE(ip) @ jump to next instruction
4775 /* 14-17 instructions */
4778 /* ------------------------------ */
4780 .L_OP_XOR_LONG: /* 0xa2 */
4781 /* File: armv5te/OP_XOR_LONG.S */
4782 /* File: armv5te/binopWide.S */
4784 * Generic 64-bit binary operation. Provide an "instr" line that
4785 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4786 * This could be an ARM instruction or a function call. (If the result
4787 * comes back in a register other than r0, you can override "result".)
4789 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4790 * vCC (r1). Useful for integer division and modulus.
4792 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4793 * xor-long, add-double, sub-double, mul-double, div-double,
4796 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4798 /* binop vAA, vBB, vCC */
4799 FETCH(r0, 1) @ r0<- CCBB
4800 mov r9, rINST, lsr #8 @ r9<- AA
4801 and r2, r0, #255 @ r2<- BB
4802 mov r3, r0, lsr #8 @ r3<- CC
4803 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4804 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4805 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4806 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4807 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4809 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4810 beq common_errDivideByZero
4812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4814 eor r0, r0, r2 @ optional op; may set condition codes
4815 eor r1, r1, r3 @ result<- op, r0-r3 changed
4816 GET_INST_OPCODE(ip) @ extract opcode from rINST
4817 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4818 GOTO_OPCODE(ip) @ jump to next instruction
4819 /* 14-17 instructions */
4822 /* ------------------------------ */
4824 .L_OP_SHL_LONG: /* 0xa3 */
4825 /* File: armv5te/OP_SHL_LONG.S */
4827 * Long integer shift. This is different from the generic 32/64-bit
4828 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4829 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4830 * 6 bits of the shift distance.
4832 /* shl-long vAA, vBB, vCC */
4833 FETCH(r0, 1) @ r0<- CCBB
4834 mov r9, rINST, lsr #8 @ r9<- AA
4835 and r3, r0, #255 @ r3<- BB
4836 mov r0, r0, lsr #8 @ r0<- CC
4837 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4838 GET_VREG(r2, r0) @ r2<- vCC
4839 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4840 and r2, r2, #63 @ r2<- r2 & 0x3f
4841 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4843 mov r1, r1, asl r2 @ r1<- r1 << r2
4844 rsb r3, r2, #32 @ r3<- 32 - r2
4845 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
4846 subs ip, r2, #32 @ ip<- r2 - 32
4847 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
4848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4849 b .LOP_SHL_LONG_finish
4851 /* ------------------------------ */
4853 .L_OP_SHR_LONG: /* 0xa4 */
4854 /* File: armv5te/OP_SHR_LONG.S */
4856 * Long integer shift. This is different from the generic 32/64-bit
4857 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4858 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4859 * 6 bits of the shift distance.
4861 /* shr-long vAA, vBB, vCC */
4862 FETCH(r0, 1) @ r0<- CCBB
4863 mov r9, rINST, lsr #8 @ r9<- AA
4864 and r3, r0, #255 @ r3<- BB
4865 mov r0, r0, lsr #8 @ r0<- CC
4866 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4867 GET_VREG(r2, r0) @ r2<- vCC
4868 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4869 and r2, r2, #63 @ r0<- r0 & 0x3f
4870 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4872 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4873 rsb r3, r2, #32 @ r3<- 32 - r2
4874 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4875 subs ip, r2, #32 @ ip<- r2 - 32
4876 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
4877 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4878 b .LOP_SHR_LONG_finish
4880 /* ------------------------------ */
4882 .L_OP_USHR_LONG: /* 0xa5 */
4883 /* File: armv5te/OP_USHR_LONG.S */
4885 * Long integer shift. This is different from the generic 32/64-bit
4886 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4887 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4888 * 6 bits of the shift distance.
4890 /* ushr-long vAA, vBB, vCC */
4891 FETCH(r0, 1) @ r0<- CCBB
4892 mov r9, rINST, lsr #8 @ r9<- AA
4893 and r3, r0, #255 @ r3<- BB
4894 mov r0, r0, lsr #8 @ r0<- CC
4895 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4896 GET_VREG(r2, r0) @ r2<- vCC
4897 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4898 and r2, r2, #63 @ r0<- r0 & 0x3f
4899 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4901 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4902 rsb r3, r2, #32 @ r3<- 32 - r2
4903 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4904 subs ip, r2, #32 @ ip<- r2 - 32
4905 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
4906 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4907 b .LOP_USHR_LONG_finish
4909 /* ------------------------------ */
4911 .L_OP_ADD_FLOAT: /* 0xa6 */
4912 /* File: arm-vfp/OP_ADD_FLOAT.S */
4913 /* File: arm-vfp/fbinop.S */
4915 * Generic 32-bit floating-point operation. Provide an "instr" line that
4916 * specifies an instruction that performs "s2 = s0 op s1". Because we
4917 * use the "softfp" ABI, this must be an instruction, not a function call.
4919 * For: add-float, sub-float, mul-float, div-float
4921 /* floatop vAA, vBB, vCC */
4922 FETCH(r0, 1) @ r0<- CCBB
4923 mov r9, rINST, lsr #8 @ r9<- AA
4924 mov r3, r0, lsr #8 @ r3<- CC
4925 and r2, r0, #255 @ r2<- BB
4926 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
4927 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
4928 flds s1, [r3] @ s1<- vCC
4929 flds s0, [r2] @ s0<- vBB
4931 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4932 fadds s2, s0, s1 @ s2<- op
4933 GET_INST_OPCODE(ip) @ extract opcode from rINST
4934 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
4935 fsts s2, [r9] @ vAA<- s2
4936 GOTO_OPCODE(ip) @ jump to next instruction
4939 /* ------------------------------ */
4941 .L_OP_SUB_FLOAT: /* 0xa7 */
4942 /* File: arm-vfp/OP_SUB_FLOAT.S */
4943 /* File: arm-vfp/fbinop.S */
4945 * Generic 32-bit floating-point operation. Provide an "instr" line that
4946 * specifies an instruction that performs "s2 = s0 op s1". Because we
4947 * use the "softfp" ABI, this must be an instruction, not a function call.
4949 * For: add-float, sub-float, mul-float, div-float
4951 /* floatop vAA, vBB, vCC */
4952 FETCH(r0, 1) @ r0<- CCBB
4953 mov r9, rINST, lsr #8 @ r9<- AA
4954 mov r3, r0, lsr #8 @ r3<- CC
4955 and r2, r0, #255 @ r2<- BB
4956 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
4957 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
4958 flds s1, [r3] @ s1<- vCC
4959 flds s0, [r2] @ s0<- vBB
4961 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4962 fsubs s2, s0, s1 @ s2<- op
4963 GET_INST_OPCODE(ip) @ extract opcode from rINST
4964 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
4965 fsts s2, [r9] @ vAA<- s2
4966 GOTO_OPCODE(ip) @ jump to next instruction
4969 /* ------------------------------ */
4971 .L_OP_MUL_FLOAT: /* 0xa8 */
4972 /* File: arm-vfp/OP_MUL_FLOAT.S */
4973 /* File: arm-vfp/fbinop.S */
4975 * Generic 32-bit floating-point operation. Provide an "instr" line that
4976 * specifies an instruction that performs "s2 = s0 op s1". Because we
4977 * use the "softfp" ABI, this must be an instruction, not a function call.
4979 * For: add-float, sub-float, mul-float, div-float
4981 /* floatop vAA, vBB, vCC */
4982 FETCH(r0, 1) @ r0<- CCBB
4983 mov r9, rINST, lsr #8 @ r9<- AA
4984 mov r3, r0, lsr #8 @ r3<- CC
4985 and r2, r0, #255 @ r2<- BB
4986 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
4987 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
4988 flds s1, [r3] @ s1<- vCC
4989 flds s0, [r2] @ s0<- vBB
4991 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4992 fmuls s2, s0, s1 @ s2<- op
4993 GET_INST_OPCODE(ip) @ extract opcode from rINST
4994 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
4995 fsts s2, [r9] @ vAA<- s2
4996 GOTO_OPCODE(ip) @ jump to next instruction
4999 /* ------------------------------ */
5001 .L_OP_DIV_FLOAT: /* 0xa9 */
5002 /* File: arm-vfp/OP_DIV_FLOAT.S */
5003 /* File: arm-vfp/fbinop.S */
5005 * Generic 32-bit floating-point operation. Provide an "instr" line that
5006 * specifies an instruction that performs "s2 = s0 op s1". Because we
5007 * use the "softfp" ABI, this must be an instruction, not a function call.
5009 * For: add-float, sub-float, mul-float, div-float
5011 /* floatop vAA, vBB, vCC */
5012 FETCH(r0, 1) @ r0<- CCBB
5013 mov r9, rINST, lsr #8 @ r9<- AA
5014 mov r3, r0, lsr #8 @ r3<- CC
5015 and r2, r0, #255 @ r2<- BB
5016 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5017 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5018 flds s1, [r3] @ s1<- vCC
5019 flds s0, [r2] @ s0<- vBB
5021 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5022 fdivs s2, s0, s1 @ s2<- op
5023 GET_INST_OPCODE(ip) @ extract opcode from rINST
5024 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5025 fsts s2, [r9] @ vAA<- s2
5026 GOTO_OPCODE(ip) @ jump to next instruction
5029 /* ------------------------------ */
5031 .L_OP_REM_FLOAT: /* 0xaa */
5032 /* File: armv5te/OP_REM_FLOAT.S */
5033 /* EABI doesn't define a float remainder function, but libm does */
5034 /* File: armv5te/binop.S */
5036 * Generic 32-bit binary operation. Provide an "instr" line that
5037 * specifies an instruction that performs "result = r0 op r1".
5038 * This could be an ARM instruction or a function call. (If the result
5039 * comes back in a register other than r0, you can override "result".)
5041 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5042 * vCC (r1). Useful for integer division and modulus. Note that we
5043 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5044 * handles it correctly.
5046 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5047 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5048 * mul-float, div-float, rem-float
5050 /* binop vAA, vBB, vCC */
5051 FETCH(r0, 1) @ r0<- CCBB
5052 mov r9, rINST, lsr #8 @ r9<- AA
5053 mov r3, r0, lsr #8 @ r3<- CC
5054 and r2, r0, #255 @ r2<- BB
5055 GET_VREG(r1, r3) @ r1<- vCC
5056 GET_VREG(r0, r2) @ r0<- vBB
5058 cmp r1, #0 @ is second operand zero?
5059 beq common_errDivideByZero
5062 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5063 @ optional op; may set condition codes
5064 bl fmodf @ r0<- op, r0-r3 changed
5065 GET_INST_OPCODE(ip) @ extract opcode from rINST
5066 SET_VREG(r0, r9) @ vAA<- r0
5067 GOTO_OPCODE(ip) @ jump to next instruction
5068 /* 11-14 instructions */
5071 /* ------------------------------ */
5073 .L_OP_ADD_DOUBLE: /* 0xab */
5074 /* File: arm-vfp/OP_ADD_DOUBLE.S */
5075 /* File: arm-vfp/fbinopWide.S */
5077 * Generic 64-bit double-precision floating point binary operation.
5078 * Provide an "instr" line that specifies an instruction that performs
5081 * for: add-double, sub-double, mul-double, div-double
5083 /* doubleop vAA, vBB, vCC */
5084 FETCH(r0, 1) @ r0<- CCBB
5085 mov r9, rINST, lsr #8 @ r9<- AA
5086 mov r3, r0, lsr #8 @ r3<- CC
5087 and r2, r0, #255 @ r2<- BB
5088 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5089 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5090 fldd d1, [r3] @ d1<- vCC
5091 fldd d0, [r2] @ d0<- vBB
5093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5094 faddd d2, d0, d1 @ s2<- op
5095 GET_INST_OPCODE(ip) @ extract opcode from rINST
5096 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5097 fstd d2, [r9] @ vAA<- d2
5098 GOTO_OPCODE(ip) @ jump to next instruction
5101 /* ------------------------------ */
5103 .L_OP_SUB_DOUBLE: /* 0xac */
5104 /* File: arm-vfp/OP_SUB_DOUBLE.S */
5105 /* File: arm-vfp/fbinopWide.S */
5107 * Generic 64-bit double-precision floating point binary operation.
5108 * Provide an "instr" line that specifies an instruction that performs
5111 * for: add-double, sub-double, mul-double, div-double
5113 /* doubleop vAA, vBB, vCC */
5114 FETCH(r0, 1) @ r0<- CCBB
5115 mov r9, rINST, lsr #8 @ r9<- AA
5116 mov r3, r0, lsr #8 @ r3<- CC
5117 and r2, r0, #255 @ r2<- BB
5118 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5119 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5120 fldd d1, [r3] @ d1<- vCC
5121 fldd d0, [r2] @ d0<- vBB
5123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5124 fsubd d2, d0, d1 @ s2<- op
5125 GET_INST_OPCODE(ip) @ extract opcode from rINST
5126 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5127 fstd d2, [r9] @ vAA<- d2
5128 GOTO_OPCODE(ip) @ jump to next instruction
5131 /* ------------------------------ */
5133 .L_OP_MUL_DOUBLE: /* 0xad */
5134 /* File: arm-vfp/OP_MUL_DOUBLE.S */
5135 /* File: arm-vfp/fbinopWide.S */
5137 * Generic 64-bit double-precision floating point binary operation.
5138 * Provide an "instr" line that specifies an instruction that performs
5141 * for: add-double, sub-double, mul-double, div-double
5143 /* doubleop vAA, vBB, vCC */
5144 FETCH(r0, 1) @ r0<- CCBB
5145 mov r9, rINST, lsr #8 @ r9<- AA
5146 mov r3, r0, lsr #8 @ r3<- CC
5147 and r2, r0, #255 @ r2<- BB
5148 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5149 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5150 fldd d1, [r3] @ d1<- vCC
5151 fldd d0, [r2] @ d0<- vBB
5153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5154 fmuld d2, d0, d1 @ s2<- op
5155 GET_INST_OPCODE(ip) @ extract opcode from rINST
5156 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5157 fstd d2, [r9] @ vAA<- d2
5158 GOTO_OPCODE(ip) @ jump to next instruction
5161 /* ------------------------------ */
5163 .L_OP_DIV_DOUBLE: /* 0xae */
5164 /* File: arm-vfp/OP_DIV_DOUBLE.S */
5165 /* File: arm-vfp/fbinopWide.S */
5167 * Generic 64-bit double-precision floating point binary operation.
5168 * Provide an "instr" line that specifies an instruction that performs
5171 * for: add-double, sub-double, mul-double, div-double
5173 /* doubleop vAA, vBB, vCC */
5174 FETCH(r0, 1) @ r0<- CCBB
5175 mov r9, rINST, lsr #8 @ r9<- AA
5176 mov r3, r0, lsr #8 @ r3<- CC
5177 and r2, r0, #255 @ r2<- BB
5178 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5179 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5180 fldd d1, [r3] @ d1<- vCC
5181 fldd d0, [r2] @ d0<- vBB
5183 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5184 fdivd d2, d0, d1 @ s2<- op
5185 GET_INST_OPCODE(ip) @ extract opcode from rINST
5186 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5187 fstd d2, [r9] @ vAA<- d2
5188 GOTO_OPCODE(ip) @ jump to next instruction
5191 /* ------------------------------ */
5193 .L_OP_REM_DOUBLE: /* 0xaf */
5194 /* File: armv5te/OP_REM_DOUBLE.S */
5195 /* EABI doesn't define a double remainder function, but libm does */
5196 /* File: armv5te/binopWide.S */
5198 * Generic 64-bit binary operation. Provide an "instr" line that
5199 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5200 * This could be an ARM instruction or a function call. (If the result
5201 * comes back in a register other than r0, you can override "result".)
5203 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5204 * vCC (r1). Useful for integer division and modulus.
5206 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5207 * xor-long, add-double, sub-double, mul-double, div-double,
5210 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5212 /* binop vAA, vBB, vCC */
5213 FETCH(r0, 1) @ r0<- CCBB
5214 mov r9, rINST, lsr #8 @ r9<- AA
5215 and r2, r0, #255 @ r2<- BB
5216 mov r3, r0, lsr #8 @ r3<- CC
5217 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5218 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5219 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5220 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5221 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5223 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5224 beq common_errDivideByZero
5226 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5228 @ optional op; may set condition codes
5229 bl fmod @ result<- op, r0-r3 changed
5230 GET_INST_OPCODE(ip) @ extract opcode from rINST
5231 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5232 GOTO_OPCODE(ip) @ jump to next instruction
5233 /* 14-17 instructions */
5236 /* ------------------------------ */
5238 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5239 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5240 /* File: armv5te/binop2addr.S */
5242 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5243 * that specifies an instruction that performs "result = r0 op r1".
5244 * This could be an ARM instruction or a function call. (If the result
5245 * comes back in a register other than r0, you can override "result".)
5247 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5248 * vCC (r1). Useful for integer division and modulus.
5250 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5251 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5252 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5253 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5255 /* binop/2addr vA, vB */
5256 mov r9, rINST, lsr #8 @ r9<- A+
5257 mov r3, rINST, lsr #12 @ r3<- B
5259 GET_VREG(r1, r3) @ r1<- vB
5260 GET_VREG(r0, r9) @ r0<- vA
5262 cmp r1, #0 @ is second operand zero?
5263 beq common_errDivideByZero
5265 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5267 @ optional op; may set condition codes
5268 add r0, r0, r1 @ r0<- op, r0-r3 changed
5269 GET_INST_OPCODE(ip) @ extract opcode from rINST
5270 SET_VREG(r0, r9) @ vAA<- r0
5271 GOTO_OPCODE(ip) @ jump to next instruction
5272 /* 10-13 instructions */
5275 /* ------------------------------ */
5277 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5278 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5279 /* File: armv5te/binop2addr.S */
5281 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5282 * that specifies an instruction that performs "result = r0 op r1".
5283 * This could be an ARM instruction or a function call. (If the result
5284 * comes back in a register other than r0, you can override "result".)
5286 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5287 * vCC (r1). Useful for integer division and modulus.
5289 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5290 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5291 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5292 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5294 /* binop/2addr vA, vB */
5295 mov r9, rINST, lsr #8 @ r9<- A+
5296 mov r3, rINST, lsr #12 @ r3<- B
5298 GET_VREG(r1, r3) @ r1<- vB
5299 GET_VREG(r0, r9) @ r0<- vA
5301 cmp r1, #0 @ is second operand zero?
5302 beq common_errDivideByZero
5304 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5306 @ optional op; may set condition codes
5307 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5308 GET_INST_OPCODE(ip) @ extract opcode from rINST
5309 SET_VREG(r0, r9) @ vAA<- r0
5310 GOTO_OPCODE(ip) @ jump to next instruction
5311 /* 10-13 instructions */
5314 /* ------------------------------ */
5316 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5317 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5318 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5319 /* File: armv5te/binop2addr.S */
5321 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5322 * that specifies an instruction that performs "result = r0 op r1".
5323 * This could be an ARM instruction or a function call. (If the result
5324 * comes back in a register other than r0, you can override "result".)
5326 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5327 * vCC (r1). Useful for integer division and modulus.
5329 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5330 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5331 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5332 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5334 /* binop/2addr vA, vB */
5335 mov r9, rINST, lsr #8 @ r9<- A+
5336 mov r3, rINST, lsr #12 @ r3<- B
5338 GET_VREG(r1, r3) @ r1<- vB
5339 GET_VREG(r0, r9) @ r0<- vA
5341 cmp r1, #0 @ is second operand zero?
5342 beq common_errDivideByZero
5344 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5346 @ optional op; may set condition codes
5347 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5348 GET_INST_OPCODE(ip) @ extract opcode from rINST
5349 SET_VREG(r0, r9) @ vAA<- r0
5350 GOTO_OPCODE(ip) @ jump to next instruction
5351 /* 10-13 instructions */
5354 /* ------------------------------ */
5356 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5357 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5358 /* File: armv5te/binop2addr.S */
5360 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5361 * that specifies an instruction that performs "result = r0 op r1".
5362 * This could be an ARM instruction or a function call. (If the result
5363 * comes back in a register other than r0, you can override "result".)
5365 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5366 * vCC (r1). Useful for integer division and modulus.
5368 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5369 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5370 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5371 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5373 /* binop/2addr vA, vB */
5374 mov r9, rINST, lsr #8 @ r9<- A+
5375 mov r3, rINST, lsr #12 @ r3<- B
5377 GET_VREG(r1, r3) @ r1<- vB
5378 GET_VREG(r0, r9) @ r0<- vA
5380 cmp r1, #0 @ is second operand zero?
5381 beq common_errDivideByZero
5383 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5385 @ optional op; may set condition codes
5386 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5387 GET_INST_OPCODE(ip) @ extract opcode from rINST
5388 SET_VREG(r0, r9) @ vAA<- r0
5389 GOTO_OPCODE(ip) @ jump to next instruction
5390 /* 10-13 instructions */
5393 /* ------------------------------ */
5395 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5396 /* File: armv5te/OP_REM_INT_2ADDR.S */
5397 /* idivmod returns quotient in r0 and remainder in r1 */
5398 /* File: armv5te/binop2addr.S */
5400 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5401 * that specifies an instruction that performs "result = r0 op r1".
5402 * This could be an ARM instruction or a function call. (If the result
5403 * comes back in a register other than r0, you can override "result".)
5405 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5406 * vCC (r1). Useful for integer division and modulus.
5408 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5409 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5410 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5411 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5413 /* binop/2addr vA, vB */
5414 mov r9, rINST, lsr #8 @ r9<- A+
5415 mov r3, rINST, lsr #12 @ r3<- B
5417 GET_VREG(r1, r3) @ r1<- vB
5418 GET_VREG(r0, r9) @ r0<- vA
5420 cmp r1, #0 @ is second operand zero?
5421 beq common_errDivideByZero
5423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5425 @ optional op; may set condition codes
5426 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5427 GET_INST_OPCODE(ip) @ extract opcode from rINST
5428 SET_VREG(r1, r9) @ vAA<- r1
5429 GOTO_OPCODE(ip) @ jump to next instruction
5430 /* 10-13 instructions */
5433 /* ------------------------------ */
5435 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5436 /* File: armv5te/OP_AND_INT_2ADDR.S */
5437 /* File: armv5te/binop2addr.S */
5439 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5440 * that specifies an instruction that performs "result = r0 op r1".
5441 * This could be an ARM instruction or a function call. (If the result
5442 * comes back in a register other than r0, you can override "result".)
5444 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5445 * vCC (r1). Useful for integer division and modulus.
5447 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5448 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5449 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5450 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5452 /* binop/2addr vA, vB */
5453 mov r9, rINST, lsr #8 @ r9<- A+
5454 mov r3, rINST, lsr #12 @ r3<- B
5456 GET_VREG(r1, r3) @ r1<- vB
5457 GET_VREG(r0, r9) @ r0<- vA
5459 cmp r1, #0 @ is second operand zero?
5460 beq common_errDivideByZero
5462 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5464 @ optional op; may set condition codes
5465 and r0, r0, r1 @ r0<- op, r0-r3 changed
5466 GET_INST_OPCODE(ip) @ extract opcode from rINST
5467 SET_VREG(r0, r9) @ vAA<- r0
5468 GOTO_OPCODE(ip) @ jump to next instruction
5469 /* 10-13 instructions */
5472 /* ------------------------------ */
5474 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5475 /* File: armv5te/OP_OR_INT_2ADDR.S */
5476 /* File: armv5te/binop2addr.S */
5478 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5479 * that specifies an instruction that performs "result = r0 op r1".
5480 * This could be an ARM instruction or a function call. (If the result
5481 * comes back in a register other than r0, you can override "result".)
5483 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5484 * vCC (r1). Useful for integer division and modulus.
5486 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5487 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5488 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5489 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5491 /* binop/2addr vA, vB */
5492 mov r9, rINST, lsr #8 @ r9<- A+
5493 mov r3, rINST, lsr #12 @ r3<- B
5495 GET_VREG(r1, r3) @ r1<- vB
5496 GET_VREG(r0, r9) @ r0<- vA
5498 cmp r1, #0 @ is second operand zero?
5499 beq common_errDivideByZero
5501 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5503 @ optional op; may set condition codes
5504 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5505 GET_INST_OPCODE(ip) @ extract opcode from rINST
5506 SET_VREG(r0, r9) @ vAA<- r0
5507 GOTO_OPCODE(ip) @ jump to next instruction
5508 /* 10-13 instructions */
5511 /* ------------------------------ */
5513 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5514 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5515 /* File: armv5te/binop2addr.S */
5517 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5518 * that specifies an instruction that performs "result = r0 op r1".
5519 * This could be an ARM instruction or a function call. (If the result
5520 * comes back in a register other than r0, you can override "result".)
5522 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5523 * vCC (r1). Useful for integer division and modulus.
5525 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5526 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5527 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5528 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5530 /* binop/2addr vA, vB */
5531 mov r9, rINST, lsr #8 @ r9<- A+
5532 mov r3, rINST, lsr #12 @ r3<- B
5534 GET_VREG(r1, r3) @ r1<- vB
5535 GET_VREG(r0, r9) @ r0<- vA
5537 cmp r1, #0 @ is second operand zero?
5538 beq common_errDivideByZero
5540 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5542 @ optional op; may set condition codes
5543 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5544 GET_INST_OPCODE(ip) @ extract opcode from rINST
5545 SET_VREG(r0, r9) @ vAA<- r0
5546 GOTO_OPCODE(ip) @ jump to next instruction
5547 /* 10-13 instructions */
5550 /* ------------------------------ */
5552 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5553 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5554 /* File: armv5te/binop2addr.S */
5556 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5557 * that specifies an instruction that performs "result = r0 op r1".
5558 * This could be an ARM instruction or a function call. (If the result
5559 * comes back in a register other than r0, you can override "result".)
5561 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5562 * vCC (r1). Useful for integer division and modulus.
5564 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5565 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5566 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5567 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5569 /* binop/2addr vA, vB */
5570 mov r9, rINST, lsr #8 @ r9<- A+
5571 mov r3, rINST, lsr #12 @ r3<- B
5573 GET_VREG(r1, r3) @ r1<- vB
5574 GET_VREG(r0, r9) @ r0<- vA
5576 cmp r1, #0 @ is second operand zero?
5577 beq common_errDivideByZero
5579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5581 and r1, r1, #31 @ optional op; may set condition codes
5582 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
5583 GET_INST_OPCODE(ip) @ extract opcode from rINST
5584 SET_VREG(r0, r9) @ vAA<- r0
5585 GOTO_OPCODE(ip) @ jump to next instruction
5586 /* 10-13 instructions */
5589 /* ------------------------------ */
5591 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5592 /* File: armv5te/OP_SHR_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 and r1, r1, #31 @ optional op; may set condition codes
5621 mov r0, r0, asr 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 */
5628 /* ------------------------------ */
5630 .L_OP_USHR_INT_2ADDR: /* 0xba */
5631 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5632 /* File: armv5te/binop2addr.S */
5634 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5635 * that specifies an instruction that performs "result = r0 op r1".
5636 * This could be an ARM instruction or a function call. (If the result
5637 * comes back in a register other than r0, you can override "result".)
5639 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5640 * vCC (r1). Useful for integer division and modulus.
5642 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5643 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5644 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5645 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5647 /* binop/2addr vA, vB */
5648 mov r9, rINST, lsr #8 @ r9<- A+
5649 mov r3, rINST, lsr #12 @ r3<- B
5651 GET_VREG(r1, r3) @ r1<- vB
5652 GET_VREG(r0, r9) @ r0<- vA
5654 cmp r1, #0 @ is second operand zero?
5655 beq common_errDivideByZero
5657 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5659 and r1, r1, #31 @ optional op; may set condition codes
5660 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
5661 GET_INST_OPCODE(ip) @ extract opcode from rINST
5662 SET_VREG(r0, r9) @ vAA<- r0
5663 GOTO_OPCODE(ip) @ jump to next instruction
5664 /* 10-13 instructions */
5667 /* ------------------------------ */
5669 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5670 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5671 /* File: armv5te/binopWide2addr.S */
5673 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5674 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5675 * This could be an ARM instruction or a function call. (If the result
5676 * comes back in a register other than r0, you can override "result".)
5678 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5679 * vCC (r1). Useful for integer division and modulus.
5681 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5682 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5683 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5686 /* binop/2addr vA, vB */
5687 mov r9, rINST, lsr #8 @ r9<- A+
5688 mov r1, rINST, lsr #12 @ r1<- B
5690 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5691 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5692 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5693 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5695 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5696 beq common_errDivideByZero
5698 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5700 adds r0, r0, r2 @ optional op; may set condition codes
5701 adc r1, r1, r3 @ result<- op, r0-r3 changed
5702 GET_INST_OPCODE(ip) @ extract opcode from rINST
5703 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5704 GOTO_OPCODE(ip) @ jump to next instruction
5705 /* 12-15 instructions */
5708 /* ------------------------------ */
5710 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5711 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
5712 /* File: armv5te/binopWide2addr.S */
5714 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5715 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5716 * This could be an ARM instruction or a function call. (If the result
5717 * comes back in a register other than r0, you can override "result".)
5719 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5720 * vCC (r1). Useful for integer division and modulus.
5722 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5723 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5724 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5727 /* binop/2addr vA, vB */
5728 mov r9, rINST, lsr #8 @ r9<- A+
5729 mov r1, rINST, lsr #12 @ r1<- B
5731 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5732 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5733 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5734 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5736 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5737 beq common_errDivideByZero
5739 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5741 subs r0, r0, r2 @ optional op; may set condition codes
5742 sbc r1, r1, r3 @ result<- op, r0-r3 changed
5743 GET_INST_OPCODE(ip) @ extract opcode from rINST
5744 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5745 GOTO_OPCODE(ip) @ jump to next instruction
5746 /* 12-15 instructions */
5749 /* ------------------------------ */
5751 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5752 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
5754 * Signed 64-bit integer multiply, "/2addr" version.
5756 * See OP_MUL_LONG for an explanation.
5758 * We get a little tight on registers, so to avoid looking up &fp[A]
5759 * again we stuff it into rINST.
5761 /* mul-long/2addr vA, vB */
5762 mov r9, rINST, lsr #8 @ r9<- A+
5763 mov r1, rINST, lsr #12 @ r1<- B
5765 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5766 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
5767 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5768 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
5769 mul ip, r2, r1 @ ip<- ZxW
5770 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
5771 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
5772 mov r0, rINST @ r0<- &fp[A] (free up rINST)
5773 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5774 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
5775 GET_INST_OPCODE(ip) @ extract opcode from rINST
5776 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
5777 GOTO_OPCODE(ip) @ jump to next instruction
5779 /* ------------------------------ */
5781 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5782 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
5783 /* File: armv5te/binopWide2addr.S */
5785 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5786 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787 * This could be an ARM instruction or a function call. (If the result
5788 * comes back in a register other than r0, you can override "result".)
5790 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791 * vCC (r1). Useful for integer division and modulus.
5793 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5798 /* binop/2addr vA, vB */
5799 mov r9, rINST, lsr #8 @ r9<- A+
5800 mov r1, rINST, lsr #12 @ r1<- B
5802 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5803 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5804 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5805 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5807 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5808 beq common_errDivideByZero
5810 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5812 @ optional op; may set condition codes
5813 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5814 GET_INST_OPCODE(ip) @ extract opcode from rINST
5815 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5816 GOTO_OPCODE(ip) @ jump to next instruction
5817 /* 12-15 instructions */
5820 /* ------------------------------ */
5822 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5823 /* File: armv5te/OP_REM_LONG_2ADDR.S */
5824 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5825 /* File: armv5te/binopWide2addr.S */
5827 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5828 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5829 * This could be an ARM instruction or a function call. (If the result
5830 * comes back in a register other than r0, you can override "result".)
5832 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5833 * vCC (r1). Useful for integer division and modulus.
5835 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5836 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5837 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5840 /* binop/2addr vA, vB */
5841 mov r9, rINST, lsr #8 @ r9<- A+
5842 mov r1, rINST, lsr #12 @ r1<- B
5844 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5845 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5846 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5847 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5849 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5850 beq common_errDivideByZero
5852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5854 @ optional op; may set condition codes
5855 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5856 GET_INST_OPCODE(ip) @ extract opcode from rINST
5857 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
5858 GOTO_OPCODE(ip) @ jump to next instruction
5859 /* 12-15 instructions */
5862 /* ------------------------------ */
5864 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
5865 /* File: armv5te/OP_AND_LONG_2ADDR.S */
5866 /* File: armv5te/binopWide2addr.S */
5868 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5869 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5870 * This could be an ARM instruction or a function call. (If the result
5871 * comes back in a register other than r0, you can override "result".)
5873 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5874 * vCC (r1). Useful for integer division and modulus.
5876 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5877 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5878 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5881 /* binop/2addr vA, vB */
5882 mov r9, rINST, lsr #8 @ r9<- A+
5883 mov r1, rINST, lsr #12 @ r1<- B
5885 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5886 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5887 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5888 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5890 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5891 beq common_errDivideByZero
5893 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5895 and r0, r0, r2 @ optional op; may set condition codes
5896 and r1, r1, r3 @ result<- op, r0-r3 changed
5897 GET_INST_OPCODE(ip) @ extract opcode from rINST
5898 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5899 GOTO_OPCODE(ip) @ jump to next instruction
5900 /* 12-15 instructions */
5903 /* ------------------------------ */
5905 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
5906 /* File: armv5te/OP_OR_LONG_2ADDR.S */
5907 /* File: armv5te/binopWide2addr.S */
5909 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5910 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5911 * This could be an ARM instruction or a function call. (If the result
5912 * comes back in a register other than r0, you can override "result".)
5914 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5915 * vCC (r1). Useful for integer division and modulus.
5917 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5918 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5919 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5922 /* binop/2addr vA, vB */
5923 mov r9, rINST, lsr #8 @ r9<- A+
5924 mov r1, rINST, lsr #12 @ r1<- B
5926 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5927 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5928 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5929 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5931 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5932 beq common_errDivideByZero
5934 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5936 orr r0, r0, r2 @ optional op; may set condition codes
5937 orr r1, r1, r3 @ result<- op, r0-r3 changed
5938 GET_INST_OPCODE(ip) @ extract opcode from rINST
5939 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5940 GOTO_OPCODE(ip) @ jump to next instruction
5941 /* 12-15 instructions */
5944 /* ------------------------------ */
5946 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5947 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
5948 /* File: armv5te/binopWide2addr.S */
5950 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5951 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5952 * This could be an ARM instruction or a function call. (If the result
5953 * comes back in a register other than r0, you can override "result".)
5955 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5956 * vCC (r1). Useful for integer division and modulus.
5958 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5959 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5960 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5963 /* binop/2addr vA, vB */
5964 mov r9, rINST, lsr #8 @ r9<- A+
5965 mov r1, rINST, lsr #12 @ r1<- B
5967 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5968 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5969 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5970 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5972 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5973 beq common_errDivideByZero
5975 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5977 eor r0, r0, r2 @ optional op; may set condition codes
5978 eor r1, r1, r3 @ result<- op, r0-r3 changed
5979 GET_INST_OPCODE(ip) @ extract opcode from rINST
5980 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5981 GOTO_OPCODE(ip) @ jump to next instruction
5982 /* 12-15 instructions */
5985 /* ------------------------------ */
5987 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5988 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
5990 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
5991 * 32-bit shift distance.
5993 /* shl-long/2addr vA, vB */
5994 mov r9, rINST, lsr #8 @ r9<- A+
5995 mov r3, rINST, lsr #12 @ r3<- B
5997 GET_VREG(r2, r3) @ r2<- vB
5998 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5999 and r2, r2, #63 @ r2<- r2 & 0x3f
6000 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6002 mov r1, r1, asl r2 @ r1<- r1 << r2
6003 rsb r3, r2, #32 @ r3<- 32 - r2
6004 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6005 subs ip, r2, #32 @ ip<- r2 - 32
6006 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6007 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6008 mov r0, r0, asl r2 @ r0<- r0 << r2
6009 b .LOP_SHL_LONG_2ADDR_finish
6011 /* ------------------------------ */
6013 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6014 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6016 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6017 * 32-bit shift distance.
6019 /* shr-long/2addr vA, vB */
6020 mov r9, rINST, lsr #8 @ r9<- A+
6021 mov r3, rINST, lsr #12 @ r3<- B
6023 GET_VREG(r2, r3) @ r2<- vB
6024 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6025 and r2, r2, #63 @ r2<- r2 & 0x3f
6026 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6028 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6029 rsb r3, r2, #32 @ r3<- 32 - r2
6030 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6031 subs ip, r2, #32 @ ip<- r2 - 32
6032 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6033 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6034 mov r1, r1, asr r2 @ r1<- r1 >> r2
6035 b .LOP_SHR_LONG_2ADDR_finish
6037 /* ------------------------------ */
6039 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6040 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6042 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6043 * 32-bit shift distance.
6045 /* ushr-long/2addr vA, vB */
6046 mov r9, rINST, lsr #8 @ r9<- A+
6047 mov r3, rINST, lsr #12 @ r3<- B
6049 GET_VREG(r2, r3) @ r2<- vB
6050 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6051 and r2, r2, #63 @ r2<- r2 & 0x3f
6052 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6054 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6055 rsb r3, r2, #32 @ r3<- 32 - r2
6056 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6057 subs ip, r2, #32 @ ip<- r2 - 32
6058 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6059 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6060 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6061 b .LOP_USHR_LONG_2ADDR_finish
6063 /* ------------------------------ */
6065 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6066 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6067 /* File: arm-vfp/fbinop2addr.S */
6069 * Generic 32-bit floating point "/2addr" binary operation. Provide
6070 * an "instr" line that specifies an instruction that performs
6073 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6075 /* binop/2addr vA, vB */
6076 mov r3, rINST, lsr #12 @ r3<- B
6077 mov r9, rINST, lsr #8 @ r9<- A+
6078 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6079 and r9, r9, #15 @ r9<- A
6080 flds s1, [r3] @ s1<- vB
6081 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6082 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6083 flds s0, [r9] @ s0<- vA
6085 fadds s2, s0, s1 @ s2<- op
6086 GET_INST_OPCODE(ip) @ extract opcode from rINST
6087 fsts s2, [r9] @ vAA<- s2
6088 GOTO_OPCODE(ip) @ jump to next instruction
6091 /* ------------------------------ */
6093 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6094 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6095 /* File: arm-vfp/fbinop2addr.S */
6097 * Generic 32-bit floating point "/2addr" binary operation. Provide
6098 * an "instr" line that specifies an instruction that performs
6101 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6103 /* binop/2addr vA, vB */
6104 mov r3, rINST, lsr #12 @ r3<- B
6105 mov r9, rINST, lsr #8 @ r9<- A+
6106 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6107 and r9, r9, #15 @ r9<- A
6108 flds s1, [r3] @ s1<- vB
6109 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6110 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6111 flds s0, [r9] @ s0<- vA
6113 fsubs s2, s0, s1 @ s2<- op
6114 GET_INST_OPCODE(ip) @ extract opcode from rINST
6115 fsts s2, [r9] @ vAA<- s2
6116 GOTO_OPCODE(ip) @ jump to next instruction
6119 /* ------------------------------ */
6121 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6122 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6123 /* File: arm-vfp/fbinop2addr.S */
6125 * Generic 32-bit floating point "/2addr" binary operation. Provide
6126 * an "instr" line that specifies an instruction that performs
6129 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6131 /* binop/2addr vA, vB */
6132 mov r3, rINST, lsr #12 @ r3<- B
6133 mov r9, rINST, lsr #8 @ r9<- A+
6134 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6135 and r9, r9, #15 @ r9<- A
6136 flds s1, [r3] @ s1<- vB
6137 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6138 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6139 flds s0, [r9] @ s0<- vA
6141 fmuls s2, s0, s1 @ s2<- op
6142 GET_INST_OPCODE(ip) @ extract opcode from rINST
6143 fsts s2, [r9] @ vAA<- s2
6144 GOTO_OPCODE(ip) @ jump to next instruction
6147 /* ------------------------------ */
6149 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6150 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6151 /* File: arm-vfp/fbinop2addr.S */
6153 * Generic 32-bit floating point "/2addr" binary operation. Provide
6154 * an "instr" line that specifies an instruction that performs
6157 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6159 /* binop/2addr vA, vB */
6160 mov r3, rINST, lsr #12 @ r3<- B
6161 mov r9, rINST, lsr #8 @ r9<- A+
6162 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6163 and r9, r9, #15 @ r9<- A
6164 flds s1, [r3] @ s1<- vB
6165 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6166 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6167 flds s0, [r9] @ s0<- vA
6169 fdivs s2, s0, s1 @ s2<- op
6170 GET_INST_OPCODE(ip) @ extract opcode from rINST
6171 fsts s2, [r9] @ vAA<- s2
6172 GOTO_OPCODE(ip) @ jump to next instruction
6175 /* ------------------------------ */
6177 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6178 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6179 /* EABI doesn't define a float remainder function, but libm does */
6180 /* File: armv5te/binop2addr.S */
6182 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6183 * that specifies an instruction that performs "result = r0 op r1".
6184 * This could be an ARM instruction or a function call. (If the result
6185 * comes back in a register other than r0, you can override "result".)
6187 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6188 * vCC (r1). Useful for integer division and modulus.
6190 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6191 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6192 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6193 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6195 /* binop/2addr vA, vB */
6196 mov r9, rINST, lsr #8 @ r9<- A+
6197 mov r3, rINST, lsr #12 @ r3<- B
6199 GET_VREG(r1, r3) @ r1<- vB
6200 GET_VREG(r0, r9) @ r0<- vA
6202 cmp r1, #0 @ is second operand zero?
6203 beq common_errDivideByZero
6205 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6207 @ optional op; may set condition codes
6208 bl fmodf @ r0<- op, r0-r3 changed
6209 GET_INST_OPCODE(ip) @ extract opcode from rINST
6210 SET_VREG(r0, r9) @ vAA<- r0
6211 GOTO_OPCODE(ip) @ jump to next instruction
6212 /* 10-13 instructions */
6215 /* ------------------------------ */
6217 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6218 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6219 /* File: arm-vfp/fbinopWide2addr.S */
6221 * Generic 64-bit floating point "/2addr" binary operation. Provide
6222 * an "instr" line that specifies an instruction that performs
6225 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6228 /* binop/2addr vA, vB */
6229 mov r3, rINST, lsr #12 @ r3<- B
6230 mov r9, rINST, lsr #8 @ r9<- A+
6231 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6232 and r9, r9, #15 @ r9<- A
6233 fldd d1, [r3] @ d1<- vB
6234 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6235 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6236 fldd d0, [r9] @ d0<- vA
6238 faddd d2, d0, d1 @ d2<- op
6239 GET_INST_OPCODE(ip) @ extract opcode from rINST
6240 fstd d2, [r9] @ vAA<- d2
6241 GOTO_OPCODE(ip) @ jump to next instruction
6244 /* ------------------------------ */
6246 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6247 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6248 /* File: arm-vfp/fbinopWide2addr.S */
6250 * Generic 64-bit floating point "/2addr" binary operation. Provide
6251 * an "instr" line that specifies an instruction that performs
6254 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6257 /* binop/2addr vA, vB */
6258 mov r3, rINST, lsr #12 @ r3<- B
6259 mov r9, rINST, lsr #8 @ r9<- A+
6260 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6261 and r9, r9, #15 @ r9<- A
6262 fldd d1, [r3] @ d1<- vB
6263 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6264 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6265 fldd d0, [r9] @ d0<- vA
6267 fsubd d2, d0, d1 @ d2<- op
6268 GET_INST_OPCODE(ip) @ extract opcode from rINST
6269 fstd d2, [r9] @ vAA<- d2
6270 GOTO_OPCODE(ip) @ jump to next instruction
6273 /* ------------------------------ */
6275 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6276 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6277 /* File: arm-vfp/fbinopWide2addr.S */
6279 * Generic 64-bit floating point "/2addr" binary operation. Provide
6280 * an "instr" line that specifies an instruction that performs
6283 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6286 /* binop/2addr vA, vB */
6287 mov r3, rINST, lsr #12 @ r3<- B
6288 mov r9, rINST, lsr #8 @ r9<- A+
6289 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6290 and r9, r9, #15 @ r9<- A
6291 fldd d1, [r3] @ d1<- vB
6292 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6293 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6294 fldd d0, [r9] @ d0<- vA
6296 fmuld d2, d0, d1 @ d2<- op
6297 GET_INST_OPCODE(ip) @ extract opcode from rINST
6298 fstd d2, [r9] @ vAA<- d2
6299 GOTO_OPCODE(ip) @ jump to next instruction
6302 /* ------------------------------ */
6304 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6305 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6306 /* File: arm-vfp/fbinopWide2addr.S */
6308 * Generic 64-bit floating point "/2addr" binary operation. Provide
6309 * an "instr" line that specifies an instruction that performs
6312 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6315 /* binop/2addr vA, vB */
6316 mov r3, rINST, lsr #12 @ r3<- B
6317 mov r9, rINST, lsr #8 @ r9<- A+
6318 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6319 and r9, r9, #15 @ r9<- A
6320 fldd d1, [r3] @ d1<- vB
6321 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6322 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6323 fldd d0, [r9] @ d0<- vA
6325 fdivd d2, d0, d1 @ d2<- op
6326 GET_INST_OPCODE(ip) @ extract opcode from rINST
6327 fstd d2, [r9] @ vAA<- d2
6328 GOTO_OPCODE(ip) @ jump to next instruction
6331 /* ------------------------------ */
6333 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6334 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6335 /* EABI doesn't define a double remainder function, but libm does */
6336 /* File: armv5te/binopWide2addr.S */
6338 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6339 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6340 * This could be an ARM instruction or a function call. (If the result
6341 * comes back in a register other than r0, you can override "result".)
6343 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6344 * vCC (r1). Useful for integer division and modulus.
6346 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6347 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6348 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6351 /* binop/2addr vA, vB */
6352 mov r9, rINST, lsr #8 @ r9<- A+
6353 mov r1, rINST, lsr #12 @ r1<- B
6355 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6356 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6357 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6358 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6360 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6361 beq common_errDivideByZero
6363 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6365 @ optional op; may set condition codes
6366 bl fmod @ result<- op, r0-r3 changed
6367 GET_INST_OPCODE(ip) @ extract opcode from rINST
6368 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6369 GOTO_OPCODE(ip) @ jump to next instruction
6370 /* 12-15 instructions */
6373 /* ------------------------------ */
6375 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6376 /* File: armv5te/OP_ADD_INT_LIT16.S */
6377 /* File: armv5te/binopLit16.S */
6379 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6380 * that specifies an instruction that performs "result = r0 op r1".
6381 * This could be an ARM instruction or a function call. (If the result
6382 * comes back in a register other than r0, you can override "result".)
6384 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6385 * vCC (r1). Useful for integer division and modulus.
6387 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6388 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6390 /* binop/lit16 vA, vB, #+CCCC */
6391 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6392 mov r2, rINST, lsr #12 @ r2<- B
6393 mov r9, rINST, lsr #8 @ r9<- A+
6394 GET_VREG(r0, r2) @ r0<- vB
6397 cmp r1, #0 @ is second operand zero?
6398 beq common_errDivideByZero
6400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6402 add r0, r0, r1 @ r0<- op, r0-r3 changed
6403 GET_INST_OPCODE(ip) @ extract opcode from rINST
6404 SET_VREG(r0, r9) @ vAA<- r0
6405 GOTO_OPCODE(ip) @ jump to next instruction
6406 /* 10-13 instructions */
6409 /* ------------------------------ */
6411 .L_OP_RSUB_INT: /* 0xd1 */
6412 /* File: armv5te/OP_RSUB_INT.S */
6413 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6414 /* File: armv5te/binopLit16.S */
6416 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6417 * that specifies an instruction that performs "result = r0 op r1".
6418 * This could be an ARM instruction or a function call. (If the result
6419 * comes back in a register other than r0, you can override "result".)
6421 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6422 * vCC (r1). Useful for integer division and modulus.
6424 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6425 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6427 /* binop/lit16 vA, vB, #+CCCC */
6428 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6429 mov r2, rINST, lsr #12 @ r2<- B
6430 mov r9, rINST, lsr #8 @ r9<- A+
6431 GET_VREG(r0, r2) @ r0<- vB
6434 cmp r1, #0 @ is second operand zero?
6435 beq common_errDivideByZero
6437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6439 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6440 GET_INST_OPCODE(ip) @ extract opcode from rINST
6441 SET_VREG(r0, r9) @ vAA<- r0
6442 GOTO_OPCODE(ip) @ jump to next instruction
6443 /* 10-13 instructions */
6446 /* ------------------------------ */
6448 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6449 /* File: armv5te/OP_MUL_INT_LIT16.S */
6450 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6451 /* File: armv5te/binopLit16.S */
6453 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6454 * that specifies an instruction that performs "result = r0 op r1".
6455 * This could be an ARM instruction or a function call. (If the result
6456 * comes back in a register other than r0, you can override "result".)
6458 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459 * vCC (r1). Useful for integer division and modulus.
6461 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6462 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6464 /* binop/lit16 vA, vB, #+CCCC */
6465 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6466 mov r2, rINST, lsr #12 @ r2<- B
6467 mov r9, rINST, lsr #8 @ r9<- A+
6468 GET_VREG(r0, r2) @ r0<- vB
6471 cmp r1, #0 @ is second operand zero?
6472 beq common_errDivideByZero
6474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6476 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6477 GET_INST_OPCODE(ip) @ extract opcode from rINST
6478 SET_VREG(r0, r9) @ vAA<- r0
6479 GOTO_OPCODE(ip) @ jump to next instruction
6480 /* 10-13 instructions */
6483 /* ------------------------------ */
6485 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6486 /* File: armv5te/OP_DIV_INT_LIT16.S */
6487 /* File: armv5te/binopLit16.S */
6489 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6490 * that specifies an instruction that performs "result = r0 op r1".
6491 * This could be an ARM instruction or a function call. (If the result
6492 * comes back in a register other than r0, you can override "result".)
6494 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6495 * vCC (r1). Useful for integer division and modulus.
6497 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6498 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6500 /* binop/lit16 vA, vB, #+CCCC */
6501 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6502 mov r2, rINST, lsr #12 @ r2<- B
6503 mov r9, rINST, lsr #8 @ r9<- A+
6504 GET_VREG(r0, r2) @ r0<- vB
6507 cmp r1, #0 @ is second operand zero?
6508 beq common_errDivideByZero
6510 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6512 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6513 GET_INST_OPCODE(ip) @ extract opcode from rINST
6514 SET_VREG(r0, r9) @ vAA<- r0
6515 GOTO_OPCODE(ip) @ jump to next instruction
6516 /* 10-13 instructions */
6519 /* ------------------------------ */
6521 .L_OP_REM_INT_LIT16: /* 0xd4 */
6522 /* File: armv5te/OP_REM_INT_LIT16.S */
6523 /* idivmod returns quotient in r0 and remainder in r1 */
6524 /* File: armv5te/binopLit16.S */
6526 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6527 * that specifies an instruction that performs "result = r0 op r1".
6528 * This could be an ARM instruction or a function call. (If the result
6529 * comes back in a register other than r0, you can override "result".)
6531 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6532 * vCC (r1). Useful for integer division and modulus.
6534 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6535 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6537 /* binop/lit16 vA, vB, #+CCCC */
6538 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6539 mov r2, rINST, lsr #12 @ r2<- B
6540 mov r9, rINST, lsr #8 @ r9<- A+
6541 GET_VREG(r0, r2) @ r0<- vB
6544 cmp r1, #0 @ is second operand zero?
6545 beq common_errDivideByZero
6547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6549 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6550 GET_INST_OPCODE(ip) @ extract opcode from rINST
6551 SET_VREG(r1, r9) @ vAA<- r1
6552 GOTO_OPCODE(ip) @ jump to next instruction
6553 /* 10-13 instructions */
6556 /* ------------------------------ */
6558 .L_OP_AND_INT_LIT16: /* 0xd5 */
6559 /* File: armv5te/OP_AND_INT_LIT16.S */
6560 /* File: armv5te/binopLit16.S */
6562 * Generic 32-bit "lit16" 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/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6571 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6573 /* binop/lit16 vA, vB, #+CCCC */
6574 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6575 mov r2, rINST, lsr #12 @ r2<- B
6576 mov r9, rINST, lsr #8 @ r9<- A+
6577 GET_VREG(r0, r2) @ r0<- vB
6580 cmp r1, #0 @ is second operand zero?
6581 beq common_errDivideByZero
6583 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6585 and r0, r0, r1 @ r0<- op, r0-r3 changed
6586 GET_INST_OPCODE(ip) @ extract opcode from rINST
6587 SET_VREG(r0, r9) @ vAA<- r0
6588 GOTO_OPCODE(ip) @ jump to next instruction
6589 /* 10-13 instructions */
6592 /* ------------------------------ */
6594 .L_OP_OR_INT_LIT16: /* 0xd6 */
6595 /* File: armv5te/OP_OR_INT_LIT16.S */
6596 /* File: armv5te/binopLit16.S */
6598 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6599 * that specifies an instruction that performs "result = r0 op r1".
6600 * This could be an ARM instruction or a function call. (If the result
6601 * comes back in a register other than r0, you can override "result".)
6603 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6604 * vCC (r1). Useful for integer division and modulus.
6606 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6607 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6609 /* binop/lit16 vA, vB, #+CCCC */
6610 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6611 mov r2, rINST, lsr #12 @ r2<- B
6612 mov r9, rINST, lsr #8 @ r9<- A+
6613 GET_VREG(r0, r2) @ r0<- vB
6616 cmp r1, #0 @ is second operand zero?
6617 beq common_errDivideByZero
6619 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6621 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6622 GET_INST_OPCODE(ip) @ extract opcode from rINST
6623 SET_VREG(r0, r9) @ vAA<- r0
6624 GOTO_OPCODE(ip) @ jump to next instruction
6625 /* 10-13 instructions */
6628 /* ------------------------------ */
6630 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6631 /* File: armv5te/OP_XOR_INT_LIT16.S */
6632 /* File: armv5te/binopLit16.S */
6634 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6635 * that specifies an instruction that performs "result = r0 op r1".
6636 * This could be an ARM instruction or a function call. (If the result
6637 * comes back in a register other than r0, you can override "result".)
6639 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6640 * vCC (r1). Useful for integer division and modulus.
6642 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6643 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6645 /* binop/lit16 vA, vB, #+CCCC */
6646 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6647 mov r2, rINST, lsr #12 @ r2<- B
6648 mov r9, rINST, lsr #8 @ r9<- A+
6649 GET_VREG(r0, r2) @ r0<- vB
6652 cmp r1, #0 @ is second operand zero?
6653 beq common_errDivideByZero
6655 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6657 eor r0, r0, r1 @ r0<- op, r0-r3 changed
6658 GET_INST_OPCODE(ip) @ extract opcode from rINST
6659 SET_VREG(r0, r9) @ vAA<- r0
6660 GOTO_OPCODE(ip) @ jump to next instruction
6661 /* 10-13 instructions */
6664 /* ------------------------------ */
6666 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6667 /* File: armv5te/OP_ADD_INT_LIT8.S */
6668 /* File: armv5te/binopLit8.S */
6670 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6671 * that specifies an instruction that performs "result = r0 op r1".
6672 * This could be an ARM instruction or a function call. (If the result
6673 * comes back in a register other than r0, you can override "result".)
6675 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6676 * vCC (r1). Useful for integer division and modulus.
6678 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6679 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6680 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6682 /* binop/lit8 vAA, vBB, #+CC */
6683 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6684 mov r9, rINST, lsr #8 @ r9<- AA
6685 and r2, r3, #255 @ r2<- BB
6686 GET_VREG(r0, r2) @ r0<- vBB
6687 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6689 @cmp r1, #0 @ is second operand zero?
6690 beq common_errDivideByZero
6692 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6694 @ optional op; may set condition codes
6695 add r0, r0, r1 @ r0<- op, r0-r3 changed
6696 GET_INST_OPCODE(ip) @ extract opcode from rINST
6697 SET_VREG(r0, r9) @ vAA<- r0
6698 GOTO_OPCODE(ip) @ jump to next instruction
6699 /* 10-12 instructions */
6702 /* ------------------------------ */
6704 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6705 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6706 /* File: armv5te/binopLit8.S */
6708 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6709 * that specifies an instruction that performs "result = r0 op r1".
6710 * This could be an ARM instruction or a function call. (If the result
6711 * comes back in a register other than r0, you can override "result".)
6713 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6714 * vCC (r1). Useful for integer division and modulus.
6716 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6717 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6718 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6720 /* binop/lit8 vAA, vBB, #+CC */
6721 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6722 mov r9, rINST, lsr #8 @ r9<- AA
6723 and r2, r3, #255 @ r2<- BB
6724 GET_VREG(r0, r2) @ r0<- vBB
6725 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6727 @cmp r1, #0 @ is second operand zero?
6728 beq common_errDivideByZero
6730 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6732 @ optional op; may set condition codes
6733 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6734 GET_INST_OPCODE(ip) @ extract opcode from rINST
6735 SET_VREG(r0, r9) @ vAA<- r0
6736 GOTO_OPCODE(ip) @ jump to next instruction
6737 /* 10-12 instructions */
6740 /* ------------------------------ */
6742 .L_OP_MUL_INT_LIT8: /* 0xda */
6743 /* File: armv5te/OP_MUL_INT_LIT8.S */
6744 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6745 /* File: armv5te/binopLit8.S */
6747 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6748 * that specifies an instruction that performs "result = r0 op r1".
6749 * This could be an ARM instruction or a function call. (If the result
6750 * comes back in a register other than r0, you can override "result".)
6752 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6753 * vCC (r1). Useful for integer division and modulus.
6755 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6756 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6757 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6759 /* binop/lit8 vAA, vBB, #+CC */
6760 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6761 mov r9, rINST, lsr #8 @ r9<- AA
6762 and r2, r3, #255 @ r2<- BB
6763 GET_VREG(r0, r2) @ r0<- vBB
6764 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6766 @cmp r1, #0 @ is second operand zero?
6767 beq common_errDivideByZero
6769 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6771 @ optional op; may set condition codes
6772 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6773 GET_INST_OPCODE(ip) @ extract opcode from rINST
6774 SET_VREG(r0, r9) @ vAA<- r0
6775 GOTO_OPCODE(ip) @ jump to next instruction
6776 /* 10-12 instructions */
6779 /* ------------------------------ */
6781 .L_OP_DIV_INT_LIT8: /* 0xdb */
6782 /* File: armv5te/OP_DIV_INT_LIT8.S */
6783 /* File: armv5te/binopLit8.S */
6785 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6786 * that specifies an instruction that performs "result = r0 op r1".
6787 * This could be an ARM instruction or a function call. (If the result
6788 * comes back in a register other than r0, you can override "result".)
6790 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6791 * vCC (r1). Useful for integer division and modulus.
6793 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6794 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6795 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6797 /* binop/lit8 vAA, vBB, #+CC */
6798 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6799 mov r9, rINST, lsr #8 @ r9<- AA
6800 and r2, r3, #255 @ r2<- BB
6801 GET_VREG(r0, r2) @ r0<- vBB
6802 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6804 @cmp r1, #0 @ is second operand zero?
6805 beq common_errDivideByZero
6807 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6809 @ optional op; may set condition codes
6810 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6811 GET_INST_OPCODE(ip) @ extract opcode from rINST
6812 SET_VREG(r0, r9) @ vAA<- r0
6813 GOTO_OPCODE(ip) @ jump to next instruction
6814 /* 10-12 instructions */
6817 /* ------------------------------ */
6819 .L_OP_REM_INT_LIT8: /* 0xdc */
6820 /* File: armv5te/OP_REM_INT_LIT8.S */
6821 /* idivmod returns quotient in r0 and remainder in r1 */
6822 /* File: armv5te/binopLit8.S */
6824 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6825 * that specifies an instruction that performs "result = r0 op r1".
6826 * This could be an ARM instruction or a function call. (If the result
6827 * comes back in a register other than r0, you can override "result".)
6829 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6830 * vCC (r1). Useful for integer division and modulus.
6832 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6833 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6834 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6836 /* binop/lit8 vAA, vBB, #+CC */
6837 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6838 mov r9, rINST, lsr #8 @ r9<- AA
6839 and r2, r3, #255 @ r2<- BB
6840 GET_VREG(r0, r2) @ r0<- vBB
6841 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6843 @cmp r1, #0 @ is second operand zero?
6844 beq common_errDivideByZero
6846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6848 @ optional op; may set condition codes
6849 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6850 GET_INST_OPCODE(ip) @ extract opcode from rINST
6851 SET_VREG(r1, r9) @ vAA<- r1
6852 GOTO_OPCODE(ip) @ jump to next instruction
6853 /* 10-12 instructions */
6856 /* ------------------------------ */
6858 .L_OP_AND_INT_LIT8: /* 0xdd */
6859 /* File: armv5te/OP_AND_INT_LIT8.S */
6860 /* File: armv5te/binopLit8.S */
6862 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6863 * that specifies an instruction that performs "result = r0 op r1".
6864 * This could be an ARM instruction or a function call. (If the result
6865 * comes back in a register other than r0, you can override "result".)
6867 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6868 * vCC (r1). Useful for integer division and modulus.
6870 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6871 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6872 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6874 /* binop/lit8 vAA, vBB, #+CC */
6875 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6876 mov r9, rINST, lsr #8 @ r9<- AA
6877 and r2, r3, #255 @ r2<- BB
6878 GET_VREG(r0, r2) @ r0<- vBB
6879 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6881 @cmp r1, #0 @ is second operand zero?
6882 beq common_errDivideByZero
6884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6886 @ optional op; may set condition codes
6887 and r0, r0, r1 @ r0<- op, r0-r3 changed
6888 GET_INST_OPCODE(ip) @ extract opcode from rINST
6889 SET_VREG(r0, r9) @ vAA<- r0
6890 GOTO_OPCODE(ip) @ jump to next instruction
6891 /* 10-12 instructions */
6894 /* ------------------------------ */
6896 .L_OP_OR_INT_LIT8: /* 0xde */
6897 /* File: armv5te/OP_OR_INT_LIT8.S */
6898 /* File: armv5te/binopLit8.S */
6900 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6901 * that specifies an instruction that performs "result = r0 op r1".
6902 * This could be an ARM instruction or a function call. (If the result
6903 * comes back in a register other than r0, you can override "result".)
6905 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6906 * vCC (r1). Useful for integer division and modulus.
6908 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6909 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6910 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6912 /* binop/lit8 vAA, vBB, #+CC */
6913 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6914 mov r9, rINST, lsr #8 @ r9<- AA
6915 and r2, r3, #255 @ r2<- BB
6916 GET_VREG(r0, r2) @ r0<- vBB
6917 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6919 @cmp r1, #0 @ is second operand zero?
6920 beq common_errDivideByZero
6922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6924 @ optional op; may set condition codes
6925 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6926 GET_INST_OPCODE(ip) @ extract opcode from rINST
6927 SET_VREG(r0, r9) @ vAA<- r0
6928 GOTO_OPCODE(ip) @ jump to next instruction
6929 /* 10-12 instructions */
6932 /* ------------------------------ */
6934 .L_OP_XOR_INT_LIT8: /* 0xdf */
6935 /* File: armv5te/OP_XOR_INT_LIT8.S */
6936 /* File: armv5te/binopLit8.S */
6938 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6939 * that specifies an instruction that performs "result = r0 op r1".
6940 * This could be an ARM instruction or a function call. (If the result
6941 * comes back in a register other than r0, you can override "result".)
6943 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6944 * vCC (r1). Useful for integer division and modulus.
6946 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6947 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6948 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6950 /* binop/lit8 vAA, vBB, #+CC */
6951 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6952 mov r9, rINST, lsr #8 @ r9<- AA
6953 and r2, r3, #255 @ r2<- BB
6954 GET_VREG(r0, r2) @ r0<- vBB
6955 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6957 @cmp r1, #0 @ is second operand zero?
6958 beq common_errDivideByZero
6960 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6962 @ optional op; may set condition codes
6963 eor r0, r0, r1 @ r0<- op, r0-r3 changed
6964 GET_INST_OPCODE(ip) @ extract opcode from rINST
6965 SET_VREG(r0, r9) @ vAA<- r0
6966 GOTO_OPCODE(ip) @ jump to next instruction
6967 /* 10-12 instructions */
6970 /* ------------------------------ */
6972 .L_OP_SHL_INT_LIT8: /* 0xe0 */
6973 /* File: armv5te/OP_SHL_INT_LIT8.S */
6974 /* File: armv5te/binopLit8.S */
6976 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6977 * that specifies an instruction that performs "result = r0 op r1".
6978 * This could be an ARM instruction or a function call. (If the result
6979 * comes back in a register other than r0, you can override "result".)
6981 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6982 * vCC (r1). Useful for integer division and modulus.
6984 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6985 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6986 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6988 /* binop/lit8 vAA, vBB, #+CC */
6989 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6990 mov r9, rINST, lsr #8 @ r9<- AA
6991 and r2, r3, #255 @ r2<- BB
6992 GET_VREG(r0, r2) @ r0<- vBB
6993 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6995 @cmp r1, #0 @ is second operand zero?
6996 beq common_errDivideByZero
6998 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7000 and r1, r1, #31 @ optional op; may set condition codes
7001 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7002 GET_INST_OPCODE(ip) @ extract opcode from rINST
7003 SET_VREG(r0, r9) @ vAA<- r0
7004 GOTO_OPCODE(ip) @ jump to next instruction
7005 /* 10-12 instructions */
7008 /* ------------------------------ */
7010 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7011 /* File: armv5te/OP_SHR_INT_LIT8.S */
7012 /* File: armv5te/binopLit8.S */
7014 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7015 * that specifies an instruction that performs "result = r0 op r1".
7016 * This could be an ARM instruction or a function call. (If the result
7017 * comes back in a register other than r0, you can override "result".)
7019 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7020 * vCC (r1). Useful for integer division and modulus.
7022 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7023 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7024 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7026 /* binop/lit8 vAA, vBB, #+CC */
7027 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7028 mov r9, rINST, lsr #8 @ r9<- AA
7029 and r2, r3, #255 @ r2<- BB
7030 GET_VREG(r0, r2) @ r0<- vBB
7031 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7033 @cmp r1, #0 @ is second operand zero?
7034 beq common_errDivideByZero
7036 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7038 and r1, r1, #31 @ optional op; may set condition codes
7039 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7040 GET_INST_OPCODE(ip) @ extract opcode from rINST
7041 SET_VREG(r0, r9) @ vAA<- r0
7042 GOTO_OPCODE(ip) @ jump to next instruction
7043 /* 10-12 instructions */
7046 /* ------------------------------ */
7048 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7049 /* File: armv5te/OP_USHR_INT_LIT8.S */
7050 /* File: armv5te/binopLit8.S */
7052 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7053 * that specifies an instruction that performs "result = r0 op r1".
7054 * This could be an ARM instruction or a function call. (If the result
7055 * comes back in a register other than r0, you can override "result".)
7057 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058 * vCC (r1). Useful for integer division and modulus.
7060 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7064 /* binop/lit8 vAA, vBB, #+CC */
7065 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7066 mov r9, rINST, lsr #8 @ r9<- AA
7067 and r2, r3, #255 @ r2<- BB
7068 GET_VREG(r0, r2) @ r0<- vBB
7069 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7071 @cmp r1, #0 @ is second operand zero?
7072 beq common_errDivideByZero
7074 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7076 and r1, r1, #31 @ optional op; may set condition codes
7077 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7078 GET_INST_OPCODE(ip) @ extract opcode from rINST
7079 SET_VREG(r0, r9) @ vAA<- r0
7080 GOTO_OPCODE(ip) @ jump to next instruction
7081 /* 10-12 instructions */
7084 /* ------------------------------ */
7086 .L_OP_IGET_VOLATILE: /* 0xe3 */
7087 /* File: armv5te/OP_IGET_VOLATILE.S */
7088 /* File: armv5te/OP_IGET.S */
7090 * General 32-bit instance field get.
7092 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7094 /* op vA, vB, field@CCCC */
7095 mov r0, rINST, lsr #12 @ r0<- B
7096 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7097 FETCH(r1, 1) @ r1<- field ref CCCC
7098 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7099 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7100 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7101 cmp r0, #0 @ is resolved entry null?
7102 bne .LOP_IGET_VOLATILE_finish @ no, already resolved
7103 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7104 EXPORT_PC() @ resolve() could throw
7105 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7106 bl dvmResolveInstField @ r0<- resolved InstField ptr
7108 bne .LOP_IGET_VOLATILE_finish
7109 b common_exceptionThrown
7112 /* ------------------------------ */
7114 .L_OP_IPUT_VOLATILE: /* 0xe4 */
7115 /* File: armv5te/OP_IPUT_VOLATILE.S */
7116 /* File: armv5te/OP_IPUT.S */
7118 * General 32-bit instance field put.
7120 * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7122 /* op vA, vB, field@CCCC */
7123 mov r0, rINST, lsr #12 @ r0<- B
7124 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7125 FETCH(r1, 1) @ r1<- field ref CCCC
7126 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7127 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7128 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7129 cmp r0, #0 @ is resolved entry null?
7130 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved
7131 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7132 EXPORT_PC() @ resolve() could throw
7133 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7134 bl dvmResolveInstField @ r0<- resolved InstField ptr
7135 cmp r0, #0 @ success?
7136 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up
7137 b common_exceptionThrown
7140 /* ------------------------------ */
7142 .L_OP_SGET_VOLATILE: /* 0xe5 */
7143 /* File: armv5te/OP_SGET_VOLATILE.S */
7144 /* File: armv5te/OP_SGET.S */
7146 * General 32-bit SGET handler.
7148 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7150 /* op vAA, field@BBBB */
7151 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7152 FETCH(r1, 1) @ r1<- field ref BBBB
7153 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7154 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7155 cmp r0, #0 @ is resolved entry null?
7156 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve
7157 .LOP_SGET_VOLATILE_finish: @ field ptr in r0
7158 ldr r1, [r0, #offStaticField_value] @ r1<- field value
7159 SMP_DMB @ acquiring load
7160 mov r2, rINST, lsr #8 @ r2<- AA
7161 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7162 SET_VREG(r1, r2) @ fp[AA]<- r1
7163 GET_INST_OPCODE(ip) @ extract opcode from rINST
7164 GOTO_OPCODE(ip) @ jump to next instruction
7167 /* ------------------------------ */
7169 .L_OP_SPUT_VOLATILE: /* 0xe6 */
7170 /* File: armv5te/OP_SPUT_VOLATILE.S */
7171 /* File: armv5te/OP_SPUT.S */
7173 * General 32-bit SPUT handler.
7175 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7177 /* op vAA, field@BBBB */
7178 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7179 FETCH(r1, 1) @ r1<- field ref BBBB
7180 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7181 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7182 cmp r0, #0 @ is resolved entry null?
7183 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve
7184 .LOP_SPUT_VOLATILE_finish: @ field ptr in r0
7185 mov r2, rINST, lsr #8 @ r2<- AA
7186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7187 GET_VREG(r1, r2) @ r1<- fp[AA]
7188 GET_INST_OPCODE(ip) @ extract opcode from rINST
7189 SMP_DMB @ releasing store
7190 str r1, [r0, #offStaticField_value] @ field<- vAA
7191 GOTO_OPCODE(ip) @ jump to next instruction
7194 /* ------------------------------ */
7196 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7197 /* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7198 /* File: armv5te/OP_IGET.S */
7200 * General 32-bit instance field get.
7202 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7204 /* op vA, vB, field@CCCC */
7205 mov r0, rINST, lsr #12 @ r0<- B
7206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7207 FETCH(r1, 1) @ r1<- field ref CCCC
7208 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7209 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7210 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7211 cmp r0, #0 @ is resolved entry null?
7212 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved
7213 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7214 EXPORT_PC() @ resolve() could throw
7215 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7216 bl dvmResolveInstField @ r0<- resolved InstField ptr
7218 bne .LOP_IGET_OBJECT_VOLATILE_finish
7219 b common_exceptionThrown
7222 /* ------------------------------ */
7224 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7225 /* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7226 /* File: armv5te/OP_IGET_WIDE.S */
7228 * Wide 32-bit instance field get.
7230 /* iget-wide vA, vB, field@CCCC */
7231 mov r0, rINST, lsr #12 @ r0<- B
7232 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7233 FETCH(r1, 1) @ r1<- field ref CCCC
7234 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7235 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7236 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7237 cmp r0, #0 @ is resolved entry null?
7238 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved
7239 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7240 EXPORT_PC() @ resolve() could throw
7241 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7242 bl dvmResolveInstField @ r0<- resolved InstField ptr
7244 bne .LOP_IGET_WIDE_VOLATILE_finish
7245 b common_exceptionThrown
7248 /* ------------------------------ */
7250 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7251 /* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7252 /* File: armv5te/OP_IPUT_WIDE.S */
7253 /* iput-wide vA, vB, field@CCCC */
7254 mov r0, rINST, lsr #12 @ r0<- B
7255 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7256 FETCH(r1, 1) @ r1<- field ref CCCC
7257 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7258 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7259 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7260 cmp r0, #0 @ is resolved entry null?
7261 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved
7262 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7263 EXPORT_PC() @ resolve() could throw
7264 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7265 bl dvmResolveInstField @ r0<- resolved InstField ptr
7266 cmp r0, #0 @ success?
7267 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up
7268 b common_exceptionThrown
7271 /* ------------------------------ */
7273 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7274 /* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7275 /* File: armv5te/OP_SGET_WIDE.S */
7277 * 64-bit SGET handler.
7279 /* sget-wide vAA, field@BBBB */
7280 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7281 FETCH(r1, 1) @ r1<- field ref BBBB
7282 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7283 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7284 cmp r0, #0 @ is resolved entry null?
7285 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
7286 .LOP_SGET_WIDE_VOLATILE_finish:
7287 mov r9, rINST, lsr #8 @ r9<- AA
7289 add r0, r0, #offStaticField_value @ r0<- pointer to data
7290 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field
7292 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7294 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
7295 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7296 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
7297 GET_INST_OPCODE(ip) @ extract opcode from rINST
7298 GOTO_OPCODE(ip) @ jump to next instruction
7301 /* ------------------------------ */
7303 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7304 /* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7305 /* File: armv5te/OP_SPUT_WIDE.S */
7307 * 64-bit SPUT handler.
7309 /* sput-wide vAA, field@BBBB */
7310 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
7311 FETCH(r1, 1) @ r1<- field ref BBBB
7312 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7313 mov r9, rINST, lsr #8 @ r9<- AA
7314 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
7315 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
7316 cmp r2, #0 @ is resolved entry null?
7317 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
7318 .LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7320 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
7321 GET_INST_OPCODE(r10) @ extract opcode from rINST
7323 add r2, r2, #offStaticField_value @ r2<- pointer to data
7324 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2
7326 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7328 GOTO_OPCODE(r10) @ jump to next instruction
7331 /* ------------------------------ */
7333 .L_OP_BREAKPOINT: /* 0xec */
7334 /* File: armv5te/OP_BREAKPOINT.S */
7335 /* File: armv5te/unused.S */
7339 /* ------------------------------ */
7341 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7342 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7344 * Handle a throw-verification-error instruction. This throws an
7345 * exception for an error discovered during verification. The
7346 * exception is indicated by AA, with some detail provided by BBBB.
7348 /* op AA, ref@BBBB */
7349 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7350 FETCH(r2, 1) @ r2<- BBBB
7351 EXPORT_PC() @ export the PC
7352 mov r1, rINST, lsr #8 @ r1<- AA
7353 bl dvmThrowVerificationError @ always throws
7354 b common_exceptionThrown @ handle exception
7356 /* ------------------------------ */
7358 .L_OP_EXECUTE_INLINE: /* 0xee */
7359 /* File: armv5te/OP_EXECUTE_INLINE.S */
7361 * Execute a "native inline" instruction.
7363 * We need to call an InlineOp4Func:
7364 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7366 * The first four args are in r0-r3, pointer to return value storage
7367 * is on the stack. The function's return value is a flag that tells
7368 * us if an exception was thrown.
7370 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7371 FETCH(r10, 1) @ r10<- BBBB
7372 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7373 EXPORT_PC() @ can throw
7374 sub sp, sp, #8 @ make room for arg, +64 bit align
7375 mov r0, rINST, lsr #12 @ r0<- B
7376 str r1, [sp] @ push &glue->retval
7377 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7378 add sp, sp, #8 @ pop stack
7379 cmp r0, #0 @ test boolean result of inline
7380 beq common_exceptionThrown @ returned false, handle exception
7381 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7382 GET_INST_OPCODE(ip) @ extract opcode from rINST
7383 GOTO_OPCODE(ip) @ jump to next instruction
7385 /* ------------------------------ */
7387 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7388 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7390 * Execute a "native inline" instruction, using "/range" semantics.
7391 * Same idea as execute-inline, but we get the args differently.
7393 * We need to call an InlineOp4Func:
7394 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7396 * The first four args are in r0-r3, pointer to return value storage
7397 * is on the stack. The function's return value is a flag that tells
7398 * us if an exception was thrown.
7400 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7401 FETCH(r10, 1) @ r10<- BBBB
7402 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7403 EXPORT_PC() @ can throw
7404 sub sp, sp, #8 @ make room for arg, +64 bit align
7405 mov r0, rINST, lsr #8 @ r0<- AA
7406 str r1, [sp] @ push &glue->retval
7407 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after
7408 add sp, sp, #8 @ pop stack
7409 cmp r0, #0 @ test boolean result of inline
7410 beq common_exceptionThrown @ returned false, handle exception
7411 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7412 GET_INST_OPCODE(ip) @ extract opcode from rINST
7413 GOTO_OPCODE(ip) @ jump to next instruction
7415 /* ------------------------------ */
7417 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7418 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7420 * invoke-direct-empty is a no-op in a "standard" interpreter.
7422 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7423 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7424 GOTO_OPCODE(ip) @ execute it
7426 /* ------------------------------ */
7428 .L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7429 /* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7431 b common_returnFromMethod
7433 /* ------------------------------ */
7435 .L_OP_IGET_QUICK: /* 0xf2 */
7436 /* File: armv5te/OP_IGET_QUICK.S */
7437 /* For: iget-quick, iget-object-quick */
7438 /* op vA, vB, offset@CCCC */
7439 mov r2, rINST, lsr #12 @ r2<- B
7440 GET_VREG(r3, r2) @ r3<- object we're operating on
7441 FETCH(r1, 1) @ r1<- field byte offset
7442 cmp r3, #0 @ check object for null
7443 mov r2, rINST, lsr #8 @ r2<- A(+)
7444 beq common_errNullObject @ object was null
7445 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7446 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7448 GET_INST_OPCODE(ip) @ extract opcode from rINST
7449 SET_VREG(r0, r2) @ fp[A]<- r0
7450 GOTO_OPCODE(ip) @ jump to next instruction
7452 /* ------------------------------ */
7454 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7455 /* File: armv5te/OP_IGET_WIDE_QUICK.S */
7456 /* iget-wide-quick vA, vB, offset@CCCC */
7457 mov r2, rINST, lsr #12 @ r2<- B
7458 GET_VREG(r3, r2) @ r3<- object we're operating on
7459 FETCH(ip, 1) @ ip<- field byte offset
7460 cmp r3, #0 @ check object for null
7461 mov r2, rINST, lsr #8 @ r2<- A(+)
7462 beq common_errNullObject @ object was null
7463 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned)
7465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7466 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7467 GET_INST_OPCODE(ip) @ extract opcode from rINST
7468 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7469 GOTO_OPCODE(ip) @ jump to next instruction
7471 /* ------------------------------ */
7473 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7474 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7475 /* File: armv5te/OP_IGET_QUICK.S */
7476 /* For: iget-quick, iget-object-quick */
7477 /* op vA, vB, offset@CCCC */
7478 mov r2, rINST, lsr #12 @ r2<- B
7479 GET_VREG(r3, r2) @ r3<- object we're operating on
7480 FETCH(r1, 1) @ r1<- field byte offset
7481 cmp r3, #0 @ check object for null
7482 mov r2, rINST, lsr #8 @ r2<- A(+)
7483 beq common_errNullObject @ object was null
7484 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7485 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7487 GET_INST_OPCODE(ip) @ extract opcode from rINST
7488 SET_VREG(r0, r2) @ fp[A]<- r0
7489 GOTO_OPCODE(ip) @ jump to next instruction
7492 /* ------------------------------ */
7494 .L_OP_IPUT_QUICK: /* 0xf5 */
7495 /* File: armv5te/OP_IPUT_QUICK.S */
7496 /* For: iput-quick */
7497 /* op vA, vB, offset@CCCC */
7498 mov r2, rINST, lsr #12 @ r2<- B
7499 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7500 FETCH(r1, 1) @ r1<- field byte offset
7501 cmp r3, #0 @ check object for null
7502 mov r2, rINST, lsr #8 @ r2<- A(+)
7503 beq common_errNullObject @ object was null
7505 GET_VREG(r0, r2) @ r0<- fp[A]
7506 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7507 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7508 GET_INST_OPCODE(ip) @ extract opcode from rINST
7509 GOTO_OPCODE(ip) @ jump to next instruction
7511 /* ------------------------------ */
7513 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7514 /* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7515 /* iput-wide-quick vA, vB, offset@CCCC */
7516 mov r0, rINST, lsr #8 @ r0<- A(+)
7517 mov r1, rINST, lsr #12 @ r1<- B
7519 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7520 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7521 cmp r2, #0 @ check object for null
7522 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7523 beq common_errNullObject @ object was null
7524 FETCH(r3, 1) @ r3<- field byte offset
7525 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7526 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1
7527 GET_INST_OPCODE(ip) @ extract opcode from rINST
7528 GOTO_OPCODE(ip) @ jump to next instruction
7530 /* ------------------------------ */
7532 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7533 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7534 /* For: iput-object-quick */
7535 /* op vA, vB, offset@CCCC */
7536 mov r2, rINST, lsr #12 @ r2<- B
7537 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7538 FETCH(r1, 1) @ r1<- field byte offset
7539 cmp r3, #0 @ check object for null
7540 mov r2, rINST, lsr #8 @ r2<- A(+)
7541 beq common_errNullObject @ object was null
7543 GET_VREG(r0, r2) @ r0<- fp[A]
7544 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
7545 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7546 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7548 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7549 GET_INST_OPCODE(ip) @ extract opcode from rINST
7550 GOTO_OPCODE(ip) @ jump to next instruction
7552 /* ------------------------------ */
7554 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7555 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7557 * Handle an optimized virtual method call.
7559 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7561 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7562 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7563 FETCH(r3, 2) @ r3<- FEDC or CCCC
7564 FETCH(r1, 1) @ r1<- BBBB
7566 and r3, r3, #15 @ r3<- C (or stays CCCC)
7568 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7569 cmp r2, #0 @ is "this" null?
7570 beq common_errNullObject @ null "this", throw exception
7571 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7572 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7573 EXPORT_PC() @ invoke must export
7574 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7575 bl common_invokeMethodNoRange @ continue on
7577 /* ------------------------------ */
7579 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7580 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7581 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7583 * Handle an optimized virtual method call.
7585 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7587 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7588 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7589 FETCH(r3, 2) @ r3<- FEDC or CCCC
7590 FETCH(r1, 1) @ r1<- BBBB
7592 and r3, r3, #15 @ r3<- C (or stays CCCC)
7594 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7595 cmp r2, #0 @ is "this" null?
7596 beq common_errNullObject @ null "this", throw exception
7597 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7598 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7599 EXPORT_PC() @ invoke must export
7600 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7601 bl common_invokeMethodRange @ continue on
7604 /* ------------------------------ */
7606 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7607 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7609 * Handle an optimized "super" method call.
7611 * for: [opt] invoke-super-quick, invoke-super-quick/range
7613 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7614 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7615 FETCH(r10, 2) @ r10<- GFED or CCCC
7616 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7618 and r10, r10, #15 @ r10<- D (or stays CCCC)
7620 FETCH(r1, 1) @ r1<- BBBB
7621 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7622 EXPORT_PC() @ must export for invoke
7623 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7624 GET_VREG(r3, r10) @ r3<- "this"
7625 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7626 cmp r3, #0 @ null "this" ref?
7627 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7628 beq common_errNullObject @ "this" is null, throw exception
7629 bl common_invokeMethodNoRange @ continue on
7631 /* ------------------------------ */
7633 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7634 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7635 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7637 * Handle an optimized "super" method call.
7639 * for: [opt] invoke-super-quick, invoke-super-quick/range
7641 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7642 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7643 FETCH(r10, 2) @ r10<- GFED or CCCC
7644 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7646 and r10, r10, #15 @ r10<- D (or stays CCCC)
7648 FETCH(r1, 1) @ r1<- BBBB
7649 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7650 EXPORT_PC() @ must export for invoke
7651 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7652 GET_VREG(r3, r10) @ r3<- "this"
7653 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7654 cmp r3, #0 @ null "this" ref?
7655 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7656 beq common_errNullObject @ "this" is null, throw exception
7657 bl common_invokeMethodRange @ continue on
7660 /* ------------------------------ */
7662 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7663 /* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7664 /* File: armv5te/OP_IPUT_OBJECT.S */
7666 * 32-bit instance field put.
7668 * for: iput-object, iput-object-volatile
7670 /* op vA, vB, field@CCCC */
7671 mov r0, rINST, lsr #12 @ r0<- B
7672 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7673 FETCH(r1, 1) @ r1<- field ref CCCC
7674 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7675 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7676 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7677 cmp r0, #0 @ is resolved entry null?
7678 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved
7679 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7680 EXPORT_PC() @ resolve() could throw
7681 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7682 bl dvmResolveInstField @ r0<- resolved InstField ptr
7683 cmp r0, #0 @ success?
7684 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up
7685 b common_exceptionThrown
7688 /* ------------------------------ */
7690 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7691 /* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7692 /* File: armv5te/OP_SGET.S */
7694 * General 32-bit SGET handler.
7696 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7698 /* op vAA, field@BBBB */
7699 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7700 FETCH(r1, 1) @ r1<- field ref BBBB
7701 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7702 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7703 cmp r0, #0 @ is resolved entry null?
7704 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve
7705 .LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7706 ldr r1, [r0, #offStaticField_value] @ r1<- field value
7707 SMP_DMB @ acquiring load
7708 mov r2, rINST, lsr #8 @ r2<- AA
7709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7710 SET_VREG(r1, r2) @ fp[AA]<- r1
7711 GET_INST_OPCODE(ip) @ extract opcode from rINST
7712 GOTO_OPCODE(ip) @ jump to next instruction
7715 /* ------------------------------ */
7717 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7718 /* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7719 /* File: armv5te/OP_SPUT_OBJECT.S */
7721 * 32-bit SPUT handler for objects
7723 * for: sput-object, sput-object-volatile
7725 /* op vAA, field@BBBB */
7726 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7727 FETCH(r1, 1) @ r1<- field ref BBBB
7728 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7729 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7730 cmp r0, #0 @ is resolved entry null?
7731 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue
7732 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
7733 EXPORT_PC() @ resolve() could throw, so export now
7734 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz
7735 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
7736 cmp r0, #0 @ success?
7737 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
7738 b common_exceptionThrown @ no, handle exception
7742 /* ------------------------------ */
7744 .L_OP_DISPATCH_FF: /* 0xff */
7745 /* File: armv5te/OP_DISPATCH_FF.S */
7746 /* File: armv5te/unused.S */
7752 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
7753 .global dvmAsmInstructionEnd
7754 dvmAsmInstructionEnd:
7757 * ===========================================================================
7758 * Sister implementations
7759 * ===========================================================================
7761 .global dvmAsmSisterStart
7762 .type dvmAsmSisterStart, %function
7767 /* continuation for OP_CONST_STRING */
7770 * Continuation if the String has not yet been resolved.
7771 * r1: BBBB (String ref)
7772 * r9: target register
7774 .LOP_CONST_STRING_resolve:
7776 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7777 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7778 bl dvmResolveString @ r0<- String reference
7779 cmp r0, #0 @ failed?
7780 beq common_exceptionThrown @ yup, handle the exception
7781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7782 GET_INST_OPCODE(ip) @ extract opcode from rINST
7783 SET_VREG(r0, r9) @ vAA<- r0
7784 GOTO_OPCODE(ip) @ jump to next instruction
7786 /* continuation for OP_CONST_STRING_JUMBO */
7789 * Continuation if the String has not yet been resolved.
7790 * r1: BBBBBBBB (String ref)
7791 * r9: target register
7793 .LOP_CONST_STRING_JUMBO_resolve:
7795 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7796 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7797 bl dvmResolveString @ r0<- String reference
7798 cmp r0, #0 @ failed?
7799 beq common_exceptionThrown @ yup, handle the exception
7800 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7801 GET_INST_OPCODE(ip) @ extract opcode from rINST
7802 SET_VREG(r0, r9) @ vAA<- r0
7803 GOTO_OPCODE(ip) @ jump to next instruction
7805 /* continuation for OP_CONST_CLASS */
7808 * Continuation if the Class has not yet been resolved.
7809 * r1: BBBB (Class ref)
7810 * r9: target register
7812 .LOP_CONST_CLASS_resolve:
7814 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7815 mov r2, #1 @ r2<- true
7816 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7817 bl dvmResolveClass @ r0<- Class reference
7818 cmp r0, #0 @ failed?
7819 beq common_exceptionThrown @ yup, handle the exception
7820 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7821 GET_INST_OPCODE(ip) @ extract opcode from rINST
7822 SET_VREG(r0, r9) @ vAA<- r0
7823 GOTO_OPCODE(ip) @ jump to next instruction
7825 /* continuation for OP_CHECK_CAST */
7828 * Trivial test failed, need to perform full check. This is common.
7829 * r0 holds obj->clazz
7830 * r1 holds desired class resolved from BBBB
7833 .LOP_CHECK_CAST_fullcheck:
7834 mov r10, r1 @ avoid ClassObject getting clobbered
7835 bl dvmInstanceofNonTrivial @ r0<- boolean result
7836 cmp r0, #0 @ failed?
7837 bne .LOP_CHECK_CAST_okay @ no, success
7839 @ A cast has failed. We need to throw a ClassCastException.
7840 EXPORT_PC() @ about to throw
7841 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class)
7842 mov r1, r10 @ r1<- desired class
7843 bl dvmThrowClassCastException
7844 b common_exceptionThrown
7847 * Resolution required. This is the least-likely path.
7852 .LOP_CHECK_CAST_resolve:
7853 EXPORT_PC() @ resolve() could throw
7854 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7855 mov r1, r2 @ r1<- BBBB
7856 mov r2, #0 @ r2<- false
7857 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7858 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7859 cmp r0, #0 @ got null?
7860 beq common_exceptionThrown @ yes, handle exception
7861 mov r1, r0 @ r1<- class resolved from BBB
7862 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
7863 b .LOP_CHECK_CAST_resolved @ pick up where we left off
7865 /* continuation for OP_INSTANCE_OF */
7868 * Trivial test failed, need to perform full check. This is common.
7869 * r0 holds obj->clazz
7870 * r1 holds class resolved from BBBB
7873 .LOP_INSTANCE_OF_fullcheck:
7874 bl dvmInstanceofNonTrivial @ r0<- boolean result
7875 @ fall through to OP_INSTANCE_OF_store
7878 * r0 holds boolean result
7881 .LOP_INSTANCE_OF_store:
7882 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7883 SET_VREG(r0, r9) @ vA<- r0
7884 GET_INST_OPCODE(ip) @ extract opcode from rINST
7885 GOTO_OPCODE(ip) @ jump to next instruction
7888 * Trivial test succeeded, save and bail.
7891 .LOP_INSTANCE_OF_trivial:
7892 mov r0, #1 @ indicate success
7893 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7894 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7895 SET_VREG(r0, r9) @ vA<- r0
7896 GET_INST_OPCODE(ip) @ extract opcode from rINST
7897 GOTO_OPCODE(ip) @ jump to next instruction
7900 * Resolution required. This is the least-likely path.
7905 .LOP_INSTANCE_OF_resolve:
7906 EXPORT_PC() @ resolve() could throw
7907 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7908 mov r1, r3 @ r1<- BBBB
7909 mov r2, #1 @ r2<- true
7910 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7911 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7912 cmp r0, #0 @ got null?
7913 beq common_exceptionThrown @ yes, handle exception
7914 mov r1, r0 @ r1<- class resolved from BBB
7915 mov r3, rINST, lsr #12 @ r3<- B
7916 GET_VREG(r0, r3) @ r0<- vB (object)
7917 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
7918 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
7920 /* continuation for OP_NEW_INSTANCE */
7922 .balign 32 @ minimize cache lines
7923 .LOP_NEW_INSTANCE_finish: @ r0=new object
7924 mov r3, rINST, lsr #8 @ r3<- AA
7925 cmp r0, #0 @ failed?
7926 beq common_exceptionThrown @ yes, handle the exception
7927 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7928 GET_INST_OPCODE(ip) @ extract opcode from rINST
7929 SET_VREG(r0, r3) @ vAA<- r0
7930 GOTO_OPCODE(ip) @ jump to next instruction
7933 * Class initialization required.
7935 * r0 holds class object
7937 .LOP_NEW_INSTANCE_needinit:
7938 mov r9, r0 @ save r0
7939 bl dvmInitClass @ initialize class
7940 cmp r0, #0 @ check boolean result
7941 mov r0, r9 @ restore r0
7942 bne .LOP_NEW_INSTANCE_initialized @ success, continue
7943 b common_exceptionThrown @ failed, deal with init exception
7946 * Resolution required. This is the least-likely path.
7950 .LOP_NEW_INSTANCE_resolve:
7951 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7952 mov r2, #0 @ r2<- false
7953 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7954 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7955 cmp r0, #0 @ got null?
7956 bne .LOP_NEW_INSTANCE_resolved @ no, continue
7957 b common_exceptionThrown @ yes, handle exception
7959 .LstrInstantiationErrorPtr:
7960 .word .LstrInstantiationError
7962 /* continuation for OP_NEW_ARRAY */
7966 * Resolve class. (This is an uncommon case.)
7968 * r1 holds array length
7969 * r2 holds class ref CCCC
7971 .LOP_NEW_ARRAY_resolve:
7972 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7973 mov r9, r1 @ r9<- length (save)
7974 mov r1, r2 @ r1<- CCCC
7975 mov r2, #0 @ r2<- false
7976 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7977 bl dvmResolveClass @ r0<- call(clazz, ref)
7978 cmp r0, #0 @ got null?
7979 mov r1, r9 @ r1<- length (restore)
7980 beq common_exceptionThrown @ yes, handle exception
7981 @ fall through to OP_NEW_ARRAY_finish
7984 * Finish allocation.
7987 * r1 holds array length
7989 .LOP_NEW_ARRAY_finish:
7990 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
7991 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
7992 cmp r0, #0 @ failed?
7993 mov r2, rINST, lsr #8 @ r2<- A+
7994 beq common_exceptionThrown @ yes, handle the exception
7995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7996 and r2, r2, #15 @ r2<- A
7997 GET_INST_OPCODE(ip) @ extract opcode from rINST
7998 SET_VREG(r0, r2) @ vA<- r0
7999 GOTO_OPCODE(ip) @ jump to next instruction
8001 /* continuation for OP_FILLED_NEW_ARRAY */
8005 * r0 holds array class
8006 * r10 holds AA or BA
8008 .LOP_FILLED_NEW_ARRAY_continue:
8009 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8010 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8011 ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
8013 mov r1, r10 @ r1<- AA (length)
8015 mov r1, r10, lsr #4 @ r1<- B (length)
8017 cmp rINST, #'I' @ array of ints?
8018 cmpne rINST, #'L' @ array of objects?
8019 cmpne rINST, #'[' @ array of arrays?
8020 mov r9, r1 @ save length in r9
8021 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
8022 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8023 cmp r0, #0 @ null return?
8024 beq common_exceptionThrown @ alloc failed, handle exception
8026 FETCH(r1, 2) @ r1<- FEDC or CCCC
8027 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8028 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8029 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8030 subs r9, r9, #1 @ length--, check for neg
8031 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8032 bmi 2f @ was zero, bail
8034 @ copy values from registers into the array
8035 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8037 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8038 1: ldr r3, [r2], #4 @ r3<- *r2++
8039 subs r9, r9, #1 @ count--
8040 str r3, [r0], #4 @ *contents++ = vX
8044 cmp r9, #4 @ length was initially 5?
8045 and r2, r10, #15 @ r2<- A
8046 bne 1f @ <= 4 args, branch
8047 GET_VREG(r3, r2) @ r3<- vA
8048 sub r9, r9, #1 @ count--
8049 str r3, [r0, #16] @ contents[4] = vA
8050 1: and r2, r1, #15 @ r2<- F/E/D/C
8051 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8052 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8053 subs r9, r9, #1 @ count--
8054 str r3, [r0], #4 @ *contents++ = vX
8060 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
8061 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
8062 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
8063 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8064 cmp r1, #'I' @ Is int array?
8065 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8066 GOTO_OPCODE(ip) @ execute it
8069 * Throw an exception indicating that we have not implemented this
8070 * mode of filled-new-array.
8072 .LOP_FILLED_NEW_ARRAY_notimpl:
8073 ldr r0, .L_strInternalError
8074 ldr r1, .L_strFilledNewArrayNotImpl
8075 bl dvmThrowException
8076 b common_exceptionThrown
8078 .if (!0) @ define in one or the other, not both
8079 .L_strFilledNewArrayNotImpl:
8080 .word .LstrFilledNewArrayNotImpl
8081 .L_strInternalError:
8082 .word .LstrInternalError
8085 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8089 * r0 holds array class
8090 * r10 holds AA or BA
8092 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8093 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8094 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8095 ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
8097 mov r1, r10 @ r1<- AA (length)
8099 mov r1, r10, lsr #4 @ r1<- B (length)
8101 cmp rINST, #'I' @ array of ints?
8102 cmpne rINST, #'L' @ array of objects?
8103 cmpne rINST, #'[' @ array of arrays?
8104 mov r9, r1 @ save length in r9
8105 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
8106 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8107 cmp r0, #0 @ null return?
8108 beq common_exceptionThrown @ alloc failed, handle exception
8110 FETCH(r1, 2) @ r1<- FEDC or CCCC
8111 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8112 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8113 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8114 subs r9, r9, #1 @ length--, check for neg
8115 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8116 bmi 2f @ was zero, bail
8118 @ copy values from registers into the array
8119 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8121 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8122 1: ldr r3, [r2], #4 @ r3<- *r2++
8123 subs r9, r9, #1 @ count--
8124 str r3, [r0], #4 @ *contents++ = vX
8128 cmp r9, #4 @ length was initially 5?
8129 and r2, r10, #15 @ r2<- A
8130 bne 1f @ <= 4 args, branch
8131 GET_VREG(r3, r2) @ r3<- vA
8132 sub r9, r9, #1 @ count--
8133 str r3, [r0, #16] @ contents[4] = vA
8134 1: and r2, r1, #15 @ r2<- F/E/D/C
8135 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8136 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8137 subs r9, r9, #1 @ count--
8138 str r3, [r0], #4 @ *contents++ = vX
8144 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
8145 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
8146 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
8147 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8148 cmp r1, #'I' @ Is int array?
8149 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8150 GOTO_OPCODE(ip) @ execute it
8153 * Throw an exception indicating that we have not implemented this
8154 * mode of filled-new-array.
8156 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8157 ldr r0, .L_strInternalError
8158 ldr r1, .L_strFilledNewArrayNotImpl
8159 bl dvmThrowException
8160 b common_exceptionThrown
8162 .if (!1) @ define in one or the other, not both
8163 .L_strFilledNewArrayNotImpl:
8164 .word .LstrFilledNewArrayNotImpl
8165 .L_strInternalError:
8166 .word .LstrInternalError
8169 /* continuation for OP_CMPL_FLOAT */
8170 .LOP_CMPL_FLOAT_finish:
8171 SET_VREG(r0, r9) @ vAA<- r0
8172 GOTO_OPCODE(ip) @ jump to next instruction
8174 /* continuation for OP_CMPG_FLOAT */
8175 .LOP_CMPG_FLOAT_finish:
8176 SET_VREG(r0, r9) @ vAA<- r0
8177 GOTO_OPCODE(ip) @ jump to next instruction
8179 /* continuation for OP_CMPL_DOUBLE */
8180 .LOP_CMPL_DOUBLE_finish:
8181 SET_VREG(r0, r9) @ vAA<- r0
8182 GOTO_OPCODE(ip) @ jump to next instruction
8184 /* continuation for OP_CMPG_DOUBLE */
8185 .LOP_CMPG_DOUBLE_finish:
8186 SET_VREG(r0, r9) @ vAA<- r0
8187 GOTO_OPCODE(ip) @ jump to next instruction
8189 /* continuation for OP_CMP_LONG */
8192 mvn r1, #0 @ r1<- -1
8193 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8194 @ instead, we just replicate the tail end.
8195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8196 SET_VREG(r1, r9) @ vAA<- r1
8197 GET_INST_OPCODE(ip) @ extract opcode from rINST
8198 GOTO_OPCODE(ip) @ jump to next instruction
8200 .LOP_CMP_LONG_greater:
8202 @ fall through to _finish
8204 .LOP_CMP_LONG_finish:
8205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8206 SET_VREG(r1, r9) @ vAA<- r1
8207 GET_INST_OPCODE(ip) @ extract opcode from rINST
8208 GOTO_OPCODE(ip) @ jump to next instruction
8210 /* continuation for OP_AGET_WIDE */
8212 .LOP_AGET_WIDE_finish:
8213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8214 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8215 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8216 GET_INST_OPCODE(ip) @ extract opcode from rINST
8217 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8218 GOTO_OPCODE(ip) @ jump to next instruction
8220 /* continuation for OP_APUT_WIDE */
8222 .LOP_APUT_WIDE_finish:
8223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8224 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8225 GET_INST_OPCODE(ip) @ extract opcode from rINST
8226 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8227 GOTO_OPCODE(ip) @ jump to next instruction
8229 /* continuation for OP_APUT_OBJECT */
8232 * rINST = vBB (arrayObj)
8234 * r10 = offset into array (vBB + vCC * width)
8236 .LOP_APUT_OBJECT_finish:
8237 cmp r9, #0 @ storing null reference?
8238 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8239 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8240 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz
8241 bl dvmCanPutArrayElement @ test object type vs. array type
8243 beq .LOP_APUT_OBJECT_throw @ no
8244 mov r1, rINST @ r1<- arrayObj
8245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8246 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base
8247 add r10, #offArrayObject_contents @ r0<- pointer to slot
8248 GET_INST_OPCODE(ip) @ extract opcode from rINST
8249 str r9, [r10] @ vBB[vCC]<- vAA
8250 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8251 GOTO_OPCODE(ip) @ jump to next instruction
8252 .LOP_APUT_OBJECT_skip_check:
8253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8254 GET_INST_OPCODE(ip) @ extract opcode from rINST
8255 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8256 GOTO_OPCODE(ip) @ jump to next instruction
8257 .LOP_APUT_OBJECT_throw:
8258 @ The types don't match. We need to throw an ArrayStoreException.
8259 ldr r0, [r9, #offObject_clazz]
8260 ldr r1, [rINST, #offObject_clazz]
8262 bl dvmThrowArrayStoreException
8263 b common_exceptionThrown
8265 /* continuation for OP_IGET */
8269 * r0 holds resolved field
8274 cmp r9, #0 @ check object for null
8275 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8276 beq common_errNullObject @ object was null
8277 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8278 @ no-op @ acquiring load
8279 mov r2, rINST, lsr #8 @ r2<- A+
8280 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8281 and r2, r2, #15 @ r2<- A
8282 GET_INST_OPCODE(ip) @ extract opcode from rINST
8283 SET_VREG(r0, r2) @ fp[A]<- r0
8284 GOTO_OPCODE(ip) @ jump to next instruction
8286 /* continuation for OP_IGET_WIDE */
8290 * r0 holds resolved field
8293 .LOP_IGET_WIDE_finish:
8294 cmp r9, #0 @ check object for null
8295 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8296 beq common_errNullObject @ object was null
8298 add r0, r9, r3 @ r0<- address of field
8299 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field
8301 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
8303 mov r2, rINST, lsr #8 @ r2<- A+
8304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8305 and r2, r2, #15 @ r2<- A
8306 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8307 GET_INST_OPCODE(ip) @ extract opcode from rINST
8308 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8309 GOTO_OPCODE(ip) @ jump to next instruction
8311 /* continuation for OP_IGET_OBJECT */
8315 * r0 holds resolved field
8318 .LOP_IGET_OBJECT_finish:
8320 cmp r9, #0 @ check object for null
8321 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8322 beq common_errNullObject @ object was null
8323 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8324 @ no-op @ acquiring load
8325 mov r2, rINST, lsr #8 @ r2<- A+
8326 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8327 and r2, r2, #15 @ r2<- A
8328 GET_INST_OPCODE(ip) @ extract opcode from rINST
8329 SET_VREG(r0, r2) @ fp[A]<- r0
8330 GOTO_OPCODE(ip) @ jump to next instruction
8332 /* continuation for OP_IGET_BOOLEAN */
8336 * r0 holds resolved field
8339 .LOP_IGET_BOOLEAN_finish:
8341 cmp r9, #0 @ check object for null
8342 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8343 beq common_errNullObject @ object was null
8344 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8345 @ no-op @ acquiring load
8346 mov r2, rINST, lsr #8 @ r2<- A+
8347 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8348 and r2, r2, #15 @ r2<- A
8349 GET_INST_OPCODE(ip) @ extract opcode from rINST
8350 SET_VREG(r0, r2) @ fp[A]<- r0
8351 GOTO_OPCODE(ip) @ jump to next instruction
8353 /* continuation for OP_IGET_BYTE */
8357 * r0 holds resolved field
8360 .LOP_IGET_BYTE_finish:
8362 cmp r9, #0 @ check object for null
8363 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8364 beq common_errNullObject @ object was null
8365 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8366 @ no-op @ acquiring load
8367 mov r2, rINST, lsr #8 @ r2<- A+
8368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8369 and r2, r2, #15 @ r2<- A
8370 GET_INST_OPCODE(ip) @ extract opcode from rINST
8371 SET_VREG(r0, r2) @ fp[A]<- r0
8372 GOTO_OPCODE(ip) @ jump to next instruction
8374 /* continuation for OP_IGET_CHAR */
8378 * r0 holds resolved field
8381 .LOP_IGET_CHAR_finish:
8383 cmp r9, #0 @ check object for null
8384 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8385 beq common_errNullObject @ object was null
8386 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8387 @ no-op @ acquiring load
8388 mov r2, rINST, lsr #8 @ r2<- A+
8389 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8390 and r2, r2, #15 @ r2<- A
8391 GET_INST_OPCODE(ip) @ extract opcode from rINST
8392 SET_VREG(r0, r2) @ fp[A]<- r0
8393 GOTO_OPCODE(ip) @ jump to next instruction
8395 /* continuation for OP_IGET_SHORT */
8399 * r0 holds resolved field
8402 .LOP_IGET_SHORT_finish:
8404 cmp r9, #0 @ check object for null
8405 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8406 beq common_errNullObject @ object was null
8407 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8408 @ no-op @ acquiring load
8409 mov r2, rINST, lsr #8 @ r2<- A+
8410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8411 and r2, r2, #15 @ r2<- A
8412 GET_INST_OPCODE(ip) @ extract opcode from rINST
8413 SET_VREG(r0, r2) @ fp[A]<- r0
8414 GOTO_OPCODE(ip) @ jump to next instruction
8416 /* continuation for OP_IPUT */
8420 * r0 holds resolved field
8425 mov r1, rINST, lsr #8 @ r1<- A+
8426 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8427 and r1, r1, #15 @ r1<- A
8428 cmp r9, #0 @ check object for null
8429 GET_VREG(r0, r1) @ r0<- fp[A]
8430 beq common_errNullObject @ object was null
8431 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8432 GET_INST_OPCODE(ip) @ extract opcode from rINST
8433 @ no-op @ releasing store
8434 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8435 GOTO_OPCODE(ip) @ jump to next instruction
8437 /* continuation for OP_IPUT_WIDE */
8441 * r0 holds resolved field
8444 .LOP_IPUT_WIDE_finish:
8445 mov r2, rINST, lsr #8 @ r2<- A+
8446 cmp r9, #0 @ check object for null
8447 and r2, r2, #15 @ r2<- A
8448 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8449 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8450 beq common_errNullObject @ object was null
8451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8452 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8453 GET_INST_OPCODE(r10) @ extract opcode from rINST
8455 add r2, r9, r3 @ r2<- target address
8456 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2
8458 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
8460 GOTO_OPCODE(r10) @ jump to next instruction
8462 /* continuation for OP_IPUT_OBJECT */
8466 * r0 holds resolved field
8469 .LOP_IPUT_OBJECT_finish:
8471 mov r1, rINST, lsr #8 @ r1<- A+
8472 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8473 and r1, r1, #15 @ r1<- A
8474 cmp r9, #0 @ check object for null
8475 GET_VREG(r0, r1) @ r0<- fp[A]
8476 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
8477 beq common_errNullObject @ object was null
8478 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8479 GET_INST_OPCODE(ip) @ extract opcode from rINST
8480 @ no-op @ releasing store
8481 str r0, [r9, r3] @ obj.field (32 bits)<- r0
8482 cmp r0, #0 @ stored a null reference?
8483 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not
8484 GOTO_OPCODE(ip) @ jump to next instruction
8486 /* continuation for OP_IPUT_BOOLEAN */
8490 * r0 holds resolved field
8493 .LOP_IPUT_BOOLEAN_finish:
8495 mov r1, rINST, lsr #8 @ r1<- A+
8496 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8497 and r1, r1, #15 @ r1<- A
8498 cmp r9, #0 @ check object for null
8499 GET_VREG(r0, r1) @ r0<- fp[A]
8500 beq common_errNullObject @ object was null
8501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8502 GET_INST_OPCODE(ip) @ extract opcode from rINST
8503 @ no-op @ releasing store
8504 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8505 GOTO_OPCODE(ip) @ jump to next instruction
8507 /* continuation for OP_IPUT_BYTE */
8511 * r0 holds resolved field
8514 .LOP_IPUT_BYTE_finish:
8516 mov r1, rINST, lsr #8 @ r1<- A+
8517 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8518 and r1, r1, #15 @ r1<- A
8519 cmp r9, #0 @ check object for null
8520 GET_VREG(r0, r1) @ r0<- fp[A]
8521 beq common_errNullObject @ object was null
8522 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8523 GET_INST_OPCODE(ip) @ extract opcode from rINST
8524 @ no-op @ releasing store
8525 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8526 GOTO_OPCODE(ip) @ jump to next instruction
8528 /* continuation for OP_IPUT_CHAR */
8532 * r0 holds resolved field
8535 .LOP_IPUT_CHAR_finish:
8537 mov r1, rINST, lsr #8 @ r1<- A+
8538 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8539 and r1, r1, #15 @ r1<- A
8540 cmp r9, #0 @ check object for null
8541 GET_VREG(r0, r1) @ r0<- fp[A]
8542 beq common_errNullObject @ object was null
8543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8544 GET_INST_OPCODE(ip) @ extract opcode from rINST
8545 @ no-op @ releasing store
8546 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8547 GOTO_OPCODE(ip) @ jump to next instruction
8549 /* continuation for OP_IPUT_SHORT */
8553 * r0 holds resolved field
8556 .LOP_IPUT_SHORT_finish:
8558 mov r1, rINST, lsr #8 @ r1<- A+
8559 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8560 and r1, r1, #15 @ r1<- A
8561 cmp r9, #0 @ check object for null
8562 GET_VREG(r0, r1) @ r0<- fp[A]
8563 beq common_errNullObject @ object was null
8564 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8565 GET_INST_OPCODE(ip) @ extract opcode from rINST
8566 @ no-op @ releasing store
8567 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8568 GOTO_OPCODE(ip) @ jump to next instruction
8570 /* continuation for OP_SGET */
8573 * Continuation if the field has not yet been resolved.
8574 * r1: BBBB field ref
8577 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8578 EXPORT_PC() @ resolve() could throw, so export now
8579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8580 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8581 cmp r0, #0 @ success?
8582 bne .LOP_SGET_finish @ yes, finish
8583 b common_exceptionThrown @ no, handle exception
8585 /* continuation for OP_SGET_WIDE */
8588 * Continuation if the field has not yet been resolved.
8589 * r1: BBBB field ref
8591 * Returns StaticField pointer in r0.
8593 .LOP_SGET_WIDE_resolve:
8594 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8595 EXPORT_PC() @ resolve() could throw, so export now
8596 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8597 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8598 cmp r0, #0 @ success?
8599 bne .LOP_SGET_WIDE_finish @ yes, finish
8600 b common_exceptionThrown @ no, handle exception
8602 /* continuation for OP_SGET_OBJECT */
8605 * Continuation if the field has not yet been resolved.
8606 * r1: BBBB field ref
8608 .LOP_SGET_OBJECT_resolve:
8609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8610 EXPORT_PC() @ resolve() could throw, so export now
8611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8613 cmp r0, #0 @ success?
8614 bne .LOP_SGET_OBJECT_finish @ yes, finish
8615 b common_exceptionThrown @ no, handle exception
8617 /* continuation for OP_SGET_BOOLEAN */
8620 * Continuation if the field has not yet been resolved.
8621 * r1: BBBB field ref
8623 .LOP_SGET_BOOLEAN_resolve:
8624 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8625 EXPORT_PC() @ resolve() could throw, so export now
8626 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8627 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8628 cmp r0, #0 @ success?
8629 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
8630 b common_exceptionThrown @ no, handle exception
8632 /* continuation for OP_SGET_BYTE */
8635 * Continuation if the field has not yet been resolved.
8636 * r1: BBBB field ref
8638 .LOP_SGET_BYTE_resolve:
8639 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8640 EXPORT_PC() @ resolve() could throw, so export now
8641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8642 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8643 cmp r0, #0 @ success?
8644 bne .LOP_SGET_BYTE_finish @ yes, finish
8645 b common_exceptionThrown @ no, handle exception
8647 /* continuation for OP_SGET_CHAR */
8650 * Continuation if the field has not yet been resolved.
8651 * r1: BBBB field ref
8653 .LOP_SGET_CHAR_resolve:
8654 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8655 EXPORT_PC() @ resolve() could throw, so export now
8656 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8657 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8658 cmp r0, #0 @ success?
8659 bne .LOP_SGET_CHAR_finish @ yes, finish
8660 b common_exceptionThrown @ no, handle exception
8662 /* continuation for OP_SGET_SHORT */
8665 * Continuation if the field has not yet been resolved.
8666 * r1: BBBB field ref
8668 .LOP_SGET_SHORT_resolve:
8669 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8670 EXPORT_PC() @ resolve() could throw, so export now
8671 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8672 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8673 cmp r0, #0 @ success?
8674 bne .LOP_SGET_SHORT_finish @ yes, finish
8675 b common_exceptionThrown @ no, handle exception
8677 /* continuation for OP_SPUT */
8680 * Continuation if the field has not yet been resolved.
8681 * r1: BBBB field ref
8684 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8685 EXPORT_PC() @ resolve() could throw, so export now
8686 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8687 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8688 cmp r0, #0 @ success?
8689 bne .LOP_SPUT_finish @ yes, finish
8690 b common_exceptionThrown @ no, handle exception
8692 /* continuation for OP_SPUT_WIDE */
8695 * Continuation if the field has not yet been resolved.
8696 * r1: BBBB field ref
8699 * Returns StaticField pointer in r2.
8701 .LOP_SPUT_WIDE_resolve:
8702 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8703 EXPORT_PC() @ resolve() could throw, so export now
8704 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8705 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8706 cmp r0, #0 @ success?
8707 mov r2, r0 @ copy to r2
8708 bne .LOP_SPUT_WIDE_finish @ yes, finish
8709 b common_exceptionThrown @ no, handle exception
8711 /* continuation for OP_SPUT_OBJECT */
8712 .LOP_SPUT_OBJECT_finish: @ field ptr in r0
8713 mov r2, rINST, lsr #8 @ r2<- AA
8714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8715 GET_VREG(r1, r2) @ r1<- fp[AA]
8716 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
8717 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz
8718 GET_INST_OPCODE(ip) @ extract opcode from rINST
8719 @ no-op @ releasing store
8720 str r1, [r0, #offStaticField_value] @ field<- vAA
8721 cmp r1, #0 @ stored a null object?
8722 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head
8723 GOTO_OPCODE(ip) @ jump to next instruction
8725 /* continuation for OP_SPUT_BOOLEAN */
8728 * Continuation if the field has not yet been resolved.
8729 * r1: BBBB field ref
8731 .LOP_SPUT_BOOLEAN_resolve:
8732 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8733 EXPORT_PC() @ resolve() could throw, so export now
8734 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8735 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8736 cmp r0, #0 @ success?
8737 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
8738 b common_exceptionThrown @ no, handle exception
8740 /* continuation for OP_SPUT_BYTE */
8743 * Continuation if the field has not yet been resolved.
8744 * r1: BBBB field ref
8746 .LOP_SPUT_BYTE_resolve:
8747 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8748 EXPORT_PC() @ resolve() could throw, so export now
8749 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8750 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8751 cmp r0, #0 @ success?
8752 bne .LOP_SPUT_BYTE_finish @ yes, finish
8753 b common_exceptionThrown @ no, handle exception
8755 /* continuation for OP_SPUT_CHAR */
8758 * Continuation if the field has not yet been resolved.
8759 * r1: BBBB field ref
8761 .LOP_SPUT_CHAR_resolve:
8762 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8763 EXPORT_PC() @ resolve() could throw, so export now
8764 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8765 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8766 cmp r0, #0 @ success?
8767 bne .LOP_SPUT_CHAR_finish @ yes, finish
8768 b common_exceptionThrown @ no, handle exception
8770 /* continuation for OP_SPUT_SHORT */
8773 * Continuation if the field has not yet been resolved.
8774 * r1: BBBB field ref
8776 .LOP_SPUT_SHORT_resolve:
8777 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8778 EXPORT_PC() @ resolve() could throw, so export now
8779 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8780 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8781 cmp r0, #0 @ success?
8782 bne .LOP_SPUT_SHORT_finish @ yes, finish
8783 b common_exceptionThrown @ no, handle exception
8785 /* continuation for OP_INVOKE_VIRTUAL */
8789 * r0 = resolved base method
8790 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8792 .LOP_INVOKE_VIRTUAL_continue:
8793 GET_VREG(r1, r10) @ r1<- "this" ptr
8794 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8795 cmp r1, #0 @ is "this" null?
8796 beq common_errNullObject @ null "this", throw exception
8797 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8798 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8799 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8800 bl common_invokeMethodNoRange @ continue on
8802 /* continuation for OP_INVOKE_SUPER */
8806 * r0 = resolved base method
8807 * r9 = method->clazz
8809 .LOP_INVOKE_SUPER_continue:
8810 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8811 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8812 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8813 EXPORT_PC() @ must export for invoke
8814 cmp r2, r3 @ compare (methodIndex, vtableCount)
8815 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
8816 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8817 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8818 bl common_invokeMethodNoRange @ continue on
8820 .LOP_INVOKE_SUPER_resolve:
8821 mov r0, r9 @ r0<- method->clazz
8822 mov r2, #METHOD_VIRTUAL @ resolver method type
8823 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8824 cmp r0, #0 @ got null?
8825 bne .LOP_INVOKE_SUPER_continue @ no, continue
8826 b common_exceptionThrown @ yes, handle exception
8829 * Throw a NoSuchMethodError with the method name as the message.
8830 * r0 = resolved base method
8832 .LOP_INVOKE_SUPER_nsm:
8833 ldr r1, [r0, #offMethod_name] @ r1<- method name
8834 b common_errNoSuchMethod
8836 /* continuation for OP_INVOKE_DIRECT */
8840 * r1 = reference (BBBB or CCCC)
8841 * r10 = "this" register
8843 .LOP_INVOKE_DIRECT_resolve:
8844 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8845 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8846 mov r2, #METHOD_DIRECT @ resolver method type
8847 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8848 cmp r0, #0 @ got null?
8849 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8850 bne .LOP_INVOKE_DIRECT_finish @ no, continue
8851 b common_exceptionThrown @ yes, handle exception
8853 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
8857 * r0 = resolved base method
8858 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8860 .LOP_INVOKE_VIRTUAL_RANGE_continue:
8861 GET_VREG(r1, r10) @ r1<- "this" ptr
8862 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8863 cmp r1, #0 @ is "this" null?
8864 beq common_errNullObject @ null "this", throw exception
8865 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8866 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8867 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8868 bl common_invokeMethodRange @ continue on
8870 /* continuation for OP_INVOKE_SUPER_RANGE */
8874 * r0 = resolved base method
8875 * r9 = method->clazz
8877 .LOP_INVOKE_SUPER_RANGE_continue:
8878 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8879 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8880 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8881 EXPORT_PC() @ must export for invoke
8882 cmp r2, r3 @ compare (methodIndex, vtableCount)
8883 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
8884 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8885 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8886 bl common_invokeMethodRange @ continue on
8888 .LOP_INVOKE_SUPER_RANGE_resolve:
8889 mov r0, r9 @ r0<- method->clazz
8890 mov r2, #METHOD_VIRTUAL @ resolver method type
8891 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8892 cmp r0, #0 @ got null?
8893 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
8894 b common_exceptionThrown @ yes, handle exception
8897 * Throw a NoSuchMethodError with the method name as the message.
8898 * r0 = resolved base method
8900 .LOP_INVOKE_SUPER_RANGE_nsm:
8901 ldr r1, [r0, #offMethod_name] @ r1<- method name
8902 b common_errNoSuchMethod
8904 /* continuation for OP_INVOKE_DIRECT_RANGE */
8908 * r1 = reference (BBBB or CCCC)
8909 * r10 = "this" register
8911 .LOP_INVOKE_DIRECT_RANGE_resolve:
8912 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8913 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8914 mov r2, #METHOD_DIRECT @ resolver method type
8915 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8916 cmp r0, #0 @ got null?
8917 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8918 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
8919 b common_exceptionThrown @ yes, handle exception
8921 /* continuation for OP_FLOAT_TO_LONG */
8923 * Convert the float in r0 to a long in r0/r1.
8925 * We have to clip values to long min/max per the specification. The
8926 * expected common case is a "reasonable" value that converts directly
8927 * to modest integer. The EABI convert function isn't doing this for us.
8931 mov r1, #0x5f000000 @ (float)maxlong
8933 bl __aeabi_fcmpge @ is arg >= maxlong?
8934 cmp r0, #0 @ nonzero == yes
8935 mvnne r0, #0 @ return maxlong (7fffffff)
8936 mvnne r1, #0x80000000
8937 ldmnefd sp!, {r4, pc}
8939 mov r0, r4 @ recover arg
8940 mov r1, #0xdf000000 @ (float)minlong
8941 bl __aeabi_fcmple @ is arg <= minlong?
8942 cmp r0, #0 @ nonzero == yes
8943 movne r0, #0 @ return minlong (80000000)
8944 movne r1, #0x80000000
8945 ldmnefd sp!, {r4, pc}
8947 mov r0, r4 @ recover arg
8949 bl __aeabi_fcmpeq @ is arg == self?
8950 cmp r0, #0 @ zero == no
8951 moveq r1, #0 @ return zero for NaN
8952 ldmeqfd sp!, {r4, pc}
8954 mov r0, r4 @ recover arg
8955 bl __aeabi_f2lz @ convert float to long
8958 /* continuation for OP_DOUBLE_TO_LONG */
8960 * Convert the double in r0/r1 to a long in r0/r1.
8962 * We have to clip values to long min/max per the specification. The
8963 * expected common case is a "reasonable" value that converts directly
8964 * to modest integer. The EABI convert function isn't doing this for us.
8967 stmfd sp!, {r4, r5, lr} @ save regs
8968 mov r3, #0x43000000 @ maxlong, as a double (high word)
8969 add r3, #0x00e00000 @ 0x43e00000
8970 mov r2, #0 @ maxlong, as a double (low word)
8971 sub sp, sp, #4 @ align for EABI
8972 mov r4, r0 @ save a copy of r0
8974 bl __aeabi_dcmpge @ is arg >= maxlong?
8975 cmp r0, #0 @ nonzero == yes
8976 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
8977 mvnne r1, #0x80000000
8980 mov r0, r4 @ recover arg
8982 mov r3, #0xc3000000 @ minlong, as a double (high word)
8983 add r3, #0x00e00000 @ 0xc3e00000
8984 mov r2, #0 @ minlong, as a double (low word)
8985 bl __aeabi_dcmple @ is arg <= minlong?
8986 cmp r0, #0 @ nonzero == yes
8987 movne r0, #0 @ return minlong (8000000000000000)
8988 movne r1, #0x80000000
8991 mov r0, r4 @ recover arg
8993 mov r2, r4 @ compare against self
8995 bl __aeabi_dcmpeq @ is arg == self?
8996 cmp r0, #0 @ zero == no
8997 moveq r1, #0 @ return zero for NaN
9000 mov r0, r4 @ recover arg
9002 bl __aeabi_d2lz @ convert double to long
9006 ldmfd sp!, {r4, r5, pc}
9008 /* continuation for OP_MUL_LONG */
9010 .LOP_MUL_LONG_finish:
9011 GET_INST_OPCODE(ip) @ extract opcode from rINST
9012 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
9013 GOTO_OPCODE(ip) @ jump to next instruction
9015 /* continuation for OP_SHL_LONG */
9017 .LOP_SHL_LONG_finish:
9018 mov r0, r0, asl r2 @ r0<- r0 << r2
9019 GET_INST_OPCODE(ip) @ extract opcode from rINST
9020 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9021 GOTO_OPCODE(ip) @ jump to next instruction
9023 /* continuation for OP_SHR_LONG */
9025 .LOP_SHR_LONG_finish:
9026 mov r1, r1, asr r2 @ r1<- r1 >> r2
9027 GET_INST_OPCODE(ip) @ extract opcode from rINST
9028 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9029 GOTO_OPCODE(ip) @ jump to next instruction
9031 /* continuation for OP_USHR_LONG */
9033 .LOP_USHR_LONG_finish:
9034 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
9035 GET_INST_OPCODE(ip) @ extract opcode from rINST
9036 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9037 GOTO_OPCODE(ip) @ jump to next instruction
9039 /* continuation for OP_SHL_LONG_2ADDR */
9041 .LOP_SHL_LONG_2ADDR_finish:
9042 GET_INST_OPCODE(ip) @ extract opcode from rINST
9043 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9044 GOTO_OPCODE(ip) @ jump to next instruction
9046 /* continuation for OP_SHR_LONG_2ADDR */
9048 .LOP_SHR_LONG_2ADDR_finish:
9049 GET_INST_OPCODE(ip) @ extract opcode from rINST
9050 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9051 GOTO_OPCODE(ip) @ jump to next instruction
9053 /* continuation for OP_USHR_LONG_2ADDR */
9055 .LOP_USHR_LONG_2ADDR_finish:
9056 GET_INST_OPCODE(ip) @ extract opcode from rINST
9057 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9058 GOTO_OPCODE(ip) @ jump to next instruction
9060 /* continuation for OP_IGET_VOLATILE */
9064 * r0 holds resolved field
9067 .LOP_IGET_VOLATILE_finish:
9069 cmp r9, #0 @ check object for null
9070 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9071 beq common_errNullObject @ object was null
9072 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
9073 SMP_DMB @ acquiring load
9074 mov r2, rINST, lsr #8 @ r2<- A+
9075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9076 and r2, r2, #15 @ r2<- A
9077 GET_INST_OPCODE(ip) @ extract opcode from rINST
9078 SET_VREG(r0, r2) @ fp[A]<- r0
9079 GOTO_OPCODE(ip) @ jump to next instruction
9081 /* continuation for OP_IPUT_VOLATILE */
9085 * r0 holds resolved field
9088 .LOP_IPUT_VOLATILE_finish:
9090 mov r1, rINST, lsr #8 @ r1<- A+
9091 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9092 and r1, r1, #15 @ r1<- A
9093 cmp r9, #0 @ check object for null
9094 GET_VREG(r0, r1) @ r0<- fp[A]
9095 beq common_errNullObject @ object was null
9096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9097 GET_INST_OPCODE(ip) @ extract opcode from rINST
9098 SMP_DMB @ releasing store
9099 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
9100 GOTO_OPCODE(ip) @ jump to next instruction
9102 /* continuation for OP_SGET_VOLATILE */
9105 * Continuation if the field has not yet been resolved.
9106 * r1: BBBB field ref
9108 .LOP_SGET_VOLATILE_resolve:
9109 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9110 EXPORT_PC() @ resolve() could throw, so export now
9111 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9112 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9113 cmp r0, #0 @ success?
9114 bne .LOP_SGET_VOLATILE_finish @ yes, finish
9115 b common_exceptionThrown @ no, handle exception
9117 /* continuation for OP_SPUT_VOLATILE */
9120 * Continuation if the field has not yet been resolved.
9121 * r1: BBBB field ref
9123 .LOP_SPUT_VOLATILE_resolve:
9124 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9125 EXPORT_PC() @ resolve() could throw, so export now
9126 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9127 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9128 cmp r0, #0 @ success?
9129 bne .LOP_SPUT_VOLATILE_finish @ yes, finish
9130 b common_exceptionThrown @ no, handle exception
9132 /* continuation for OP_IGET_OBJECT_VOLATILE */
9136 * r0 holds resolved field
9139 .LOP_IGET_OBJECT_VOLATILE_finish:
9141 cmp r9, #0 @ check object for null
9142 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9143 beq common_errNullObject @ object was null
9144 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
9145 SMP_DMB @ acquiring load
9146 mov r2, rINST, lsr #8 @ r2<- A+
9147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9148 and r2, r2, #15 @ r2<- A
9149 GET_INST_OPCODE(ip) @ extract opcode from rINST
9150 SET_VREG(r0, r2) @ fp[A]<- r0
9151 GOTO_OPCODE(ip) @ jump to next instruction
9153 /* continuation for OP_IGET_WIDE_VOLATILE */
9157 * r0 holds resolved field
9160 .LOP_IGET_WIDE_VOLATILE_finish:
9161 cmp r9, #0 @ check object for null
9162 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9163 beq common_errNullObject @ object was null
9165 add r0, r9, r3 @ r0<- address of field
9166 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field
9168 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
9170 mov r2, rINST, lsr #8 @ r2<- A+
9171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9172 and r2, r2, #15 @ r2<- A
9173 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
9174 GET_INST_OPCODE(ip) @ extract opcode from rINST
9175 stmia r3, {r0-r1} @ fp[A]<- r0/r1
9176 GOTO_OPCODE(ip) @ jump to next instruction
9178 /* continuation for OP_IPUT_WIDE_VOLATILE */
9182 * r0 holds resolved field
9185 .LOP_IPUT_WIDE_VOLATILE_finish:
9186 mov r2, rINST, lsr #8 @ r2<- A+
9187 cmp r9, #0 @ check object for null
9188 and r2, r2, #15 @ r2<- A
9189 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9190 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
9191 beq common_errNullObject @ object was null
9192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9193 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
9194 GET_INST_OPCODE(r10) @ extract opcode from rINST
9196 add r2, r9, r3 @ r2<- target address
9197 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2
9199 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
9201 GOTO_OPCODE(r10) @ jump to next instruction
9203 /* continuation for OP_SGET_WIDE_VOLATILE */
9206 * Continuation if the field has not yet been resolved.
9207 * r1: BBBB field ref
9209 * Returns StaticField pointer in r0.
9211 .LOP_SGET_WIDE_VOLATILE_resolve:
9212 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9213 EXPORT_PC() @ resolve() could throw, so export now
9214 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9215 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9216 cmp r0, #0 @ success?
9217 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish
9218 b common_exceptionThrown @ no, handle exception
9220 /* continuation for OP_SPUT_WIDE_VOLATILE */
9223 * Continuation if the field has not yet been resolved.
9224 * r1: BBBB field ref
9227 * Returns StaticField pointer in r2.
9229 .LOP_SPUT_WIDE_VOLATILE_resolve:
9230 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9231 EXPORT_PC() @ resolve() could throw, so export now
9232 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9233 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9234 cmp r0, #0 @ success?
9235 mov r2, r0 @ copy to r2
9236 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
9237 b common_exceptionThrown @ no, handle exception
9239 /* continuation for OP_EXECUTE_INLINE */
9242 * Extract args, call function.
9243 * r0 = #of args (0-4)
9245 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9248 * - Use a jump table from the main piece to jump directly into the
9249 * AND/LDR pairs. Costs a data load, saves a branch.
9250 * - Have five separate pieces that do the loading, so we can work the
9251 * interleave a little better. Increases code size.
9253 .LOP_EXECUTE_INLINE_continue:
9254 rsb r0, r0, #4 @ r0<- 4-r0
9255 FETCH(r9, 2) @ r9<- FEDC
9256 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9257 bl common_abort @ (skipped due to ARM prefetch)
9258 4: and ip, r9, #0xf000 @ isolate F
9259 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
9260 3: and ip, r9, #0x0f00 @ isolate E
9261 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
9262 2: and ip, r9, #0x00f0 @ isolate D
9263 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
9264 1: and ip, r9, #0x000f @ isolate C
9265 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
9267 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
9268 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry
9271 .LOP_EXECUTE_INLINE_table:
9272 .word gDvmInlineOpsTable
9274 /* continuation for OP_EXECUTE_INLINE_RANGE */
9277 * Extract args, call function.
9278 * r0 = #of args (0-4)
9280 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9282 .LOP_EXECUTE_INLINE_RANGE_continue:
9283 rsb r0, r0, #4 @ r0<- 4-r0
9284 FETCH(r9, 2) @ r9<- CCCC
9285 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9286 bl common_abort @ (skipped due to ARM prefetch)
9287 4: add ip, r9, #3 @ base+3
9288 GET_VREG(r3, ip) @ r3<- vBase[3]
9289 3: add ip, r9, #2 @ base+2
9290 GET_VREG(r2, ip) @ r2<- vBase[2]
9291 2: add ip, r9, #1 @ base+1
9292 GET_VREG(r1, ip) @ r1<- vBase[1]
9293 1: add ip, r9, #0 @ (nop)
9294 GET_VREG(r0, ip) @ r0<- vBase[0]
9296 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation
9297 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry
9300 .LOP_EXECUTE_INLINE_RANGE_table:
9301 .word gDvmInlineOpsTable
9303 /* continuation for OP_IPUT_OBJECT_VOLATILE */
9307 * r0 holds resolved field
9310 .LOP_IPUT_OBJECT_VOLATILE_finish:
9312 mov r1, rINST, lsr #8 @ r1<- A+
9313 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9314 and r1, r1, #15 @ r1<- A
9315 cmp r9, #0 @ check object for null
9316 GET_VREG(r0, r1) @ r0<- fp[A]
9317 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
9318 beq common_errNullObject @ object was null
9319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9320 GET_INST_OPCODE(ip) @ extract opcode from rINST
9321 SMP_DMB @ releasing store
9322 str r0, [r9, r3] @ obj.field (32 bits)<- r0
9323 cmp r0, #0 @ stored a null reference?
9324 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not
9325 GOTO_OPCODE(ip) @ jump to next instruction
9327 /* continuation for OP_SGET_OBJECT_VOLATILE */
9330 * Continuation if the field has not yet been resolved.
9331 * r1: BBBB field ref
9333 .LOP_SGET_OBJECT_VOLATILE_resolve:
9334 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9335 EXPORT_PC() @ resolve() could throw, so export now
9336 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9337 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9338 cmp r0, #0 @ success?
9339 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish
9340 b common_exceptionThrown @ no, handle exception
9342 /* continuation for OP_SPUT_OBJECT_VOLATILE */
9343 .LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
9344 mov r2, rINST, lsr #8 @ r2<- AA
9345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9346 GET_VREG(r1, r2) @ r1<- fp[AA]
9347 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
9348 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz
9349 GET_INST_OPCODE(ip) @ extract opcode from rINST
9350 SMP_DMB @ releasing store
9351 str r1, [r0, #offStaticField_value] @ field<- vAA
9352 cmp r1, #0 @ stored a null object?
9353 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head
9354 GOTO_OPCODE(ip) @ jump to next instruction
9356 .size dvmAsmSisterStart, .-dvmAsmSisterStart
9357 .global dvmAsmSisterEnd
9360 /* File: armv5te/footer.S */
9363 * ===========================================================================
9364 * Common subroutines and data
9365 * ===========================================================================
9373 #if defined(WITH_JIT)
9374 #if defined(WITH_SELF_VERIFICATION)
9375 .global dvmJitToInterpPunt
9377 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9378 mov r2,#kSVSPunt @ r2<- interpreter entry point
9380 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9381 b jitSVShadowRunEnd @ doesn't return
9383 .global dvmJitToInterpSingleStep
9384 dvmJitToInterpSingleStep:
9385 str lr,[rGLUE,#offGlue_jitResumeNPC]
9386 str r1,[rGLUE,#offGlue_jitResumeDPC]
9387 mov r2,#kSVSSingleStep @ r2<- interpreter entry point
9388 b jitSVShadowRunEnd @ doesn't return
9390 .global dvmJitToInterpNoChainNoProfile
9391 dvmJitToInterpNoChainNoProfile:
9392 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9393 mov r0,rPC @ pass our target PC
9394 mov r2,#kSVSNoProfile @ r2<- interpreter entry point
9395 mov r3, #0 @ 0 means !inJitCodeCache
9396 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9397 b jitSVShadowRunEnd @ doesn't return
9399 .global dvmJitToInterpTraceSelectNoChain
9400 dvmJitToInterpTraceSelectNoChain:
9401 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9402 mov r0,rPC @ pass our target PC
9403 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
9404 mov r3, #0 @ 0 means !inJitCodeCache
9405 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9406 b jitSVShadowRunEnd @ doesn't return
9408 .global dvmJitToInterpTraceSelect
9409 dvmJitToInterpTraceSelect:
9410 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9411 ldr r0,[lr, #-1] @ pass our target PC
9412 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
9413 mov r3, #0 @ 0 means !inJitCodeCache
9414 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9415 b jitSVShadowRunEnd @ doesn't return
9417 .global dvmJitToInterpBackwardBranch
9418 dvmJitToInterpBackwardBranch:
9419 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9420 ldr r0,[lr, #-1] @ pass our target PC
9421 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
9422 mov r3, #0 @ 0 means !inJitCodeCache
9423 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9424 b jitSVShadowRunEnd @ doesn't return
9426 .global dvmJitToInterpNormal
9427 dvmJitToInterpNormal:
9428 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9429 ldr r0,[lr, #-1] @ pass our target PC
9430 mov r2,#kSVSNormal @ r2<- interpreter entry point
9431 mov r3, #0 @ 0 means !inJitCodeCache
9432 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9433 b jitSVShadowRunEnd @ doesn't return
9435 .global dvmJitToInterpNoChain
9436 dvmJitToInterpNoChain:
9437 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9438 mov r0,rPC @ pass our target PC
9439 mov r2,#kSVSNoChain @ r2<- interpreter entry point
9440 mov r3, #0 @ 0 means !inJitCodeCache
9441 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9442 b jitSVShadowRunEnd @ doesn't return
9445 * Return from the translation cache to the interpreter when the compiler is
9446 * having issues translating/executing a Dalvik instruction. We have to skip
9447 * the code cache lookup otherwise it is possible to indefinitely bouce
9448 * between the interpreter and the code cache if the instruction that fails
9449 * to be compiled happens to be at a trace start.
9451 .global dvmJitToInterpPunt
9453 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9455 #if defined(WITH_JIT_TUNING)
9461 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9462 adrl rIBASE, dvmAsmInstructionStart
9468 * Return to the interpreter to handle a single instruction.
9471 * r1 <= PC of resume instruction
9472 * lr <= resume point in translation
9474 .global dvmJitToInterpSingleStep
9475 dvmJitToInterpSingleStep:
9476 str lr,[rGLUE,#offGlue_jitResumeNPC]
9477 str r1,[rGLUE,#offGlue_jitResumeDPC]
9478 mov r1,#kInterpEntryInstr
9479 @ enum is 4 byte in aapcs-EABI
9480 str r1, [rGLUE, #offGlue_entryPoint]
9484 adrl rIBASE, dvmAsmInstructionStart
9485 mov r2,#kJitSingleStep @ Ask for single step and then revert
9486 str r2,[rGLUE,#offGlue_jitState]
9487 mov r1,#1 @ set changeInterp to bail to debug interp
9491 * Return from the translation cache and immediately request
9492 * a translation for the exit target. Commonly used for callees.
9494 .global dvmJitToInterpTraceSelectNoChain
9495 dvmJitToInterpTraceSelectNoChain:
9496 #if defined(WITH_JIT_TUNING)
9499 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9501 bl dvmJitGetCodeAddr @ Is there a translation?
9502 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9503 mov r1, rPC @ arg1 of translation may need this
9504 mov lr, #0 @ in case target is HANDLER_INTERPRET
9505 cmp r0,#0 @ !0 means translation exists
9506 bxne r0 @ continue native execution if so
9507 b 2f @ branch over to use the interpreter
9510 * Return from the translation cache and immediately request
9511 * a translation for the exit target. Commonly used following
9514 .global dvmJitToInterpTraceSelect
9515 dvmJitToInterpTraceSelect:
9516 ldr rPC,[lr, #-1] @ get our target PC
9517 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9518 add rINST,lr,#-5 @ save start of chain branch
9519 add rINST, #-4 @ .. which is 9 bytes back
9521 bl dvmJitGetCodeAddr @ Is there a translation?
9522 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9526 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9527 mov r1, rPC @ arg1 of translation may need this
9528 mov lr, #0 @ in case target is HANDLER_INTERPRET
9529 cmp r0,#0 @ successful chain?
9530 bxne r0 @ continue native execution
9531 b toInterpreter @ didn't chain - resume with interpreter
9533 /* No translation, so request one if profiling isn't disabled*/
9535 adrl rIBASE, dvmAsmInstructionStart
9536 GET_JIT_PROF_TABLE(r0)
9539 movne r2,#kJitTSelectRequestHot @ ask for trace selection
9540 bne common_selectTrace
9545 * Return from the translation cache to the interpreter.
9546 * The return was done with a BLX from thumb mode, and
9547 * the following 32-bit word contains the target rPC value.
9548 * Note that lr (r14) will have its low-order bit set to denote
9549 * its thumb-mode origin.
9551 * We'll need to stash our lr origin away, recover the new
9552 * target and then check to see if there is a translation available
9553 * for our new target. If so, we do a translation chain and
9554 * go back to native execution. Otherwise, it's back to the
9555 * interpreter (after treating this entry as a potential
9558 .global dvmJitToInterpNormal
9559 dvmJitToInterpNormal:
9560 ldr rPC,[lr, #-1] @ get our target PC
9561 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9562 add rINST,lr,#-5 @ save start of chain branch
9563 add rINST,#-4 @ .. which is 9 bytes back
9564 #if defined(WITH_JIT_TUNING)
9568 bl dvmJitGetCodeAddr @ Is there a translation?
9569 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9571 beq toInterpreter @ go if not, otherwise do chain
9573 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9574 mov r1, rPC @ arg1 of translation may need this
9575 mov lr, #0 @ in case target is HANDLER_INTERPRET
9576 cmp r0,#0 @ successful chain?
9577 bxne r0 @ continue native execution
9578 b toInterpreter @ didn't chain - resume with interpreter
9581 * Return from the translation cache to the interpreter to do method invocation.
9582 * Check if translation exists for the callee, but don't chain to it.
9584 .global dvmJitToInterpNoChainNoProfile
9585 dvmJitToInterpNoChainNoProfile:
9586 #if defined(WITH_JIT_TUNING)
9589 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9591 bl dvmJitGetCodeAddr @ Is there a translation?
9592 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9593 mov r1, rPC @ arg1 of translation may need this
9594 mov lr, #0 @ in case target is HANDLER_INTERPRET
9596 bxne r0 @ continue native execution if so
9598 adrl rIBASE, dvmAsmInstructionStart
9600 GET_INST_OPCODE(ip) @ extract opcode from rINST
9601 GOTO_OPCODE(ip) @ jump to next instruction
9604 * Return from the translation cache to the interpreter to do method invocation.
9605 * Check if translation exists for the callee, but don't chain to it.
9607 .global dvmJitToInterpNoChain
9608 dvmJitToInterpNoChain:
9609 #if defined(WITH_JIT_TUNING)
9612 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9614 bl dvmJitGetCodeAddr @ Is there a translation?
9615 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9616 mov r1, rPC @ arg1 of translation may need this
9617 mov lr, #0 @ in case target is HANDLER_INTERPRET
9619 bxne r0 @ continue native execution if so
9623 * No translation, restore interpreter regs and start interpreting.
9624 * rGLUE & rFP were preserved in the translated code, and rPC has
9625 * already been restored by the time we get here. We'll need to set
9626 * up rIBASE & rINST, and load the address of the JitTable into r0.
9630 adrl rIBASE, dvmAsmInstructionStart
9632 GET_JIT_PROF_TABLE(r0)
9633 @ NOTE: intended fallthrough
9636 * Common code to update potential trace start counter, and initiate
9637 * a trace-build if appropriate. On entry, rPC should point to the
9638 * next instruction to execute, and rINST should be already loaded with
9639 * the next opcode word, and r0 holds a pointer to the jit profile
9640 * table (pJitProfTable).
9642 common_testUpdateProfile:
9645 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */
9647 common_updateProfile:
9648 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9649 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits
9650 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9652 subs r1,r1,#1 @ decrement counter
9653 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9654 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
9657 * Here, we switch to the debug interpreter to request
9658 * trace selection. First, though, check to see if there
9659 * is already a native translation in place (and, if so,
9662 GET_JIT_THRESHOLD(r1)
9663 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9664 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9667 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
9668 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9669 mov r1, rPC @ arg1 of translation may need this
9670 mov lr, #0 @ in case target is HANDLER_INTERPRET
9672 #if !defined(WITH_SELF_VERIFICATION)
9673 bxne r0 @ jump to the translation
9674 mov r2,#kJitTSelectRequest @ ask for trace selection
9675 @ fall-through to common_selectTrace
9677 moveq r2,#kJitTSelectRequest @ ask for trace selection
9678 beq common_selectTrace
9680 * At this point, we have a target translation. However, if
9681 * that translation is actually the interpret-only pseudo-translation
9682 * we want to treat it the same as no translation.
9684 mov r10, r0 @ save target
9685 bl dvmCompilerGetInterpretTemplate
9686 cmp r0, r10 @ special case?
9687 bne jitSVShadowRunStart @ set up self verification shadow space
9688 @ Need to clear the inJitCodeCache flag
9689 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self
9690 mov r3, #0 @ 0 means not in the JIT code cache
9691 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9699 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9702 str r2,[rGLUE,#offGlue_jitState]
9703 mov r2,#kInterpEntryInstr @ normal entry reason
9704 str r2,[rGLUE,#offGlue_entryPoint]
9705 mov r1,#1 @ set changeInterp
9708 #if defined(WITH_SELF_VERIFICATION)
9710 * Save PC and registers to shadow memory for self verification mode
9711 * before jumping to native translation.
9713 * rPC, rFP, rGLUE: the values that they should contain
9714 * r10: the address of the target translation.
9716 jitSVShadowRunStart:
9717 mov r0,rPC @ r0<- program counter
9718 mov r1,rFP @ r1<- frame pointer
9719 mov r2,rGLUE @ r2<- InterpState pointer
9720 mov r3,r10 @ r3<- target translation
9721 bl dvmSelfVerificationSaveState @ save registers to shadow space
9722 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9723 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9724 bx r10 @ jump to the translation
9727 * Restore PC, registers, and interpState to original values
9728 * before jumping back to the interpreter.
9731 mov r1,rFP @ pass ending fp
9732 bl dvmSelfVerificationRestoreState @ restore pc and fp values
9733 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
9734 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
9735 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9736 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
9737 cmp r1,#0 @ check for punt condition
9739 mov r2,#kJitSelfVerification @ ask for self verification
9740 str r2,[rGLUE,#offGlue_jitState]
9741 mov r2,#kInterpEntryInstr @ normal entry reason
9742 str r2,[rGLUE,#offGlue_entryPoint]
9743 mov r1,#1 @ set changeInterp
9746 1: @ exit to interpreter without check
9748 adrl rIBASE, dvmAsmInstructionStart
9757 * Common code when a backward branch is taken.
9759 * TODO: we could avoid a branch by just setting r0 and falling through
9760 * into the common_periodicChecks code, and having a test on r0 at the
9761 * end determine if we should return to the caller or update & branch to
9765 * r9 is PC adjustment *in bytes*
9767 common_backwardBranch:
9768 mov r0, #kInterpEntryInstr
9769 bl common_periodicChecks
9770 #if defined(WITH_JIT)
9771 GET_JIT_PROF_TABLE(r0)
9772 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9774 bne common_updateProfile
9778 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9779 GET_INST_OPCODE(ip) @ extract opcode from rINST
9780 GOTO_OPCODE(ip) @ jump to next instruction
9785 * Need to see if the thread needs to be suspended or debugger/profiler
9786 * activity has begun. If so, we suspend the thread or side-exit to
9787 * the debug interpreter as appropriate.
9789 * The common case is no activity on any of these, so we want to figure
9790 * that out quickly. If something is up, we can then sort out what.
9792 * We want to be fast if the VM was built without debugger or profiler
9793 * support, but we also need to recognize that the system is usually
9794 * shipped with both of these enabled.
9796 * TODO: reduce this so we're just checking a single location.
9799 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9800 * r9 is trampoline PC adjustment *in bytes*
9802 common_periodicChecks:
9803 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9805 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9806 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9808 ldr ip, [r3] @ ip<- suspendCount (int)
9810 cmp r1, #0 @ debugger enabled?
9811 #if defined(WORKAROUND_CORTEX_A9_745320)
9812 /* Don't use conditional loads if the HW defect exists */
9814 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean)
9817 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean)
9819 ldr r2, [r2] @ r2<- activeProfilers (int)
9820 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive
9822 * Don't switch the interpreter in the libdvm_traceview build even if the
9823 * profiler is active.
9824 * The code here is opted for less intrusion instead of performance.
9825 * That is, *pActiveProfilers is still loaded into r2 even though it is not
9826 * used when WITH_INLINE_PROFILING is defined.
9828 #if !defined(WITH_INLINE_PROFILING)
9829 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z
9833 bxeq lr @ all zero, return
9836 * One or more interesting events have happened. Figure out what.
9838 * If debugging or profiling are compiled in, we need to disambiguate.
9840 * r0 still holds the reentry type.
9842 ldr ip, [r3] @ ip<- suspendCount (int)
9843 cmp ip, #0 @ want suspend?
9844 beq 1f @ no, must be debugger/profiler
9846 stmfd sp!, {r0, lr} @ preserve r0 and lr
9847 #if defined(WITH_JIT)
9849 * Refresh the Jit's cached copy of profile table pointer. This pointer
9850 * doubles as the Jit's on/off switch.
9852 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9853 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9854 ldr r3, [r3] @ r3 <- pJitProfTable
9855 EXPORT_PC() @ need for precise GC
9856 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9858 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9859 EXPORT_PC() @ need for precise GC
9861 bl dvmCheckSuspendPending @ do full check, suspend if necessary
9862 ldmfd sp!, {r0, lr} @ restore r0 and lr
9865 * Reload the debugger/profiler enable flags. We're checking to see
9866 * if either of these got set while we were suspended.
9868 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9869 * is enabled or not as the profiling will be done inline.
9871 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9872 cmp r1, #0 @ debugger enabled?
9873 #if defined(WORKAROUND_CORTEX_A9_745320)
9874 /* Don't use conditional loads if the HW defect exists */
9876 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean)
9879 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean)
9882 #if !defined(WITH_INLINE_PROFILING)
9883 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9884 ldr r2, [r2] @ r2<- activeProfilers (int)
9887 cmp r1, #0 @ only consult the debuggerActive flag
9892 1: @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9893 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof
9894 add rPC, rPC, r9 @ update rPC
9895 mov r1, #1 @ "want switch" = true
9896 b common_gotoBail @ side exit
9899 bx lr @ nothing to do, return
9903 * The equivalent of "goto bail", this calls through the "bail handler".
9905 * State registers will be saved to the "glue" area before bailing.
9908 * r1 is "bool changeInterp", indicating if we want to switch to the
9909 * other interpreter or just bail all the way out
9912 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9913 mov r0, rGLUE @ r0<- glue ptr
9914 b dvmMterpStdBail @ call(glue, changeInterp)
9916 @add r1, r1, #1 @ using (boolean+1)
9917 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9918 @bl _longjmp @ does not return
9923 * Common code for method invocation with range.
9926 * r0 is "Method* methodToCall", the method we're trying to call
9928 common_invokeMethodRange:
9930 @ prepare to copy args to "outs" area of current frame
9931 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9932 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9933 beq .LinvokeArgsDone @ if no args, skip the rest
9934 FETCH(r1, 2) @ r1<- CCCC
9936 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9937 @ (very few methods have > 10 args; could unroll for common cases)
9938 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9939 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9940 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9941 1: ldr r1, [r3], #4 @ val = *fp++
9942 subs r2, r2, #1 @ count--
9943 str r1, [r10], #4 @ *outs++ = val
9944 bne 1b @ ...while count != 0
9945 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9949 * Common code for method invocation without range.
9952 * r0 is "Method* methodToCall", the method we're trying to call
9954 common_invokeMethodNoRange:
9956 @ prepare to copy args to "outs" area of current frame
9957 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9958 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9959 FETCH(r1, 2) @ r1<- GFED (load here to hide latency)
9960 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9961 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9962 beq .LinvokeArgsDone
9964 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9966 rsb r2, r2, #5 @ r2<- 5-r2
9967 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
9968 bl common_abort @ (skipped due to ARM prefetch)
9969 5: and ip, rINST, #0x0f00 @ isolate A
9970 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2)
9972 str r2, [r10, #-4]! @ *--outs = vA
9973 4: and ip, r1, #0xf000 @ isolate G
9974 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2)
9976 str r2, [r10, #-4]! @ *--outs = vG
9977 3: and ip, r1, #0x0f00 @ isolate F
9978 ldr r2, [rFP, ip, lsr #6] @ r2<- vF
9980 str r2, [r10, #-4]! @ *--outs = vF
9981 2: and ip, r1, #0x00f0 @ isolate E
9982 ldr r2, [rFP, ip, lsr #2] @ r2<- vE
9984 str r2, [r10, #-4]! @ *--outs = vE
9985 1: and ip, r1, #0x000f @ isolate D
9986 ldr r2, [rFP, ip, lsl #2] @ r2<- vD
9988 str r2, [r10, #-4]! @ *--outs = vD
9989 0: @ fall through to .LinvokeArgsDone
9991 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9992 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns
9993 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz
9994 @ find space for the new stack frame, check for overflow
9995 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
9996 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize)
9997 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
9998 @ bl common_dumpRegs
9999 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
10000 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
10001 cmp r3, r9 @ bottom < interpStackEnd?
10002 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10003 blo .LstackOverflow @ yes, this frame will overflow stack
10005 @ set up newSaveArea
10007 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
10008 str ip, [r10, #offStackSaveArea_prevSave]
10010 str rFP, [r10, #offStackSaveArea_prevFrame]
10011 str rPC, [r10, #offStackSaveArea_savedPc]
10012 #if defined(WITH_JIT)
10014 str r9, [r10, #offStackSaveArea_returnAddr]
10016 #if defined(WITH_INLINE_PROFILING)
10017 stmfd sp!, {r0-r3} @ preserve r0-r3
10019 @ r0=methodToCall, r1=rGlue
10020 bl dvmFastMethodTraceEnter
10021 ldmfd sp!, {r0-r3} @ restore r0-r3
10023 str r0, [r10, #offStackSaveArea_method]
10024 tst r3, #ACC_NATIVE
10029 bl common_printNewline
10038 bl common_printNewline
10042 ldrh r9, [r2] @ r9 <- load INST from new PC
10043 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10044 mov rPC, r2 @ publish new rPC
10045 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
10047 @ Update "glue" values for the new method
10048 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10049 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
10050 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10051 #if defined(WITH_JIT)
10052 GET_JIT_PROF_TABLE(r0)
10053 mov rFP, r1 @ fp = newFp
10054 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
10055 mov rINST, r9 @ publish new rINST
10056 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
10058 bne common_updateProfile
10059 GOTO_OPCODE(ip) @ jump to next instruction
10061 mov rFP, r1 @ fp = newFp
10062 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
10063 mov rINST, r9 @ publish new rINST
10064 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
10065 GOTO_OPCODE(ip) @ jump to next instruction
10069 @ Prep for the native call
10070 @ r0=methodToCall, r1=newFp, r10=newSaveArea
10071 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
10072 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10073 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
10074 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10075 mov r9, r3 @ r9<- glue->self (preserve)
10077 mov r2, r0 @ r2<- methodToCall
10078 mov r0, r1 @ r0<- newFp (points to args)
10079 add r1, rGLUE, #offGlue_retval @ r1<- &retval
10081 #ifdef ASSIST_DEBUGGER
10082 /* insert fake function header to help gdb find the stack frame */
10084 .type dalvik_mterp, %function
10092 #if defined(WITH_INLINE_PROFILING)
10093 @ r2=JNIMethod, r6=rGLUE
10097 mov lr, pc @ set return addr
10098 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10100 #if defined(WITH_INLINE_PROFILING)
10101 @ r0=JNIMethod, r1=rGLUE
10103 bl dvmFastNativeMethodTraceExit
10106 #if defined(WITH_JIT)
10107 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10110 @ native return; r9=self, r10=newSaveArea
10111 @ equivalent to dvmPopJniLocals
10112 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10113 ldr r1, [r9, #offThread_exception] @ check for exception
10114 #if defined(WITH_JIT)
10115 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable
10117 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
10119 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10120 #if defined(WITH_JIT)
10121 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10123 bne common_exceptionThrown @ no, handle exception
10125 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
10126 GET_INST_OPCODE(ip) @ extract opcode from rINST
10127 GOTO_OPCODE(ip) @ jump to next instruction
10129 .LstackOverflow: @ r0=methodToCall
10130 mov r1, r0 @ r1<- methodToCall
10131 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
10132 bl dvmHandleStackOverflow
10133 b common_exceptionThrown
10134 #ifdef ASSIST_DEBUGGER
10140 * Common code for method invocation, calling through "glue code".
10142 * TODO: now that we have range and non-range invoke handlers, this
10143 * needs to be split into two. Maybe just create entry points
10144 * that set r9 and jump here?
10147 * r0 is "Method* methodToCall", the method we're trying to call
10148 * r9 is "bool methodCallRange", indicating if this is a /range variant
10152 sub sp, sp, #8 @ space for args + pad
10153 FETCH(ip, 2) @ ip<- FEDC or CCCC
10154 mov r2, r0 @ A2<- methodToCall
10155 mov r0, rGLUE @ A0<- glue
10156 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
10157 mov r1, r9 @ A1<- methodCallRange
10158 mov r3, rINST, lsr #8 @ A3<- AA
10159 str ip, [sp, #0] @ A4<- ip
10160 bl dvmMterp_invokeMethod @ call the C invokeMethod
10161 add sp, sp, #8 @ remove arg area
10162 b common_resumeAfterGlueCall @ continue to next instruction
10168 * Common code for handling a return instruction.
10170 * This does not return.
10172 common_returnFromMethod:
10174 mov r0, #kInterpEntryReturn
10176 bl common_periodicChecks
10178 #if defined(WITH_INLINE_PROFILING)
10179 stmfd sp!, {r0-r3} @ preserve r0-r3
10182 bl dvmFastJavaMethodTraceExit
10183 ldmfd sp!, {r0-r3} @ restore r0-r3
10185 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
10186 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10187 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10188 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10189 @ r2<- method we're returning to
10190 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
10191 cmp r2, #0 @ is this a break frame?
10192 #if defined(WORKAROUND_CORTEX_A9_745320)
10193 /* Don't use conditional loads if the HW defect exists */
10195 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10198 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10200 mov r1, #0 @ "want switch" = false
10201 beq common_gotoBail @ break frame, bail out completely
10203 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10204 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10205 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
10206 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
10207 #if defined(WITH_JIT)
10208 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10209 mov rPC, r9 @ publish new rPC
10210 str r1, [rGLUE, #offGlue_methodClassDex]
10211 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land
10212 cmp r10, #0 @ caller is compiled code
10214 GET_INST_OPCODE(ip) @ extract opcode from rINST
10215 GOTO_OPCODE(ip) @ jump to next instruction
10217 GET_INST_OPCODE(ip) @ extract opcode from rINST
10218 mov rPC, r9 @ publish new rPC
10219 str r1, [rGLUE, #offGlue_methodClassDex]
10220 GOTO_OPCODE(ip) @ jump to next instruction
10224 * Return handling, calls through "glue code".
10228 SAVE_PC_FP_TO_GLUE() @ export state
10229 mov r0, rGLUE @ arg to function
10230 bl dvmMterp_returnFromMethod
10231 b common_resumeAfterGlueCall
10236 * Somebody has thrown an exception. Handle it.
10238 * If the exception processing code returns to us (instead of falling
10239 * out of the interpreter), continue with whatever the next instruction
10240 * now happens to be.
10242 * This does not return.
10244 .global dvmMterpCommonExceptionThrown
10245 dvmMterpCommonExceptionThrown:
10246 common_exceptionThrown:
10248 mov r0, #kInterpEntryThrow
10250 bl common_periodicChecks
10252 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10253 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
10254 mov r1, r10 @ r1<- self
10255 mov r0, r9 @ r0<- exception
10256 bl dvmAddTrackedAlloc @ don't let the exception be GCed
10257 mov r3, #0 @ r3<- NULL
10258 str r3, [r10, #offThread_exception] @ self->exception = NULL
10260 /* set up args and a local for "&fp" */
10261 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
10262 str rFP, [sp, #-4]! @ *--sp = fp
10263 mov ip, sp @ ip<- &fp
10264 mov r3, #0 @ r3<- false
10265 str ip, [sp, #-4]! @ *--sp = &fp
10266 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10267 mov r0, r10 @ r0<- self
10268 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
10269 mov r2, r9 @ r2<- exception
10270 sub r1, rPC, r1 @ r1<- pc - method->insns
10271 mov r1, r1, asr #1 @ r1<- offset in code units
10273 /* call, r0 gets catchRelPc (a code-unit offset) */
10274 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
10276 /* fix earlier stack overflow if necessary; may trash rFP */
10277 ldrb r1, [r10, #offThread_stackOverflowed]
10278 cmp r1, #0 @ did we overflow earlier?
10279 beq 1f @ no, skip ahead
10280 mov rFP, r0 @ save relPc result in rFP
10281 mov r0, r10 @ r0<- self
10282 mov r1, r9 @ r1<- exception
10283 bl dvmCleanupStackOverflow @ call(self)
10284 mov r0, rFP @ restore result
10287 /* update frame pointer and check result from dvmFindCatchBlock */
10288 ldr rFP, [sp, #4] @ retrieve the updated rFP
10289 cmp r0, #0 @ is catchRelPc < 0?
10290 add sp, sp, #8 @ restore stack
10291 bmi .LnotCaughtLocally
10293 /* adjust locals to match self->curFrame and updated PC */
10294 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
10295 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
10296 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
10297 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
10298 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
10299 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10300 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
10301 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10303 /* release the tracked alloc on the exception */
10304 mov r0, r9 @ r0<- exception
10305 mov r1, r10 @ r1<- self
10306 bl dvmReleaseTrackedAlloc @ release the exception
10308 /* restore the exception if the handler wants it */
10309 FETCH_INST() @ load rINST from rPC
10310 GET_INST_OPCODE(ip) @ extract opcode from rINST
10311 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
10312 streq r9, [r10, #offThread_exception] @ yes, restore the exception
10313 GOTO_OPCODE(ip) @ jump to next instruction
10315 .LnotCaughtLocally: @ r9=exception, r10=self
10316 /* fix stack overflow if necessary */
10317 ldrb r1, [r10, #offThread_stackOverflowed]
10318 cmp r1, #0 @ did we overflow earlier?
10319 movne r0, r10 @ if yes: r0<- self
10320 movne r1, r9 @ if yes: r1<- exception
10321 blne dvmCleanupStackOverflow @ if yes: call(self)
10323 @ may want to show "not caught locally" debug messages here
10324 #if DVM_SHOW_EXCEPTION >= 2
10325 /* call __android_log_print(prio, tag, format, ...) */
10326 /* "Exception %s from %s:%d not caught locally" */
10327 @ dvmLineNumFromPC(method, pc - method->insns)
10328 ldr r0, [rGLUE, #offGlue_method]
10329 ldr r1, [r0, #offMethod_insns]
10332 bl dvmLineNumFromPC
10334 @ dvmGetMethodSourceFile(method)
10335 ldr r0, [rGLUE, #offGlue_method]
10336 bl dvmGetMethodSourceFile
10338 @ exception->clazz->descriptor
10339 ldr r3, [r9, #offObject_clazz]
10340 ldr r3, [r3, #offClassObject_descriptor]
10342 ldr r2, strExceptionNotCaughtLocally
10344 mov r0, #3 @ LOG_DEBUG
10345 bl __android_log_print
10347 str r9, [r10, #offThread_exception] @ restore exception
10348 mov r0, r9 @ r0<- exception
10349 mov r1, r10 @ r1<- self
10350 bl dvmReleaseTrackedAlloc @ release the exception
10351 mov r1, #0 @ "want switch" = false
10352 b common_gotoBail @ bail out
10356 * Exception handling, calls through "glue code".
10360 SAVE_PC_FP_TO_GLUE() @ export state
10361 mov r0, rGLUE @ arg to function
10362 bl dvmMterp_exceptionThrown
10363 b common_resumeAfterGlueCall
10368 * After returning from a "glued" function, pull out the updated
10369 * values and start executing at the next instruction.
10371 common_resumeAfterGlueCall:
10372 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
10373 FETCH_INST() @ load rINST from rPC
10374 GET_INST_OPCODE(ip) @ extract opcode from rINST
10375 GOTO_OPCODE(ip) @ jump to next instruction
10378 * Invalid array index. Note that our calling convention is strange; we use r1
10379 * and r3 because those just happen to be the registers all our callers are
10380 * using. We shuffle them here before calling the C function.
10384 common_errArrayIndex:
10389 b common_exceptionThrown
10392 * Integer divide or mod by zero.
10394 common_errDivideByZero:
10396 ldr r0, strArithmeticException
10397 ldr r1, strDivideByZero
10398 bl dvmThrowException
10399 b common_exceptionThrown
10402 * Attempt to allocate an array with a negative size.
10404 common_errNegativeArraySize:
10406 ldr r0, strNegativeArraySizeException
10408 bl dvmThrowException
10409 b common_exceptionThrown
10412 * Invocation of a non-existent method.
10414 common_errNoSuchMethod:
10416 ldr r0, strNoSuchMethodError
10418 bl dvmThrowException
10419 b common_exceptionThrown
10422 * We encountered a null object when we weren't expecting one. We
10423 * export the PC, throw a NullPointerException, and goto the exception
10426 common_errNullObject:
10428 ldr r0, strNullPointerException
10430 bl dvmThrowException
10431 b common_exceptionThrown
10434 * For debugging, cause an immediate fault. The source address will
10435 * be in lr (use a bl instruction to jump here).
10443 * Spit out a "we were here", preserving all registers. (The attempt
10444 * to save ip won't work, but we need to save an even number of
10445 * registers for EABI 64-bit stack alignment.)
10449 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10453 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10465 * Spit out the number in r0, preserving registers.
10468 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10472 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10476 * Print a newline, preserving registers.
10478 common_printNewline:
10479 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10482 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10486 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10489 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10491 ldr r0, strPrintHex
10493 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10497 * Print the 64-bit quantity in r0-r1, preserving registers.
10500 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10503 ldr r0, strPrintLong
10505 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10509 * Print full method info. Pass the Method* in r0. Preserves regs.
10511 common_printMethod:
10512 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10513 bl dvmMterpPrintMethod
10514 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10518 * Call a C helper function that dumps regs and possibly some
10519 * additional info. Requires the C function to be compiled in.
10523 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10524 bl dvmMterpDumpArmRegs
10525 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10531 * Experiment on VFP mode.
10533 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10535 * Updates the bits specified by "mask", setting them to the values in "val".
10538 and r0, r0, r1 @ make sure no stray bits are set
10539 fmrx r2, fpscr @ get VFP reg
10540 mvn r1, r1 @ bit-invert mask
10541 and r2, r2, r1 @ clear masked bits
10542 orr r2, r2, r0 @ set specified bits
10543 fmxr fpscr, r2 @ set VFP reg
10544 mov r0, r2 @ return new value
10548 .global dvmConfigureFP
10549 .type dvmConfigureFP, %function
10551 stmfd sp!, {ip, lr}
10552 /* 0x03000000 sets DN/FZ */
10553 /* 0x00009f00 clears the six exception enable flags */
10555 mov r0, #0x03000000 @ r0<- 0x03000000
10556 add r1, r0, #0x9f00 @ r1<- 0x03009f00
10558 ldmfd sp!, {ip, pc}
10563 * String references, must be close to the code that uses them.
10566 strArithmeticException:
10567 .word .LstrArithmeticException
10569 .word .LstrDivideByZero
10570 strNegativeArraySizeException:
10571 .word .LstrNegativeArraySizeException
10572 strNoSuchMethodError:
10573 .word .LstrNoSuchMethodError
10574 strNullPointerException:
10575 .word .LstrNullPointerException
10579 strExceptionNotCaughtLocally:
10580 .word .LstrExceptionNotCaughtLocally
10587 .word .LstrPrintHex
10589 .word .LstrPrintLong
10592 * Zero-terminated ASCII string data.
10594 * On ARM we have two choices: do like gcc does, and LDR from a .word
10595 * with the address, or use an ADR pseudo-op to get the address
10596 * directly. ADR saves 4 bytes and an indirection, but it's using a
10597 * PC-relative addressing mode and hence has a limited range, which
10598 * makes it not work well with mergeable string sections.
10600 .section .rodata.str1.4,"aMS",%progbits,1
10602 .LstrBadEntryPoint:
10603 .asciz "Bad entry point %d\n"
10604 .LstrArithmeticException:
10605 .asciz "Ljava/lang/ArithmeticException;"
10607 .asciz "divide by zero"
10608 .LstrFilledNewArrayNotImpl:
10609 .asciz "filled-new-array only implemented for objects and 'int'"
10610 .LstrInternalError:
10611 .asciz "Ljava/lang/InternalError;"
10612 .LstrInstantiationError:
10613 .asciz "Ljava/lang/InstantiationError;"
10614 .LstrNegativeArraySizeException:
10615 .asciz "Ljava/lang/NegativeArraySizeException;"
10616 .LstrNoSuchMethodError:
10617 .asciz "Ljava/lang/NoSuchMethodError;"
10618 .LstrNullPointerException:
10619 .asciz "Ljava/lang/NullPointerException;"
10623 .LstrExceptionNotCaughtLocally:
10624 .asciz "Exception %s from %s:%d not caught locally\n"