2 * This file was generated automatically by gen-mterp.py for 'armv4t'.
7 /* File: armv5te/header.S */
9 * Copyright (C) 2008 The Android Open Source Project
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
24 * ARMv5 definitions and declarations.
28 ARM EABI general notes:
30 r0-r3 hold first 4 args to a method; they are not preserved across method calls
31 r4-r8 are available for general use
32 r9 is given special treatment in some situations, but not for us
33 r10 (sl) seems to be generally available
34 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35 r12 (ip) is scratch -- not preserved across method calls
36 r13 (sp) should be managed carefully in case a signal arrives
37 r14 (lr) must be preserved
38 r15 (pc) can be tinkered with directly
40 r0 holds returns of <= 4 bytes
41 r0-r1 hold returns of 8 bytes, low word in r0
43 Callee must save/restore r4+ (except r12) if it modifies them. If VFP
44 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45 s0-s15 (d0-d7, q0-a3) do not need to be.
47 Stack is "full descending". Only the arguments that don't fit in the first 4
48 registers are placed on the stack. "sp" points at the first stacked argument
51 VFP: single-precision results in s0, double-precision results in d0.
53 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
54 64-bit quantities (long long, double) must be 64-bit aligned.
60 The following registers have fixed assignments:
63 r4 rPC interpreted program counter, used for fetching instructions
64 r5 rFP interpreted frame pointer, used for accessing locals and args
65 r6 rGLUE MterpGlue pointer
66 r7 rINST first 16-bit code unit of current instruction
67 r8 rIBASE interpreted instruction base pointer, used for computed goto
69 Macros are provided for common operations. Each macro MUST emit only
70 one instruction to make instruction-counting easier. They MUST NOT alter
71 unspecified registers or condition codes.
74 /* single-purpose registers, given names for clarity */
81 /* save/restore the PC and/or FP from the glue struct */
82 #define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc]
83 #define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc]
84 #define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp]
85 #define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp]
86 #define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP}
87 #define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP}
90 * "export" the PC to the stack frame, f/b/o future exception objects. Must
91 * be done *before* something calls dvmThrowException.
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 * It's okay to do this more than once.
99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
102 * Given a frame pointer, find the stack save area.
104 * In C this is "((StackSaveArea*)(_fp) -1)".
106 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
107 sub _reg, _fpreg, #sizeofStackSaveArea
110 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
112 #define FETCH_INST() ldrh rINST, [rPC]
115 * Fetch the next instruction from the specified offset. Advances rPC
116 * to point to the next instruction. "_count" is in 16-bit code units.
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss. (This also implies that it must come after
126 #define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]!
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133 ldrh _dreg, [_sreg, #(_count*2)]!
136 * Fetch the next instruction from an offset specified by _reg. Updates
137 * rPC to point to the next instruction. "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
145 #define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]!
148 * Fetch a half-word code unit from an offset past the current PC. The
149 * "_count" value is in 16-bit code units. Does not advance rPC.
151 * The "_S" variant works the same but treats the value as signed.
153 #define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)]
154 #define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)]
157 * Fetch one byte from an offset past the current PC. Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
161 #define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)]
164 * Put the instruction's opcode field into the specified register.
166 #define GET_INST_OPCODE(_reg) and _reg, rINST, #255
169 * Put the prefetched instruction's opcode field into the specified register.
171 #define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255
174 * Begin executing the opcode in _reg. Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 #define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6
178 #define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6
179 #define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6
182 * Get/set the 32-bit value from a Dalvik register.
184 #define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2]
185 #define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2]
187 #if defined(WITH_JIT)
188 #define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable]
189 #define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold]
193 * Convert a virtual register index into an address.
195 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196 add _reg, rFP, _vreg, lsl #2
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
202 #include "../common/asm-constants.h"
204 #if defined(WITH_JIT)
205 #include "../common/jit-config.h"
208 /* File: armv5te/platform.S */
210 * ===========================================================================
211 * CPU-version-specific defines
212 * ===========================================================================
216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a
219 * May modify IP. Does not modify LR.
226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227 * Jump to subroutine.
229 * May modify IP and LR.
231 .macro LDR_PC_LR source
237 * Macro for "LDMFD SP!, {...regs...,PC}".
239 * May modify IP and LR.
242 ldmfd sp!, {\regs,pc}
246 /* File: armv5te/entry.S */
248 * Copyright (C) 2008 The Android Open Source Project
250 * Licensed under the Apache License, Version 2.0 (the "License");
251 * you may not use this file except in compliance with the License.
252 * You may obtain a copy of the License at
254 * http://www.apache.org/licenses/LICENSE-2.0
256 * Unless required by applicable law or agreed to in writing, software
257 * distributed under the License is distributed on an "AS IS" BASIS,
258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259 * See the License for the specific language governing permissions and
260 * limitations under the License.
263 * Interpreter entry point.
267 * We don't have formal stack frames, so gdb scans upward in the code
268 * to find the start of the function (a label with the %function type),
269 * and then looks at the next few instructions to figure out what
270 * got pushed onto the stack. From this it figures out how to restore
271 * the registers, including PC, for the previous stack frame. If gdb
272 * sees a non-function label, it stops scanning, so either we need to
273 * have nothing but assembler-local labels between the entry point and
274 * the break, or we need to fake it out.
276 * When this is defined, we add some stuff to make gdb less confused.
278 #define ASSIST_DEBUGGER 1
282 .global dvmMterpStdRun
283 .type dvmMterpStdRun, %function
289 * This function returns a boolean "changeInterp" value. The return comes
290 * via a call to dvmMterpStdBail().
293 #define MTERP_ENTRY1 \
294 .save {r4-r10,fp,lr}; \
295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs
296 #define MTERP_ENTRY2 \
298 sub sp, sp, #4 @ align 64
304 /* save stack pointer, add magic word for debuggerd */
305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return
307 /* set up "named" registers, figure out entry point */
308 mov rGLUE, r0 @ set rGLUE
309 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char
310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue"
311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE
312 cmp r1, #kInterpEntryInstr @ usual case?
313 bne .Lnot_instr @ no, handle it
315 #if defined(WITH_JIT)
317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
318 /* Entry is always a possible trace start */
319 GET_JIT_PROF_TABLE(r0)
321 mov r1, #0 @ prepare the value for the new state
322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
324 bne common_updateProfile
328 /* start executing the instruction at rPC */
329 FETCH_INST() @ load rINST from rPC
330 GET_INST_OPCODE(ip) @ extract opcode from rINST
331 GOTO_OPCODE(ip) @ jump to next instruction
335 cmp r1, #kInterpEntryReturn @ were we returning from a method?
336 beq common_returnFromMethod
339 cmp r1, #kInterpEntryThrow @ were we throwing an exception?
340 beq common_exceptionThrown
342 #if defined(WITH_JIT)
344 ldr r0,[rGLUE, #offGlue_jitResume]
345 ldr r2,[rGLUE, #offGlue_jitResumePC]
346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step?
349 bne .Lno_singleStep @ must have branched, don't resume
350 mov r1, #kInterpEntryInstr
351 strb r1, [rGLUE, #offGlue_entryPoint]
352 ldr rINST, .LdvmCompilerTemplate
353 bx r0 @ re-enter the translation
354 .LdvmCompilerTemplate:
355 .word dvmCompilerTemplateStart
359 ldr r0, strBadEntryPoint
360 @ r1 holds value of entryPoint
366 .global dvmMterpStdBail
367 .type dvmMterpStdBail, %function
370 * Restore the stack pointer and PC from the save point established on entry.
371 * This is essentially the same as a longjmp, but should be cheaper. The
372 * last instruction causes us to return to whoever called dvmMterpStdRun.
374 * We pushed some registers on the stack in dvmMterpStdRun, then saved
375 * SP and LR. Here we restore SP, restore the registers, and then restore
380 * r1 bool changeInterp
383 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP
384 mov r0, r1 @ return the changeInterp value
385 add sp, sp, #4 @ un-align 64
386 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return
393 .word .LstrBadEntryPoint
397 .global dvmAsmInstructionStart
398 .type dvmAsmInstructionStart, %function
399 dvmAsmInstructionStart = .L_OP_NOP
402 /* ------------------------------ */
404 .L_OP_NOP: /* 0x00 */
405 /* File: armv5te/OP_NOP.S */
406 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST
407 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
408 GOTO_OPCODE(ip) @ execute it
410 #ifdef ASSIST_DEBUGGER
411 /* insert fake function header to help gdb find the stack frame */
412 .type dalvik_inst, %function
421 /* ------------------------------ */
423 .L_OP_MOVE: /* 0x01 */
424 /* File: armv5te/OP_MOVE.S */
425 /* for move, move-object, long-to-int */
427 mov r1, rINST, lsr #12 @ r1<- B from 15:12
428 mov r0, rINST, lsr #8 @ r0<- A from 11:8
429 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
430 GET_VREG(r2, r1) @ r2<- fp[B]
432 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
433 SET_VREG(r2, r0) @ fp[A]<- r2
434 GOTO_OPCODE(ip) @ execute next instruction
437 /* ------------------------------ */
439 .L_OP_MOVE_FROM16: /* 0x02 */
440 /* File: armv5te/OP_MOVE_FROM16.S */
441 /* for: move/from16, move-object/from16 */
443 FETCH(r1, 1) @ r1<- BBBB
444 mov r0, rINST, lsr #8 @ r0<- AA
445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
446 GET_VREG(r2, r1) @ r2<- fp[BBBB]
447 GET_INST_OPCODE(ip) @ extract opcode from rINST
448 SET_VREG(r2, r0) @ fp[AA]<- r2
449 GOTO_OPCODE(ip) @ jump to next instruction
452 /* ------------------------------ */
454 .L_OP_MOVE_16: /* 0x03 */
455 /* File: armv5te/OP_MOVE_16.S */
456 /* for: move/16, move-object/16 */
457 /* op vAAAA, vBBBB */
458 FETCH(r1, 2) @ r1<- BBBB
459 FETCH(r0, 1) @ r0<- AAAA
460 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
461 GET_VREG(r2, r1) @ r2<- fp[BBBB]
462 GET_INST_OPCODE(ip) @ extract opcode from rINST
463 SET_VREG(r2, r0) @ fp[AAAA]<- r2
464 GOTO_OPCODE(ip) @ jump to next instruction
467 /* ------------------------------ */
469 .L_OP_MOVE_WIDE: /* 0x04 */
470 /* File: armv5te/OP_MOVE_WIDE.S */
471 /* move-wide vA, vB */
472 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
473 mov r2, rINST, lsr #8 @ r2<- A(+)
474 mov r3, rINST, lsr #12 @ r3<- B
476 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
477 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
478 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
479 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
480 GET_INST_OPCODE(ip) @ extract opcode from rINST
481 stmia r2, {r0-r1} @ fp[A]<- r0/r1
482 GOTO_OPCODE(ip) @ jump to next instruction
485 /* ------------------------------ */
487 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
488 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
489 /* move-wide/from16 vAA, vBBBB */
490 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
491 FETCH(r3, 1) @ r3<- BBBB
492 mov r2, rINST, lsr #8 @ r2<- AA
493 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
494 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
495 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
497 GET_INST_OPCODE(ip) @ extract opcode from rINST
498 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
499 GOTO_OPCODE(ip) @ jump to next instruction
502 /* ------------------------------ */
504 .L_OP_MOVE_WIDE_16: /* 0x06 */
505 /* File: armv5te/OP_MOVE_WIDE_16.S */
506 /* move-wide/16 vAAAA, vBBBB */
507 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
508 FETCH(r3, 2) @ r3<- BBBB
509 FETCH(r2, 1) @ r2<- AAAA
510 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
511 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
512 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
513 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
514 GET_INST_OPCODE(ip) @ extract opcode from rINST
515 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
516 GOTO_OPCODE(ip) @ jump to next instruction
519 /* ------------------------------ */
521 .L_OP_MOVE_OBJECT: /* 0x07 */
522 /* File: armv5te/OP_MOVE_OBJECT.S */
523 /* File: armv5te/OP_MOVE.S */
524 /* for move, move-object, long-to-int */
526 mov r1, rINST, lsr #12 @ r1<- B from 15:12
527 mov r0, rINST, lsr #8 @ r0<- A from 11:8
528 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
529 GET_VREG(r2, r1) @ r2<- fp[B]
531 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
532 SET_VREG(r2, r0) @ fp[A]<- r2
533 GOTO_OPCODE(ip) @ execute next instruction
537 /* ------------------------------ */
539 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
540 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
541 /* File: armv5te/OP_MOVE_FROM16.S */
542 /* for: move/from16, move-object/from16 */
544 FETCH(r1, 1) @ r1<- BBBB
545 mov r0, rINST, lsr #8 @ r0<- AA
546 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
547 GET_VREG(r2, r1) @ r2<- fp[BBBB]
548 GET_INST_OPCODE(ip) @ extract opcode from rINST
549 SET_VREG(r2, r0) @ fp[AA]<- r2
550 GOTO_OPCODE(ip) @ jump to next instruction
554 /* ------------------------------ */
556 .L_OP_MOVE_OBJECT_16: /* 0x09 */
557 /* File: armv5te/OP_MOVE_OBJECT_16.S */
558 /* File: armv5te/OP_MOVE_16.S */
559 /* for: move/16, move-object/16 */
560 /* op vAAAA, vBBBB */
561 FETCH(r1, 2) @ r1<- BBBB
562 FETCH(r0, 1) @ r0<- AAAA
563 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
564 GET_VREG(r2, r1) @ r2<- fp[BBBB]
565 GET_INST_OPCODE(ip) @ extract opcode from rINST
566 SET_VREG(r2, r0) @ fp[AAAA]<- r2
567 GOTO_OPCODE(ip) @ jump to next instruction
571 /* ------------------------------ */
573 .L_OP_MOVE_RESULT: /* 0x0a */
574 /* File: armv5te/OP_MOVE_RESULT.S */
575 /* for: move-result, move-result-object */
577 mov r2, rINST, lsr #8 @ r2<- AA
578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
579 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
580 GET_INST_OPCODE(ip) @ extract opcode from rINST
581 SET_VREG(r0, r2) @ fp[AA]<- r0
582 GOTO_OPCODE(ip) @ jump to next instruction
585 /* ------------------------------ */
587 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
588 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
589 /* move-result-wide vAA */
590 mov r2, rINST, lsr #8 @ r2<- AA
591 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
592 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
593 ldmia r3, {r0-r1} @ r0/r1<- retval.j
594 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
595 GET_INST_OPCODE(ip) @ extract opcode from rINST
596 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
597 GOTO_OPCODE(ip) @ jump to next instruction
600 /* ------------------------------ */
602 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
603 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
604 /* File: armv5te/OP_MOVE_RESULT.S */
605 /* for: move-result, move-result-object */
607 mov r2, rINST, lsr #8 @ r2<- AA
608 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
609 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
610 GET_INST_OPCODE(ip) @ extract opcode from rINST
611 SET_VREG(r0, r2) @ fp[AA]<- r0
612 GOTO_OPCODE(ip) @ jump to next instruction
616 /* ------------------------------ */
618 .L_OP_MOVE_EXCEPTION: /* 0x0d */
619 /* File: armv5te/OP_MOVE_EXCEPTION.S */
620 /* move-exception vAA */
621 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
622 mov r2, rINST, lsr #8 @ r2<- AA
623 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
625 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
626 SET_VREG(r3, r2) @ fp[AA]<- exception obj
627 GET_INST_OPCODE(ip) @ extract opcode from rINST
628 str r1, [r0, #offThread_exception] @ dvmClearException bypass
629 GOTO_OPCODE(ip) @ jump to next instruction
632 /* ------------------------------ */
634 .L_OP_RETURN_VOID: /* 0x0e */
635 /* File: armv5te/OP_RETURN_VOID.S */
636 b common_returnFromMethod
639 /* ------------------------------ */
641 .L_OP_RETURN: /* 0x0f */
642 /* File: armv5te/OP_RETURN.S */
644 * Return a 32-bit value. Copies the return value into the "glue"
645 * structure, then jumps to the return handler.
647 * for: return, return-object
650 mov r2, rINST, lsr #8 @ r2<- AA
651 GET_VREG(r0, r2) @ r0<- vAA
652 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
653 b common_returnFromMethod
656 /* ------------------------------ */
658 .L_OP_RETURN_WIDE: /* 0x10 */
659 /* File: armv5te/OP_RETURN_WIDE.S */
661 * Return a 64-bit value. Copies the return value into the "glue"
662 * structure, then jumps to the return handler.
664 /* return-wide vAA */
665 mov r2, rINST, lsr #8 @ r2<- AA
666 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
667 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
668 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
669 stmia r3, {r0-r1} @ retval<- r0/r1
670 b common_returnFromMethod
673 /* ------------------------------ */
675 .L_OP_RETURN_OBJECT: /* 0x11 */
676 /* File: armv5te/OP_RETURN_OBJECT.S */
677 /* File: armv5te/OP_RETURN.S */
679 * Return a 32-bit value. Copies the return value into the "glue"
680 * structure, then jumps to the return handler.
682 * for: return, return-object
685 mov r2, rINST, lsr #8 @ r2<- AA
686 GET_VREG(r0, r2) @ r0<- vAA
687 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
688 b common_returnFromMethod
692 /* ------------------------------ */
694 .L_OP_CONST_4: /* 0x12 */
695 /* File: armv5te/OP_CONST_4.S */
696 /* const/4 vA, #+B */
697 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
698 mov r0, rINST, lsr #8 @ r0<- A+
699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
700 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
702 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
703 SET_VREG(r1, r0) @ fp[A]<- r1
704 GOTO_OPCODE(ip) @ execute next instruction
707 /* ------------------------------ */
709 .L_OP_CONST_16: /* 0x13 */
710 /* File: armv5te/OP_CONST_16.S */
711 /* const/16 vAA, #+BBBB */
712 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
713 mov r3, rINST, lsr #8 @ r3<- AA
714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
715 SET_VREG(r0, r3) @ vAA<- r0
716 GET_INST_OPCODE(ip) @ extract opcode from rINST
717 GOTO_OPCODE(ip) @ jump to next instruction
720 /* ------------------------------ */
722 .L_OP_CONST: /* 0x14 */
723 /* File: armv5te/OP_CONST.S */
724 /* const vAA, #+BBBBbbbb */
725 mov r3, rINST, lsr #8 @ r3<- AA
726 FETCH(r0, 1) @ r0<- bbbb (low)
727 FETCH(r1, 2) @ r1<- BBBB (high)
728 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
730 GET_INST_OPCODE(ip) @ extract opcode from rINST
731 SET_VREG(r0, r3) @ vAA<- r0
732 GOTO_OPCODE(ip) @ jump to next instruction
735 /* ------------------------------ */
737 .L_OP_CONST_HIGH16: /* 0x15 */
738 /* File: armv5te/OP_CONST_HIGH16.S */
739 /* const/high16 vAA, #+BBBB0000 */
740 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
741 mov r3, rINST, lsr #8 @ r3<- AA
742 mov r0, r0, lsl #16 @ r0<- BBBB0000
743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
744 SET_VREG(r0, r3) @ vAA<- r0
745 GET_INST_OPCODE(ip) @ extract opcode from rINST
746 GOTO_OPCODE(ip) @ jump to next instruction
749 /* ------------------------------ */
751 .L_OP_CONST_WIDE_16: /* 0x16 */
752 /* File: armv5te/OP_CONST_WIDE_16.S */
753 /* const-wide/16 vAA, #+BBBB */
754 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
755 mov r3, rINST, lsr #8 @ r3<- AA
756 mov r1, r0, asr #31 @ r1<- ssssssss
757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
758 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
759 GET_INST_OPCODE(ip) @ extract opcode from rINST
760 stmia r3, {r0-r1} @ vAA<- r0/r1
761 GOTO_OPCODE(ip) @ jump to next instruction
764 /* ------------------------------ */
766 .L_OP_CONST_WIDE_32: /* 0x17 */
767 /* File: armv5te/OP_CONST_WIDE_32.S */
768 /* const-wide/32 vAA, #+BBBBbbbb */
769 FETCH(r0, 1) @ r0<- 0000bbbb (low)
770 mov r3, rINST, lsr #8 @ r3<- AA
771 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
772 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
773 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
774 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
775 mov r1, r0, asr #31 @ r1<- ssssssss
776 GET_INST_OPCODE(ip) @ extract opcode from rINST
777 stmia r3, {r0-r1} @ vAA<- r0/r1
778 GOTO_OPCODE(ip) @ jump to next instruction
781 /* ------------------------------ */
783 .L_OP_CONST_WIDE: /* 0x18 */
784 /* File: armv5te/OP_CONST_WIDE.S */
785 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786 FETCH(r0, 1) @ r0<- bbbb (low)
787 FETCH(r1, 2) @ r1<- BBBB (low middle)
788 FETCH(r2, 3) @ r2<- hhhh (high middle)
789 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
790 FETCH(r3, 4) @ r3<- HHHH (high)
791 mov r9, rINST, lsr #8 @ r9<- AA
792 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
793 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
794 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
795 GET_INST_OPCODE(ip) @ extract opcode from rINST
796 stmia r9, {r0-r1} @ vAA<- r0/r1
797 GOTO_OPCODE(ip) @ jump to next instruction
800 /* ------------------------------ */
802 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804 /* const-wide/high16 vAA, #+BBBB000000000000 */
805 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
806 mov r3, rINST, lsr #8 @ r3<- AA
807 mov r0, #0 @ r0<- 00000000
808 mov r1, r1, lsl #16 @ r1<- BBBB0000
809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
810 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
811 GET_INST_OPCODE(ip) @ extract opcode from rINST
812 stmia r3, {r0-r1} @ vAA<- r0/r1
813 GOTO_OPCODE(ip) @ jump to next instruction
816 /* ------------------------------ */
818 .L_OP_CONST_STRING: /* 0x1a */
819 /* File: armv5te/OP_CONST_STRING.S */
820 /* const/string vAA, String@BBBB */
821 FETCH(r1, 1) @ r1<- BBBB
822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
823 mov r9, rINST, lsr #8 @ r9<- AA
824 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
825 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
826 cmp r0, #0 @ not yet resolved?
827 beq .LOP_CONST_STRING_resolve
828 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
829 GET_INST_OPCODE(ip) @ extract opcode from rINST
830 SET_VREG(r0, r9) @ vAA<- r0
831 GOTO_OPCODE(ip) @ jump to next instruction
833 /* ------------------------------ */
835 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
836 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
837 /* const/string vAA, String@BBBBBBBB */
838 FETCH(r0, 1) @ r0<- bbbb (low)
839 FETCH(r1, 2) @ r1<- BBBB (high)
840 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
841 mov r9, rINST, lsr #8 @ r9<- AA
842 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
843 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
844 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
846 beq .LOP_CONST_STRING_JUMBO_resolve
847 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
848 GET_INST_OPCODE(ip) @ extract opcode from rINST
849 SET_VREG(r0, r9) @ vAA<- r0
850 GOTO_OPCODE(ip) @ jump to next instruction
852 /* ------------------------------ */
854 .L_OP_CONST_CLASS: /* 0x1c */
855 /* File: armv5te/OP_CONST_CLASS.S */
856 /* const/class vAA, Class@BBBB */
857 FETCH(r1, 1) @ r1<- BBBB
858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
859 mov r9, rINST, lsr #8 @ r9<- AA
860 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
861 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
862 cmp r0, #0 @ not yet resolved?
863 beq .LOP_CONST_CLASS_resolve
864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
865 GET_INST_OPCODE(ip) @ extract opcode from rINST
866 SET_VREG(r0, r9) @ vAA<- r0
867 GOTO_OPCODE(ip) @ jump to next instruction
869 /* ------------------------------ */
871 .L_OP_MONITOR_ENTER: /* 0x1d */
872 /* File: armv5te/OP_MONITOR_ENTER.S */
874 * Synchronize on an object.
876 /* monitor-enter vAA */
877 mov r2, rINST, lsr #8 @ r2<- AA
878 GET_VREG(r1, r2) @ r1<- vAA (object)
879 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
880 cmp r1, #0 @ null object?
881 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING
882 beq common_errNullObject @ null object, throw an exception
883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
884 bl dvmLockObject @ call(self, obj)
885 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
887 ldr r1, [r0, #offThread_exception] @ check for exception
889 bne common_exceptionThrown @ exception raised, bail out
891 GET_INST_OPCODE(ip) @ extract opcode from rINST
892 GOTO_OPCODE(ip) @ jump to next instruction
895 /* ------------------------------ */
897 .L_OP_MONITOR_EXIT: /* 0x1e */
898 /* File: armv5te/OP_MONITOR_EXIT.S */
902 * Exceptions that occur when unlocking a monitor need to appear as
903 * if they happened at the following instruction. See the Dalvik
906 /* monitor-exit vAA */
907 mov r2, rINST, lsr #8 @ r2<- AA
908 EXPORT_PC() @ before fetch: export the PC
909 GET_VREG(r1, r2) @ r1<- vAA (object)
910 cmp r1, #0 @ null object?
912 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
913 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
915 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
916 beq common_exceptionThrown @ yes, exception is pending
917 GET_INST_OPCODE(ip) @ extract opcode from rINST
918 GOTO_OPCODE(ip) @ jump to next instruction
920 FETCH_ADVANCE_INST(1) @ advance before throw
921 b common_errNullObject
924 /* ------------------------------ */
926 .L_OP_CHECK_CAST: /* 0x1f */
927 /* File: armv5te/OP_CHECK_CAST.S */
929 * Check to see if a cast from one class to another is allowed.
931 /* check-cast vAA, class@BBBB */
932 mov r3, rINST, lsr #8 @ r3<- AA
933 FETCH(r2, 1) @ r2<- BBBB
934 GET_VREG(r9, r3) @ r9<- object
935 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
936 cmp r9, #0 @ is object null?
937 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
938 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
939 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
940 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
941 cmp r1, #0 @ have we resolved this before?
942 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
943 .LOP_CHECK_CAST_resolved:
944 cmp r0, r1 @ same class (trivial success)?
945 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
946 .LOP_CHECK_CAST_okay:
947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
948 GET_INST_OPCODE(ip) @ extract opcode from rINST
949 GOTO_OPCODE(ip) @ jump to next instruction
951 /* ------------------------------ */
953 .L_OP_INSTANCE_OF: /* 0x20 */
954 /* File: armv5te/OP_INSTANCE_OF.S */
956 * Check to see if an object reference is an instance of a class.
958 * Most common situation is a non-null object, being compared against
959 * an already-resolved class.
961 /* instance-of vA, vB, class@CCCC */
962 mov r3, rINST, lsr #12 @ r3<- B
963 mov r9, rINST, lsr #8 @ r9<- A+
964 GET_VREG(r0, r3) @ r0<- vB (object)
965 and r9, r9, #15 @ r9<- A
966 cmp r0, #0 @ is object null?
967 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
968 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
969 FETCH(r3, 1) @ r3<- CCCC
970 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
971 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
972 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
973 cmp r1, #0 @ have we resolved this before?
974 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
975 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
976 cmp r0, r1 @ same class (trivial success)?
977 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
978 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
980 /* ------------------------------ */
982 .L_OP_ARRAY_LENGTH: /* 0x21 */
983 /* File: armv5te/OP_ARRAY_LENGTH.S */
985 * Return the length of an array.
987 mov r1, rINST, lsr #12 @ r1<- B
988 mov r2, rINST, lsr #8 @ r2<- A+
989 GET_VREG(r0, r1) @ r0<- vB (object ref)
990 and r2, r2, #15 @ r2<- A
991 cmp r0, #0 @ is object null?
992 beq common_errNullObject @ yup, fail
993 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
994 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
995 GET_INST_OPCODE(ip) @ extract opcode from rINST
996 SET_VREG(r3, r2) @ vB<- length
997 GOTO_OPCODE(ip) @ jump to next instruction
1000 /* ------------------------------ */
1002 .L_OP_NEW_INSTANCE: /* 0x22 */
1003 /* File: armv5te/OP_NEW_INSTANCE.S */
1005 * Create a new instance of a class.
1007 /* new-instance vAA, class@BBBB */
1008 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1009 FETCH(r1, 1) @ r1<- BBBB
1010 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1011 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1012 EXPORT_PC() @ req'd for init, resolve, alloc
1013 cmp r0, #0 @ already resolved?
1014 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
1015 .LOP_NEW_INSTANCE_resolved: @ r0=class
1016 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
1017 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
1018 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
1019 .LOP_NEW_INSTANCE_initialized: @ r0=class
1020 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
1021 bl dvmAllocObject @ r0<- new object
1022 b .LOP_NEW_INSTANCE_finish @ continue
1024 /* ------------------------------ */
1026 .L_OP_NEW_ARRAY: /* 0x23 */
1027 /* File: armv5te/OP_NEW_ARRAY.S */
1029 * Allocate an array of objects, specified with the array class
1032 * The verifier guarantees that this is an array class, so we don't
1033 * check for it here.
1035 /* new-array vA, vB, class@CCCC */
1036 mov r0, rINST, lsr #12 @ r0<- B
1037 FETCH(r2, 1) @ r2<- CCCC
1038 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1039 GET_VREG(r1, r0) @ r1<- vB (array length)
1040 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1041 cmp r1, #0 @ check length
1042 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
1043 bmi common_errNegativeArraySize @ negative length, bail
1044 cmp r0, #0 @ already resolved?
1045 EXPORT_PC() @ req'd for resolve, alloc
1046 bne .LOP_NEW_ARRAY_finish @ resolved, continue
1047 b .LOP_NEW_ARRAY_resolve @ do resolve now
1049 /* ------------------------------ */
1051 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1052 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1054 * Create a new array with elements filled from registers.
1056 * for: filled-new-array, filled-new-array/range
1058 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1059 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1060 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1061 FETCH(r1, 1) @ r1<- BBBB
1062 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1063 EXPORT_PC() @ need for resolve and alloc
1064 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1065 mov r10, rINST, lsr #8 @ r10<- AA or BA
1066 cmp r0, #0 @ already resolved?
1067 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
1068 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1069 mov r2, #0 @ r2<- false
1070 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1071 bl dvmResolveClass @ r0<- call(clazz, ref)
1072 cmp r0, #0 @ got null?
1073 beq common_exceptionThrown @ yes, handle exception
1074 b .LOP_FILLED_NEW_ARRAY_continue
1076 /* ------------------------------ */
1078 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1079 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1080 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1082 * Create a new array with elements filled from registers.
1084 * for: filled-new-array, filled-new-array/range
1086 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1087 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1088 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1089 FETCH(r1, 1) @ r1<- BBBB
1090 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1091 EXPORT_PC() @ need for resolve and alloc
1092 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1093 mov r10, rINST, lsr #8 @ r10<- AA or BA
1094 cmp r0, #0 @ already resolved?
1095 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
1096 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1097 mov r2, #0 @ r2<- false
1098 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1099 bl dvmResolveClass @ r0<- call(clazz, ref)
1100 cmp r0, #0 @ got null?
1101 beq common_exceptionThrown @ yes, handle exception
1102 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1105 /* ------------------------------ */
1107 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1108 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1109 /* fill-array-data vAA, +BBBBBBBB */
1110 FETCH(r0, 1) @ r0<- bbbb (lo)
1111 FETCH(r1, 2) @ r1<- BBBB (hi)
1112 mov r3, rINST, lsr #8 @ r3<- AA
1113 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1114 GET_VREG(r0, r3) @ r0<- vAA (array object)
1115 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1117 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1118 cmp r0, #0 @ 0 means an exception is thrown
1119 beq common_exceptionThrown @ has exception
1120 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1121 GET_INST_OPCODE(ip) @ extract opcode from rINST
1122 GOTO_OPCODE(ip) @ jump to next instruction
1124 /* ------------------------------ */
1126 .L_OP_THROW: /* 0x27 */
1127 /* File: armv5te/OP_THROW.S */
1129 * Throw an exception object in the current thread.
1132 mov r2, rINST, lsr #8 @ r2<- AA
1133 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1134 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1135 cmp r1, #0 @ null object?
1136 beq common_errNullObject @ yes, throw an NPE instead
1137 @ bypass dvmSetException, just store it
1138 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1139 b common_exceptionThrown
1142 /* ------------------------------ */
1144 .L_OP_GOTO: /* 0x28 */
1145 /* File: armv5te/OP_GOTO.S */
1147 * Unconditional branch, 8-bit offset.
1149 * The branch distance is a signed code-unit offset, which we need to
1150 * double to get a byte offset.
1153 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1154 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1155 mov r9, r9, lsl #1 @ r9<- byte offset
1156 bmi common_backwardBranch @ backward branch, do periodic checks
1157 #if defined(WITH_JIT)
1158 GET_JIT_PROF_TABLE(r0)
1159 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1161 bne common_updateProfile
1162 GET_INST_OPCODE(ip) @ extract opcode from rINST
1163 GOTO_OPCODE(ip) @ jump to next instruction
1165 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1166 GET_INST_OPCODE(ip) @ extract opcode from rINST
1167 GOTO_OPCODE(ip) @ jump to next instruction
1170 /* ------------------------------ */
1172 .L_OP_GOTO_16: /* 0x29 */
1173 /* File: armv5te/OP_GOTO_16.S */
1175 * Unconditional branch, 16-bit offset.
1177 * The branch distance is a signed code-unit offset, which we need to
1178 * double to get a byte offset.
1181 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1182 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1183 bmi common_backwardBranch @ backward branch, do periodic checks
1184 #if defined(WITH_JIT)
1185 GET_JIT_PROF_TABLE(r0)
1186 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1188 bne common_updateProfile
1189 GET_INST_OPCODE(ip) @ extract opcode from rINST
1190 GOTO_OPCODE(ip) @ jump to next instruction
1192 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1193 GET_INST_OPCODE(ip) @ extract opcode from rINST
1194 GOTO_OPCODE(ip) @ jump to next instruction
1198 /* ------------------------------ */
1200 .L_OP_GOTO_32: /* 0x2a */
1201 /* File: armv5te/OP_GOTO_32.S */
1203 * Unconditional branch, 32-bit offset.
1205 * The branch distance is a signed code-unit offset, which we need to
1206 * double to get a byte offset.
1208 * Unlike most opcodes, this one is allowed to branch to itself, so
1209 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1210 * instruction doesn't affect the V flag, so we need to clear it
1213 /* goto/32 +AAAAAAAA */
1214 FETCH(r0, 1) @ r0<- aaaa (lo)
1215 FETCH(r1, 2) @ r1<- AAAA (hi)
1216 cmp ip, ip @ (clear V flag during stall)
1217 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1218 mov r9, r0, asl #1 @ r9<- byte offset
1219 ble common_backwardBranch @ backward branch, do periodic checks
1220 #if defined(WITH_JIT)
1221 GET_JIT_PROF_TABLE(r0)
1222 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1224 bne common_updateProfile
1225 GET_INST_OPCODE(ip) @ extract opcode from rINST
1226 GOTO_OPCODE(ip) @ jump to next instruction
1228 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1229 GET_INST_OPCODE(ip) @ extract opcode from rINST
1230 GOTO_OPCODE(ip) @ jump to next instruction
1233 /* ------------------------------ */
1235 .L_OP_PACKED_SWITCH: /* 0x2b */
1236 /* File: armv5te/OP_PACKED_SWITCH.S */
1238 * Handle a packed-switch or sparse-switch instruction. In both cases
1239 * we decode it and hand it off to a helper function.
1241 * We don't really expect backward branches in a switch statement, but
1242 * they're perfectly legal, so we check for them here.
1244 * for: packed-switch, sparse-switch
1247 FETCH(r0, 1) @ r0<- bbbb (lo)
1248 FETCH(r1, 2) @ r1<- BBBB (hi)
1249 mov r3, rINST, lsr #8 @ r3<- AA
1250 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1251 GET_VREG(r1, r3) @ r1<- vAA
1252 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1253 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1254 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1255 bmi common_backwardBranch @ backward branch, do periodic checks
1256 beq common_backwardBranch @ (want to use BLE but V is unknown)
1257 #if defined(WITH_JIT)
1258 GET_JIT_PROF_TABLE(r0)
1259 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1261 bne common_updateProfile
1262 GET_INST_OPCODE(ip) @ extract opcode from rINST
1263 GOTO_OPCODE(ip) @ jump to next instruction
1265 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1266 GET_INST_OPCODE(ip) @ extract opcode from rINST
1267 GOTO_OPCODE(ip) @ jump to next instruction
1271 /* ------------------------------ */
1273 .L_OP_SPARSE_SWITCH: /* 0x2c */
1274 /* File: armv5te/OP_SPARSE_SWITCH.S */
1275 /* File: armv5te/OP_PACKED_SWITCH.S */
1277 * Handle a packed-switch or sparse-switch instruction. In both cases
1278 * we decode it and hand it off to a helper function.
1280 * We don't really expect backward branches in a switch statement, but
1281 * they're perfectly legal, so we check for them here.
1283 * for: packed-switch, sparse-switch
1286 FETCH(r0, 1) @ r0<- bbbb (lo)
1287 FETCH(r1, 2) @ r1<- BBBB (hi)
1288 mov r3, rINST, lsr #8 @ r3<- AA
1289 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1290 GET_VREG(r1, r3) @ r1<- vAA
1291 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1292 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1293 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1294 bmi common_backwardBranch @ backward branch, do periodic checks
1295 beq common_backwardBranch @ (want to use BLE but V is unknown)
1296 #if defined(WITH_JIT)
1297 GET_JIT_PROF_TABLE(r0)
1298 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1300 bne common_updateProfile
1301 GET_INST_OPCODE(ip) @ extract opcode from rINST
1302 GOTO_OPCODE(ip) @ jump to next instruction
1304 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1305 GET_INST_OPCODE(ip) @ extract opcode from rINST
1306 GOTO_OPCODE(ip) @ jump to next instruction
1311 /* ------------------------------ */
1313 .L_OP_CMPL_FLOAT: /* 0x2d */
1314 /* File: armv5te/OP_CMPL_FLOAT.S */
1316 * Compare two floating-point values. Puts 0, 1, or -1 into the
1317 * destination register based on the results of the comparison.
1319 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1320 * on what value we'd like to return when one of the operands is NaN.
1322 * The operation we're implementing is:
1330 * return {-1,1}; // one or both operands was NaN
1332 * The straightforward implementation requires 3 calls to functions
1333 * that return a result in r0. We can do it with two calls if our
1334 * EABI library supports __aeabi_cfcmple (only one if we want to check
1335 * for NaN directly):
1343 * for: cmpl-float, cmpg-float
1345 /* op vAA, vBB, vCC */
1346 FETCH(r0, 1) @ r0<- CCBB
1347 and r2, r0, #255 @ r2<- BB
1348 mov r3, r0, lsr #8 @ r3<- CC
1349 GET_VREG(r9, r2) @ r9<- vBB
1350 GET_VREG(r10, r3) @ r10<- vCC
1351 mov r0, r9 @ copy to arg registers
1353 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1354 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1355 mvncc r1, #0 @ (less than) r1<- -1
1356 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1357 .LOP_CMPL_FLOAT_finish:
1358 mov r3, rINST, lsr #8 @ r3<- AA
1359 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1360 SET_VREG(r1, r3) @ vAA<- r1
1361 GET_INST_OPCODE(ip) @ extract opcode from rINST
1362 GOTO_OPCODE(ip) @ jump to next instruction
1364 /* ------------------------------ */
1366 .L_OP_CMPG_FLOAT: /* 0x2e */
1367 /* File: armv5te/OP_CMPG_FLOAT.S */
1368 /* File: armv5te/OP_CMPL_FLOAT.S */
1370 * Compare two floating-point values. Puts 0, 1, or -1 into the
1371 * destination register based on the results of the comparison.
1373 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1374 * on what value we'd like to return when one of the operands is NaN.
1376 * The operation we're implementing is:
1384 * return {-1,1}; // one or both operands was NaN
1386 * The straightforward implementation requires 3 calls to functions
1387 * that return a result in r0. We can do it with two calls if our
1388 * EABI library supports __aeabi_cfcmple (only one if we want to check
1389 * for NaN directly):
1397 * for: cmpl-float, cmpg-float
1399 /* op vAA, vBB, vCC */
1400 FETCH(r0, 1) @ r0<- CCBB
1401 and r2, r0, #255 @ r2<- BB
1402 mov r3, r0, lsr #8 @ r3<- CC
1403 GET_VREG(r9, r2) @ r9<- vBB
1404 GET_VREG(r10, r3) @ r10<- vCC
1405 mov r0, r9 @ copy to arg registers
1407 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1408 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1409 mvncc r1, #0 @ (less than) r1<- -1
1410 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1411 .LOP_CMPG_FLOAT_finish:
1412 mov r3, rINST, lsr #8 @ r3<- AA
1413 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1414 SET_VREG(r1, r3) @ vAA<- r1
1415 GET_INST_OPCODE(ip) @ extract opcode from rINST
1416 GOTO_OPCODE(ip) @ jump to next instruction
1419 /* ------------------------------ */
1421 .L_OP_CMPL_DOUBLE: /* 0x2f */
1422 /* File: armv5te/OP_CMPL_DOUBLE.S */
1424 * Compare two floating-point values. Puts 0, 1, or -1 into the
1425 * destination register based on the results of the comparison.
1427 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1428 * on what value we'd like to return when one of the operands is NaN.
1430 * See OP_CMPL_FLOAT for an explanation.
1432 * For: cmpl-double, cmpg-double
1434 /* op vAA, vBB, vCC */
1435 FETCH(r0, 1) @ r0<- CCBB
1436 and r9, r0, #255 @ r9<- BB
1437 mov r10, r0, lsr #8 @ r10<- CC
1438 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1439 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1440 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1441 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1442 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1443 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1444 mvncc r1, #0 @ (less than) r1<- -1
1445 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1446 .LOP_CMPL_DOUBLE_finish:
1447 mov r3, rINST, lsr #8 @ r3<- AA
1448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1449 SET_VREG(r1, r3) @ vAA<- r1
1450 GET_INST_OPCODE(ip) @ extract opcode from rINST
1451 GOTO_OPCODE(ip) @ jump to next instruction
1453 /* ------------------------------ */
1455 .L_OP_CMPG_DOUBLE: /* 0x30 */
1456 /* File: armv5te/OP_CMPG_DOUBLE.S */
1457 /* File: armv5te/OP_CMPL_DOUBLE.S */
1459 * Compare two floating-point values. Puts 0, 1, or -1 into the
1460 * destination register based on the results of the comparison.
1462 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1463 * on what value we'd like to return when one of the operands is NaN.
1465 * See OP_CMPL_FLOAT for an explanation.
1467 * For: cmpl-double, cmpg-double
1469 /* op vAA, vBB, vCC */
1470 FETCH(r0, 1) @ r0<- CCBB
1471 and r9, r0, #255 @ r9<- BB
1472 mov r10, r0, lsr #8 @ r10<- CC
1473 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1474 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1475 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1476 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1477 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1478 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1479 mvncc r1, #0 @ (less than) r1<- -1
1480 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1481 .LOP_CMPG_DOUBLE_finish:
1482 mov r3, rINST, lsr #8 @ r3<- AA
1483 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1484 SET_VREG(r1, r3) @ vAA<- r1
1485 GET_INST_OPCODE(ip) @ extract opcode from rINST
1486 GOTO_OPCODE(ip) @ jump to next instruction
1489 /* ------------------------------ */
1491 .L_OP_CMP_LONG: /* 0x31 */
1492 /* File: armv5te/OP_CMP_LONG.S */
1494 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1495 * register based on the results of the comparison.
1497 * We load the full values with LDM, but in practice many values could
1498 * be resolved by only looking at the high word. This could be made
1499 * faster or slower by splitting the LDM into a pair of LDRs.
1501 * If we just wanted to set condition flags, we could do this:
1505 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1506 * integer value, which we can do with 2 conditional mov/mvn instructions
1507 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1508 * us a constant 5-cycle path plus a branch at the end to the
1509 * instruction epilogue code. The multi-compare approach below needs
1510 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1511 * in the worst case (the 64-bit values are equal).
1513 /* cmp-long vAA, vBB, vCC */
1514 FETCH(r0, 1) @ r0<- CCBB
1515 mov r9, rINST, lsr #8 @ r9<- AA
1516 and r2, r0, #255 @ r2<- BB
1517 mov r3, r0, lsr #8 @ r3<- CC
1518 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1519 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1520 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1521 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1522 cmp r1, r3 @ compare (vBB+1, vCC+1)
1523 blt .LOP_CMP_LONG_less @ signed compare on high part
1524 bgt .LOP_CMP_LONG_greater
1525 subs r1, r0, r2 @ r1<- r0 - r2
1526 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1527 bne .LOP_CMP_LONG_less
1528 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1530 /* ------------------------------ */
1532 .L_OP_IF_EQ: /* 0x32 */
1533 /* File: armv5te/OP_IF_EQ.S */
1534 /* File: armv5te/bincmp.S */
1536 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1537 * fragment that specifies the *reverse* comparison to perform, e.g.
1538 * for "if-le" you would use "gt".
1540 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1542 /* if-cmp vA, vB, +CCCC */
1543 mov r0, rINST, lsr #8 @ r0<- A+
1544 mov r1, rINST, lsr #12 @ r1<- B
1546 GET_VREG(r3, r1) @ r3<- vB
1547 GET_VREG(r2, r0) @ r2<- vA
1548 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1549 cmp r2, r3 @ compare (vA, vB)
1550 bne 1f @ branch to 1 if comparison failed
1551 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1552 movs r9, r9, asl #1 @ convert to bytes, check sign
1553 bmi common_backwardBranch @ yes, do periodic checks
1555 #if defined(WITH_JIT)
1556 GET_JIT_PROF_TABLE(r0)
1557 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1558 b common_testUpdateProfile
1560 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1561 GET_INST_OPCODE(ip) @ extract opcode from rINST
1562 GOTO_OPCODE(ip) @ jump to next instruction
1567 /* ------------------------------ */
1569 .L_OP_IF_NE: /* 0x33 */
1570 /* File: armv5te/OP_IF_NE.S */
1571 /* File: armv5te/bincmp.S */
1573 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1574 * fragment that specifies the *reverse* comparison to perform, e.g.
1575 * for "if-le" you would use "gt".
1577 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1579 /* if-cmp vA, vB, +CCCC */
1580 mov r0, rINST, lsr #8 @ r0<- A+
1581 mov r1, rINST, lsr #12 @ r1<- B
1583 GET_VREG(r3, r1) @ r3<- vB
1584 GET_VREG(r2, r0) @ r2<- vA
1585 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1586 cmp r2, r3 @ compare (vA, vB)
1587 beq 1f @ branch to 1 if comparison failed
1588 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1589 movs r9, r9, asl #1 @ convert to bytes, check sign
1590 bmi common_backwardBranch @ yes, do periodic checks
1592 #if defined(WITH_JIT)
1593 GET_JIT_PROF_TABLE(r0)
1594 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1595 b common_testUpdateProfile
1597 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1598 GET_INST_OPCODE(ip) @ extract opcode from rINST
1599 GOTO_OPCODE(ip) @ jump to next instruction
1604 /* ------------------------------ */
1606 .L_OP_IF_LT: /* 0x34 */
1607 /* File: armv5te/OP_IF_LT.S */
1608 /* File: armv5te/bincmp.S */
1610 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1611 * fragment that specifies the *reverse* comparison to perform, e.g.
1612 * for "if-le" you would use "gt".
1614 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1616 /* if-cmp vA, vB, +CCCC */
1617 mov r0, rINST, lsr #8 @ r0<- A+
1618 mov r1, rINST, lsr #12 @ r1<- B
1620 GET_VREG(r3, r1) @ r3<- vB
1621 GET_VREG(r2, r0) @ r2<- vA
1622 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1623 cmp r2, r3 @ compare (vA, vB)
1624 bge 1f @ branch to 1 if comparison failed
1625 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1626 movs r9, r9, asl #1 @ convert to bytes, check sign
1627 bmi common_backwardBranch @ yes, do periodic checks
1629 #if defined(WITH_JIT)
1630 GET_JIT_PROF_TABLE(r0)
1631 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1632 b common_testUpdateProfile
1634 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1635 GET_INST_OPCODE(ip) @ extract opcode from rINST
1636 GOTO_OPCODE(ip) @ jump to next instruction
1641 /* ------------------------------ */
1643 .L_OP_IF_GE: /* 0x35 */
1644 /* File: armv5te/OP_IF_GE.S */
1645 /* File: armv5te/bincmp.S */
1647 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1648 * fragment that specifies the *reverse* comparison to perform, e.g.
1649 * for "if-le" you would use "gt".
1651 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1653 /* if-cmp vA, vB, +CCCC */
1654 mov r0, rINST, lsr #8 @ r0<- A+
1655 mov r1, rINST, lsr #12 @ r1<- B
1657 GET_VREG(r3, r1) @ r3<- vB
1658 GET_VREG(r2, r0) @ r2<- vA
1659 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1660 cmp r2, r3 @ compare (vA, vB)
1661 blt 1f @ branch to 1 if comparison failed
1662 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1663 movs r9, r9, asl #1 @ convert to bytes, check sign
1664 bmi common_backwardBranch @ yes, do periodic checks
1666 #if defined(WITH_JIT)
1667 GET_JIT_PROF_TABLE(r0)
1668 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1669 b common_testUpdateProfile
1671 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1672 GET_INST_OPCODE(ip) @ extract opcode from rINST
1673 GOTO_OPCODE(ip) @ jump to next instruction
1678 /* ------------------------------ */
1680 .L_OP_IF_GT: /* 0x36 */
1681 /* File: armv5te/OP_IF_GT.S */
1682 /* File: armv5te/bincmp.S */
1684 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1685 * fragment that specifies the *reverse* comparison to perform, e.g.
1686 * for "if-le" you would use "gt".
1688 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1690 /* if-cmp vA, vB, +CCCC */
1691 mov r0, rINST, lsr #8 @ r0<- A+
1692 mov r1, rINST, lsr #12 @ r1<- B
1694 GET_VREG(r3, r1) @ r3<- vB
1695 GET_VREG(r2, r0) @ r2<- vA
1696 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1697 cmp r2, r3 @ compare (vA, vB)
1698 ble 1f @ branch to 1 if comparison failed
1699 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1700 movs r9, r9, asl #1 @ convert to bytes, check sign
1701 bmi common_backwardBranch @ yes, do periodic checks
1703 #if defined(WITH_JIT)
1704 GET_JIT_PROF_TABLE(r0)
1705 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1706 b common_testUpdateProfile
1708 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1709 GET_INST_OPCODE(ip) @ extract opcode from rINST
1710 GOTO_OPCODE(ip) @ jump to next instruction
1715 /* ------------------------------ */
1717 .L_OP_IF_LE: /* 0x37 */
1718 /* File: armv5te/OP_IF_LE.S */
1719 /* File: armv5te/bincmp.S */
1721 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1722 * fragment that specifies the *reverse* comparison to perform, e.g.
1723 * for "if-le" you would use "gt".
1725 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1727 /* if-cmp vA, vB, +CCCC */
1728 mov r0, rINST, lsr #8 @ r0<- A+
1729 mov r1, rINST, lsr #12 @ r1<- B
1731 GET_VREG(r3, r1) @ r3<- vB
1732 GET_VREG(r2, r0) @ r2<- vA
1733 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1734 cmp r2, r3 @ compare (vA, vB)
1735 bgt 1f @ branch to 1 if comparison failed
1736 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1737 movs r9, r9, asl #1 @ convert to bytes, check sign
1738 bmi common_backwardBranch @ yes, do periodic checks
1740 #if defined(WITH_JIT)
1741 GET_JIT_PROF_TABLE(r0)
1742 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1743 b common_testUpdateProfile
1745 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1746 GET_INST_OPCODE(ip) @ extract opcode from rINST
1747 GOTO_OPCODE(ip) @ jump to next instruction
1752 /* ------------------------------ */
1754 .L_OP_IF_EQZ: /* 0x38 */
1755 /* File: armv5te/OP_IF_EQZ.S */
1756 /* File: armv5te/zcmp.S */
1758 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1759 * fragment that specifies the *reverse* comparison to perform, e.g.
1760 * for "if-le" you would use "gt".
1762 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1764 /* if-cmp vAA, +BBBB */
1765 mov r0, rINST, lsr #8 @ r0<- AA
1766 GET_VREG(r2, r0) @ r2<- vAA
1767 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1768 cmp r2, #0 @ compare (vA, 0)
1769 bne 1f @ branch to 1 if comparison failed
1770 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1771 movs r9, r9, asl #1 @ convert to bytes, check sign
1772 bmi common_backwardBranch @ backward branch, do periodic checks
1774 #if defined(WITH_JIT)
1775 GET_JIT_PROF_TABLE(r0)
1776 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1778 bne common_updateProfile
1779 GET_INST_OPCODE(ip) @ extract opcode from rINST
1780 GOTO_OPCODE(ip) @ jump to next instruction
1782 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1783 GET_INST_OPCODE(ip) @ extract opcode from rINST
1784 GOTO_OPCODE(ip) @ jump to next instruction
1789 /* ------------------------------ */
1791 .L_OP_IF_NEZ: /* 0x39 */
1792 /* File: armv5te/OP_IF_NEZ.S */
1793 /* File: armv5te/zcmp.S */
1795 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1796 * fragment that specifies the *reverse* comparison to perform, e.g.
1797 * for "if-le" you would use "gt".
1799 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1801 /* if-cmp vAA, +BBBB */
1802 mov r0, rINST, lsr #8 @ r0<- AA
1803 GET_VREG(r2, r0) @ r2<- vAA
1804 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1805 cmp r2, #0 @ compare (vA, 0)
1806 beq 1f @ branch to 1 if comparison failed
1807 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1808 movs r9, r9, asl #1 @ convert to bytes, check sign
1809 bmi common_backwardBranch @ backward branch, do periodic checks
1811 #if defined(WITH_JIT)
1812 GET_JIT_PROF_TABLE(r0)
1813 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1815 bne common_updateProfile
1816 GET_INST_OPCODE(ip) @ extract opcode from rINST
1817 GOTO_OPCODE(ip) @ jump to next instruction
1819 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1820 GET_INST_OPCODE(ip) @ extract opcode from rINST
1821 GOTO_OPCODE(ip) @ jump to next instruction
1826 /* ------------------------------ */
1828 .L_OP_IF_LTZ: /* 0x3a */
1829 /* File: armv5te/OP_IF_LTZ.S */
1830 /* File: armv5te/zcmp.S */
1832 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1833 * fragment that specifies the *reverse* comparison to perform, e.g.
1834 * for "if-le" you would use "gt".
1836 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1838 /* if-cmp vAA, +BBBB */
1839 mov r0, rINST, lsr #8 @ r0<- AA
1840 GET_VREG(r2, r0) @ r2<- vAA
1841 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1842 cmp r2, #0 @ compare (vA, 0)
1843 bge 1f @ branch to 1 if comparison failed
1844 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1845 movs r9, r9, asl #1 @ convert to bytes, check sign
1846 bmi common_backwardBranch @ backward branch, do periodic checks
1848 #if defined(WITH_JIT)
1849 GET_JIT_PROF_TABLE(r0)
1850 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1852 bne common_updateProfile
1853 GET_INST_OPCODE(ip) @ extract opcode from rINST
1854 GOTO_OPCODE(ip) @ jump to next instruction
1856 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1857 GET_INST_OPCODE(ip) @ extract opcode from rINST
1858 GOTO_OPCODE(ip) @ jump to next instruction
1863 /* ------------------------------ */
1865 .L_OP_IF_GEZ: /* 0x3b */
1866 /* File: armv5te/OP_IF_GEZ.S */
1867 /* File: armv5te/zcmp.S */
1869 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1870 * fragment that specifies the *reverse* comparison to perform, e.g.
1871 * for "if-le" you would use "gt".
1873 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1875 /* if-cmp vAA, +BBBB */
1876 mov r0, rINST, lsr #8 @ r0<- AA
1877 GET_VREG(r2, r0) @ r2<- vAA
1878 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1879 cmp r2, #0 @ compare (vA, 0)
1880 blt 1f @ branch to 1 if comparison failed
1881 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1882 movs r9, r9, asl #1 @ convert to bytes, check sign
1883 bmi common_backwardBranch @ backward branch, do periodic checks
1885 #if defined(WITH_JIT)
1886 GET_JIT_PROF_TABLE(r0)
1887 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1889 bne common_updateProfile
1890 GET_INST_OPCODE(ip) @ extract opcode from rINST
1891 GOTO_OPCODE(ip) @ jump to next instruction
1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1894 GET_INST_OPCODE(ip) @ extract opcode from rINST
1895 GOTO_OPCODE(ip) @ jump to next instruction
1900 /* ------------------------------ */
1902 .L_OP_IF_GTZ: /* 0x3c */
1903 /* File: armv5te/OP_IF_GTZ.S */
1904 /* File: armv5te/zcmp.S */
1906 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1907 * fragment that specifies the *reverse* comparison to perform, e.g.
1908 * for "if-le" you would use "gt".
1910 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1912 /* if-cmp vAA, +BBBB */
1913 mov r0, rINST, lsr #8 @ r0<- AA
1914 GET_VREG(r2, r0) @ r2<- vAA
1915 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1916 cmp r2, #0 @ compare (vA, 0)
1917 ble 1f @ branch to 1 if comparison failed
1918 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1919 movs r9, r9, asl #1 @ convert to bytes, check sign
1920 bmi common_backwardBranch @ backward branch, do periodic checks
1922 #if defined(WITH_JIT)
1923 GET_JIT_PROF_TABLE(r0)
1924 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1926 bne common_updateProfile
1927 GET_INST_OPCODE(ip) @ extract opcode from rINST
1928 GOTO_OPCODE(ip) @ jump to next instruction
1930 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1931 GET_INST_OPCODE(ip) @ extract opcode from rINST
1932 GOTO_OPCODE(ip) @ jump to next instruction
1937 /* ------------------------------ */
1939 .L_OP_IF_LEZ: /* 0x3d */
1940 /* File: armv5te/OP_IF_LEZ.S */
1941 /* File: armv5te/zcmp.S */
1943 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1944 * fragment that specifies the *reverse* comparison to perform, e.g.
1945 * for "if-le" you would use "gt".
1947 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1949 /* if-cmp vAA, +BBBB */
1950 mov r0, rINST, lsr #8 @ r0<- AA
1951 GET_VREG(r2, r0) @ r2<- vAA
1952 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1953 cmp r2, #0 @ compare (vA, 0)
1954 bgt 1f @ branch to 1 if comparison failed
1955 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1956 movs r9, r9, asl #1 @ convert to bytes, check sign
1957 bmi common_backwardBranch @ backward branch, do periodic checks
1959 #if defined(WITH_JIT)
1960 GET_JIT_PROF_TABLE(r0)
1961 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1963 bne common_updateProfile
1964 GET_INST_OPCODE(ip) @ extract opcode from rINST
1965 GOTO_OPCODE(ip) @ jump to next instruction
1967 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1968 GET_INST_OPCODE(ip) @ extract opcode from rINST
1969 GOTO_OPCODE(ip) @ jump to next instruction
1974 /* ------------------------------ */
1976 .L_OP_UNUSED_3E: /* 0x3e */
1977 /* File: armv5te/OP_UNUSED_3E.S */
1978 /* File: armv5te/unused.S */
1983 /* ------------------------------ */
1985 .L_OP_UNUSED_3F: /* 0x3f */
1986 /* File: armv5te/OP_UNUSED_3F.S */
1987 /* File: armv5te/unused.S */
1992 /* ------------------------------ */
1994 .L_OP_UNUSED_40: /* 0x40 */
1995 /* File: armv5te/OP_UNUSED_40.S */
1996 /* File: armv5te/unused.S */
2001 /* ------------------------------ */
2003 .L_OP_UNUSED_41: /* 0x41 */
2004 /* File: armv5te/OP_UNUSED_41.S */
2005 /* File: armv5te/unused.S */
2010 /* ------------------------------ */
2012 .L_OP_UNUSED_42: /* 0x42 */
2013 /* File: armv5te/OP_UNUSED_42.S */
2014 /* File: armv5te/unused.S */
2019 /* ------------------------------ */
2021 .L_OP_UNUSED_43: /* 0x43 */
2022 /* File: armv5te/OP_UNUSED_43.S */
2023 /* File: armv5te/unused.S */
2028 /* ------------------------------ */
2030 .L_OP_AGET: /* 0x44 */
2031 /* File: armv5te/OP_AGET.S */
2033 * Array get, 32 bits or less. vAA <- vBB[vCC].
2035 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2036 * instructions. We use a pair of FETCH_Bs instead.
2038 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2040 /* op vAA, vBB, vCC */
2041 FETCH_B(r2, 1, 0) @ r2<- BB
2042 mov r9, rINST, lsr #8 @ r9<- AA
2043 FETCH_B(r3, 1, 1) @ r3<- CC
2044 GET_VREG(r0, r2) @ r0<- vBB (array object)
2045 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2046 cmp r0, #0 @ null array object?
2047 beq common_errNullObject @ yes, bail
2048 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2049 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2050 cmp r1, r3 @ compare unsigned index, length
2051 bcs common_errArrayIndex @ index >= length, bail
2052 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2053 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2054 GET_INST_OPCODE(ip) @ extract opcode from rINST
2055 SET_VREG(r2, r9) @ vAA<- r2
2056 GOTO_OPCODE(ip) @ jump to next instruction
2059 /* ------------------------------ */
2061 .L_OP_AGET_WIDE: /* 0x45 */
2062 /* File: armv4t/OP_AGET_WIDE.S */
2064 * Array get, 64 bits. vAA <- vBB[vCC].
2066 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2068 /* aget-wide vAA, vBB, vCC */
2069 FETCH(r0, 1) @ r0<- CCBB
2070 mov r9, rINST, lsr #8 @ r9<- AA
2071 and r2, r0, #255 @ r2<- BB
2072 mov r3, r0, lsr #8 @ r3<- CC
2073 GET_VREG(r0, r2) @ r0<- vBB (array object)
2074 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2075 cmp r0, #0 @ null array object?
2076 beq common_errNullObject @ yes, bail
2077 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2078 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2079 cmp r1, r3 @ compare unsigned index, length
2080 bcc .LOP_AGET_WIDE_finish @ okay, continue below
2081 b common_errArrayIndex @ index >= length, bail
2082 @ May want to swap the order of these two branches depending on how the
2083 @ branch prediction (if any) handles conditional forward branches vs.
2084 @ unconditional forward branches.
2086 /* ------------------------------ */
2088 .L_OP_AGET_OBJECT: /* 0x46 */
2089 /* File: armv5te/OP_AGET_OBJECT.S */
2090 /* File: armv5te/OP_AGET.S */
2092 * Array get, 32 bits or less. vAA <- vBB[vCC].
2094 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2095 * instructions. We use a pair of FETCH_Bs instead.
2097 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2099 /* op vAA, vBB, vCC */
2100 FETCH_B(r2, 1, 0) @ r2<- BB
2101 mov r9, rINST, lsr #8 @ r9<- AA
2102 FETCH_B(r3, 1, 1) @ r3<- CC
2103 GET_VREG(r0, r2) @ r0<- vBB (array object)
2104 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2105 cmp r0, #0 @ null array object?
2106 beq common_errNullObject @ yes, bail
2107 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2108 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2109 cmp r1, r3 @ compare unsigned index, length
2110 bcs common_errArrayIndex @ index >= length, bail
2111 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2112 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2113 GET_INST_OPCODE(ip) @ extract opcode from rINST
2114 SET_VREG(r2, r9) @ vAA<- r2
2115 GOTO_OPCODE(ip) @ jump to next instruction
2119 /* ------------------------------ */
2121 .L_OP_AGET_BOOLEAN: /* 0x47 */
2122 /* File: armv5te/OP_AGET_BOOLEAN.S */
2123 /* File: armv5te/OP_AGET.S */
2125 * Array get, 32 bits or less. vAA <- vBB[vCC].
2127 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2128 * instructions. We use a pair of FETCH_Bs instead.
2130 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2132 /* op vAA, vBB, vCC */
2133 FETCH_B(r2, 1, 0) @ r2<- BB
2134 mov r9, rINST, lsr #8 @ r9<- AA
2135 FETCH_B(r3, 1, 1) @ r3<- CC
2136 GET_VREG(r0, r2) @ r0<- vBB (array object)
2137 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2138 cmp r0, #0 @ null array object?
2139 beq common_errNullObject @ yes, bail
2140 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2141 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2142 cmp r1, r3 @ compare unsigned index, length
2143 bcs common_errArrayIndex @ index >= length, bail
2144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2145 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2146 GET_INST_OPCODE(ip) @ extract opcode from rINST
2147 SET_VREG(r2, r9) @ vAA<- r2
2148 GOTO_OPCODE(ip) @ jump to next instruction
2152 /* ------------------------------ */
2154 .L_OP_AGET_BYTE: /* 0x48 */
2155 /* File: armv5te/OP_AGET_BYTE.S */
2156 /* File: armv5te/OP_AGET.S */
2158 * Array get, 32 bits or less. vAA <- vBB[vCC].
2160 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2161 * instructions. We use a pair of FETCH_Bs instead.
2163 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2165 /* op vAA, vBB, vCC */
2166 FETCH_B(r2, 1, 0) @ r2<- BB
2167 mov r9, rINST, lsr #8 @ r9<- AA
2168 FETCH_B(r3, 1, 1) @ r3<- CC
2169 GET_VREG(r0, r2) @ r0<- vBB (array object)
2170 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2171 cmp r0, #0 @ null array object?
2172 beq common_errNullObject @ yes, bail
2173 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2174 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2175 cmp r1, r3 @ compare unsigned index, length
2176 bcs common_errArrayIndex @ index >= length, bail
2177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2178 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2179 GET_INST_OPCODE(ip) @ extract opcode from rINST
2180 SET_VREG(r2, r9) @ vAA<- r2
2181 GOTO_OPCODE(ip) @ jump to next instruction
2185 /* ------------------------------ */
2187 .L_OP_AGET_CHAR: /* 0x49 */
2188 /* File: armv5te/OP_AGET_CHAR.S */
2189 /* File: armv5te/OP_AGET.S */
2191 * Array get, 32 bits or less. vAA <- vBB[vCC].
2193 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2194 * instructions. We use a pair of FETCH_Bs instead.
2196 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2198 /* op vAA, vBB, vCC */
2199 FETCH_B(r2, 1, 0) @ r2<- BB
2200 mov r9, rINST, lsr #8 @ r9<- AA
2201 FETCH_B(r3, 1, 1) @ r3<- CC
2202 GET_VREG(r0, r2) @ r0<- vBB (array object)
2203 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2204 cmp r0, #0 @ null array object?
2205 beq common_errNullObject @ yes, bail
2206 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2207 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2208 cmp r1, r3 @ compare unsigned index, length
2209 bcs common_errArrayIndex @ index >= length, bail
2210 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2211 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2212 GET_INST_OPCODE(ip) @ extract opcode from rINST
2213 SET_VREG(r2, r9) @ vAA<- r2
2214 GOTO_OPCODE(ip) @ jump to next instruction
2218 /* ------------------------------ */
2220 .L_OP_AGET_SHORT: /* 0x4a */
2221 /* File: armv5te/OP_AGET_SHORT.S */
2222 /* File: armv5te/OP_AGET.S */
2224 * Array get, 32 bits or less. vAA <- vBB[vCC].
2226 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2227 * instructions. We use a pair of FETCH_Bs instead.
2229 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2231 /* op vAA, vBB, vCC */
2232 FETCH_B(r2, 1, 0) @ r2<- BB
2233 mov r9, rINST, lsr #8 @ r9<- AA
2234 FETCH_B(r3, 1, 1) @ r3<- CC
2235 GET_VREG(r0, r2) @ r0<- vBB (array object)
2236 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2237 cmp r0, #0 @ null array object?
2238 beq common_errNullObject @ yes, bail
2239 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2240 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2241 cmp r1, r3 @ compare unsigned index, length
2242 bcs common_errArrayIndex @ index >= length, bail
2243 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2244 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2245 GET_INST_OPCODE(ip) @ extract opcode from rINST
2246 SET_VREG(r2, r9) @ vAA<- r2
2247 GOTO_OPCODE(ip) @ jump to next instruction
2251 /* ------------------------------ */
2253 .L_OP_APUT: /* 0x4b */
2254 /* File: armv5te/OP_APUT.S */
2256 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2258 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2259 * instructions. We use a pair of FETCH_Bs instead.
2261 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2263 /* op vAA, vBB, vCC */
2264 FETCH_B(r2, 1, 0) @ r2<- BB
2265 mov r9, rINST, lsr #8 @ r9<- AA
2266 FETCH_B(r3, 1, 1) @ r3<- CC
2267 GET_VREG(r0, r2) @ r0<- vBB (array object)
2268 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2269 cmp r0, #0 @ null array object?
2270 beq common_errNullObject @ yes, bail
2271 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2272 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2273 cmp r1, r3 @ compare unsigned index, length
2274 bcs common_errArrayIndex @ index >= length, bail
2275 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2276 GET_VREG(r2, r9) @ r2<- vAA
2277 GET_INST_OPCODE(ip) @ extract opcode from rINST
2278 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2279 GOTO_OPCODE(ip) @ jump to next instruction
2282 /* ------------------------------ */
2284 .L_OP_APUT_WIDE: /* 0x4c */
2285 /* File: armv4t/OP_APUT_WIDE.S */
2287 * Array put, 64 bits. vBB[vCC] <- vAA.
2289 /* aput-wide vAA, vBB, vCC */
2290 FETCH(r0, 1) @ r0<- CCBB
2291 mov r9, rINST, lsr #8 @ r9<- AA
2292 and r2, r0, #255 @ r2<- BB
2293 mov r3, r0, lsr #8 @ r3<- CC
2294 GET_VREG(r0, r2) @ r0<- vBB (array object)
2295 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2296 cmp r0, #0 @ null array object?
2297 beq common_errNullObject @ yes, bail
2298 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2299 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2300 cmp r1, r3 @ compare unsigned index, length
2301 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2302 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2303 b common_errArrayIndex @ index >= length, bail
2304 @ May want to swap the order of these two branches depending on how the
2305 @ branch prediction (if any) handles conditional forward branches vs.
2306 @ unconditional forward branches.
2308 /* ------------------------------ */
2310 .L_OP_APUT_OBJECT: /* 0x4d */
2311 /* File: armv5te/OP_APUT_OBJECT.S */
2313 * Store an object into an array. vBB[vCC] <- vAA.
2315 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2316 * instructions. We use a pair of FETCH_Bs instead.
2318 /* op vAA, vBB, vCC */
2319 FETCH(r0, 1) @ r0<- CCBB
2320 mov r9, rINST, lsr #8 @ r9<- AA
2321 and r2, r0, #255 @ r2<- BB
2322 mov r3, r0, lsr #8 @ r3<- CC
2323 GET_VREG(r1, r2) @ r1<- vBB (array object)
2324 GET_VREG(r0, r3) @ r0<- vCC (requested index)
2325 cmp r1, #0 @ null array object?
2326 GET_VREG(r9, r9) @ r9<- vAA
2327 beq common_errNullObject @ yes, bail
2328 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length
2329 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width
2330 cmp r0, r3 @ compare unsigned index, length
2331 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2332 b common_errArrayIndex @ index >= length, bail
2335 /* ------------------------------ */
2337 .L_OP_APUT_BOOLEAN: /* 0x4e */
2338 /* File: armv5te/OP_APUT_BOOLEAN.S */
2339 /* File: armv5te/OP_APUT.S */
2341 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2343 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2344 * instructions. We use a pair of FETCH_Bs instead.
2346 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2348 /* op vAA, vBB, vCC */
2349 FETCH_B(r2, 1, 0) @ r2<- BB
2350 mov r9, rINST, lsr #8 @ r9<- AA
2351 FETCH_B(r3, 1, 1) @ r3<- CC
2352 GET_VREG(r0, r2) @ r0<- vBB (array object)
2353 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2354 cmp r0, #0 @ null array object?
2355 beq common_errNullObject @ yes, bail
2356 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2357 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2358 cmp r1, r3 @ compare unsigned index, length
2359 bcs common_errArrayIndex @ index >= length, bail
2360 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2361 GET_VREG(r2, r9) @ r2<- vAA
2362 GET_INST_OPCODE(ip) @ extract opcode from rINST
2363 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2364 GOTO_OPCODE(ip) @ jump to next instruction
2368 /* ------------------------------ */
2370 .L_OP_APUT_BYTE: /* 0x4f */
2371 /* File: armv5te/OP_APUT_BYTE.S */
2372 /* File: armv5te/OP_APUT.S */
2374 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2376 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2377 * instructions. We use a pair of FETCH_Bs instead.
2379 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2381 /* op vAA, vBB, vCC */
2382 FETCH_B(r2, 1, 0) @ r2<- BB
2383 mov r9, rINST, lsr #8 @ r9<- AA
2384 FETCH_B(r3, 1, 1) @ r3<- CC
2385 GET_VREG(r0, r2) @ r0<- vBB (array object)
2386 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2387 cmp r0, #0 @ null array object?
2388 beq common_errNullObject @ yes, bail
2389 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2390 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2391 cmp r1, r3 @ compare unsigned index, length
2392 bcs common_errArrayIndex @ index >= length, bail
2393 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2394 GET_VREG(r2, r9) @ r2<- vAA
2395 GET_INST_OPCODE(ip) @ extract opcode from rINST
2396 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2397 GOTO_OPCODE(ip) @ jump to next instruction
2401 /* ------------------------------ */
2403 .L_OP_APUT_CHAR: /* 0x50 */
2404 /* File: armv5te/OP_APUT_CHAR.S */
2405 /* File: armv5te/OP_APUT.S */
2407 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2409 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2410 * instructions. We use a pair of FETCH_Bs instead.
2412 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2414 /* op vAA, vBB, vCC */
2415 FETCH_B(r2, 1, 0) @ r2<- BB
2416 mov r9, rINST, lsr #8 @ r9<- AA
2417 FETCH_B(r3, 1, 1) @ r3<- CC
2418 GET_VREG(r0, r2) @ r0<- vBB (array object)
2419 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2420 cmp r0, #0 @ null array object?
2421 beq common_errNullObject @ yes, bail
2422 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2423 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2424 cmp r1, r3 @ compare unsigned index, length
2425 bcs common_errArrayIndex @ index >= length, bail
2426 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2427 GET_VREG(r2, r9) @ r2<- vAA
2428 GET_INST_OPCODE(ip) @ extract opcode from rINST
2429 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2430 GOTO_OPCODE(ip) @ jump to next instruction
2434 /* ------------------------------ */
2436 .L_OP_APUT_SHORT: /* 0x51 */
2437 /* File: armv5te/OP_APUT_SHORT.S */
2438 /* File: armv5te/OP_APUT.S */
2440 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2442 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2443 * instructions. We use a pair of FETCH_Bs instead.
2445 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2447 /* op vAA, vBB, vCC */
2448 FETCH_B(r2, 1, 0) @ r2<- BB
2449 mov r9, rINST, lsr #8 @ r9<- AA
2450 FETCH_B(r3, 1, 1) @ r3<- CC
2451 GET_VREG(r0, r2) @ r0<- vBB (array object)
2452 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2453 cmp r0, #0 @ null array object?
2454 beq common_errNullObject @ yes, bail
2455 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2456 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2457 cmp r1, r3 @ compare unsigned index, length
2458 bcs common_errArrayIndex @ index >= length, bail
2459 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2460 GET_VREG(r2, r9) @ r2<- vAA
2461 GET_INST_OPCODE(ip) @ extract opcode from rINST
2462 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2463 GOTO_OPCODE(ip) @ jump to next instruction
2467 /* ------------------------------ */
2469 .L_OP_IGET: /* 0x52 */
2470 /* File: armv5te/OP_IGET.S */
2472 * General 32-bit instance field get.
2474 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2476 /* op vA, vB, field@CCCC */
2477 mov r0, rINST, lsr #12 @ r0<- B
2478 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2479 FETCH(r1, 1) @ r1<- field ref CCCC
2480 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2481 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2482 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2483 cmp r0, #0 @ is resolved entry null?
2484 bne .LOP_IGET_finish @ no, already resolved
2485 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2486 EXPORT_PC() @ resolve() could throw
2487 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2488 bl dvmResolveInstField @ r0<- resolved InstField ptr
2490 bne .LOP_IGET_finish
2491 b common_exceptionThrown
2493 /* ------------------------------ */
2495 .L_OP_IGET_WIDE: /* 0x53 */
2496 /* File: armv4t/OP_IGET_WIDE.S */
2498 * Wide 32-bit instance field get.
2500 /* iget-wide vA, vB, field@CCCC */
2501 mov r0, rINST, lsr #12 @ r0<- B
2502 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2503 FETCH(r1, 1) @ r1<- field ref CCCC
2504 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2505 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2506 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2507 cmp r0, #0 @ is resolved entry null?
2508 bne .LOP_IGET_WIDE_finish @ no, already resolved
2509 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2510 EXPORT_PC() @ resolve() could throw
2511 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2512 bl dvmResolveInstField @ r0<- resolved InstField ptr
2514 bne .LOP_IGET_WIDE_finish
2515 b common_exceptionThrown
2517 /* ------------------------------ */
2519 .L_OP_IGET_OBJECT: /* 0x54 */
2520 /* File: armv5te/OP_IGET_OBJECT.S */
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_OBJECT_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_OBJECT_finish
2542 b common_exceptionThrown
2545 /* ------------------------------ */
2547 .L_OP_IGET_BOOLEAN: /* 0x55 */
2548 /* File: armv5te/OP_IGET_BOOLEAN.S */
2549 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
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_BOOLEAN_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_BOOLEAN_finish
2571 b common_exceptionThrown
2574 /* ------------------------------ */
2576 .L_OP_IGET_BYTE: /* 0x56 */
2577 /* File: armv5te/OP_IGET_BYTE.S */
2578 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2579 /* File: armv5te/OP_IGET.S */
2581 * General 32-bit instance field get.
2583 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2585 /* op vA, vB, field@CCCC */
2586 mov r0, rINST, lsr #12 @ r0<- B
2587 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2588 FETCH(r1, 1) @ r1<- field ref CCCC
2589 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2590 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2591 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2592 cmp r0, #0 @ is resolved entry null?
2593 bne .LOP_IGET_BYTE_finish @ no, already resolved
2594 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2595 EXPORT_PC() @ resolve() could throw
2596 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2597 bl dvmResolveInstField @ r0<- resolved InstField ptr
2599 bne .LOP_IGET_BYTE_finish
2600 b common_exceptionThrown
2603 /* ------------------------------ */
2605 .L_OP_IGET_CHAR: /* 0x57 */
2606 /* File: armv5te/OP_IGET_CHAR.S */
2607 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2608 /* File: armv5te/OP_IGET.S */
2610 * General 32-bit instance field get.
2612 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2614 /* op vA, vB, field@CCCC */
2615 mov r0, rINST, lsr #12 @ r0<- B
2616 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2617 FETCH(r1, 1) @ r1<- field ref CCCC
2618 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2619 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2620 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2621 cmp r0, #0 @ is resolved entry null?
2622 bne .LOP_IGET_CHAR_finish @ no, already resolved
2623 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2624 EXPORT_PC() @ resolve() could throw
2625 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2626 bl dvmResolveInstField @ r0<- resolved InstField ptr
2628 bne .LOP_IGET_CHAR_finish
2629 b common_exceptionThrown
2632 /* ------------------------------ */
2634 .L_OP_IGET_SHORT: /* 0x58 */
2635 /* File: armv5te/OP_IGET_SHORT.S */
2636 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2637 /* File: armv5te/OP_IGET.S */
2639 * General 32-bit instance field get.
2641 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2643 /* op vA, vB, field@CCCC */
2644 mov r0, rINST, lsr #12 @ r0<- B
2645 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2646 FETCH(r1, 1) @ r1<- field ref CCCC
2647 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2648 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2649 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2650 cmp r0, #0 @ is resolved entry null?
2651 bne .LOP_IGET_SHORT_finish @ no, already resolved
2652 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2653 EXPORT_PC() @ resolve() could throw
2654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2655 bl dvmResolveInstField @ r0<- resolved InstField ptr
2657 bne .LOP_IGET_SHORT_finish
2658 b common_exceptionThrown
2661 /* ------------------------------ */
2663 .L_OP_IPUT: /* 0x59 */
2664 /* File: armv5te/OP_IPUT.S */
2666 * General 32-bit instance field put.
2668 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2670 /* op vA, vB, field@CCCC */
2671 mov r0, rINST, lsr #12 @ r0<- B
2672 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2673 FETCH(r1, 1) @ r1<- field ref CCCC
2674 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2675 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2676 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2677 cmp r0, #0 @ is resolved entry null?
2678 bne .LOP_IPUT_finish @ no, already resolved
2679 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2680 EXPORT_PC() @ resolve() could throw
2681 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2682 bl dvmResolveInstField @ r0<- resolved InstField ptr
2683 cmp r0, #0 @ success?
2684 bne .LOP_IPUT_finish @ yes, finish up
2685 b common_exceptionThrown
2687 /* ------------------------------ */
2689 .L_OP_IPUT_WIDE: /* 0x5a */
2690 /* File: armv4t/OP_IPUT_WIDE.S */
2691 /* iput-wide vA, vB, field@CCCC */
2692 mov r0, rINST, lsr #12 @ r0<- B
2693 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2694 FETCH(r1, 1) @ r1<- field ref CCCC
2695 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2696 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2698 cmp r0, #0 @ is resolved entry null?
2699 bne .LOP_IPUT_WIDE_finish @ no, already resolved
2700 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2701 EXPORT_PC() @ resolve() could throw
2702 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2703 bl dvmResolveInstField @ r0<- resolved InstField ptr
2704 cmp r0, #0 @ success?
2705 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2706 b common_exceptionThrown
2708 /* ------------------------------ */
2710 .L_OP_IPUT_OBJECT: /* 0x5b */
2711 /* File: armv5te/OP_IPUT_OBJECT.S */
2712 /* File: armv5te/OP_IPUT.S */
2714 * General 32-bit instance field put.
2716 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2718 /* op vA, vB, field@CCCC */
2719 mov r0, rINST, lsr #12 @ r0<- B
2720 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2721 FETCH(r1, 1) @ r1<- field ref CCCC
2722 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2723 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2724 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2725 cmp r0, #0 @ is resolved entry null?
2726 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
2727 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2728 EXPORT_PC() @ resolve() could throw
2729 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2730 bl dvmResolveInstField @ r0<- resolved InstField ptr
2731 cmp r0, #0 @ success?
2732 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2733 b common_exceptionThrown
2736 /* ------------------------------ */
2738 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2739 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2740 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2741 /* File: armv5te/OP_IPUT.S */
2743 * General 32-bit instance field put.
2745 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2747 /* op vA, vB, field@CCCC */
2748 mov r0, rINST, lsr #12 @ r0<- B
2749 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2750 FETCH(r1, 1) @ r1<- field ref CCCC
2751 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2752 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2753 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2754 cmp r0, #0 @ is resolved entry null?
2755 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
2756 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2757 EXPORT_PC() @ resolve() could throw
2758 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2759 bl dvmResolveInstField @ r0<- resolved InstField ptr
2760 cmp r0, #0 @ success?
2761 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2762 b common_exceptionThrown
2765 /* ------------------------------ */
2767 .L_OP_IPUT_BYTE: /* 0x5d */
2768 /* File: armv5te/OP_IPUT_BYTE.S */
2769 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2770 /* File: armv5te/OP_IPUT.S */
2772 * General 32-bit instance field put.
2774 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2776 /* op vA, vB, field@CCCC */
2777 mov r0, rINST, lsr #12 @ r0<- B
2778 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2779 FETCH(r1, 1) @ r1<- field ref CCCC
2780 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2781 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2782 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2783 cmp r0, #0 @ is resolved entry null?
2784 bne .LOP_IPUT_BYTE_finish @ no, already resolved
2785 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2786 EXPORT_PC() @ resolve() could throw
2787 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2788 bl dvmResolveInstField @ r0<- resolved InstField ptr
2789 cmp r0, #0 @ success?
2790 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2791 b common_exceptionThrown
2794 /* ------------------------------ */
2796 .L_OP_IPUT_CHAR: /* 0x5e */
2797 /* File: armv5te/OP_IPUT_CHAR.S */
2798 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2799 /* File: armv5te/OP_IPUT.S */
2801 * General 32-bit instance field put.
2803 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2805 /* op vA, vB, field@CCCC */
2806 mov r0, rINST, lsr #12 @ r0<- B
2807 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2808 FETCH(r1, 1) @ r1<- field ref CCCC
2809 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2810 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2811 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2812 cmp r0, #0 @ is resolved entry null?
2813 bne .LOP_IPUT_CHAR_finish @ no, already resolved
2814 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2815 EXPORT_PC() @ resolve() could throw
2816 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2817 bl dvmResolveInstField @ r0<- resolved InstField ptr
2818 cmp r0, #0 @ success?
2819 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2820 b common_exceptionThrown
2823 /* ------------------------------ */
2825 .L_OP_IPUT_SHORT: /* 0x5f */
2826 /* File: armv5te/OP_IPUT_SHORT.S */
2827 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2828 /* File: armv5te/OP_IPUT.S */
2830 * General 32-bit instance field put.
2832 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2834 /* op vA, vB, field@CCCC */
2835 mov r0, rINST, lsr #12 @ r0<- B
2836 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2837 FETCH(r1, 1) @ r1<- field ref CCCC
2838 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2839 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2840 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2841 cmp r0, #0 @ is resolved entry null?
2842 bne .LOP_IPUT_SHORT_finish @ no, already resolved
2843 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2844 EXPORT_PC() @ resolve() could throw
2845 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2846 bl dvmResolveInstField @ r0<- resolved InstField ptr
2847 cmp r0, #0 @ success?
2848 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2849 b common_exceptionThrown
2852 /* ------------------------------ */
2854 .L_OP_SGET: /* 0x60 */
2855 /* File: armv5te/OP_SGET.S */
2857 * General 32-bit SGET handler.
2859 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2861 /* op vAA, field@BBBB */
2862 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2863 FETCH(r1, 1) @ r1<- field ref BBBB
2864 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2865 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2866 cmp r0, #0 @ is resolved entry null?
2867 beq .LOP_SGET_resolve @ yes, do resolve
2868 .LOP_SGET_finish: @ field ptr in r0
2869 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2870 mov r2, rINST, lsr #8 @ r2<- AA
2871 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2872 SET_VREG(r1, r2) @ fp[AA]<- r1
2873 GET_INST_OPCODE(ip) @ extract opcode from rINST
2874 GOTO_OPCODE(ip) @ jump to next instruction
2876 /* ------------------------------ */
2878 .L_OP_SGET_WIDE: /* 0x61 */
2879 /* File: armv4t/OP_SGET_WIDE.S */
2881 * 64-bit SGET handler.
2883 /* sget-wide vAA, field@BBBB */
2884 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2885 FETCH(r1, 1) @ r1<- field ref BBBB
2886 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2887 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2888 cmp r0, #0 @ is resolved entry null?
2889 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2890 .LOP_SGET_WIDE_finish:
2891 mov r1, rINST, lsr #8 @ r1<- AA
2892 add r0, r0, #offStaticField_value
2893 ldmia r0, {r2-r3} @ r2/r3<- field value (aligned)
2894 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
2895 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2896 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
2897 GET_INST_OPCODE(ip) @ extract opcode from rINST
2898 GOTO_OPCODE(ip) @ jump to next instruction
2900 /* ------------------------------ */
2902 .L_OP_SGET_OBJECT: /* 0x62 */
2903 /* File: armv5te/OP_SGET_OBJECT.S */
2904 /* File: armv5te/OP_SGET.S */
2906 * General 32-bit SGET handler.
2908 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2910 /* op vAA, field@BBBB */
2911 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2912 FETCH(r1, 1) @ r1<- field ref BBBB
2913 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2914 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2915 cmp r0, #0 @ is resolved entry null?
2916 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2917 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2918 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2919 mov r2, rINST, lsr #8 @ r2<- AA
2920 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2921 SET_VREG(r1, r2) @ fp[AA]<- r1
2922 GET_INST_OPCODE(ip) @ extract opcode from rINST
2923 GOTO_OPCODE(ip) @ jump to next instruction
2926 /* ------------------------------ */
2928 .L_OP_SGET_BOOLEAN: /* 0x63 */
2929 /* File: armv5te/OP_SGET_BOOLEAN.S */
2930 /* File: armv5te/OP_SGET.S */
2932 * General 32-bit SGET handler.
2934 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2936 /* op vAA, field@BBBB */
2937 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2938 FETCH(r1, 1) @ r1<- field ref BBBB
2939 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2940 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2941 cmp r0, #0 @ is resolved entry null?
2942 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2943 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2944 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2945 mov r2, rINST, lsr #8 @ r2<- AA
2946 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2947 SET_VREG(r1, r2) @ fp[AA]<- r1
2948 GET_INST_OPCODE(ip) @ extract opcode from rINST
2949 GOTO_OPCODE(ip) @ jump to next instruction
2952 /* ------------------------------ */
2954 .L_OP_SGET_BYTE: /* 0x64 */
2955 /* File: armv5te/OP_SGET_BYTE.S */
2956 /* File: armv5te/OP_SGET.S */
2958 * General 32-bit SGET handler.
2960 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2962 /* op vAA, field@BBBB */
2963 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2964 FETCH(r1, 1) @ r1<- field ref BBBB
2965 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2966 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2967 cmp r0, #0 @ is resolved entry null?
2968 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2969 .LOP_SGET_BYTE_finish: @ field ptr in r0
2970 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2971 mov r2, rINST, lsr #8 @ r2<- AA
2972 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2973 SET_VREG(r1, r2) @ fp[AA]<- r1
2974 GET_INST_OPCODE(ip) @ extract opcode from rINST
2975 GOTO_OPCODE(ip) @ jump to next instruction
2978 /* ------------------------------ */
2980 .L_OP_SGET_CHAR: /* 0x65 */
2981 /* File: armv5te/OP_SGET_CHAR.S */
2982 /* File: armv5te/OP_SGET.S */
2984 * General 32-bit SGET handler.
2986 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2988 /* op vAA, field@BBBB */
2989 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2990 FETCH(r1, 1) @ r1<- field ref BBBB
2991 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2992 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2993 cmp r0, #0 @ is resolved entry null?
2994 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2995 .LOP_SGET_CHAR_finish: @ field ptr in r0
2996 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2997 mov r2, rINST, lsr #8 @ r2<- AA
2998 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2999 SET_VREG(r1, r2) @ fp[AA]<- r1
3000 GET_INST_OPCODE(ip) @ extract opcode from rINST
3001 GOTO_OPCODE(ip) @ jump to next instruction
3004 /* ------------------------------ */
3006 .L_OP_SGET_SHORT: /* 0x66 */
3007 /* File: armv5te/OP_SGET_SHORT.S */
3008 /* File: armv5te/OP_SGET.S */
3010 * General 32-bit SGET handler.
3012 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3014 /* op vAA, field@BBBB */
3015 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3016 FETCH(r1, 1) @ r1<- field ref BBBB
3017 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3018 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3019 cmp r0, #0 @ is resolved entry null?
3020 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
3021 .LOP_SGET_SHORT_finish: @ field ptr in r0
3022 ldr r1, [r0, #offStaticField_value] @ r1<- field value
3023 mov r2, rINST, lsr #8 @ r2<- AA
3024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3025 SET_VREG(r1, r2) @ fp[AA]<- r1
3026 GET_INST_OPCODE(ip) @ extract opcode from rINST
3027 GOTO_OPCODE(ip) @ jump to next instruction
3030 /* ------------------------------ */
3032 .L_OP_SPUT: /* 0x67 */
3033 /* File: armv5te/OP_SPUT.S */
3035 * General 32-bit SPUT handler.
3037 * for: sput, sput-object, 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_resolve @ yes, do resolve
3046 .LOP_SPUT_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 str r1, [r0, #offStaticField_value] @ field<- vAA
3052 GOTO_OPCODE(ip) @ jump to next instruction
3054 /* ------------------------------ */
3056 .L_OP_SPUT_WIDE: /* 0x68 */
3057 /* File: armv4t/OP_SPUT_WIDE.S */
3059 * 64-bit SPUT handler.
3061 /* sput-wide vAA, field@BBBB */
3062 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3063 FETCH(r1, 1) @ r1<- field ref BBBB
3064 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3065 mov r9, rINST, lsr #8 @ r9<- AA
3066 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3067 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
3068 cmp r0, #0 @ is resolved entry null?
3069 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
3070 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3071 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3072 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
3073 GET_INST_OPCODE(ip) @ extract opcode from rINST
3074 add r0, r0, #offStaticField_value
3075 stmia r0, {r2-r3} @ field<- vAA/vAA+1
3076 GOTO_OPCODE(ip) @ jump to next instruction
3078 /* ------------------------------ */
3080 .L_OP_SPUT_OBJECT: /* 0x69 */
3081 /* File: armv5te/OP_SPUT_OBJECT.S */
3082 /* File: armv5te/OP_SPUT.S */
3084 * General 32-bit SPUT handler.
3086 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3088 /* op vAA, field@BBBB */
3089 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3090 FETCH(r1, 1) @ r1<- field ref BBBB
3091 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3092 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3093 cmp r0, #0 @ is resolved entry null?
3094 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
3095 .LOP_SPUT_OBJECT_finish: @ field ptr in r0
3096 mov r2, rINST, lsr #8 @ r2<- AA
3097 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3098 GET_VREG(r1, r2) @ r1<- fp[AA]
3099 GET_INST_OPCODE(ip) @ extract opcode from rINST
3100 str r1, [r0, #offStaticField_value] @ field<- vAA
3101 GOTO_OPCODE(ip) @ jump to next instruction
3104 /* ------------------------------ */
3106 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3107 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3108 /* File: armv5te/OP_SPUT.S */
3110 * General 32-bit SPUT handler.
3112 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3114 /* op vAA, field@BBBB */
3115 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3116 FETCH(r1, 1) @ r1<- field ref BBBB
3117 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3118 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3119 cmp r0, #0 @ is resolved entry null?
3120 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve
3121 .LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
3122 mov r2, rINST, lsr #8 @ r2<- AA
3123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3124 GET_VREG(r1, r2) @ r1<- fp[AA]
3125 GET_INST_OPCODE(ip) @ extract opcode from rINST
3126 str r1, [r0, #offStaticField_value] @ field<- vAA
3127 GOTO_OPCODE(ip) @ jump to next instruction
3130 /* ------------------------------ */
3132 .L_OP_SPUT_BYTE: /* 0x6b */
3133 /* File: armv5te/OP_SPUT_BYTE.S */
3134 /* File: armv5te/OP_SPUT.S */
3136 * General 32-bit SPUT handler.
3138 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3140 /* op vAA, field@BBBB */
3141 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3142 FETCH(r1, 1) @ r1<- field ref BBBB
3143 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3144 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3145 cmp r0, #0 @ is resolved entry null?
3146 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve
3147 .LOP_SPUT_BYTE_finish: @ field ptr in r0
3148 mov r2, rINST, lsr #8 @ r2<- AA
3149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3150 GET_VREG(r1, r2) @ r1<- fp[AA]
3151 GET_INST_OPCODE(ip) @ extract opcode from rINST
3152 str r1, [r0, #offStaticField_value] @ field<- vAA
3153 GOTO_OPCODE(ip) @ jump to next instruction
3156 /* ------------------------------ */
3158 .L_OP_SPUT_CHAR: /* 0x6c */
3159 /* File: armv5te/OP_SPUT_CHAR.S */
3160 /* File: armv5te/OP_SPUT.S */
3162 * General 32-bit SPUT handler.
3164 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3166 /* op vAA, field@BBBB */
3167 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3168 FETCH(r1, 1) @ r1<- field ref BBBB
3169 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3170 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3171 cmp r0, #0 @ is resolved entry null?
3172 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve
3173 .LOP_SPUT_CHAR_finish: @ field ptr in r0
3174 mov r2, rINST, lsr #8 @ r2<- AA
3175 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3176 GET_VREG(r1, r2) @ r1<- fp[AA]
3177 GET_INST_OPCODE(ip) @ extract opcode from rINST
3178 str r1, [r0, #offStaticField_value] @ field<- vAA
3179 GOTO_OPCODE(ip) @ jump to next instruction
3182 /* ------------------------------ */
3184 .L_OP_SPUT_SHORT: /* 0x6d */
3185 /* File: armv5te/OP_SPUT_SHORT.S */
3186 /* File: armv5te/OP_SPUT.S */
3188 * General 32-bit SPUT handler.
3190 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3192 /* op vAA, field@BBBB */
3193 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3194 FETCH(r1, 1) @ r1<- field ref BBBB
3195 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3196 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3197 cmp r0, #0 @ is resolved entry null?
3198 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve
3199 .LOP_SPUT_SHORT_finish: @ field ptr in r0
3200 mov r2, rINST, lsr #8 @ r2<- AA
3201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3202 GET_VREG(r1, r2) @ r1<- fp[AA]
3203 GET_INST_OPCODE(ip) @ extract opcode from rINST
3204 str r1, [r0, #offStaticField_value] @ field<- vAA
3205 GOTO_OPCODE(ip) @ jump to next instruction
3208 /* ------------------------------ */
3210 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3211 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3213 * Handle a virtual method call.
3215 * for: invoke-virtual, invoke-virtual/range
3217 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3218 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3219 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3220 FETCH(r1, 1) @ r1<- BBBB
3221 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3222 FETCH(r10, 2) @ r10<- GFED or CCCC
3223 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3225 and r10, r10, #15 @ r10<- D (or stays CCCC)
3227 cmp r0, #0 @ already resolved?
3228 EXPORT_PC() @ must export for invoke
3229 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3230 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3231 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3232 mov r2, #METHOD_VIRTUAL @ resolver method type
3233 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3234 cmp r0, #0 @ got null?
3235 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3236 b common_exceptionThrown @ yes, handle exception
3238 /* ------------------------------ */
3240 .L_OP_INVOKE_SUPER: /* 0x6f */
3241 /* File: armv5te/OP_INVOKE_SUPER.S */
3243 * Handle a "super" method call.
3245 * for: invoke-super, invoke-super/range
3247 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3248 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3249 FETCH(r10, 2) @ r10<- GFED or CCCC
3250 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3252 and r10, r10, #15 @ r10<- D (or stays CCCC)
3254 FETCH(r1, 1) @ r1<- BBBB
3255 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3256 GET_VREG(r2, r10) @ r2<- "this" ptr
3257 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3258 cmp r2, #0 @ null "this"?
3259 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3260 beq common_errNullObject @ null "this", throw exception
3261 cmp r0, #0 @ already resolved?
3262 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3263 EXPORT_PC() @ must export for invoke
3264 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3265 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3267 /* ------------------------------ */
3269 .L_OP_INVOKE_DIRECT: /* 0x70 */
3270 /* File: armv5te/OP_INVOKE_DIRECT.S */
3272 * Handle a direct method call.
3274 * (We could defer the "is 'this' pointer null" test to the common
3275 * method invocation code, and use a flag to indicate that static
3276 * calls don't count. If we do this as part of copying the arguments
3277 * out we could avoiding loading the first arg twice.)
3279 * for: invoke-direct, invoke-direct/range
3281 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3282 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3283 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3284 FETCH(r1, 1) @ r1<- BBBB
3285 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3286 FETCH(r10, 2) @ r10<- GFED or CCCC
3287 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3289 and r10, r10, #15 @ r10<- D (or stays CCCC)
3291 cmp r0, #0 @ already resolved?
3292 EXPORT_PC() @ must export for invoke
3293 GET_VREG(r2, r10) @ r2<- "this" ptr
3294 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3295 .LOP_INVOKE_DIRECT_finish:
3296 cmp r2, #0 @ null "this" ref?
3297 bne common_invokeMethodNoRange @ no, continue on
3298 b common_errNullObject @ yes, throw exception
3300 /* ------------------------------ */
3302 .L_OP_INVOKE_STATIC: /* 0x71 */
3303 /* File: armv5te/OP_INVOKE_STATIC.S */
3305 * Handle a static method call.
3307 * for: invoke-static, invoke-static/range
3309 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3310 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3311 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3312 FETCH(r1, 1) @ r1<- BBBB
3313 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3314 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3315 cmp r0, #0 @ already resolved?
3316 EXPORT_PC() @ must export for invoke
3317 bne common_invokeMethodNoRange @ yes, continue on
3318 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3319 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3320 mov r2, #METHOD_STATIC @ resolver method type
3321 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3322 cmp r0, #0 @ got null?
3323 bne common_invokeMethodNoRange @ no, continue
3324 b common_exceptionThrown @ yes, handle exception
3327 /* ------------------------------ */
3329 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3330 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3332 * Handle an interface method call.
3334 * for: invoke-interface, invoke-interface/range
3336 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3337 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3338 FETCH(r2, 2) @ r2<- FEDC or CCCC
3339 FETCH(r1, 1) @ r1<- BBBB
3341 and r2, r2, #15 @ r2<- C (or stays CCCC)
3343 EXPORT_PC() @ must export for invoke
3344 GET_VREG(r0, r2) @ r0<- first arg ("this")
3345 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3346 cmp r0, #0 @ null obj?
3347 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3348 beq common_errNullObject @ yes, fail
3349 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3350 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3351 cmp r0, #0 @ failed?
3352 beq common_exceptionThrown @ yes, handle exception
3353 b common_invokeMethodNoRange @ jump to common handler
3356 /* ------------------------------ */
3358 .L_OP_UNUSED_73: /* 0x73 */
3359 /* File: armv5te/OP_UNUSED_73.S */
3360 /* File: armv5te/unused.S */
3365 /* ------------------------------ */
3367 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3368 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3369 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3371 * Handle a virtual method call.
3373 * for: invoke-virtual, invoke-virtual/range
3375 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3376 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3377 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3378 FETCH(r1, 1) @ r1<- BBBB
3379 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3380 FETCH(r10, 2) @ r10<- GFED or CCCC
3381 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3383 and r10, r10, #15 @ r10<- D (or stays CCCC)
3385 cmp r0, #0 @ already resolved?
3386 EXPORT_PC() @ must export for invoke
3387 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3388 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3389 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3390 mov r2, #METHOD_VIRTUAL @ resolver method type
3391 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3392 cmp r0, #0 @ got null?
3393 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3394 b common_exceptionThrown @ yes, handle exception
3397 /* ------------------------------ */
3399 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3400 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3401 /* File: armv5te/OP_INVOKE_SUPER.S */
3403 * Handle a "super" method call.
3405 * for: invoke-super, invoke-super/range
3407 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3408 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3409 FETCH(r10, 2) @ r10<- GFED or CCCC
3410 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3412 and r10, r10, #15 @ r10<- D (or stays CCCC)
3414 FETCH(r1, 1) @ r1<- BBBB
3415 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3416 GET_VREG(r2, r10) @ r2<- "this" ptr
3417 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3418 cmp r2, #0 @ null "this"?
3419 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3420 beq common_errNullObject @ null "this", throw exception
3421 cmp r0, #0 @ already resolved?
3422 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3423 EXPORT_PC() @ must export for invoke
3424 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3425 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3428 /* ------------------------------ */
3430 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3431 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3432 /* File: armv5te/OP_INVOKE_DIRECT.S */
3434 * Handle a direct method call.
3436 * (We could defer the "is 'this' pointer null" test to the common
3437 * method invocation code, and use a flag to indicate that static
3438 * calls don't count. If we do this as part of copying the arguments
3439 * out we could avoiding loading the first arg twice.)
3441 * for: invoke-direct, invoke-direct/range
3443 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3444 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3445 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3446 FETCH(r1, 1) @ r1<- BBBB
3447 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3448 FETCH(r10, 2) @ r10<- GFED or CCCC
3449 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3451 and r10, r10, #15 @ r10<- D (or stays CCCC)
3453 cmp r0, #0 @ already resolved?
3454 EXPORT_PC() @ must export for invoke
3455 GET_VREG(r2, r10) @ r2<- "this" ptr
3456 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3457 .LOP_INVOKE_DIRECT_RANGE_finish:
3458 cmp r2, #0 @ null "this" ref?
3459 bne common_invokeMethodRange @ no, continue on
3460 b common_errNullObject @ yes, throw exception
3463 /* ------------------------------ */
3465 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3466 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3467 /* File: armv5te/OP_INVOKE_STATIC.S */
3469 * Handle a static method call.
3471 * for: invoke-static, invoke-static/range
3473 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3474 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3475 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3476 FETCH(r1, 1) @ r1<- BBBB
3477 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3478 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3479 cmp r0, #0 @ already resolved?
3480 EXPORT_PC() @ must export for invoke
3481 bne common_invokeMethodRange @ yes, continue on
3482 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3483 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3484 mov r2, #METHOD_STATIC @ resolver method type
3485 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3486 cmp r0, #0 @ got null?
3487 bne common_invokeMethodRange @ no, continue
3488 b common_exceptionThrown @ yes, handle exception
3492 /* ------------------------------ */
3494 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3495 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3496 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3498 * Handle an interface method call.
3500 * for: invoke-interface, invoke-interface/range
3502 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3503 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3504 FETCH(r2, 2) @ r2<- FEDC or CCCC
3505 FETCH(r1, 1) @ r1<- BBBB
3507 and r2, r2, #15 @ r2<- C (or stays CCCC)
3509 EXPORT_PC() @ must export for invoke
3510 GET_VREG(r0, r2) @ r0<- first arg ("this")
3511 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3512 cmp r0, #0 @ null obj?
3513 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3514 beq common_errNullObject @ yes, fail
3515 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3516 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3517 cmp r0, #0 @ failed?
3518 beq common_exceptionThrown @ yes, handle exception
3519 b common_invokeMethodRange @ jump to common handler
3523 /* ------------------------------ */
3525 .L_OP_UNUSED_79: /* 0x79 */
3526 /* File: armv5te/OP_UNUSED_79.S */
3527 /* File: armv5te/unused.S */
3532 /* ------------------------------ */
3534 .L_OP_UNUSED_7A: /* 0x7a */
3535 /* File: armv5te/OP_UNUSED_7A.S */
3536 /* File: armv5te/unused.S */
3541 /* ------------------------------ */
3543 .L_OP_NEG_INT: /* 0x7b */
3544 /* File: armv5te/OP_NEG_INT.S */
3545 /* File: armv5te/unop.S */
3547 * Generic 32-bit unary operation. Provide an "instr" line that
3548 * specifies an instruction that performs "result = op r0".
3549 * This could be an ARM instruction or a function call.
3551 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3552 * int-to-byte, int-to-char, int-to-short
3555 mov r3, rINST, lsr #12 @ r3<- B
3556 mov r9, rINST, lsr #8 @ r9<- A+
3557 GET_VREG(r0, r3) @ r0<- vB
3559 @ optional op; may set condition codes
3560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3561 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3562 GET_INST_OPCODE(ip) @ extract opcode from rINST
3563 SET_VREG(r0, r9) @ vAA<- r0
3564 GOTO_OPCODE(ip) @ jump to next instruction
3565 /* 9-10 instructions */
3568 /* ------------------------------ */
3570 .L_OP_NOT_INT: /* 0x7c */
3571 /* File: armv5te/OP_NOT_INT.S */
3572 /* File: armv5te/unop.S */
3574 * Generic 32-bit unary operation. Provide an "instr" line that
3575 * specifies an instruction that performs "result = op r0".
3576 * This could be an ARM instruction or a function call.
3578 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3579 * int-to-byte, int-to-char, int-to-short
3582 mov r3, rINST, lsr #12 @ r3<- B
3583 mov r9, rINST, lsr #8 @ r9<- A+
3584 GET_VREG(r0, r3) @ r0<- vB
3586 @ optional op; may set condition codes
3587 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3588 mvn r0, r0 @ r0<- op, r0-r3 changed
3589 GET_INST_OPCODE(ip) @ extract opcode from rINST
3590 SET_VREG(r0, r9) @ vAA<- r0
3591 GOTO_OPCODE(ip) @ jump to next instruction
3592 /* 9-10 instructions */
3595 /* ------------------------------ */
3597 .L_OP_NEG_LONG: /* 0x7d */
3598 /* File: armv5te/OP_NEG_LONG.S */
3599 /* File: armv5te/unopWide.S */
3601 * Generic 64-bit unary operation. Provide an "instr" line that
3602 * specifies an instruction that performs "result = op r0/r1".
3603 * This could be an ARM instruction or a function call.
3605 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3608 mov r9, rINST, lsr #8 @ r9<- A+
3609 mov r3, rINST, lsr #12 @ r3<- B
3611 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3612 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3613 ldmia r3, {r0-r1} @ r0/r1<- vAA
3614 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3615 rsbs r0, r0, #0 @ optional op; may set condition codes
3616 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3617 GET_INST_OPCODE(ip) @ extract opcode from rINST
3618 stmia r9, {r0-r1} @ vAA<- r0/r1
3619 GOTO_OPCODE(ip) @ jump to next instruction
3620 /* 12-13 instructions */
3624 /* ------------------------------ */
3626 .L_OP_NOT_LONG: /* 0x7e */
3627 /* File: armv5te/OP_NOT_LONG.S */
3628 /* File: armv5te/unopWide.S */
3630 * Generic 64-bit unary operation. Provide an "instr" line that
3631 * specifies an instruction that performs "result = op r0/r1".
3632 * This could be an ARM instruction or a function call.
3634 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3637 mov r9, rINST, lsr #8 @ r9<- A+
3638 mov r3, rINST, lsr #12 @ r3<- B
3640 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3641 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3642 ldmia r3, {r0-r1} @ r0/r1<- vAA
3643 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3644 mvn r0, r0 @ optional op; may set condition codes
3645 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3646 GET_INST_OPCODE(ip) @ extract opcode from rINST
3647 stmia r9, {r0-r1} @ vAA<- r0/r1
3648 GOTO_OPCODE(ip) @ jump to next instruction
3649 /* 12-13 instructions */
3653 /* ------------------------------ */
3655 .L_OP_NEG_FLOAT: /* 0x7f */
3656 /* File: armv5te/OP_NEG_FLOAT.S */
3657 /* File: armv5te/unop.S */
3659 * Generic 32-bit unary operation. Provide an "instr" line that
3660 * specifies an instruction that performs "result = op r0".
3661 * This could be an ARM instruction or a function call.
3663 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3664 * int-to-byte, int-to-char, int-to-short
3667 mov r3, rINST, lsr #12 @ r3<- B
3668 mov r9, rINST, lsr #8 @ r9<- A+
3669 GET_VREG(r0, r3) @ r0<- vB
3671 @ optional op; may set condition codes
3672 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3673 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3674 GET_INST_OPCODE(ip) @ extract opcode from rINST
3675 SET_VREG(r0, r9) @ vAA<- r0
3676 GOTO_OPCODE(ip) @ jump to next instruction
3677 /* 9-10 instructions */
3680 /* ------------------------------ */
3682 .L_OP_NEG_DOUBLE: /* 0x80 */
3683 /* File: armv5te/OP_NEG_DOUBLE.S */
3684 /* File: armv5te/unopWide.S */
3686 * Generic 64-bit unary operation. Provide an "instr" line that
3687 * specifies an instruction that performs "result = op r0/r1".
3688 * This could be an ARM instruction or a function call.
3690 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3693 mov r9, rINST, lsr #8 @ r9<- A+
3694 mov r3, rINST, lsr #12 @ r3<- B
3696 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3697 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3698 ldmia r3, {r0-r1} @ r0/r1<- vAA
3699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3700 @ optional op; may set condition codes
3701 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed
3702 GET_INST_OPCODE(ip) @ extract opcode from rINST
3703 stmia r9, {r0-r1} @ vAA<- r0/r1
3704 GOTO_OPCODE(ip) @ jump to next instruction
3705 /* 12-13 instructions */
3709 /* ------------------------------ */
3711 .L_OP_INT_TO_LONG: /* 0x81 */
3712 /* File: armv5te/OP_INT_TO_LONG.S */
3713 /* File: armv5te/unopWider.S */
3715 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3716 * that specifies an instruction that performs "result = op r0", where
3717 * "result" is a 64-bit quantity in r0/r1.
3719 * For: int-to-long, int-to-double, float-to-long, float-to-double
3722 mov r9, rINST, lsr #8 @ r9<- A+
3723 mov r3, rINST, lsr #12 @ r3<- B
3725 GET_VREG(r0, r3) @ r0<- vB
3726 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3727 @ optional op; may set condition codes
3728 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3729 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3730 GET_INST_OPCODE(ip) @ extract opcode from rINST
3731 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3732 GOTO_OPCODE(ip) @ jump to next instruction
3733 /* 10-11 instructions */
3736 /* ------------------------------ */
3738 .L_OP_INT_TO_FLOAT: /* 0x82 */
3739 /* File: armv5te/OP_INT_TO_FLOAT.S */
3740 /* File: armv5te/unop.S */
3742 * Generic 32-bit unary operation. Provide an "instr" line that
3743 * specifies an instruction that performs "result = op r0".
3744 * This could be an ARM instruction or a function call.
3746 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3747 * int-to-byte, int-to-char, int-to-short
3750 mov r3, rINST, lsr #12 @ r3<- B
3751 mov r9, rINST, lsr #8 @ r9<- A+
3752 GET_VREG(r0, r3) @ r0<- vB
3754 @ optional op; may set condition codes
3755 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3756 bl __aeabi_i2f @ r0<- op, r0-r3 changed
3757 GET_INST_OPCODE(ip) @ extract opcode from rINST
3758 SET_VREG(r0, r9) @ vAA<- r0
3759 GOTO_OPCODE(ip) @ jump to next instruction
3760 /* 9-10 instructions */
3763 /* ------------------------------ */
3765 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3766 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3767 /* File: armv5te/unopWider.S */
3769 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3770 * that specifies an instruction that performs "result = op r0", where
3771 * "result" is a 64-bit quantity in r0/r1.
3773 * For: int-to-long, int-to-double, float-to-long, float-to-double
3776 mov r9, rINST, lsr #8 @ r9<- A+
3777 mov r3, rINST, lsr #12 @ r3<- B
3779 GET_VREG(r0, r3) @ r0<- vB
3780 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3781 @ optional op; may set condition codes
3782 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3783 bl __aeabi_i2d @ r0<- op, r0-r3 changed
3784 GET_INST_OPCODE(ip) @ extract opcode from rINST
3785 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3786 GOTO_OPCODE(ip) @ jump to next instruction
3787 /* 10-11 instructions */
3790 /* ------------------------------ */
3792 .L_OP_LONG_TO_INT: /* 0x84 */
3793 /* File: armv5te/OP_LONG_TO_INT.S */
3794 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3795 /* File: armv5te/OP_MOVE.S */
3796 /* for move, move-object, long-to-int */
3798 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3799 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3800 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3801 GET_VREG(r2, r1) @ r2<- fp[B]
3803 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3804 SET_VREG(r2, r0) @ fp[A]<- r2
3805 GOTO_OPCODE(ip) @ execute next instruction
3809 /* ------------------------------ */
3811 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3812 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3813 /* File: armv5te/unopNarrower.S */
3815 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3816 * that specifies an instruction that performs "result = op r0/r1", where
3817 * "result" is a 32-bit quantity in r0.
3819 * For: long-to-float, double-to-int, double-to-float
3821 * (This would work for long-to-int, but that instruction is actually
3822 * an exact match for OP_MOVE.)
3825 mov r3, rINST, lsr #12 @ r3<- B
3826 mov r9, rINST, lsr #8 @ r9<- A+
3827 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3829 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3830 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3831 @ optional op; may set condition codes
3832 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3833 GET_INST_OPCODE(ip) @ extract opcode from rINST
3834 SET_VREG(r0, r9) @ vA<- r0
3835 GOTO_OPCODE(ip) @ jump to next instruction
3836 /* 10-11 instructions */
3839 /* ------------------------------ */
3841 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3842 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3843 /* File: armv5te/unopWide.S */
3845 * Generic 64-bit unary operation. Provide an "instr" line that
3846 * specifies an instruction that performs "result = op r0/r1".
3847 * This could be an ARM instruction or a function call.
3849 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3852 mov r9, rINST, lsr #8 @ r9<- A+
3853 mov r3, rINST, lsr #12 @ r3<- B
3855 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3856 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3857 ldmia r3, {r0-r1} @ r0/r1<- vAA
3858 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3859 @ optional op; may set condition codes
3860 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3861 GET_INST_OPCODE(ip) @ extract opcode from rINST
3862 stmia r9, {r0-r1} @ vAA<- r0/r1
3863 GOTO_OPCODE(ip) @ jump to next instruction
3864 /* 12-13 instructions */
3868 /* ------------------------------ */
3870 .L_OP_FLOAT_TO_INT: /* 0x87 */
3871 /* File: armv5te/OP_FLOAT_TO_INT.S */
3872 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3873 /* File: armv5te/unop.S */
3875 * Generic 32-bit unary operation. Provide an "instr" line that
3876 * specifies an instruction that performs "result = op r0".
3877 * This could be an ARM instruction or a function call.
3879 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3880 * int-to-byte, int-to-char, int-to-short
3883 mov r3, rINST, lsr #12 @ r3<- B
3884 mov r9, rINST, lsr #8 @ r9<- A+
3885 GET_VREG(r0, r3) @ r0<- vB
3887 @ optional op; may set condition codes
3888 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3889 bl __aeabi_f2iz @ r0<- op, r0-r3 changed
3890 GET_INST_OPCODE(ip) @ extract opcode from rINST
3891 SET_VREG(r0, r9) @ vAA<- r0
3892 GOTO_OPCODE(ip) @ jump to next instruction
3893 /* 9-10 instructions */
3897 @include "armv5te/unop.S" {"instr":"bl f2i_doconv"}
3900 * Convert the float in r0 to an int in r0.
3902 * We have to clip values to int min/max per the specification. The
3903 * expected common case is a "reasonable" value that converts directly
3904 * to modest integer. The EABI convert function isn't doing this for us.
3908 mov r1, #0x4f000000 @ (float)maxint
3910 bl __aeabi_fcmpge @ is arg >= maxint?
3911 cmp r0, #0 @ nonzero == yes
3912 mvnne r0, #0x80000000 @ return maxint (7fffffff)
3913 ldmnefd sp!, {r4, pc}
3915 mov r0, r4 @ recover arg
3916 mov r1, #0xcf000000 @ (float)minint
3917 bl __aeabi_fcmple @ is arg <= minint?
3918 cmp r0, #0 @ nonzero == yes
3919 movne r0, #0x80000000 @ return minint (80000000)
3920 ldmnefd sp!, {r4, pc}
3922 mov r0, r4 @ recover arg
3924 bl __aeabi_fcmpeq @ is arg == self?
3925 cmp r0, #0 @ zero == no
3926 ldmeqfd sp!, {r4, pc} @ return zero for NaN
3928 mov r0, r4 @ recover arg
3929 bl __aeabi_f2iz @ convert float to int
3934 /* ------------------------------ */
3936 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3937 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3938 @include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3939 /* File: armv5te/unopWider.S */
3941 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3942 * that specifies an instruction that performs "result = op r0", where
3943 * "result" is a 64-bit quantity in r0/r1.
3945 * For: int-to-long, int-to-double, float-to-long, float-to-double
3948 mov r9, rINST, lsr #8 @ r9<- A+
3949 mov r3, rINST, lsr #12 @ r3<- B
3951 GET_VREG(r0, r3) @ r0<- vB
3952 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3953 @ optional op; may set condition codes
3954 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3955 bl f2l_doconv @ r0<- op, r0-r3 changed
3956 GET_INST_OPCODE(ip) @ extract opcode from rINST
3957 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3958 GOTO_OPCODE(ip) @ jump to next instruction
3959 /* 10-11 instructions */
3963 /* ------------------------------ */
3965 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3966 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3967 /* File: armv5te/unopWider.S */
3969 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3970 * that specifies an instruction that performs "result = op r0", where
3971 * "result" is a 64-bit quantity in r0/r1.
3973 * For: int-to-long, int-to-double, float-to-long, float-to-double
3976 mov r9, rINST, lsr #8 @ r9<- A+
3977 mov r3, rINST, lsr #12 @ r3<- B
3979 GET_VREG(r0, r3) @ r0<- vB
3980 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3981 @ optional op; may set condition codes
3982 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3983 bl __aeabi_f2d @ r0<- op, r0-r3 changed
3984 GET_INST_OPCODE(ip) @ extract opcode from rINST
3985 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3986 GOTO_OPCODE(ip) @ jump to next instruction
3987 /* 10-11 instructions */
3990 /* ------------------------------ */
3992 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3993 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3994 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3995 /* File: armv5te/unopNarrower.S */
3997 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3998 * that specifies an instruction that performs "result = op r0/r1", where
3999 * "result" is a 32-bit quantity in r0.
4001 * For: long-to-float, double-to-int, double-to-float
4003 * (This would work for long-to-int, but that instruction is actually
4004 * an exact match for OP_MOVE.)
4007 mov r3, rINST, lsr #12 @ r3<- B
4008 mov r9, rINST, lsr #8 @ r9<- A+
4009 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4011 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
4012 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4013 @ optional op; may set condition codes
4014 bl __aeabi_d2iz @ r0<- op, r0-r3 changed
4015 GET_INST_OPCODE(ip) @ extract opcode from rINST
4016 SET_VREG(r0, r9) @ vA<- r0
4017 GOTO_OPCODE(ip) @ jump to next instruction
4018 /* 10-11 instructions */
4022 @include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"}
4025 * Convert the double in r0/r1 to an int in r0.
4027 * We have to clip values to int min/max per the specification. The
4028 * expected common case is a "reasonable" value that converts directly
4029 * to modest integer. The EABI convert function isn't doing this for us.
4032 stmfd sp!, {r4, r5, lr} @ save regs
4033 mov r2, #0x80000000 @ maxint, as a double (low word)
4034 mov r2, r2, asr #9 @ 0xffc00000
4035 sub sp, sp, #4 @ align for EABI
4036 mvn r3, #0xbe000000 @ maxint, as a double (high word)
4037 sub r3, r3, #0x00200000 @ 0x41dfffff
4038 mov r4, r0 @ save a copy of r0
4040 bl __aeabi_dcmpge @ is arg >= maxint?
4041 cmp r0, #0 @ nonzero == yes
4042 mvnne r0, #0x80000000 @ return maxint (0x7fffffff)
4045 mov r0, r4 @ recover arg
4047 mov r3, #0xc1000000 @ minint, as a double (high word)
4048 add r3, r3, #0x00e00000 @ 0xc1e00000
4049 mov r2, #0 @ minint, as a double (low word)
4050 bl __aeabi_dcmple @ is arg <= minint?
4051 cmp r0, #0 @ nonzero == yes
4052 movne r0, #0x80000000 @ return minint (80000000)
4055 mov r0, r4 @ recover arg
4057 mov r2, r4 @ compare against self
4059 bl __aeabi_dcmpeq @ is arg == self?
4060 cmp r0, #0 @ zero == no
4061 beq 1f @ return zero for NaN
4063 mov r0, r4 @ recover arg
4065 bl __aeabi_d2iz @ convert double to int
4069 ldmfd sp!, {r4, r5, pc}
4073 /* ------------------------------ */
4075 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
4076 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
4077 @include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"}
4078 /* File: armv5te/unopWide.S */
4080 * Generic 64-bit unary operation. Provide an "instr" line that
4081 * specifies an instruction that performs "result = op r0/r1".
4082 * This could be an ARM instruction or a function call.
4084 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4087 mov r9, rINST, lsr #8 @ r9<- A+
4088 mov r3, rINST, lsr #12 @ r3<- B
4090 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4091 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
4092 ldmia r3, {r0-r1} @ r0/r1<- vAA
4093 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4094 @ optional op; may set condition codes
4095 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
4096 GET_INST_OPCODE(ip) @ extract opcode from rINST
4097 stmia r9, {r0-r1} @ vAA<- r0/r1
4098 GOTO_OPCODE(ip) @ jump to next instruction
4099 /* 12-13 instructions */
4104 /* ------------------------------ */
4106 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4107 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4108 /* File: armv5te/unopNarrower.S */
4110 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
4111 * that specifies an instruction that performs "result = op r0/r1", where
4112 * "result" is a 32-bit quantity in r0.
4114 * For: long-to-float, double-to-int, double-to-float
4116 * (This would work for long-to-int, but that instruction is actually
4117 * an exact match for OP_MOVE.)
4120 mov r3, rINST, lsr #12 @ r3<- B
4121 mov r9, rINST, lsr #8 @ r9<- A+
4122 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
4124 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
4125 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4126 @ optional op; may set condition codes
4127 bl __aeabi_d2f @ r0<- op, r0-r3 changed
4128 GET_INST_OPCODE(ip) @ extract opcode from rINST
4129 SET_VREG(r0, r9) @ vA<- r0
4130 GOTO_OPCODE(ip) @ jump to next instruction
4131 /* 10-11 instructions */
4134 /* ------------------------------ */
4136 .L_OP_INT_TO_BYTE: /* 0x8d */
4137 /* File: armv5te/OP_INT_TO_BYTE.S */
4138 /* File: armv5te/unop.S */
4140 * Generic 32-bit unary operation. Provide an "instr" line that
4141 * specifies an instruction that performs "result = op r0".
4142 * This could be an ARM instruction or a function call.
4144 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4145 * int-to-byte, int-to-char, int-to-short
4148 mov r3, rINST, lsr #12 @ r3<- B
4149 mov r9, rINST, lsr #8 @ r9<- A+
4150 GET_VREG(r0, r3) @ r0<- vB
4152 mov r0, r0, asl #24 @ optional op; may set condition codes
4153 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4154 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed
4155 GET_INST_OPCODE(ip) @ extract opcode from rINST
4156 SET_VREG(r0, r9) @ vAA<- r0
4157 GOTO_OPCODE(ip) @ jump to next instruction
4158 /* 9-10 instructions */
4161 /* ------------------------------ */
4163 .L_OP_INT_TO_CHAR: /* 0x8e */
4164 /* File: armv5te/OP_INT_TO_CHAR.S */
4165 /* File: armv5te/unop.S */
4167 * Generic 32-bit unary operation. Provide an "instr" line that
4168 * specifies an instruction that performs "result = op r0".
4169 * This could be an ARM instruction or a function call.
4171 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4172 * int-to-byte, int-to-char, int-to-short
4175 mov r3, rINST, lsr #12 @ r3<- B
4176 mov r9, rINST, lsr #8 @ r9<- A+
4177 GET_VREG(r0, r3) @ r0<- vB
4179 mov r0, r0, asl #16 @ optional op; may set condition codes
4180 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4181 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed
4182 GET_INST_OPCODE(ip) @ extract opcode from rINST
4183 SET_VREG(r0, r9) @ vAA<- r0
4184 GOTO_OPCODE(ip) @ jump to next instruction
4185 /* 9-10 instructions */
4188 /* ------------------------------ */
4190 .L_OP_INT_TO_SHORT: /* 0x8f */
4191 /* File: armv5te/OP_INT_TO_SHORT.S */
4192 /* File: armv5te/unop.S */
4194 * Generic 32-bit unary operation. Provide an "instr" line that
4195 * specifies an instruction that performs "result = op r0".
4196 * This could be an ARM instruction or a function call.
4198 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4199 * int-to-byte, int-to-char, int-to-short
4202 mov r3, rINST, lsr #12 @ r3<- B
4203 mov r9, rINST, lsr #8 @ r9<- A+
4204 GET_VREG(r0, r3) @ r0<- vB
4206 mov r0, r0, asl #16 @ optional op; may set condition codes
4207 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4208 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed
4209 GET_INST_OPCODE(ip) @ extract opcode from rINST
4210 SET_VREG(r0, r9) @ vAA<- r0
4211 GOTO_OPCODE(ip) @ jump to next instruction
4212 /* 9-10 instructions */
4215 /* ------------------------------ */
4217 .L_OP_ADD_INT: /* 0x90 */
4218 /* File: armv5te/OP_ADD_INT.S */
4219 /* File: armv5te/binop.S */
4221 * Generic 32-bit binary operation. Provide an "instr" line that
4222 * specifies an instruction that performs "result = r0 op r1".
4223 * This could be an ARM instruction or a function call. (If the result
4224 * comes back in a register other than r0, you can override "result".)
4226 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4227 * vCC (r1). Useful for integer division and modulus. Note that we
4228 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4229 * handles it correctly.
4231 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4232 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4233 * mul-float, div-float, rem-float
4235 /* binop vAA, vBB, vCC */
4236 FETCH(r0, 1) @ r0<- CCBB
4237 mov r9, rINST, lsr #8 @ r9<- AA
4238 mov r3, r0, lsr #8 @ r3<- CC
4239 and r2, r0, #255 @ r2<- BB
4240 GET_VREG(r1, r3) @ r1<- vCC
4241 GET_VREG(r0, r2) @ r0<- vBB
4243 cmp r1, #0 @ is second operand zero?
4244 beq common_errDivideByZero
4247 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4248 @ optional op; may set condition codes
4249 add r0, r0, r1 @ r0<- op, r0-r3 changed
4250 GET_INST_OPCODE(ip) @ extract opcode from rINST
4251 SET_VREG(r0, r9) @ vAA<- r0
4252 GOTO_OPCODE(ip) @ jump to next instruction
4253 /* 11-14 instructions */
4257 /* ------------------------------ */
4259 .L_OP_SUB_INT: /* 0x91 */
4260 /* File: armv5te/OP_SUB_INT.S */
4261 /* File: armv5te/binop.S */
4263 * Generic 32-bit binary operation. Provide an "instr" line that
4264 * specifies an instruction that performs "result = r0 op r1".
4265 * This could be an ARM instruction or a function call. (If the result
4266 * comes back in a register other than r0, you can override "result".)
4268 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4269 * vCC (r1). Useful for integer division and modulus. Note that we
4270 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4271 * handles it correctly.
4273 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4274 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4275 * mul-float, div-float, rem-float
4277 /* binop vAA, vBB, vCC */
4278 FETCH(r0, 1) @ r0<- CCBB
4279 mov r9, rINST, lsr #8 @ r9<- AA
4280 mov r3, r0, lsr #8 @ r3<- CC
4281 and r2, r0, #255 @ r2<- BB
4282 GET_VREG(r1, r3) @ r1<- vCC
4283 GET_VREG(r0, r2) @ r0<- vBB
4285 cmp r1, #0 @ is second operand zero?
4286 beq common_errDivideByZero
4289 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4290 @ optional op; may set condition codes
4291 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4292 GET_INST_OPCODE(ip) @ extract opcode from rINST
4293 SET_VREG(r0, r9) @ vAA<- r0
4294 GOTO_OPCODE(ip) @ jump to next instruction
4295 /* 11-14 instructions */
4299 /* ------------------------------ */
4301 .L_OP_MUL_INT: /* 0x92 */
4302 /* File: armv5te/OP_MUL_INT.S */
4303 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4304 /* File: armv5te/binop.S */
4306 * Generic 32-bit binary operation. Provide an "instr" line that
4307 * specifies an instruction that performs "result = r0 op r1".
4308 * This could be an ARM instruction or a function call. (If the result
4309 * comes back in a register other than r0, you can override "result".)
4311 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4312 * vCC (r1). Useful for integer division and modulus. Note that we
4313 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4314 * handles it correctly.
4316 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4317 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4318 * mul-float, div-float, rem-float
4320 /* binop vAA, vBB, vCC */
4321 FETCH(r0, 1) @ r0<- CCBB
4322 mov r9, rINST, lsr #8 @ r9<- AA
4323 mov r3, r0, lsr #8 @ r3<- CC
4324 and r2, r0, #255 @ r2<- BB
4325 GET_VREG(r1, r3) @ r1<- vCC
4326 GET_VREG(r0, r2) @ r0<- vBB
4328 cmp r1, #0 @ is second operand zero?
4329 beq common_errDivideByZero
4332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4333 @ optional op; may set condition codes
4334 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4335 GET_INST_OPCODE(ip) @ extract opcode from rINST
4336 SET_VREG(r0, r9) @ vAA<- r0
4337 GOTO_OPCODE(ip) @ jump to next instruction
4338 /* 11-14 instructions */
4342 /* ------------------------------ */
4344 .L_OP_DIV_INT: /* 0x93 */
4345 /* File: armv5te/OP_DIV_INT.S */
4346 /* File: armv5te/binop.S */
4348 * Generic 32-bit binary operation. Provide an "instr" line that
4349 * specifies an instruction that performs "result = r0 op r1".
4350 * This could be an ARM instruction or a function call. (If the result
4351 * comes back in a register other than r0, you can override "result".)
4353 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4354 * vCC (r1). Useful for integer division and modulus. Note that we
4355 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4356 * handles it correctly.
4358 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4359 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4360 * mul-float, div-float, rem-float
4362 /* binop vAA, vBB, vCC */
4363 FETCH(r0, 1) @ r0<- CCBB
4364 mov r9, rINST, lsr #8 @ r9<- AA
4365 mov r3, r0, lsr #8 @ r3<- CC
4366 and r2, r0, #255 @ r2<- BB
4367 GET_VREG(r1, r3) @ r1<- vCC
4368 GET_VREG(r0, r2) @ r0<- vBB
4370 cmp r1, #0 @ is second operand zero?
4371 beq common_errDivideByZero
4374 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4375 @ optional op; may set condition codes
4376 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4377 GET_INST_OPCODE(ip) @ extract opcode from rINST
4378 SET_VREG(r0, r9) @ vAA<- r0
4379 GOTO_OPCODE(ip) @ jump to next instruction
4380 /* 11-14 instructions */
4384 /* ------------------------------ */
4386 .L_OP_REM_INT: /* 0x94 */
4387 /* File: armv5te/OP_REM_INT.S */
4388 /* idivmod returns quotient in r0 and remainder in r1 */
4389 /* File: armv5te/binop.S */
4391 * Generic 32-bit binary operation. Provide an "instr" line that
4392 * specifies an instruction that performs "result = r0 op r1".
4393 * This could be an ARM instruction or a function call. (If the result
4394 * comes back in a register other than r0, you can override "result".)
4396 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4397 * vCC (r1). Useful for integer division and modulus. Note that we
4398 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4399 * handles it correctly.
4401 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4402 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4403 * mul-float, div-float, rem-float
4405 /* binop vAA, vBB, vCC */
4406 FETCH(r0, 1) @ r0<- CCBB
4407 mov r9, rINST, lsr #8 @ r9<- AA
4408 mov r3, r0, lsr #8 @ r3<- CC
4409 and r2, r0, #255 @ r2<- BB
4410 GET_VREG(r1, r3) @ r1<- vCC
4411 GET_VREG(r0, r2) @ r0<- vBB
4413 cmp r1, #0 @ is second operand zero?
4414 beq common_errDivideByZero
4417 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4418 @ optional op; may set condition codes
4419 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4420 GET_INST_OPCODE(ip) @ extract opcode from rINST
4421 SET_VREG(r1, r9) @ vAA<- r1
4422 GOTO_OPCODE(ip) @ jump to next instruction
4423 /* 11-14 instructions */
4427 /* ------------------------------ */
4429 .L_OP_AND_INT: /* 0x95 */
4430 /* File: armv5te/OP_AND_INT.S */
4431 /* File: armv5te/binop.S */
4433 * Generic 32-bit binary operation. Provide an "instr" line that
4434 * specifies an instruction that performs "result = r0 op r1".
4435 * This could be an ARM instruction or a function call. (If the result
4436 * comes back in a register other than r0, you can override "result".)
4438 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4439 * vCC (r1). Useful for integer division and modulus. Note that we
4440 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4441 * handles it correctly.
4443 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4444 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4445 * mul-float, div-float, rem-float
4447 /* binop vAA, vBB, vCC */
4448 FETCH(r0, 1) @ r0<- CCBB
4449 mov r9, rINST, lsr #8 @ r9<- AA
4450 mov r3, r0, lsr #8 @ r3<- CC
4451 and r2, r0, #255 @ r2<- BB
4452 GET_VREG(r1, r3) @ r1<- vCC
4453 GET_VREG(r0, r2) @ r0<- vBB
4455 cmp r1, #0 @ is second operand zero?
4456 beq common_errDivideByZero
4459 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4460 @ optional op; may set condition codes
4461 and r0, r0, r1 @ r0<- op, r0-r3 changed
4462 GET_INST_OPCODE(ip) @ extract opcode from rINST
4463 SET_VREG(r0, r9) @ vAA<- r0
4464 GOTO_OPCODE(ip) @ jump to next instruction
4465 /* 11-14 instructions */
4469 /* ------------------------------ */
4471 .L_OP_OR_INT: /* 0x96 */
4472 /* File: armv5te/OP_OR_INT.S */
4473 /* File: armv5te/binop.S */
4475 * Generic 32-bit binary operation. Provide an "instr" line that
4476 * specifies an instruction that performs "result = r0 op r1".
4477 * This could be an ARM instruction or a function call. (If the result
4478 * comes back in a register other than r0, you can override "result".)
4480 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4481 * vCC (r1). Useful for integer division and modulus. Note that we
4482 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4483 * handles it correctly.
4485 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4486 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4487 * mul-float, div-float, rem-float
4489 /* binop vAA, vBB, vCC */
4490 FETCH(r0, 1) @ r0<- CCBB
4491 mov r9, rINST, lsr #8 @ r9<- AA
4492 mov r3, r0, lsr #8 @ r3<- CC
4493 and r2, r0, #255 @ r2<- BB
4494 GET_VREG(r1, r3) @ r1<- vCC
4495 GET_VREG(r0, r2) @ r0<- vBB
4497 cmp r1, #0 @ is second operand zero?
4498 beq common_errDivideByZero
4501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4502 @ optional op; may set condition codes
4503 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4504 GET_INST_OPCODE(ip) @ extract opcode from rINST
4505 SET_VREG(r0, r9) @ vAA<- r0
4506 GOTO_OPCODE(ip) @ jump to next instruction
4507 /* 11-14 instructions */
4511 /* ------------------------------ */
4513 .L_OP_XOR_INT: /* 0x97 */
4514 /* File: armv5te/OP_XOR_INT.S */
4515 /* File: armv5te/binop.S */
4517 * Generic 32-bit binary operation. Provide an "instr" line that
4518 * specifies an instruction that performs "result = r0 op r1".
4519 * This could be an ARM instruction or a function call. (If the result
4520 * comes back in a register other than r0, you can override "result".)
4522 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4523 * vCC (r1). Useful for integer division and modulus. Note that we
4524 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4525 * handles it correctly.
4527 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4528 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4529 * mul-float, div-float, rem-float
4531 /* binop vAA, vBB, vCC */
4532 FETCH(r0, 1) @ r0<- CCBB
4533 mov r9, rINST, lsr #8 @ r9<- AA
4534 mov r3, r0, lsr #8 @ r3<- CC
4535 and r2, r0, #255 @ r2<- BB
4536 GET_VREG(r1, r3) @ r1<- vCC
4537 GET_VREG(r0, r2) @ r0<- vBB
4539 cmp r1, #0 @ is second operand zero?
4540 beq common_errDivideByZero
4543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4544 @ optional op; may set condition codes
4545 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4546 GET_INST_OPCODE(ip) @ extract opcode from rINST
4547 SET_VREG(r0, r9) @ vAA<- r0
4548 GOTO_OPCODE(ip) @ jump to next instruction
4549 /* 11-14 instructions */
4553 /* ------------------------------ */
4555 .L_OP_SHL_INT: /* 0x98 */
4556 /* File: armv5te/OP_SHL_INT.S */
4557 /* File: armv5te/binop.S */
4559 * Generic 32-bit binary operation. Provide an "instr" line that
4560 * specifies an instruction that performs "result = r0 op r1".
4561 * This could be an ARM instruction or a function call. (If the result
4562 * comes back in a register other than r0, you can override "result".)
4564 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4565 * vCC (r1). Useful for integer division and modulus. Note that we
4566 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4567 * handles it correctly.
4569 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4570 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4571 * mul-float, div-float, rem-float
4573 /* binop vAA, vBB, vCC */
4574 FETCH(r0, 1) @ r0<- CCBB
4575 mov r9, rINST, lsr #8 @ r9<- AA
4576 mov r3, r0, lsr #8 @ r3<- CC
4577 and r2, r0, #255 @ r2<- BB
4578 GET_VREG(r1, r3) @ r1<- vCC
4579 GET_VREG(r0, r2) @ r0<- vBB
4581 cmp r1, #0 @ is second operand zero?
4582 beq common_errDivideByZero
4585 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4586 and r1, r1, #31 @ optional op; may set condition codes
4587 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4588 GET_INST_OPCODE(ip) @ extract opcode from rINST
4589 SET_VREG(r0, r9) @ vAA<- r0
4590 GOTO_OPCODE(ip) @ jump to next instruction
4591 /* 11-14 instructions */
4595 /* ------------------------------ */
4597 .L_OP_SHR_INT: /* 0x99 */
4598 /* File: armv5te/OP_SHR_INT.S */
4599 /* File: armv5te/binop.S */
4601 * Generic 32-bit binary operation. Provide an "instr" line that
4602 * specifies an instruction that performs "result = r0 op r1".
4603 * This could be an ARM instruction or a function call. (If the result
4604 * comes back in a register other than r0, you can override "result".)
4606 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4607 * vCC (r1). Useful for integer division and modulus. Note that we
4608 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4609 * handles it correctly.
4611 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4612 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4613 * mul-float, div-float, rem-float
4615 /* binop vAA, vBB, vCC */
4616 FETCH(r0, 1) @ r0<- CCBB
4617 mov r9, rINST, lsr #8 @ r9<- AA
4618 mov r3, r0, lsr #8 @ r3<- CC
4619 and r2, r0, #255 @ r2<- BB
4620 GET_VREG(r1, r3) @ r1<- vCC
4621 GET_VREG(r0, r2) @ r0<- vBB
4623 cmp r1, #0 @ is second operand zero?
4624 beq common_errDivideByZero
4627 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4628 and r1, r1, #31 @ optional op; may set condition codes
4629 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4630 GET_INST_OPCODE(ip) @ extract opcode from rINST
4631 SET_VREG(r0, r9) @ vAA<- r0
4632 GOTO_OPCODE(ip) @ jump to next instruction
4633 /* 11-14 instructions */
4637 /* ------------------------------ */
4639 .L_OP_USHR_INT: /* 0x9a */
4640 /* File: armv5te/OP_USHR_INT.S */
4641 /* File: armv5te/binop.S */
4643 * Generic 32-bit binary operation. Provide an "instr" line that
4644 * specifies an instruction that performs "result = r0 op r1".
4645 * This could be an ARM instruction or a function call. (If the result
4646 * comes back in a register other than r0, you can override "result".)
4648 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4649 * vCC (r1). Useful for integer division and modulus. Note that we
4650 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4651 * handles it correctly.
4653 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4654 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4655 * mul-float, div-float, rem-float
4657 /* binop vAA, vBB, vCC */
4658 FETCH(r0, 1) @ r0<- CCBB
4659 mov r9, rINST, lsr #8 @ r9<- AA
4660 mov r3, r0, lsr #8 @ r3<- CC
4661 and r2, r0, #255 @ r2<- BB
4662 GET_VREG(r1, r3) @ r1<- vCC
4663 GET_VREG(r0, r2) @ r0<- vBB
4665 cmp r1, #0 @ is second operand zero?
4666 beq common_errDivideByZero
4669 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4670 and r1, r1, #31 @ optional op; may set condition codes
4671 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4672 GET_INST_OPCODE(ip) @ extract opcode from rINST
4673 SET_VREG(r0, r9) @ vAA<- r0
4674 GOTO_OPCODE(ip) @ jump to next instruction
4675 /* 11-14 instructions */
4679 /* ------------------------------ */
4681 .L_OP_ADD_LONG: /* 0x9b */
4682 /* File: armv5te/OP_ADD_LONG.S */
4683 /* File: armv5te/binopWide.S */
4685 * Generic 64-bit binary operation. Provide an "instr" line that
4686 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4687 * This could be an ARM instruction or a function call. (If the result
4688 * comes back in a register other than r0, you can override "result".)
4690 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4691 * vCC (r1). Useful for integer division and modulus.
4693 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4694 * xor-long, add-double, sub-double, mul-double, div-double,
4697 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4699 /* binop vAA, vBB, vCC */
4700 FETCH(r0, 1) @ r0<- CCBB
4701 mov r9, rINST, lsr #8 @ r9<- AA
4702 and r2, r0, #255 @ r2<- BB
4703 mov r3, r0, lsr #8 @ r3<- CC
4704 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4705 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4706 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4707 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4708 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4710 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4711 beq common_errDivideByZero
4713 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4715 adds r0, r0, r2 @ optional op; may set condition codes
4716 adc r1, r1, r3 @ result<- op, r0-r3 changed
4717 GET_INST_OPCODE(ip) @ extract opcode from rINST
4718 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4719 GOTO_OPCODE(ip) @ jump to next instruction
4720 /* 14-17 instructions */
4724 /* ------------------------------ */
4726 .L_OP_SUB_LONG: /* 0x9c */
4727 /* File: armv5te/OP_SUB_LONG.S */
4728 /* File: armv5te/binopWide.S */
4730 * Generic 64-bit binary operation. Provide an "instr" line that
4731 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4732 * This could be an ARM instruction or a function call. (If the result
4733 * comes back in a register other than r0, you can override "result".)
4735 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4736 * vCC (r1). Useful for integer division and modulus.
4738 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4739 * xor-long, add-double, sub-double, mul-double, div-double,
4742 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4744 /* binop vAA, vBB, vCC */
4745 FETCH(r0, 1) @ r0<- CCBB
4746 mov r9, rINST, lsr #8 @ r9<- AA
4747 and r2, r0, #255 @ r2<- BB
4748 mov r3, r0, lsr #8 @ r3<- CC
4749 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4750 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4751 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4752 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4753 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4755 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4756 beq common_errDivideByZero
4758 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4760 subs r0, r0, r2 @ optional op; may set condition codes
4761 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4762 GET_INST_OPCODE(ip) @ extract opcode from rINST
4763 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4764 GOTO_OPCODE(ip) @ jump to next instruction
4765 /* 14-17 instructions */
4769 /* ------------------------------ */
4771 .L_OP_MUL_LONG: /* 0x9d */
4772 /* File: armv5te/OP_MUL_LONG.S */
4774 * Signed 64-bit integer multiply.
4776 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4783 * The low word of the result holds ZX, the high word holds
4784 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4785 * it doesn't fit in the low 64 bits.
4787 * Unlike most ARM math operations, multiply instructions have
4788 * restrictions on using the same register more than once (Rd and Rm
4789 * cannot be the same).
4791 /* mul-long vAA, vBB, vCC */
4792 FETCH(r0, 1) @ r0<- CCBB
4793 and r2, r0, #255 @ r2<- BB
4794 mov r3, r0, lsr #8 @ r3<- CC
4795 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4796 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4797 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4798 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4799 mul ip, r2, r1 @ ip<- ZxW
4800 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4801 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4802 mov r0, rINST, lsr #8 @ r0<- AA
4803 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4804 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4805 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4806 b .LOP_MUL_LONG_finish
4808 /* ------------------------------ */
4810 .L_OP_DIV_LONG: /* 0x9e */
4811 /* File: armv5te/OP_DIV_LONG.S */
4812 /* File: armv5te/binopWide.S */
4814 * Generic 64-bit binary operation. Provide an "instr" line that
4815 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4816 * This could be an ARM instruction or a function call. (If the result
4817 * comes back in a register other than r0, you can override "result".)
4819 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4820 * vCC (r1). Useful for integer division and modulus.
4822 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4823 * xor-long, add-double, sub-double, mul-double, div-double,
4826 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4828 /* binop vAA, vBB, vCC */
4829 FETCH(r0, 1) @ r0<- CCBB
4830 mov r9, rINST, lsr #8 @ r9<- AA
4831 and r2, r0, #255 @ r2<- BB
4832 mov r3, r0, lsr #8 @ r3<- CC
4833 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4834 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4835 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4836 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4837 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4839 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4840 beq common_errDivideByZero
4842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4844 @ optional op; may set condition codes
4845 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4846 GET_INST_OPCODE(ip) @ extract opcode from rINST
4847 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4848 GOTO_OPCODE(ip) @ jump to next instruction
4849 /* 14-17 instructions */
4853 /* ------------------------------ */
4855 .L_OP_REM_LONG: /* 0x9f */
4856 /* File: armv5te/OP_REM_LONG.S */
4857 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4858 /* File: armv5te/binopWide.S */
4860 * Generic 64-bit binary operation. Provide an "instr" line that
4861 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4862 * This could be an ARM instruction or a function call. (If the result
4863 * comes back in a register other than r0, you can override "result".)
4865 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4866 * vCC (r1). Useful for integer division and modulus.
4868 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4869 * xor-long, add-double, sub-double, mul-double, div-double,
4872 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4874 /* binop vAA, vBB, vCC */
4875 FETCH(r0, 1) @ r0<- CCBB
4876 mov r9, rINST, lsr #8 @ r9<- AA
4877 and r2, r0, #255 @ r2<- BB
4878 mov r3, r0, lsr #8 @ r3<- CC
4879 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4880 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4881 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4882 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4883 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4885 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4886 beq common_errDivideByZero
4888 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4890 @ optional op; may set condition codes
4891 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4892 GET_INST_OPCODE(ip) @ extract opcode from rINST
4893 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4894 GOTO_OPCODE(ip) @ jump to next instruction
4895 /* 14-17 instructions */
4899 /* ------------------------------ */
4901 .L_OP_AND_LONG: /* 0xa0 */
4902 /* File: armv5te/OP_AND_LONG.S */
4903 /* File: armv5te/binopWide.S */
4905 * Generic 64-bit binary operation. Provide an "instr" line that
4906 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4907 * This could be an ARM instruction or a function call. (If the result
4908 * comes back in a register other than r0, you can override "result".)
4910 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4911 * vCC (r1). Useful for integer division and modulus.
4913 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4914 * xor-long, add-double, sub-double, mul-double, div-double,
4917 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4919 /* binop vAA, vBB, vCC */
4920 FETCH(r0, 1) @ r0<- CCBB
4921 mov r9, rINST, lsr #8 @ r9<- AA
4922 and r2, r0, #255 @ r2<- BB
4923 mov r3, r0, lsr #8 @ r3<- CC
4924 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4925 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4926 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4927 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4928 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4930 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4931 beq common_errDivideByZero
4933 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4935 and r0, r0, r2 @ optional op; may set condition codes
4936 and r1, r1, r3 @ result<- op, r0-r3 changed
4937 GET_INST_OPCODE(ip) @ extract opcode from rINST
4938 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4939 GOTO_OPCODE(ip) @ jump to next instruction
4940 /* 14-17 instructions */
4944 /* ------------------------------ */
4946 .L_OP_OR_LONG: /* 0xa1 */
4947 /* File: armv5te/OP_OR_LONG.S */
4948 /* File: armv5te/binopWide.S */
4950 * Generic 64-bit binary operation. Provide an "instr" line that
4951 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4952 * This could be an ARM instruction or a function call. (If the result
4953 * comes back in a register other than r0, you can override "result".)
4955 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4956 * vCC (r1). Useful for integer division and modulus.
4958 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4959 * xor-long, add-double, sub-double, mul-double, div-double,
4962 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4964 /* binop vAA, vBB, vCC */
4965 FETCH(r0, 1) @ r0<- CCBB
4966 mov r9, rINST, lsr #8 @ r9<- AA
4967 and r2, r0, #255 @ r2<- BB
4968 mov r3, r0, lsr #8 @ r3<- CC
4969 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4970 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4971 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4972 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4973 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4975 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4976 beq common_errDivideByZero
4978 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4980 orr r0, r0, r2 @ optional op; may set condition codes
4981 orr r1, r1, r3 @ result<- op, r0-r3 changed
4982 GET_INST_OPCODE(ip) @ extract opcode from rINST
4983 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4984 GOTO_OPCODE(ip) @ jump to next instruction
4985 /* 14-17 instructions */
4989 /* ------------------------------ */
4991 .L_OP_XOR_LONG: /* 0xa2 */
4992 /* File: armv5te/OP_XOR_LONG.S */
4993 /* File: armv5te/binopWide.S */
4995 * Generic 64-bit binary operation. Provide an "instr" line that
4996 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4997 * This could be an ARM instruction or a function call. (If the result
4998 * comes back in a register other than r0, you can override "result".)
5000 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5001 * vCC (r1). Useful for integer division and modulus.
5003 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5004 * xor-long, add-double, sub-double, mul-double, div-double,
5007 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5009 /* binop vAA, vBB, vCC */
5010 FETCH(r0, 1) @ r0<- CCBB
5011 mov r9, rINST, lsr #8 @ r9<- AA
5012 and r2, r0, #255 @ r2<- BB
5013 mov r3, r0, lsr #8 @ r3<- CC
5014 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5015 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5016 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5017 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5018 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5020 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5021 beq common_errDivideByZero
5023 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5025 eor r0, r0, r2 @ optional op; may set condition codes
5026 eor r1, r1, r3 @ result<- op, r0-r3 changed
5027 GET_INST_OPCODE(ip) @ extract opcode from rINST
5028 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5029 GOTO_OPCODE(ip) @ jump to next instruction
5030 /* 14-17 instructions */
5034 /* ------------------------------ */
5036 .L_OP_SHL_LONG: /* 0xa3 */
5037 /* File: armv5te/OP_SHL_LONG.S */
5039 * Long integer shift. This is different from the generic 32/64-bit
5040 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5041 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5042 * 6 bits of the shift distance.
5044 /* shl-long vAA, vBB, vCC */
5045 FETCH(r0, 1) @ r0<- CCBB
5046 mov r9, rINST, lsr #8 @ r9<- AA
5047 and r3, r0, #255 @ r3<- BB
5048 mov r0, r0, lsr #8 @ r0<- CC
5049 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5050 GET_VREG(r2, r0) @ r2<- vCC
5051 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5052 and r2, r2, #63 @ r2<- r2 & 0x3f
5053 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5055 mov r1, r1, asl r2 @ r1<- r1 << r2
5056 rsb r3, r2, #32 @ r3<- 32 - r2
5057 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
5058 subs ip, r2, #32 @ ip<- r2 - 32
5059 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
5060 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5061 b .LOP_SHL_LONG_finish
5063 /* ------------------------------ */
5065 .L_OP_SHR_LONG: /* 0xa4 */
5066 /* File: armv5te/OP_SHR_LONG.S */
5068 * Long integer shift. This is different from the generic 32/64-bit
5069 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5070 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5071 * 6 bits of the shift distance.
5073 /* shr-long vAA, vBB, vCC */
5074 FETCH(r0, 1) @ r0<- CCBB
5075 mov r9, rINST, lsr #8 @ r9<- AA
5076 and r3, r0, #255 @ r3<- BB
5077 mov r0, r0, lsr #8 @ r0<- CC
5078 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5079 GET_VREG(r2, r0) @ r2<- vCC
5080 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5081 and r2, r2, #63 @ r0<- r0 & 0x3f
5082 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5084 mov r0, r0, lsr r2 @ r0<- r2 >> r2
5085 rsb r3, r2, #32 @ r3<- 32 - r2
5086 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
5087 subs ip, r2, #32 @ ip<- r2 - 32
5088 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
5089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5090 b .LOP_SHR_LONG_finish
5092 /* ------------------------------ */
5094 .L_OP_USHR_LONG: /* 0xa5 */
5095 /* File: armv5te/OP_USHR_LONG.S */
5097 * Long integer shift. This is different from the generic 32/64-bit
5098 * binary operations because vAA/vBB are 64-bit but vCC (the shift
5099 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
5100 * 6 bits of the shift distance.
5102 /* ushr-long vAA, vBB, vCC */
5103 FETCH(r0, 1) @ r0<- CCBB
5104 mov r9, rINST, lsr #8 @ r9<- AA
5105 and r3, r0, #255 @ r3<- BB
5106 mov r0, r0, lsr #8 @ r0<- CC
5107 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
5108 GET_VREG(r2, r0) @ r2<- vCC
5109 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
5110 and r2, r2, #63 @ r0<- r0 & 0x3f
5111 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5113 mov r0, r0, lsr r2 @ r0<- r2 >> r2
5114 rsb r3, r2, #32 @ r3<- 32 - r2
5115 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
5116 subs ip, r2, #32 @ ip<- r2 - 32
5117 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
5118 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5119 b .LOP_USHR_LONG_finish
5121 /* ------------------------------ */
5123 .L_OP_ADD_FLOAT: /* 0xa6 */
5124 /* File: armv5te/OP_ADD_FLOAT.S */
5125 /* File: armv5te/binop.S */
5127 * Generic 32-bit binary operation. Provide an "instr" line that
5128 * specifies an instruction that performs "result = r0 op r1".
5129 * This could be an ARM instruction or a function call. (If the result
5130 * comes back in a register other than r0, you can override "result".)
5132 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5133 * vCC (r1). Useful for integer division and modulus. Note that we
5134 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5135 * handles it correctly.
5137 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5138 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5139 * mul-float, div-float, rem-float
5141 /* binop vAA, vBB, vCC */
5142 FETCH(r0, 1) @ r0<- CCBB
5143 mov r9, rINST, lsr #8 @ r9<- AA
5144 mov r3, r0, lsr #8 @ r3<- CC
5145 and r2, r0, #255 @ r2<- BB
5146 GET_VREG(r1, r3) @ r1<- vCC
5147 GET_VREG(r0, r2) @ r0<- vBB
5149 cmp r1, #0 @ is second operand zero?
5150 beq common_errDivideByZero
5153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5154 @ optional op; may set condition codes
5155 bl __aeabi_fadd @ r0<- op, r0-r3 changed
5156 GET_INST_OPCODE(ip) @ extract opcode from rINST
5157 SET_VREG(r0, r9) @ vAA<- r0
5158 GOTO_OPCODE(ip) @ jump to next instruction
5159 /* 11-14 instructions */
5163 /* ------------------------------ */
5165 .L_OP_SUB_FLOAT: /* 0xa7 */
5166 /* File: armv5te/OP_SUB_FLOAT.S */
5167 /* File: armv5te/binop.S */
5169 * Generic 32-bit binary operation. Provide an "instr" line that
5170 * specifies an instruction that performs "result = r0 op r1".
5171 * This could be an ARM instruction or a function call. (If the result
5172 * comes back in a register other than r0, you can override "result".)
5174 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5175 * vCC (r1). Useful for integer division and modulus. Note that we
5176 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5177 * handles it correctly.
5179 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5180 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5181 * mul-float, div-float, rem-float
5183 /* binop vAA, vBB, vCC */
5184 FETCH(r0, 1) @ r0<- CCBB
5185 mov r9, rINST, lsr #8 @ r9<- AA
5186 mov r3, r0, lsr #8 @ r3<- CC
5187 and r2, r0, #255 @ r2<- BB
5188 GET_VREG(r1, r3) @ r1<- vCC
5189 GET_VREG(r0, r2) @ r0<- vBB
5191 cmp r1, #0 @ is second operand zero?
5192 beq common_errDivideByZero
5195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5196 @ optional op; may set condition codes
5197 bl __aeabi_fsub @ r0<- op, r0-r3 changed
5198 GET_INST_OPCODE(ip) @ extract opcode from rINST
5199 SET_VREG(r0, r9) @ vAA<- r0
5200 GOTO_OPCODE(ip) @ jump to next instruction
5201 /* 11-14 instructions */
5205 /* ------------------------------ */
5207 .L_OP_MUL_FLOAT: /* 0xa8 */
5208 /* File: armv5te/OP_MUL_FLOAT.S */
5209 /* File: armv5te/binop.S */
5211 * Generic 32-bit binary operation. Provide an "instr" line that
5212 * specifies an instruction that performs "result = r0 op r1".
5213 * This could be an ARM instruction or a function call. (If the result
5214 * comes back in a register other than r0, you can override "result".)
5216 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5217 * vCC (r1). Useful for integer division and modulus. Note that we
5218 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5219 * handles it correctly.
5221 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5222 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5223 * mul-float, div-float, rem-float
5225 /* binop vAA, vBB, vCC */
5226 FETCH(r0, 1) @ r0<- CCBB
5227 mov r9, rINST, lsr #8 @ r9<- AA
5228 mov r3, r0, lsr #8 @ r3<- CC
5229 and r2, r0, #255 @ r2<- BB
5230 GET_VREG(r1, r3) @ r1<- vCC
5231 GET_VREG(r0, r2) @ r0<- vBB
5233 cmp r1, #0 @ is second operand zero?
5234 beq common_errDivideByZero
5237 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5238 @ optional op; may set condition codes
5239 bl __aeabi_fmul @ r0<- op, r0-r3 changed
5240 GET_INST_OPCODE(ip) @ extract opcode from rINST
5241 SET_VREG(r0, r9) @ vAA<- r0
5242 GOTO_OPCODE(ip) @ jump to next instruction
5243 /* 11-14 instructions */
5247 /* ------------------------------ */
5249 .L_OP_DIV_FLOAT: /* 0xa9 */
5250 /* File: armv5te/OP_DIV_FLOAT.S */
5251 /* File: armv5te/binop.S */
5253 * Generic 32-bit binary operation. Provide an "instr" line that
5254 * specifies an instruction that performs "result = r0 op r1".
5255 * This could be an ARM instruction or a function call. (If the result
5256 * comes back in a register other than r0, you can override "result".)
5258 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5259 * vCC (r1). Useful for integer division and modulus. Note that we
5260 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5261 * handles it correctly.
5263 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5264 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5265 * mul-float, div-float, rem-float
5267 /* binop vAA, vBB, vCC */
5268 FETCH(r0, 1) @ r0<- CCBB
5269 mov r9, rINST, lsr #8 @ r9<- AA
5270 mov r3, r0, lsr #8 @ r3<- CC
5271 and r2, r0, #255 @ r2<- BB
5272 GET_VREG(r1, r3) @ r1<- vCC
5273 GET_VREG(r0, r2) @ r0<- vBB
5275 cmp r1, #0 @ is second operand zero?
5276 beq common_errDivideByZero
5279 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5280 @ optional op; may set condition codes
5281 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
5282 GET_INST_OPCODE(ip) @ extract opcode from rINST
5283 SET_VREG(r0, r9) @ vAA<- r0
5284 GOTO_OPCODE(ip) @ jump to next instruction
5285 /* 11-14 instructions */
5289 /* ------------------------------ */
5291 .L_OP_REM_FLOAT: /* 0xaa */
5292 /* File: armv5te/OP_REM_FLOAT.S */
5293 /* EABI doesn't define a float remainder function, but libm does */
5294 /* File: armv5te/binop.S */
5296 * Generic 32-bit binary operation. Provide an "instr" line that
5297 * specifies an instruction that performs "result = r0 op r1".
5298 * This could be an ARM instruction or a function call. (If the result
5299 * comes back in a register other than r0, you can override "result".)
5301 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5302 * vCC (r1). Useful for integer division and modulus. Note that we
5303 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5304 * handles it correctly.
5306 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5307 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5308 * mul-float, div-float, rem-float
5310 /* binop vAA, vBB, vCC */
5311 FETCH(r0, 1) @ r0<- CCBB
5312 mov r9, rINST, lsr #8 @ r9<- AA
5313 mov r3, r0, lsr #8 @ r3<- CC
5314 and r2, r0, #255 @ r2<- BB
5315 GET_VREG(r1, r3) @ r1<- vCC
5316 GET_VREG(r0, r2) @ r0<- vBB
5318 cmp r1, #0 @ is second operand zero?
5319 beq common_errDivideByZero
5322 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5323 @ optional op; may set condition codes
5324 bl fmodf @ r0<- op, r0-r3 changed
5325 GET_INST_OPCODE(ip) @ extract opcode from rINST
5326 SET_VREG(r0, r9) @ vAA<- r0
5327 GOTO_OPCODE(ip) @ jump to next instruction
5328 /* 11-14 instructions */
5332 /* ------------------------------ */
5334 .L_OP_ADD_DOUBLE: /* 0xab */
5335 /* File: armv5te/OP_ADD_DOUBLE.S */
5336 /* File: armv5te/binopWide.S */
5338 * Generic 64-bit binary operation. Provide an "instr" line that
5339 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5340 * This could be an ARM instruction or a function call. (If the result
5341 * comes back in a register other than r0, you can override "result".)
5343 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5344 * vCC (r1). Useful for integer division and modulus.
5346 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5347 * xor-long, add-double, sub-double, mul-double, div-double,
5350 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5352 /* binop vAA, vBB, vCC */
5353 FETCH(r0, 1) @ r0<- CCBB
5354 mov r9, rINST, lsr #8 @ r9<- AA
5355 and r2, r0, #255 @ r2<- BB
5356 mov r3, r0, lsr #8 @ r3<- CC
5357 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5358 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5359 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5360 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5361 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5363 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5364 beq common_errDivideByZero
5366 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5368 @ optional op; may set condition codes
5369 bl __aeabi_dadd @ result<- op, r0-r3 changed
5370 GET_INST_OPCODE(ip) @ extract opcode from rINST
5371 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5372 GOTO_OPCODE(ip) @ jump to next instruction
5373 /* 14-17 instructions */
5377 /* ------------------------------ */
5379 .L_OP_SUB_DOUBLE: /* 0xac */
5380 /* File: armv5te/OP_SUB_DOUBLE.S */
5381 /* File: armv5te/binopWide.S */
5383 * Generic 64-bit binary operation. Provide an "instr" line that
5384 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5385 * This could be an ARM instruction or a function call. (If the result
5386 * comes back in a register other than r0, you can override "result".)
5388 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5389 * vCC (r1). Useful for integer division and modulus.
5391 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5392 * xor-long, add-double, sub-double, mul-double, div-double,
5395 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5397 /* binop vAA, vBB, vCC */
5398 FETCH(r0, 1) @ r0<- CCBB
5399 mov r9, rINST, lsr #8 @ r9<- AA
5400 and r2, r0, #255 @ r2<- BB
5401 mov r3, r0, lsr #8 @ r3<- CC
5402 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5403 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5404 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5405 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5406 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5408 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5409 beq common_errDivideByZero
5411 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5413 @ optional op; may set condition codes
5414 bl __aeabi_dsub @ result<- op, r0-r3 changed
5415 GET_INST_OPCODE(ip) @ extract opcode from rINST
5416 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5417 GOTO_OPCODE(ip) @ jump to next instruction
5418 /* 14-17 instructions */
5422 /* ------------------------------ */
5424 .L_OP_MUL_DOUBLE: /* 0xad */
5425 /* File: armv5te/OP_MUL_DOUBLE.S */
5426 /* File: armv5te/binopWide.S */
5428 * Generic 64-bit binary operation. Provide an "instr" line that
5429 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5430 * This could be an ARM instruction or a function call. (If the result
5431 * comes back in a register other than r0, you can override "result".)
5433 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5434 * vCC (r1). Useful for integer division and modulus.
5436 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5437 * xor-long, add-double, sub-double, mul-double, div-double,
5440 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5442 /* binop vAA, vBB, vCC */
5443 FETCH(r0, 1) @ r0<- CCBB
5444 mov r9, rINST, lsr #8 @ r9<- AA
5445 and r2, r0, #255 @ r2<- BB
5446 mov r3, r0, lsr #8 @ r3<- CC
5447 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5448 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5449 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5450 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5451 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5453 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5454 beq common_errDivideByZero
5456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5458 @ optional op; may set condition codes
5459 bl __aeabi_dmul @ result<- op, r0-r3 changed
5460 GET_INST_OPCODE(ip) @ extract opcode from rINST
5461 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5462 GOTO_OPCODE(ip) @ jump to next instruction
5463 /* 14-17 instructions */
5467 /* ------------------------------ */
5469 .L_OP_DIV_DOUBLE: /* 0xae */
5470 /* File: armv5te/OP_DIV_DOUBLE.S */
5471 /* File: armv5te/binopWide.S */
5473 * Generic 64-bit binary operation. Provide an "instr" line that
5474 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5475 * This could be an ARM instruction or a function call. (If the result
5476 * comes back in a register other than r0, you can override "result".)
5478 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5479 * vCC (r1). Useful for integer division and modulus.
5481 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5482 * xor-long, add-double, sub-double, mul-double, div-double,
5485 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5487 /* binop vAA, vBB, vCC */
5488 FETCH(r0, 1) @ r0<- CCBB
5489 mov r9, rINST, lsr #8 @ r9<- AA
5490 and r2, r0, #255 @ r2<- BB
5491 mov r3, r0, lsr #8 @ r3<- CC
5492 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5493 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5494 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5495 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5496 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5498 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5499 beq common_errDivideByZero
5501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5503 @ optional op; may set condition codes
5504 bl __aeabi_ddiv @ result<- op, r0-r3 changed
5505 GET_INST_OPCODE(ip) @ extract opcode from rINST
5506 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5507 GOTO_OPCODE(ip) @ jump to next instruction
5508 /* 14-17 instructions */
5512 /* ------------------------------ */
5514 .L_OP_REM_DOUBLE: /* 0xaf */
5515 /* File: armv5te/OP_REM_DOUBLE.S */
5516 /* EABI doesn't define a double remainder function, but libm does */
5517 /* File: armv5te/binopWide.S */
5519 * Generic 64-bit binary operation. Provide an "instr" line that
5520 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5521 * This could be an ARM instruction or a function call. (If the result
5522 * comes back in a register other than r0, you can override "result".)
5524 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5525 * vCC (r1). Useful for integer division and modulus.
5527 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5528 * xor-long, add-double, sub-double, mul-double, div-double,
5531 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5533 /* binop vAA, vBB, vCC */
5534 FETCH(r0, 1) @ r0<- CCBB
5535 mov r9, rINST, lsr #8 @ r9<- AA
5536 and r2, r0, #255 @ r2<- BB
5537 mov r3, r0, lsr #8 @ r3<- CC
5538 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5539 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5540 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5541 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5542 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5544 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5545 beq common_errDivideByZero
5547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5549 @ optional op; may set condition codes
5550 bl fmod @ result<- op, r0-r3 changed
5551 GET_INST_OPCODE(ip) @ extract opcode from rINST
5552 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5553 GOTO_OPCODE(ip) @ jump to next instruction
5554 /* 14-17 instructions */
5558 /* ------------------------------ */
5560 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5561 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5562 /* File: armv5te/binop2addr.S */
5564 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5565 * that specifies an instruction that performs "result = r0 op r1".
5566 * This could be an ARM instruction or a function call. (If the result
5567 * comes back in a register other than r0, you can override "result".)
5569 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5570 * vCC (r1). Useful for integer division and modulus.
5572 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5573 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5574 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5575 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5577 /* binop/2addr vA, vB */
5578 mov r9, rINST, lsr #8 @ r9<- A+
5579 mov r3, rINST, lsr #12 @ r3<- B
5581 GET_VREG(r1, r3) @ r1<- vB
5582 GET_VREG(r0, r9) @ r0<- vA
5584 cmp r1, #0 @ is second operand zero?
5585 beq common_errDivideByZero
5587 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5589 @ optional op; may set condition codes
5590 add r0, r0, r1 @ r0<- op, r0-r3 changed
5591 GET_INST_OPCODE(ip) @ extract opcode from rINST
5592 SET_VREG(r0, r9) @ vAA<- r0
5593 GOTO_OPCODE(ip) @ jump to next instruction
5594 /* 10-13 instructions */
5598 /* ------------------------------ */
5600 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5601 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5602 /* File: armv5te/binop2addr.S */
5604 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5605 * that specifies an instruction that performs "result = r0 op r1".
5606 * This could be an ARM instruction or a function call. (If the result
5607 * comes back in a register other than r0, you can override "result".)
5609 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5610 * vCC (r1). Useful for integer division and modulus.
5612 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5613 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5614 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5615 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5617 /* binop/2addr vA, vB */
5618 mov r9, rINST, lsr #8 @ r9<- A+
5619 mov r3, rINST, lsr #12 @ r3<- B
5621 GET_VREG(r1, r3) @ r1<- vB
5622 GET_VREG(r0, r9) @ r0<- vA
5624 cmp r1, #0 @ is second operand zero?
5625 beq common_errDivideByZero
5627 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5629 @ optional op; may set condition codes
5630 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5631 GET_INST_OPCODE(ip) @ extract opcode from rINST
5632 SET_VREG(r0, r9) @ vAA<- r0
5633 GOTO_OPCODE(ip) @ jump to next instruction
5634 /* 10-13 instructions */
5638 /* ------------------------------ */
5640 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5641 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5642 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5643 /* File: armv5te/binop2addr.S */
5645 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5646 * that specifies an instruction that performs "result = r0 op r1".
5647 * This could be an ARM instruction or a function call. (If the result
5648 * comes back in a register other than r0, you can override "result".)
5650 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5651 * vCC (r1). Useful for integer division and modulus.
5653 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5654 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5655 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5656 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5658 /* binop/2addr vA, vB */
5659 mov r9, rINST, lsr #8 @ r9<- A+
5660 mov r3, rINST, lsr #12 @ r3<- B
5662 GET_VREG(r1, r3) @ r1<- vB
5663 GET_VREG(r0, r9) @ r0<- vA
5665 cmp r1, #0 @ is second operand zero?
5666 beq common_errDivideByZero
5668 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5670 @ optional op; may set condition codes
5671 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5672 GET_INST_OPCODE(ip) @ extract opcode from rINST
5673 SET_VREG(r0, r9) @ vAA<- r0
5674 GOTO_OPCODE(ip) @ jump to next instruction
5675 /* 10-13 instructions */
5679 /* ------------------------------ */
5681 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5682 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5683 /* File: armv5te/binop2addr.S */
5685 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5686 * that specifies an instruction that performs "result = r0 op r1".
5687 * This could be an ARM instruction or a function call. (If the result
5688 * comes back in a register other than r0, you can override "result".)
5690 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5691 * vCC (r1). Useful for integer division and modulus.
5693 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5694 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5695 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5696 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5698 /* binop/2addr vA, vB */
5699 mov r9, rINST, lsr #8 @ r9<- A+
5700 mov r3, rINST, lsr #12 @ r3<- B
5702 GET_VREG(r1, r3) @ r1<- vB
5703 GET_VREG(r0, r9) @ r0<- vA
5705 cmp r1, #0 @ is second operand zero?
5706 beq common_errDivideByZero
5708 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5710 @ optional op; may set condition codes
5711 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5712 GET_INST_OPCODE(ip) @ extract opcode from rINST
5713 SET_VREG(r0, r9) @ vAA<- r0
5714 GOTO_OPCODE(ip) @ jump to next instruction
5715 /* 10-13 instructions */
5719 /* ------------------------------ */
5721 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5722 /* File: armv5te/OP_REM_INT_2ADDR.S */
5723 /* idivmod returns quotient in r0 and remainder in r1 */
5724 /* File: armv5te/binop2addr.S */
5726 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5727 * that specifies an instruction that performs "result = r0 op r1".
5728 * This could be an ARM instruction or a function call. (If the result
5729 * comes back in a register other than r0, you can override "result".)
5731 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5732 * vCC (r1). Useful for integer division and modulus.
5734 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5735 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5736 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5737 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5739 /* binop/2addr vA, vB */
5740 mov r9, rINST, lsr #8 @ r9<- A+
5741 mov r3, rINST, lsr #12 @ r3<- B
5743 GET_VREG(r1, r3) @ r1<- vB
5744 GET_VREG(r0, r9) @ r0<- vA
5746 cmp r1, #0 @ is second operand zero?
5747 beq common_errDivideByZero
5749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5751 @ optional op; may set condition codes
5752 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5753 GET_INST_OPCODE(ip) @ extract opcode from rINST
5754 SET_VREG(r1, r9) @ vAA<- r1
5755 GOTO_OPCODE(ip) @ jump to next instruction
5756 /* 10-13 instructions */
5760 /* ------------------------------ */
5762 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5763 /* File: armv5te/OP_AND_INT_2ADDR.S */
5764 /* File: armv5te/binop2addr.S */
5766 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5767 * that specifies an instruction that performs "result = r0 op r1".
5768 * This could be an ARM instruction or a function call. (If the result
5769 * comes back in a register other than r0, you can override "result".)
5771 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5772 * vCC (r1). Useful for integer division and modulus.
5774 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5775 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5776 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5777 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5779 /* binop/2addr vA, vB */
5780 mov r9, rINST, lsr #8 @ r9<- A+
5781 mov r3, rINST, lsr #12 @ r3<- B
5783 GET_VREG(r1, r3) @ r1<- vB
5784 GET_VREG(r0, r9) @ r0<- vA
5786 cmp r1, #0 @ is second operand zero?
5787 beq common_errDivideByZero
5789 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5791 @ optional op; may set condition codes
5792 and r0, r0, r1 @ r0<- op, r0-r3 changed
5793 GET_INST_OPCODE(ip) @ extract opcode from rINST
5794 SET_VREG(r0, r9) @ vAA<- r0
5795 GOTO_OPCODE(ip) @ jump to next instruction
5796 /* 10-13 instructions */
5800 /* ------------------------------ */
5802 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5803 /* File: armv5te/OP_OR_INT_2ADDR.S */
5804 /* File: armv5te/binop2addr.S */
5806 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5807 * that specifies an instruction that performs "result = r0 op r1".
5808 * This could be an ARM instruction or a function call. (If the result
5809 * comes back in a register other than r0, you can override "result".)
5811 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5812 * vCC (r1). Useful for integer division and modulus.
5814 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5815 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5816 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5817 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5819 /* binop/2addr vA, vB */
5820 mov r9, rINST, lsr #8 @ r9<- A+
5821 mov r3, rINST, lsr #12 @ r3<- B
5823 GET_VREG(r1, r3) @ r1<- vB
5824 GET_VREG(r0, r9) @ r0<- vA
5826 cmp r1, #0 @ is second operand zero?
5827 beq common_errDivideByZero
5829 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5831 @ optional op; may set condition codes
5832 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5833 GET_INST_OPCODE(ip) @ extract opcode from rINST
5834 SET_VREG(r0, r9) @ vAA<- r0
5835 GOTO_OPCODE(ip) @ jump to next instruction
5836 /* 10-13 instructions */
5840 /* ------------------------------ */
5842 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5843 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5844 /* File: armv5te/binop2addr.S */
5846 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5847 * that specifies an instruction that performs "result = r0 op r1".
5848 * This could be an ARM instruction or a function call. (If the result
5849 * comes back in a register other than r0, you can override "result".)
5851 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5852 * vCC (r1). Useful for integer division and modulus.
5854 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5855 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5856 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5857 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5859 /* binop/2addr vA, vB */
5860 mov r9, rINST, lsr #8 @ r9<- A+
5861 mov r3, rINST, lsr #12 @ r3<- B
5863 GET_VREG(r1, r3) @ r1<- vB
5864 GET_VREG(r0, r9) @ r0<- vA
5866 cmp r1, #0 @ is second operand zero?
5867 beq common_errDivideByZero
5869 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5871 @ optional op; may set condition codes
5872 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5873 GET_INST_OPCODE(ip) @ extract opcode from rINST
5874 SET_VREG(r0, r9) @ vAA<- r0
5875 GOTO_OPCODE(ip) @ jump to next instruction
5876 /* 10-13 instructions */
5880 /* ------------------------------ */
5882 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5883 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5884 /* File: armv5te/binop2addr.S */
5886 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5887 * that specifies an instruction that performs "result = r0 op r1".
5888 * This could be an ARM instruction or a function call. (If the result
5889 * comes back in a register other than r0, you can override "result".)
5891 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5892 * vCC (r1). Useful for integer division and modulus.
5894 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5895 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5896 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5897 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5899 /* binop/2addr vA, vB */
5900 mov r9, rINST, lsr #8 @ r9<- A+
5901 mov r3, rINST, lsr #12 @ r3<- B
5903 GET_VREG(r1, r3) @ r1<- vB
5904 GET_VREG(r0, r9) @ r0<- vA
5906 cmp r1, #0 @ is second operand zero?
5907 beq common_errDivideByZero
5909 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5911 and r1, r1, #31 @ optional op; may set condition codes
5912 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
5913 GET_INST_OPCODE(ip) @ extract opcode from rINST
5914 SET_VREG(r0, r9) @ vAA<- r0
5915 GOTO_OPCODE(ip) @ jump to next instruction
5916 /* 10-13 instructions */
5920 /* ------------------------------ */
5922 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5923 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5924 /* File: armv5te/binop2addr.S */
5926 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5927 * that specifies an instruction that performs "result = r0 op r1".
5928 * This could be an ARM instruction or a function call. (If the result
5929 * comes back in a register other than r0, you can override "result".)
5931 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5932 * vCC (r1). Useful for integer division and modulus.
5934 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5935 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5936 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5937 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5939 /* binop/2addr vA, vB */
5940 mov r9, rINST, lsr #8 @ r9<- A+
5941 mov r3, rINST, lsr #12 @ r3<- B
5943 GET_VREG(r1, r3) @ r1<- vB
5944 GET_VREG(r0, r9) @ r0<- vA
5946 cmp r1, #0 @ is second operand zero?
5947 beq common_errDivideByZero
5949 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5951 and r1, r1, #31 @ optional op; may set condition codes
5952 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
5953 GET_INST_OPCODE(ip) @ extract opcode from rINST
5954 SET_VREG(r0, r9) @ vAA<- r0
5955 GOTO_OPCODE(ip) @ jump to next instruction
5956 /* 10-13 instructions */
5960 /* ------------------------------ */
5962 .L_OP_USHR_INT_2ADDR: /* 0xba */
5963 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5964 /* File: armv5te/binop2addr.S */
5966 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5967 * that specifies an instruction that performs "result = r0 op r1".
5968 * This could be an ARM instruction or a function call. (If the result
5969 * comes back in a register other than r0, you can override "result".)
5971 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5972 * vCC (r1). Useful for integer division and modulus.
5974 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5975 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5976 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5977 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5979 /* binop/2addr vA, vB */
5980 mov r9, rINST, lsr #8 @ r9<- A+
5981 mov r3, rINST, lsr #12 @ r3<- B
5983 GET_VREG(r1, r3) @ r1<- vB
5984 GET_VREG(r0, r9) @ r0<- vA
5986 cmp r1, #0 @ is second operand zero?
5987 beq common_errDivideByZero
5989 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5991 and r1, r1, #31 @ optional op; may set condition codes
5992 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
5993 GET_INST_OPCODE(ip) @ extract opcode from rINST
5994 SET_VREG(r0, r9) @ vAA<- r0
5995 GOTO_OPCODE(ip) @ jump to next instruction
5996 /* 10-13 instructions */
6000 /* ------------------------------ */
6002 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
6003 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
6004 /* File: armv5te/binopWide2addr.S */
6006 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6007 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6008 * This could be an ARM instruction or a function call. (If the result
6009 * comes back in a register other than r0, you can override "result".)
6011 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6012 * vCC (r1). Useful for integer division and modulus.
6014 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6015 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6016 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6019 /* binop/2addr vA, vB */
6020 mov r9, rINST, lsr #8 @ r9<- A+
6021 mov r1, rINST, lsr #12 @ r1<- B
6023 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6024 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6025 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6026 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6028 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6029 beq common_errDivideByZero
6031 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6033 adds r0, r0, r2 @ optional op; may set condition codes
6034 adc r1, r1, r3 @ result<- op, r0-r3 changed
6035 GET_INST_OPCODE(ip) @ extract opcode from rINST
6036 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6037 GOTO_OPCODE(ip) @ jump to next instruction
6038 /* 12-15 instructions */
6042 /* ------------------------------ */
6044 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
6045 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
6046 /* File: armv5te/binopWide2addr.S */
6048 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6049 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6050 * This could be an ARM instruction or a function call. (If the result
6051 * comes back in a register other than r0, you can override "result".)
6053 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6054 * vCC (r1). Useful for integer division and modulus.
6056 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6057 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6058 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6061 /* binop/2addr vA, vB */
6062 mov r9, rINST, lsr #8 @ r9<- A+
6063 mov r1, rINST, lsr #12 @ r1<- B
6065 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6066 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6067 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6068 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6070 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6071 beq common_errDivideByZero
6073 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6075 subs r0, r0, r2 @ optional op; may set condition codes
6076 sbc r1, r1, r3 @ result<- op, r0-r3 changed
6077 GET_INST_OPCODE(ip) @ extract opcode from rINST
6078 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6079 GOTO_OPCODE(ip) @ jump to next instruction
6080 /* 12-15 instructions */
6084 /* ------------------------------ */
6086 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
6087 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
6089 * Signed 64-bit integer multiply, "/2addr" version.
6091 * See OP_MUL_LONG for an explanation.
6093 * We get a little tight on registers, so to avoid looking up &fp[A]
6094 * again we stuff it into rINST.
6096 /* mul-long/2addr vA, vB */
6097 mov r9, rINST, lsr #8 @ r9<- A+
6098 mov r1, rINST, lsr #12 @ r1<- B
6100 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6101 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
6102 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6103 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
6104 mul ip, r2, r1 @ ip<- ZxW
6105 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
6106 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
6107 mov r0, rINST @ r0<- &fp[A] (free up rINST)
6108 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6109 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
6110 GET_INST_OPCODE(ip) @ extract opcode from rINST
6111 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
6112 GOTO_OPCODE(ip) @ jump to next instruction
6115 /* ------------------------------ */
6117 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
6118 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
6119 /* File: armv5te/binopWide2addr.S */
6121 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6122 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6123 * This could be an ARM instruction or a function call. (If the result
6124 * comes back in a register other than r0, you can override "result".)
6126 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6127 * vCC (r1). Useful for integer division and modulus.
6129 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6130 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6131 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6134 /* binop/2addr vA, vB */
6135 mov r9, rINST, lsr #8 @ r9<- A+
6136 mov r1, rINST, lsr #12 @ r1<- B
6138 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6139 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6140 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6141 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6143 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6144 beq common_errDivideByZero
6146 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6148 @ optional op; may set condition codes
6149 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
6150 GET_INST_OPCODE(ip) @ extract opcode from rINST
6151 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6152 GOTO_OPCODE(ip) @ jump to next instruction
6153 /* 12-15 instructions */
6157 /* ------------------------------ */
6159 .L_OP_REM_LONG_2ADDR: /* 0xbf */
6160 /* File: armv5te/OP_REM_LONG_2ADDR.S */
6161 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6162 /* File: armv5te/binopWide2addr.S */
6164 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6165 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6166 * This could be an ARM instruction or a function call. (If the result
6167 * comes back in a register other than r0, you can override "result".)
6169 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6170 * vCC (r1). Useful for integer division and modulus.
6172 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6173 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6174 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6177 /* binop/2addr vA, vB */
6178 mov r9, rINST, lsr #8 @ r9<- A+
6179 mov r1, rINST, lsr #12 @ r1<- B
6181 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6182 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6183 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6184 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6186 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6187 beq common_errDivideByZero
6189 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6191 @ optional op; may set condition codes
6192 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
6193 GET_INST_OPCODE(ip) @ extract opcode from rINST
6194 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
6195 GOTO_OPCODE(ip) @ jump to next instruction
6196 /* 12-15 instructions */
6200 /* ------------------------------ */
6202 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6203 /* File: armv5te/OP_AND_LONG_2ADDR.S */
6204 /* File: armv5te/binopWide2addr.S */
6206 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6207 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6208 * This could be an ARM instruction or a function call. (If the result
6209 * comes back in a register other than r0, you can override "result".)
6211 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6212 * vCC (r1). Useful for integer division and modulus.
6214 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6215 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6216 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6219 /* binop/2addr vA, vB */
6220 mov r9, rINST, lsr #8 @ r9<- A+
6221 mov r1, rINST, lsr #12 @ r1<- B
6223 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6224 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6225 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6226 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6228 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6229 beq common_errDivideByZero
6231 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6233 and r0, r0, r2 @ optional op; may set condition codes
6234 and r1, r1, r3 @ result<- op, r0-r3 changed
6235 GET_INST_OPCODE(ip) @ extract opcode from rINST
6236 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6237 GOTO_OPCODE(ip) @ jump to next instruction
6238 /* 12-15 instructions */
6242 /* ------------------------------ */
6244 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
6245 /* File: armv5te/OP_OR_LONG_2ADDR.S */
6246 /* File: armv5te/binopWide2addr.S */
6248 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6249 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6250 * This could be an ARM instruction or a function call. (If the result
6251 * comes back in a register other than r0, you can override "result".)
6253 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6254 * vCC (r1). Useful for integer division and modulus.
6256 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6257 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6258 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6261 /* binop/2addr vA, vB */
6262 mov r9, rINST, lsr #8 @ r9<- A+
6263 mov r1, rINST, lsr #12 @ r1<- B
6265 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6266 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6267 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6268 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6270 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6271 beq common_errDivideByZero
6273 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6275 orr r0, r0, r2 @ optional op; may set condition codes
6276 orr r1, r1, r3 @ result<- op, r0-r3 changed
6277 GET_INST_OPCODE(ip) @ extract opcode from rINST
6278 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6279 GOTO_OPCODE(ip) @ jump to next instruction
6280 /* 12-15 instructions */
6284 /* ------------------------------ */
6286 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6287 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6288 /* File: armv5te/binopWide2addr.S */
6290 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6291 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6292 * This could be an ARM instruction or a function call. (If the result
6293 * comes back in a register other than r0, you can override "result".)
6295 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6296 * vCC (r1). Useful for integer division and modulus.
6298 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6299 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6300 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6303 /* binop/2addr vA, vB */
6304 mov r9, rINST, lsr #8 @ r9<- A+
6305 mov r1, rINST, lsr #12 @ r1<- B
6307 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6308 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6309 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6310 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6312 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6313 beq common_errDivideByZero
6315 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6317 eor r0, r0, r2 @ optional op; may set condition codes
6318 eor r1, r1, r3 @ result<- op, r0-r3 changed
6319 GET_INST_OPCODE(ip) @ extract opcode from rINST
6320 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6321 GOTO_OPCODE(ip) @ jump to next instruction
6322 /* 12-15 instructions */
6326 /* ------------------------------ */
6328 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6329 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6331 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6332 * 32-bit shift distance.
6334 /* shl-long/2addr vA, vB */
6335 mov r9, rINST, lsr #8 @ r9<- A+
6336 mov r3, rINST, lsr #12 @ r3<- B
6338 GET_VREG(r2, r3) @ r2<- vB
6339 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6340 and r2, r2, #63 @ r2<- r2 & 0x3f
6341 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6343 mov r1, r1, asl r2 @ r1<- r1 << r2
6344 rsb r3, r2, #32 @ r3<- 32 - r2
6345 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6346 subs ip, r2, #32 @ ip<- r2 - 32
6347 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6348 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6349 mov r0, r0, asl r2 @ r0<- r0 << r2
6350 b .LOP_SHL_LONG_2ADDR_finish
6352 /* ------------------------------ */
6354 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6355 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6357 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6358 * 32-bit shift distance.
6360 /* shr-long/2addr vA, vB */
6361 mov r9, rINST, lsr #8 @ r9<- A+
6362 mov r3, rINST, lsr #12 @ r3<- B
6364 GET_VREG(r2, r3) @ r2<- vB
6365 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6366 and r2, r2, #63 @ r2<- r2 & 0x3f
6367 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6369 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6370 rsb r3, r2, #32 @ r3<- 32 - r2
6371 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6372 subs ip, r2, #32 @ ip<- r2 - 32
6373 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6374 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6375 mov r1, r1, asr r2 @ r1<- r1 >> r2
6376 b .LOP_SHR_LONG_2ADDR_finish
6378 /* ------------------------------ */
6380 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6381 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6383 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6384 * 32-bit shift distance.
6386 /* ushr-long/2addr vA, vB */
6387 mov r9, rINST, lsr #8 @ r9<- A+
6388 mov r3, rINST, lsr #12 @ r3<- B
6390 GET_VREG(r2, r3) @ r2<- vB
6391 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6392 and r2, r2, #63 @ r2<- r2 & 0x3f
6393 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6395 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6396 rsb r3, r2, #32 @ r3<- 32 - r2
6397 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6398 subs ip, r2, #32 @ ip<- r2 - 32
6399 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6400 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6401 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6402 b .LOP_USHR_LONG_2ADDR_finish
6404 /* ------------------------------ */
6406 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6407 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6408 /* File: armv5te/binop2addr.S */
6410 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6411 * that specifies an instruction that performs "result = r0 op r1".
6412 * This could be an ARM instruction or a function call. (If the result
6413 * comes back in a register other than r0, you can override "result".)
6415 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6416 * vCC (r1). Useful for integer division and modulus.
6418 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6419 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6420 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6421 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6423 /* binop/2addr vA, vB */
6424 mov r9, rINST, lsr #8 @ r9<- A+
6425 mov r3, rINST, lsr #12 @ r3<- B
6427 GET_VREG(r1, r3) @ r1<- vB
6428 GET_VREG(r0, r9) @ r0<- vA
6430 cmp r1, #0 @ is second operand zero?
6431 beq common_errDivideByZero
6433 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6435 @ optional op; may set condition codes
6436 bl __aeabi_fadd @ r0<- op, r0-r3 changed
6437 GET_INST_OPCODE(ip) @ extract opcode from rINST
6438 SET_VREG(r0, r9) @ vAA<- r0
6439 GOTO_OPCODE(ip) @ jump to next instruction
6440 /* 10-13 instructions */
6444 /* ------------------------------ */
6446 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6447 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6448 /* File: armv5te/binop2addr.S */
6450 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6451 * that specifies an instruction that performs "result = r0 op r1".
6452 * This could be an ARM instruction or a function call. (If the result
6453 * comes back in a register other than r0, you can override "result".)
6455 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6456 * vCC (r1). Useful for integer division and modulus.
6458 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6459 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6460 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6461 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6463 /* binop/2addr vA, vB */
6464 mov r9, rINST, lsr #8 @ r9<- A+
6465 mov r3, rINST, lsr #12 @ r3<- B
6467 GET_VREG(r1, r3) @ r1<- vB
6468 GET_VREG(r0, r9) @ r0<- vA
6470 cmp r1, #0 @ is second operand zero?
6471 beq common_errDivideByZero
6473 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6475 @ optional op; may set condition codes
6476 bl __aeabi_fsub @ 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 */
6484 /* ------------------------------ */
6486 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6487 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6488 /* File: armv5te/binop2addr.S */
6490 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6491 * that specifies an instruction that performs "result = r0 op r1".
6492 * This could be an ARM instruction or a function call. (If the result
6493 * comes back in a register other than r0, you can override "result".)
6495 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6496 * vCC (r1). Useful for integer division and modulus.
6498 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6499 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6500 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6501 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6503 /* binop/2addr vA, vB */
6504 mov r9, rINST, lsr #8 @ r9<- A+
6505 mov r3, rINST, lsr #12 @ r3<- B
6507 GET_VREG(r1, r3) @ r1<- vB
6508 GET_VREG(r0, r9) @ r0<- vA
6510 cmp r1, #0 @ is second operand zero?
6511 beq common_errDivideByZero
6513 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6515 @ optional op; may set condition codes
6516 bl __aeabi_fmul @ r0<- op, r0-r3 changed
6517 GET_INST_OPCODE(ip) @ extract opcode from rINST
6518 SET_VREG(r0, r9) @ vAA<- r0
6519 GOTO_OPCODE(ip) @ jump to next instruction
6520 /* 10-13 instructions */
6524 /* ------------------------------ */
6526 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6527 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6528 /* File: armv5te/binop2addr.S */
6530 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6531 * that specifies an instruction that performs "result = r0 op r1".
6532 * This could be an ARM instruction or a function call. (If the result
6533 * comes back in a register other than r0, you can override "result".)
6535 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6536 * vCC (r1). Useful for integer division and modulus.
6538 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6539 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6540 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6541 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6543 /* binop/2addr vA, vB */
6544 mov r9, rINST, lsr #8 @ r9<- A+
6545 mov r3, rINST, lsr #12 @ r3<- B
6547 GET_VREG(r1, r3) @ r1<- vB
6548 GET_VREG(r0, r9) @ r0<- vA
6550 cmp r1, #0 @ is second operand zero?
6551 beq common_errDivideByZero
6553 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6555 @ optional op; may set condition codes
6556 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
6557 GET_INST_OPCODE(ip) @ extract opcode from rINST
6558 SET_VREG(r0, r9) @ vAA<- r0
6559 GOTO_OPCODE(ip) @ jump to next instruction
6560 /* 10-13 instructions */
6564 /* ------------------------------ */
6566 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6567 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6568 /* EABI doesn't define a float remainder function, but libm does */
6569 /* File: armv5te/binop2addr.S */
6571 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6572 * that specifies an instruction that performs "result = r0 op r1".
6573 * This could be an ARM instruction or a function call. (If the result
6574 * comes back in a register other than r0, you can override "result".)
6576 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6577 * vCC (r1). Useful for integer division and modulus.
6579 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6580 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6581 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6582 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6584 /* binop/2addr vA, vB */
6585 mov r9, rINST, lsr #8 @ r9<- A+
6586 mov r3, rINST, lsr #12 @ r3<- B
6588 GET_VREG(r1, r3) @ r1<- vB
6589 GET_VREG(r0, r9) @ r0<- vA
6591 cmp r1, #0 @ is second operand zero?
6592 beq common_errDivideByZero
6594 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6596 @ optional op; may set condition codes
6597 bl fmodf @ r0<- op, r0-r3 changed
6598 GET_INST_OPCODE(ip) @ extract opcode from rINST
6599 SET_VREG(r0, r9) @ vAA<- r0
6600 GOTO_OPCODE(ip) @ jump to next instruction
6601 /* 10-13 instructions */
6605 /* ------------------------------ */
6607 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6608 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6609 /* File: armv5te/binopWide2addr.S */
6611 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6612 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6613 * This could be an ARM instruction or a function call. (If the result
6614 * comes back in a register other than r0, you can override "result".)
6616 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6617 * vCC (r1). Useful for integer division and modulus.
6619 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6620 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6621 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6624 /* binop/2addr vA, vB */
6625 mov r9, rINST, lsr #8 @ r9<- A+
6626 mov r1, rINST, lsr #12 @ r1<- B
6628 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6629 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6630 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6631 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6633 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6634 beq common_errDivideByZero
6636 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6638 @ optional op; may set condition codes
6639 bl __aeabi_dadd @ result<- op, r0-r3 changed
6640 GET_INST_OPCODE(ip) @ extract opcode from rINST
6641 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6642 GOTO_OPCODE(ip) @ jump to next instruction
6643 /* 12-15 instructions */
6647 /* ------------------------------ */
6649 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6650 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6651 /* File: armv5te/binopWide2addr.S */
6653 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6654 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6655 * This could be an ARM instruction or a function call. (If the result
6656 * comes back in a register other than r0, you can override "result".)
6658 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6659 * vCC (r1). Useful for integer division and modulus.
6661 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6662 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6663 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6666 /* binop/2addr vA, vB */
6667 mov r9, rINST, lsr #8 @ r9<- A+
6668 mov r1, rINST, lsr #12 @ r1<- B
6670 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6671 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6672 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6673 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6675 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6676 beq common_errDivideByZero
6678 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6680 @ optional op; may set condition codes
6681 bl __aeabi_dsub @ result<- op, r0-r3 changed
6682 GET_INST_OPCODE(ip) @ extract opcode from rINST
6683 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6684 GOTO_OPCODE(ip) @ jump to next instruction
6685 /* 12-15 instructions */
6689 /* ------------------------------ */
6691 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6692 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6693 /* File: armv5te/binopWide2addr.S */
6695 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6696 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6697 * This could be an ARM instruction or a function call. (If the result
6698 * comes back in a register other than r0, you can override "result".)
6700 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6701 * vCC (r1). Useful for integer division and modulus.
6703 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6704 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6705 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6708 /* binop/2addr vA, vB */
6709 mov r9, rINST, lsr #8 @ r9<- A+
6710 mov r1, rINST, lsr #12 @ r1<- B
6712 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6713 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6714 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6715 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6717 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6718 beq common_errDivideByZero
6720 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6722 @ optional op; may set condition codes
6723 bl __aeabi_dmul @ result<- op, r0-r3 changed
6724 GET_INST_OPCODE(ip) @ extract opcode from rINST
6725 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6726 GOTO_OPCODE(ip) @ jump to next instruction
6727 /* 12-15 instructions */
6731 /* ------------------------------ */
6733 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6734 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6735 /* File: armv5te/binopWide2addr.S */
6737 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6738 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6739 * This could be an ARM instruction or a function call. (If the result
6740 * comes back in a register other than r0, you can override "result".)
6742 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6743 * vCC (r1). Useful for integer division and modulus.
6745 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6746 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6747 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6750 /* binop/2addr vA, vB */
6751 mov r9, rINST, lsr #8 @ r9<- A+
6752 mov r1, rINST, lsr #12 @ r1<- B
6754 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6755 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6756 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6757 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6759 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6760 beq common_errDivideByZero
6762 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6764 @ optional op; may set condition codes
6765 bl __aeabi_ddiv @ result<- op, r0-r3 changed
6766 GET_INST_OPCODE(ip) @ extract opcode from rINST
6767 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6768 GOTO_OPCODE(ip) @ jump to next instruction
6769 /* 12-15 instructions */
6773 /* ------------------------------ */
6775 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6776 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6777 /* EABI doesn't define a double remainder function, but libm does */
6778 /* File: armv5te/binopWide2addr.S */
6780 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6781 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6782 * This could be an ARM instruction or a function call. (If the result
6783 * comes back in a register other than r0, you can override "result".)
6785 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6786 * vCC (r1). Useful for integer division and modulus.
6788 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6789 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6790 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6793 /* binop/2addr vA, vB */
6794 mov r9, rINST, lsr #8 @ r9<- A+
6795 mov r1, rINST, lsr #12 @ r1<- B
6797 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6798 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6799 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6800 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6802 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6803 beq common_errDivideByZero
6805 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6807 @ optional op; may set condition codes
6808 bl fmod @ result<- op, r0-r3 changed
6809 GET_INST_OPCODE(ip) @ extract opcode from rINST
6810 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6811 GOTO_OPCODE(ip) @ jump to next instruction
6812 /* 12-15 instructions */
6816 /* ------------------------------ */
6818 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6819 /* File: armv5te/OP_ADD_INT_LIT16.S */
6820 /* File: armv5te/binopLit16.S */
6822 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6823 * that specifies an instruction that performs "result = r0 op r1".
6824 * This could be an ARM instruction or a function call. (If the result
6825 * comes back in a register other than r0, you can override "result".)
6827 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6828 * vCC (r1). Useful for integer division and modulus.
6830 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6831 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6833 /* binop/lit16 vA, vB, #+CCCC */
6834 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6835 mov r2, rINST, lsr #12 @ r2<- B
6836 mov r9, rINST, lsr #8 @ r9<- A+
6837 GET_VREG(r0, r2) @ r0<- vB
6840 cmp r1, #0 @ is second operand zero?
6841 beq common_errDivideByZero
6843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6845 add r0, r0, r1 @ r0<- op, r0-r3 changed
6846 GET_INST_OPCODE(ip) @ extract opcode from rINST
6847 SET_VREG(r0, r9) @ vAA<- r0
6848 GOTO_OPCODE(ip) @ jump to next instruction
6849 /* 10-13 instructions */
6853 /* ------------------------------ */
6855 .L_OP_RSUB_INT: /* 0xd1 */
6856 /* File: armv5te/OP_RSUB_INT.S */
6857 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6858 /* File: armv5te/binopLit16.S */
6860 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6861 * that specifies an instruction that performs "result = r0 op r1".
6862 * This could be an ARM instruction or a function call. (If the result
6863 * comes back in a register other than r0, you can override "result".)
6865 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6866 * vCC (r1). Useful for integer division and modulus.
6868 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6869 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6871 /* binop/lit16 vA, vB, #+CCCC */
6872 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6873 mov r2, rINST, lsr #12 @ r2<- B
6874 mov r9, rINST, lsr #8 @ r9<- A+
6875 GET_VREG(r0, r2) @ r0<- vB
6878 cmp r1, #0 @ is second operand zero?
6879 beq common_errDivideByZero
6881 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6883 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6884 GET_INST_OPCODE(ip) @ extract opcode from rINST
6885 SET_VREG(r0, r9) @ vAA<- r0
6886 GOTO_OPCODE(ip) @ jump to next instruction
6887 /* 10-13 instructions */
6891 /* ------------------------------ */
6893 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6894 /* File: armv5te/OP_MUL_INT_LIT16.S */
6895 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6896 /* File: armv5te/binopLit16.S */
6898 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6899 * that specifies an instruction that performs "result = r0 op r1".
6900 * This could be an ARM instruction or a function call. (If the result
6901 * comes back in a register other than r0, you can override "result".)
6903 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6904 * vCC (r1). Useful for integer division and modulus.
6906 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6907 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6909 /* binop/lit16 vA, vB, #+CCCC */
6910 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6911 mov r2, rINST, lsr #12 @ r2<- B
6912 mov r9, rINST, lsr #8 @ r9<- A+
6913 GET_VREG(r0, r2) @ r0<- vB
6916 cmp r1, #0 @ is second operand zero?
6917 beq common_errDivideByZero
6919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6921 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6922 GET_INST_OPCODE(ip) @ extract opcode from rINST
6923 SET_VREG(r0, r9) @ vAA<- r0
6924 GOTO_OPCODE(ip) @ jump to next instruction
6925 /* 10-13 instructions */
6929 /* ------------------------------ */
6931 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6932 /* File: armv5te/OP_DIV_INT_LIT16.S */
6933 /* File: armv5te/binopLit16.S */
6935 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6936 * that specifies an instruction that performs "result = r0 op r1".
6937 * This could be an ARM instruction or a function call. (If the result
6938 * comes back in a register other than r0, you can override "result".)
6940 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6941 * vCC (r1). Useful for integer division and modulus.
6943 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6944 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6946 /* binop/lit16 vA, vB, #+CCCC */
6947 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6948 mov r2, rINST, lsr #12 @ r2<- B
6949 mov r9, rINST, lsr #8 @ r9<- A+
6950 GET_VREG(r0, r2) @ r0<- vB
6953 cmp r1, #0 @ is second operand zero?
6954 beq common_errDivideByZero
6956 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6958 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6959 GET_INST_OPCODE(ip) @ extract opcode from rINST
6960 SET_VREG(r0, r9) @ vAA<- r0
6961 GOTO_OPCODE(ip) @ jump to next instruction
6962 /* 10-13 instructions */
6966 /* ------------------------------ */
6968 .L_OP_REM_INT_LIT16: /* 0xd4 */
6969 /* File: armv5te/OP_REM_INT_LIT16.S */
6970 /* idivmod returns quotient in r0 and remainder in r1 */
6971 /* File: armv5te/binopLit16.S */
6973 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6974 * that specifies an instruction that performs "result = r0 op r1".
6975 * This could be an ARM instruction or a function call. (If the result
6976 * comes back in a register other than r0, you can override "result".)
6978 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6979 * vCC (r1). Useful for integer division and modulus.
6981 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6982 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6984 /* binop/lit16 vA, vB, #+CCCC */
6985 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6986 mov r2, rINST, lsr #12 @ r2<- B
6987 mov r9, rINST, lsr #8 @ r9<- A+
6988 GET_VREG(r0, r2) @ r0<- vB
6991 cmp r1, #0 @ is second operand zero?
6992 beq common_errDivideByZero
6994 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6996 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6997 GET_INST_OPCODE(ip) @ extract opcode from rINST
6998 SET_VREG(r1, r9) @ vAA<- r1
6999 GOTO_OPCODE(ip) @ jump to next instruction
7000 /* 10-13 instructions */
7004 /* ------------------------------ */
7006 .L_OP_AND_INT_LIT16: /* 0xd5 */
7007 /* File: armv5te/OP_AND_INT_LIT16.S */
7008 /* File: armv5te/binopLit16.S */
7010 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7011 * that specifies an instruction that performs "result = r0 op r1".
7012 * This could be an ARM instruction or a function call. (If the result
7013 * comes back in a register other than r0, you can override "result".)
7015 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7016 * vCC (r1). Useful for integer division and modulus.
7018 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7019 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7021 /* binop/lit16 vA, vB, #+CCCC */
7022 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7023 mov r2, rINST, lsr #12 @ r2<- B
7024 mov r9, rINST, lsr #8 @ r9<- A+
7025 GET_VREG(r0, r2) @ r0<- vB
7028 cmp r1, #0 @ is second operand zero?
7029 beq common_errDivideByZero
7031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7033 and r0, r0, r1 @ r0<- op, r0-r3 changed
7034 GET_INST_OPCODE(ip) @ extract opcode from rINST
7035 SET_VREG(r0, r9) @ vAA<- r0
7036 GOTO_OPCODE(ip) @ jump to next instruction
7037 /* 10-13 instructions */
7041 /* ------------------------------ */
7043 .L_OP_OR_INT_LIT16: /* 0xd6 */
7044 /* File: armv5te/OP_OR_INT_LIT16.S */
7045 /* File: armv5te/binopLit16.S */
7047 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7048 * that specifies an instruction that performs "result = r0 op r1".
7049 * This could be an ARM instruction or a function call. (If the result
7050 * comes back in a register other than r0, you can override "result".)
7052 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7053 * vCC (r1). Useful for integer division and modulus.
7055 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7056 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7058 /* binop/lit16 vA, vB, #+CCCC */
7059 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7060 mov r2, rINST, lsr #12 @ r2<- B
7061 mov r9, rINST, lsr #8 @ r9<- A+
7062 GET_VREG(r0, r2) @ r0<- vB
7065 cmp r1, #0 @ is second operand zero?
7066 beq common_errDivideByZero
7068 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7070 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7071 GET_INST_OPCODE(ip) @ extract opcode from rINST
7072 SET_VREG(r0, r9) @ vAA<- r0
7073 GOTO_OPCODE(ip) @ jump to next instruction
7074 /* 10-13 instructions */
7078 /* ------------------------------ */
7080 .L_OP_XOR_INT_LIT16: /* 0xd7 */
7081 /* File: armv5te/OP_XOR_INT_LIT16.S */
7082 /* File: armv5te/binopLit16.S */
7084 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
7085 * that specifies an instruction that performs "result = r0 op r1".
7086 * This could be an ARM instruction or a function call. (If the result
7087 * comes back in a register other than r0, you can override "result".)
7089 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7090 * vCC (r1). Useful for integer division and modulus.
7092 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7093 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7095 /* binop/lit16 vA, vB, #+CCCC */
7096 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
7097 mov r2, rINST, lsr #12 @ r2<- B
7098 mov r9, rINST, lsr #8 @ r9<- A+
7099 GET_VREG(r0, r2) @ r0<- vB
7102 cmp r1, #0 @ is second operand zero?
7103 beq common_errDivideByZero
7105 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7107 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7108 GET_INST_OPCODE(ip) @ extract opcode from rINST
7109 SET_VREG(r0, r9) @ vAA<- r0
7110 GOTO_OPCODE(ip) @ jump to next instruction
7111 /* 10-13 instructions */
7115 /* ------------------------------ */
7117 .L_OP_ADD_INT_LIT8: /* 0xd8 */
7118 /* File: armv5te/OP_ADD_INT_LIT8.S */
7119 /* File: armv5te/binopLit8.S */
7121 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7122 * that specifies an instruction that performs "result = r0 op r1".
7123 * This could be an ARM instruction or a function call. (If the result
7124 * comes back in a register other than r0, you can override "result".)
7126 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7127 * vCC (r1). Useful for integer division and modulus.
7129 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7130 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7131 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7133 /* binop/lit8 vAA, vBB, #+CC */
7134 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7135 mov r9, rINST, lsr #8 @ r9<- AA
7136 and r2, r3, #255 @ r2<- BB
7137 GET_VREG(r0, r2) @ r0<- vBB
7138 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7140 @cmp r1, #0 @ is second operand zero?
7141 beq common_errDivideByZero
7143 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7145 @ optional op; may set condition codes
7146 add r0, r0, r1 @ r0<- op, r0-r3 changed
7147 GET_INST_OPCODE(ip) @ extract opcode from rINST
7148 SET_VREG(r0, r9) @ vAA<- r0
7149 GOTO_OPCODE(ip) @ jump to next instruction
7150 /* 10-12 instructions */
7154 /* ------------------------------ */
7156 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
7157 /* File: armv5te/OP_RSUB_INT_LIT8.S */
7158 /* File: armv5te/binopLit8.S */
7160 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7161 * that specifies an instruction that performs "result = r0 op r1".
7162 * This could be an ARM instruction or a function call. (If the result
7163 * comes back in a register other than r0, you can override "result".)
7165 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7166 * vCC (r1). Useful for integer division and modulus.
7168 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7169 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7170 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7172 /* binop/lit8 vAA, vBB, #+CC */
7173 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7174 mov r9, rINST, lsr #8 @ r9<- AA
7175 and r2, r3, #255 @ r2<- BB
7176 GET_VREG(r0, r2) @ r0<- vBB
7177 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7179 @cmp r1, #0 @ is second operand zero?
7180 beq common_errDivideByZero
7182 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7184 @ optional op; may set condition codes
7185 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
7186 GET_INST_OPCODE(ip) @ extract opcode from rINST
7187 SET_VREG(r0, r9) @ vAA<- r0
7188 GOTO_OPCODE(ip) @ jump to next instruction
7189 /* 10-12 instructions */
7193 /* ------------------------------ */
7195 .L_OP_MUL_INT_LIT8: /* 0xda */
7196 /* File: armv5te/OP_MUL_INT_LIT8.S */
7197 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7198 /* File: armv5te/binopLit8.S */
7200 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7201 * that specifies an instruction that performs "result = r0 op r1".
7202 * This could be an ARM instruction or a function call. (If the result
7203 * comes back in a register other than r0, you can override "result".)
7205 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7206 * vCC (r1). Useful for integer division and modulus.
7208 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7209 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7210 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7212 /* binop/lit8 vAA, vBB, #+CC */
7213 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7214 mov r9, rINST, lsr #8 @ r9<- AA
7215 and r2, r3, #255 @ r2<- BB
7216 GET_VREG(r0, r2) @ r0<- vBB
7217 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7219 @cmp r1, #0 @ is second operand zero?
7220 beq common_errDivideByZero
7222 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7224 @ optional op; may set condition codes
7225 mul r0, r1, r0 @ r0<- op, r0-r3 changed
7226 GET_INST_OPCODE(ip) @ extract opcode from rINST
7227 SET_VREG(r0, r9) @ vAA<- r0
7228 GOTO_OPCODE(ip) @ jump to next instruction
7229 /* 10-12 instructions */
7233 /* ------------------------------ */
7235 .L_OP_DIV_INT_LIT8: /* 0xdb */
7236 /* File: armv5te/OP_DIV_INT_LIT8.S */
7237 /* File: armv5te/binopLit8.S */
7239 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7240 * that specifies an instruction that performs "result = r0 op r1".
7241 * This could be an ARM instruction or a function call. (If the result
7242 * comes back in a register other than r0, you can override "result".)
7244 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7245 * vCC (r1). Useful for integer division and modulus.
7247 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7248 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7249 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7251 /* binop/lit8 vAA, vBB, #+CC */
7252 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7253 mov r9, rINST, lsr #8 @ r9<- AA
7254 and r2, r3, #255 @ r2<- BB
7255 GET_VREG(r0, r2) @ r0<- vBB
7256 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7258 @cmp r1, #0 @ is second operand zero?
7259 beq common_errDivideByZero
7261 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7263 @ optional op; may set condition codes
7264 bl __aeabi_idiv @ r0<- op, r0-r3 changed
7265 GET_INST_OPCODE(ip) @ extract opcode from rINST
7266 SET_VREG(r0, r9) @ vAA<- r0
7267 GOTO_OPCODE(ip) @ jump to next instruction
7268 /* 10-12 instructions */
7272 /* ------------------------------ */
7274 .L_OP_REM_INT_LIT8: /* 0xdc */
7275 /* File: armv5te/OP_REM_INT_LIT8.S */
7276 /* idivmod returns quotient in r0 and remainder in r1 */
7277 /* File: armv5te/binopLit8.S */
7279 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7280 * that specifies an instruction that performs "result = r0 op r1".
7281 * This could be an ARM instruction or a function call. (If the result
7282 * comes back in a register other than r0, you can override "result".)
7284 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7285 * vCC (r1). Useful for integer division and modulus.
7287 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7288 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7289 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7291 /* binop/lit8 vAA, vBB, #+CC */
7292 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7293 mov r9, rINST, lsr #8 @ r9<- AA
7294 and r2, r3, #255 @ r2<- BB
7295 GET_VREG(r0, r2) @ r0<- vBB
7296 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7298 @cmp r1, #0 @ is second operand zero?
7299 beq common_errDivideByZero
7301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7303 @ optional op; may set condition codes
7304 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
7305 GET_INST_OPCODE(ip) @ extract opcode from rINST
7306 SET_VREG(r1, r9) @ vAA<- r1
7307 GOTO_OPCODE(ip) @ jump to next instruction
7308 /* 10-12 instructions */
7312 /* ------------------------------ */
7314 .L_OP_AND_INT_LIT8: /* 0xdd */
7315 /* File: armv5te/OP_AND_INT_LIT8.S */
7316 /* File: armv5te/binopLit8.S */
7318 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7319 * that specifies an instruction that performs "result = r0 op r1".
7320 * This could be an ARM instruction or a function call. (If the result
7321 * comes back in a register other than r0, you can override "result".)
7323 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7324 * vCC (r1). Useful for integer division and modulus.
7326 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7327 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7328 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7330 /* binop/lit8 vAA, vBB, #+CC */
7331 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7332 mov r9, rINST, lsr #8 @ r9<- AA
7333 and r2, r3, #255 @ r2<- BB
7334 GET_VREG(r0, r2) @ r0<- vBB
7335 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7337 @cmp r1, #0 @ is second operand zero?
7338 beq common_errDivideByZero
7340 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7342 @ optional op; may set condition codes
7343 and r0, r0, r1 @ r0<- op, r0-r3 changed
7344 GET_INST_OPCODE(ip) @ extract opcode from rINST
7345 SET_VREG(r0, r9) @ vAA<- r0
7346 GOTO_OPCODE(ip) @ jump to next instruction
7347 /* 10-12 instructions */
7351 /* ------------------------------ */
7353 .L_OP_OR_INT_LIT8: /* 0xde */
7354 /* File: armv5te/OP_OR_INT_LIT8.S */
7355 /* File: armv5te/binopLit8.S */
7357 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7358 * that specifies an instruction that performs "result = r0 op r1".
7359 * This could be an ARM instruction or a function call. (If the result
7360 * comes back in a register other than r0, you can override "result".)
7362 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7363 * vCC (r1). Useful for integer division and modulus.
7365 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7366 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7367 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7369 /* binop/lit8 vAA, vBB, #+CC */
7370 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7371 mov r9, rINST, lsr #8 @ r9<- AA
7372 and r2, r3, #255 @ r2<- BB
7373 GET_VREG(r0, r2) @ r0<- vBB
7374 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7376 @cmp r1, #0 @ is second operand zero?
7377 beq common_errDivideByZero
7379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7381 @ optional op; may set condition codes
7382 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7383 GET_INST_OPCODE(ip) @ extract opcode from rINST
7384 SET_VREG(r0, r9) @ vAA<- r0
7385 GOTO_OPCODE(ip) @ jump to next instruction
7386 /* 10-12 instructions */
7390 /* ------------------------------ */
7392 .L_OP_XOR_INT_LIT8: /* 0xdf */
7393 /* File: armv5te/OP_XOR_INT_LIT8.S */
7394 /* File: armv5te/binopLit8.S */
7396 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7397 * that specifies an instruction that performs "result = r0 op r1".
7398 * This could be an ARM instruction or a function call. (If the result
7399 * comes back in a register other than r0, you can override "result".)
7401 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7402 * vCC (r1). Useful for integer division and modulus.
7404 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7405 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7406 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7408 /* binop/lit8 vAA, vBB, #+CC */
7409 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7410 mov r9, rINST, lsr #8 @ r9<- AA
7411 and r2, r3, #255 @ r2<- BB
7412 GET_VREG(r0, r2) @ r0<- vBB
7413 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7415 @cmp r1, #0 @ is second operand zero?
7416 beq common_errDivideByZero
7418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7420 @ optional op; may set condition codes
7421 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7422 GET_INST_OPCODE(ip) @ extract opcode from rINST
7423 SET_VREG(r0, r9) @ vAA<- r0
7424 GOTO_OPCODE(ip) @ jump to next instruction
7425 /* 10-12 instructions */
7429 /* ------------------------------ */
7431 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7432 /* File: armv5te/OP_SHL_INT_LIT8.S */
7433 /* File: armv5te/binopLit8.S */
7435 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7436 * that specifies an instruction that performs "result = r0 op r1".
7437 * This could be an ARM instruction or a function call. (If the result
7438 * comes back in a register other than r0, you can override "result".)
7440 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7441 * vCC (r1). Useful for integer division and modulus.
7443 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7444 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7445 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7447 /* binop/lit8 vAA, vBB, #+CC */
7448 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7449 mov r9, rINST, lsr #8 @ r9<- AA
7450 and r2, r3, #255 @ r2<- BB
7451 GET_VREG(r0, r2) @ r0<- vBB
7452 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7454 @cmp r1, #0 @ is second operand zero?
7455 beq common_errDivideByZero
7457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7459 and r1, r1, #31 @ optional op; may set condition codes
7460 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7461 GET_INST_OPCODE(ip) @ extract opcode from rINST
7462 SET_VREG(r0, r9) @ vAA<- r0
7463 GOTO_OPCODE(ip) @ jump to next instruction
7464 /* 10-12 instructions */
7468 /* ------------------------------ */
7470 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7471 /* File: armv5te/OP_SHR_INT_LIT8.S */
7472 /* File: armv5te/binopLit8.S */
7474 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7475 * that specifies an instruction that performs "result = r0 op r1".
7476 * This could be an ARM instruction or a function call. (If the result
7477 * comes back in a register other than r0, you can override "result".)
7479 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7480 * vCC (r1). Useful for integer division and modulus.
7482 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7483 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7484 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7486 /* binop/lit8 vAA, vBB, #+CC */
7487 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7488 mov r9, rINST, lsr #8 @ r9<- AA
7489 and r2, r3, #255 @ r2<- BB
7490 GET_VREG(r0, r2) @ r0<- vBB
7491 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7493 @cmp r1, #0 @ is second operand zero?
7494 beq common_errDivideByZero
7496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7498 and r1, r1, #31 @ optional op; may set condition codes
7499 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7500 GET_INST_OPCODE(ip) @ extract opcode from rINST
7501 SET_VREG(r0, r9) @ vAA<- r0
7502 GOTO_OPCODE(ip) @ jump to next instruction
7503 /* 10-12 instructions */
7507 /* ------------------------------ */
7509 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7510 /* File: armv5te/OP_USHR_INT_LIT8.S */
7511 /* File: armv5te/binopLit8.S */
7513 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7514 * that specifies an instruction that performs "result = r0 op r1".
7515 * This could be an ARM instruction or a function call. (If the result
7516 * comes back in a register other than r0, you can override "result".)
7518 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7519 * vCC (r1). Useful for integer division and modulus.
7521 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7522 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7523 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7525 /* binop/lit8 vAA, vBB, #+CC */
7526 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7527 mov r9, rINST, lsr #8 @ r9<- AA
7528 and r2, r3, #255 @ r2<- BB
7529 GET_VREG(r0, r2) @ r0<- vBB
7530 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7532 @cmp r1, #0 @ is second operand zero?
7533 beq common_errDivideByZero
7535 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7537 and r1, r1, #31 @ optional op; may set condition codes
7538 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7539 GET_INST_OPCODE(ip) @ extract opcode from rINST
7540 SET_VREG(r0, r9) @ vAA<- r0
7541 GOTO_OPCODE(ip) @ jump to next instruction
7542 /* 10-12 instructions */
7546 /* ------------------------------ */
7548 .L_OP_UNUSED_E3: /* 0xe3 */
7549 /* File: armv5te/OP_UNUSED_E3.S */
7550 /* File: armv5te/unused.S */
7555 /* ------------------------------ */
7557 .L_OP_UNUSED_E4: /* 0xe4 */
7558 /* File: armv5te/OP_UNUSED_E4.S */
7559 /* File: armv5te/unused.S */
7564 /* ------------------------------ */
7566 .L_OP_UNUSED_E5: /* 0xe5 */
7567 /* File: armv5te/OP_UNUSED_E5.S */
7568 /* File: armv5te/unused.S */
7573 /* ------------------------------ */
7575 .L_OP_UNUSED_E6: /* 0xe6 */
7576 /* File: armv5te/OP_UNUSED_E6.S */
7577 /* File: armv5te/unused.S */
7582 /* ------------------------------ */
7584 .L_OP_UNUSED_E7: /* 0xe7 */
7585 /* File: armv5te/OP_UNUSED_E7.S */
7586 /* File: armv5te/unused.S */
7591 /* ------------------------------ */
7593 .L_OP_UNUSED_E8: /* 0xe8 */
7594 /* File: armv5te/OP_UNUSED_E8.S */
7595 /* File: armv5te/unused.S */
7600 /* ------------------------------ */
7602 .L_OP_UNUSED_E9: /* 0xe9 */
7603 /* File: armv5te/OP_UNUSED_E9.S */
7604 /* File: armv5te/unused.S */
7609 /* ------------------------------ */
7611 .L_OP_UNUSED_EA: /* 0xea */
7612 /* File: armv5te/OP_UNUSED_EA.S */
7613 /* File: armv5te/unused.S */
7618 /* ------------------------------ */
7620 .L_OP_UNUSED_EB: /* 0xeb */
7621 /* File: armv5te/OP_UNUSED_EB.S */
7622 /* File: armv5te/unused.S */
7627 /* ------------------------------ */
7629 .L_OP_BREAKPOINT: /* 0xec */
7630 /* File: armv5te/OP_BREAKPOINT.S */
7631 /* File: armv5te/unused.S */
7636 /* ------------------------------ */
7638 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7639 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7641 * Handle a throw-verification-error instruction. This throws an
7642 * exception for an error discovered during verification. The
7643 * exception is indicated by AA, with some detail provided by BBBB.
7645 /* op AA, ref@BBBB */
7646 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7647 FETCH(r2, 1) @ r2<- BBBB
7648 EXPORT_PC() @ export the PC
7649 mov r1, rINST, lsr #8 @ r1<- AA
7650 bl dvmThrowVerificationError @ always throws
7651 b common_exceptionThrown @ handle exception
7654 /* ------------------------------ */
7656 .L_OP_EXECUTE_INLINE: /* 0xee */
7657 /* File: armv5te/OP_EXECUTE_INLINE.S */
7659 * Execute a "native inline" instruction.
7661 * We need to call an InlineOp4Func:
7662 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7664 * The first four args are in r0-r3, pointer to return value storage
7665 * is on the stack. The function's return value is a flag that tells
7666 * us if an exception was thrown.
7668 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7669 FETCH(r10, 1) @ r10<- BBBB
7670 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7671 EXPORT_PC() @ can throw
7672 sub sp, sp, #8 @ make room for arg, +64 bit align
7673 mov r0, rINST, lsr #12 @ r0<- B
7674 str r1, [sp] @ push &glue->retval
7675 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7676 add sp, sp, #8 @ pop stack
7677 cmp r0, #0 @ test boolean result of inline
7678 beq common_exceptionThrown @ returned false, handle exception
7679 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7680 GET_INST_OPCODE(ip) @ extract opcode from rINST
7681 GOTO_OPCODE(ip) @ jump to next instruction
7683 /* ------------------------------ */
7685 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7686 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7688 * Execute a "native inline" instruction, using "/range" semantics.
7689 * Same idea as execute-inline, but we get the args differently.
7691 * We need to call an InlineOp4Func:
7692 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7694 * The first four args are in r0-r3, pointer to return value storage
7695 * is on the stack. The function's return value is a flag that tells
7696 * us if an exception was thrown.
7698 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7699 FETCH(r10, 1) @ r10<- BBBB
7700 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7701 EXPORT_PC() @ can throw
7702 sub sp, sp, #8 @ make room for arg, +64 bit align
7703 mov r0, rINST, lsr #8 @ r0<- AA
7704 str r1, [sp] @ push &glue->retval
7705 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after
7706 add sp, sp, #8 @ pop stack
7707 cmp r0, #0 @ test boolean result of inline
7708 beq common_exceptionThrown @ returned false, handle exception
7709 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7710 GET_INST_OPCODE(ip) @ extract opcode from rINST
7711 GOTO_OPCODE(ip) @ jump to next instruction
7713 /* ------------------------------ */
7715 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7716 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7718 * invoke-direct-empty is a no-op in a "standard" interpreter.
7720 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7721 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7722 GOTO_OPCODE(ip) @ execute it
7724 /* ------------------------------ */
7726 .L_OP_UNUSED_F1: /* 0xf1 */
7727 /* File: armv5te/OP_UNUSED_F1.S */
7728 /* File: armv5te/unused.S */
7733 /* ------------------------------ */
7735 .L_OP_IGET_QUICK: /* 0xf2 */
7736 /* File: armv5te/OP_IGET_QUICK.S */
7737 /* For: iget-quick, iget-object-quick */
7738 /* op vA, vB, offset@CCCC */
7739 mov r2, rINST, lsr #12 @ r2<- B
7740 GET_VREG(r3, r2) @ r3<- object we're operating on
7741 FETCH(r1, 1) @ r1<- field byte offset
7742 cmp r3, #0 @ check object for null
7743 mov r2, rINST, lsr #8 @ r2<- A(+)
7744 beq common_errNullObject @ object was null
7745 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7746 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7748 GET_INST_OPCODE(ip) @ extract opcode from rINST
7749 SET_VREG(r0, r2) @ fp[A]<- r0
7750 GOTO_OPCODE(ip) @ jump to next instruction
7753 /* ------------------------------ */
7755 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7756 /* File: armv4t/OP_IGET_WIDE_QUICK.S */
7757 /* iget-wide-quick vA, vB, offset@CCCC */
7758 mov r2, rINST, lsr #12 @ r2<- B
7759 GET_VREG(r3, r2) @ r3<- object we're operating on
7760 FETCH(r1, 1) @ r1<- field byte offset
7761 cmp r3, #0 @ check object for null
7762 mov r2, rINST, lsr #8 @ r2<- A(+)
7763 beq common_errNullObject @ object was null
7764 add r9, r3, r1 @ r9<- object + offset
7765 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64 bits, aligned)
7766 and r2, r2, #15 @ r2<- A
7767 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7768 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7769 GET_INST_OPCODE(ip) @ extract opcode from rINST
7770 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7771 GOTO_OPCODE(ip) @ jump to next instruction
7774 /* ------------------------------ */
7776 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7777 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7778 /* File: armv5te/OP_IGET_QUICK.S */
7779 /* For: iget-quick, iget-object-quick */
7780 /* op vA, vB, offset@CCCC */
7781 mov r2, rINST, lsr #12 @ r2<- B
7782 GET_VREG(r3, r2) @ r3<- object we're operating on
7783 FETCH(r1, 1) @ r1<- field byte offset
7784 cmp r3, #0 @ check object for null
7785 mov r2, rINST, lsr #8 @ r2<- A(+)
7786 beq common_errNullObject @ object was null
7787 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7790 GET_INST_OPCODE(ip) @ extract opcode from rINST
7791 SET_VREG(r0, r2) @ fp[A]<- r0
7792 GOTO_OPCODE(ip) @ jump to next instruction
7796 /* ------------------------------ */
7798 .L_OP_IPUT_QUICK: /* 0xf5 */
7799 /* File: armv5te/OP_IPUT_QUICK.S */
7800 /* For: iput-quick, iput-object-quick */
7801 /* op vA, vB, offset@CCCC */
7802 mov r2, rINST, lsr #12 @ r2<- B
7803 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7804 FETCH(r1, 1) @ r1<- field byte offset
7805 cmp r3, #0 @ check object for null
7806 mov r2, rINST, lsr #8 @ r2<- A(+)
7807 beq common_errNullObject @ object was null
7809 GET_VREG(r0, r2) @ r0<- fp[A]
7810 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7811 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7812 GET_INST_OPCODE(ip) @ extract opcode from rINST
7813 GOTO_OPCODE(ip) @ jump to next instruction
7816 /* ------------------------------ */
7818 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7819 /* File: armv4t/OP_IPUT_WIDE_QUICK.S */
7820 /* iput-wide-quick vA, vB, offset@CCCC */
7821 mov r0, rINST, lsr #8 @ r0<- A(+)
7822 mov r1, rINST, lsr #12 @ r1<- B
7824 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7825 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7826 cmp r2, #0 @ check object for null
7827 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7828 beq common_errNullObject @ object was null
7829 FETCH(r3, 1) @ r3<- field byte offset
7830 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7831 add r2, r2, r3 @ r2<- object + byte offset
7832 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
7833 GET_INST_OPCODE(ip) @ extract opcode from rINST
7834 GOTO_OPCODE(ip) @ jump to next instruction
7837 /* ------------------------------ */
7839 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7840 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7841 /* File: armv5te/OP_IPUT_QUICK.S */
7842 /* For: iput-quick, iput-object-quick */
7843 /* op vA, vB, offset@CCCC */
7844 mov r2, rINST, lsr #12 @ r2<- B
7845 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7846 FETCH(r1, 1) @ r1<- field byte offset
7847 cmp r3, #0 @ check object for null
7848 mov r2, rINST, lsr #8 @ r2<- A(+)
7849 beq common_errNullObject @ object was null
7851 GET_VREG(r0, r2) @ r0<- fp[A]
7852 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7853 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7854 GET_INST_OPCODE(ip) @ extract opcode from rINST
7855 GOTO_OPCODE(ip) @ jump to next instruction
7859 /* ------------------------------ */
7861 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7862 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7864 * Handle an optimized virtual method call.
7866 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7868 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7869 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7870 FETCH(r3, 2) @ r3<- FEDC or CCCC
7871 FETCH(r1, 1) @ r1<- BBBB
7873 and r3, r3, #15 @ r3<- C (or stays CCCC)
7875 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7876 cmp r2, #0 @ is "this" null?
7877 beq common_errNullObject @ null "this", throw exception
7878 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7879 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7880 EXPORT_PC() @ invoke must export
7881 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7882 bl common_invokeMethodNoRange @ continue on
7884 /* ------------------------------ */
7886 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7887 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7888 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7890 * Handle an optimized virtual method call.
7892 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7894 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7895 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7896 FETCH(r3, 2) @ r3<- FEDC or CCCC
7897 FETCH(r1, 1) @ r1<- BBBB
7899 and r3, r3, #15 @ r3<- C (or stays CCCC)
7901 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7902 cmp r2, #0 @ is "this" null?
7903 beq common_errNullObject @ null "this", throw exception
7904 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7905 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7906 EXPORT_PC() @ invoke must export
7907 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7908 bl common_invokeMethodRange @ continue on
7911 /* ------------------------------ */
7913 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7914 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7916 * Handle an optimized "super" method call.
7918 * for: [opt] invoke-super-quick, invoke-super-quick/range
7920 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7921 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7922 FETCH(r10, 2) @ r10<- GFED or CCCC
7923 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7925 and r10, r10, #15 @ r10<- D (or stays CCCC)
7927 FETCH(r1, 1) @ r1<- BBBB
7928 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7929 EXPORT_PC() @ must export for invoke
7930 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7931 GET_VREG(r3, r10) @ r3<- "this"
7932 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7933 cmp r3, #0 @ null "this" ref?
7934 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7935 beq common_errNullObject @ "this" is null, throw exception
7936 bl common_invokeMethodNoRange @ continue on
7939 /* ------------------------------ */
7941 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7942 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7943 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7945 * Handle an optimized "super" method call.
7947 * for: [opt] invoke-super-quick, invoke-super-quick/range
7949 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7950 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7951 FETCH(r10, 2) @ r10<- GFED or CCCC
7952 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7954 and r10, r10, #15 @ r10<- D (or stays CCCC)
7956 FETCH(r1, 1) @ r1<- BBBB
7957 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7958 EXPORT_PC() @ must export for invoke
7959 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7960 GET_VREG(r3, r10) @ r3<- "this"
7961 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7962 cmp r3, #0 @ null "this" ref?
7963 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7964 beq common_errNullObject @ "this" is null, throw exception
7965 bl common_invokeMethodRange @ continue on
7969 /* ------------------------------ */
7971 .L_OP_UNUSED_FC: /* 0xfc */
7972 /* File: armv5te/OP_UNUSED_FC.S */
7973 /* File: armv5te/unused.S */
7978 /* ------------------------------ */
7980 .L_OP_UNUSED_FD: /* 0xfd */
7981 /* File: armv5te/OP_UNUSED_FD.S */
7982 /* File: armv5te/unused.S */
7987 /* ------------------------------ */
7989 .L_OP_UNUSED_FE: /* 0xfe */
7990 /* File: armv5te/OP_UNUSED_FE.S */
7991 /* File: armv5te/unused.S */
7996 /* ------------------------------ */
7998 .L_OP_UNUSED_FF: /* 0xff */
7999 /* File: armv5te/OP_UNUSED_FF.S */
8000 /* File: armv5te/unused.S */
8007 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
8008 .global dvmAsmInstructionEnd
8009 dvmAsmInstructionEnd:
8012 * ===========================================================================
8013 * Sister implementations
8014 * ===========================================================================
8016 .global dvmAsmSisterStart
8017 .type dvmAsmSisterStart, %function
8022 /* continuation for OP_CONST_STRING */
8025 * Continuation if the String has not yet been resolved.
8026 * r1: BBBB (String ref)
8027 * r9: target register
8029 .LOP_CONST_STRING_resolve:
8031 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8032 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8033 bl dvmResolveString @ r0<- String reference
8034 cmp r0, #0 @ failed?
8035 beq common_exceptionThrown @ yup, handle the exception
8036 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8037 GET_INST_OPCODE(ip) @ extract opcode from rINST
8038 SET_VREG(r0, r9) @ vAA<- r0
8039 GOTO_OPCODE(ip) @ jump to next instruction
8042 /* continuation for OP_CONST_STRING_JUMBO */
8045 * Continuation if the String has not yet been resolved.
8046 * r1: BBBBBBBB (String ref)
8047 * r9: target register
8049 .LOP_CONST_STRING_JUMBO_resolve:
8051 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8052 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8053 bl dvmResolveString @ r0<- String reference
8054 cmp r0, #0 @ failed?
8055 beq common_exceptionThrown @ yup, handle the exception
8056 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
8057 GET_INST_OPCODE(ip) @ extract opcode from rINST
8058 SET_VREG(r0, r9) @ vAA<- r0
8059 GOTO_OPCODE(ip) @ jump to next instruction
8062 /* continuation for OP_CONST_CLASS */
8065 * Continuation if the Class has not yet been resolved.
8066 * r1: BBBB (Class ref)
8067 * r9: target register
8069 .LOP_CONST_CLASS_resolve:
8071 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8072 mov r2, #1 @ r2<- true
8073 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8074 bl dvmResolveClass @ r0<- Class reference
8075 cmp r0, #0 @ failed?
8076 beq common_exceptionThrown @ yup, handle the exception
8077 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8078 GET_INST_OPCODE(ip) @ extract opcode from rINST
8079 SET_VREG(r0, r9) @ vAA<- r0
8080 GOTO_OPCODE(ip) @ jump to next instruction
8083 /* continuation for OP_CHECK_CAST */
8086 * Trivial test failed, need to perform full check. This is common.
8087 * r0 holds obj->clazz
8088 * r1 holds class resolved from BBBB
8091 .LOP_CHECK_CAST_fullcheck:
8092 bl dvmInstanceofNonTrivial @ r0<- boolean result
8093 cmp r0, #0 @ failed?
8094 bne .LOP_CHECK_CAST_okay @ no, success
8096 @ A cast has failed. We need to throw a ClassCastException with the
8097 @ class of the object that failed to be cast.
8098 EXPORT_PC() @ about to throw
8099 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz
8100 ldr r0, .LstrClassCastExceptionPtr
8101 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8102 bl dvmThrowExceptionWithClassMessage
8103 b common_exceptionThrown
8106 * Resolution required. This is the least-likely path.
8111 .LOP_CHECK_CAST_resolve:
8112 EXPORT_PC() @ resolve() could throw
8113 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8114 mov r1, r2 @ r1<- BBBB
8115 mov r2, #0 @ r2<- false
8116 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8117 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8118 cmp r0, #0 @ got null?
8119 beq common_exceptionThrown @ yes, handle exception
8120 mov r1, r0 @ r1<- class resolved from BBB
8121 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8122 b .LOP_CHECK_CAST_resolved @ pick up where we left off
8124 .LstrClassCastExceptionPtr:
8125 .word .LstrClassCastException
8128 /* continuation for OP_INSTANCE_OF */
8131 * Trivial test failed, need to perform full check. This is common.
8132 * r0 holds obj->clazz
8133 * r1 holds class resolved from BBBB
8136 .LOP_INSTANCE_OF_fullcheck:
8137 bl dvmInstanceofNonTrivial @ r0<- boolean result
8138 @ fall through to OP_INSTANCE_OF_store
8141 * r0 holds boolean result
8144 .LOP_INSTANCE_OF_store:
8145 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8146 SET_VREG(r0, r9) @ vA<- r0
8147 GET_INST_OPCODE(ip) @ extract opcode from rINST
8148 GOTO_OPCODE(ip) @ jump to next instruction
8151 * Trivial test succeeded, save and bail.
8154 .LOP_INSTANCE_OF_trivial:
8155 mov r0, #1 @ indicate success
8156 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8157 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8158 SET_VREG(r0, r9) @ vA<- r0
8159 GET_INST_OPCODE(ip) @ extract opcode from rINST
8160 GOTO_OPCODE(ip) @ jump to next instruction
8163 * Resolution required. This is the least-likely path.
8168 .LOP_INSTANCE_OF_resolve:
8169 EXPORT_PC() @ resolve() could throw
8170 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8171 mov r1, r3 @ r1<- BBBB
8172 mov r2, #1 @ r2<- true
8173 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
8174 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8175 cmp r0, #0 @ got null?
8176 beq common_exceptionThrown @ yes, handle exception
8177 mov r1, r0 @ r1<- class resolved from BBB
8178 mov r3, rINST, lsr #12 @ r3<- B
8179 GET_VREG(r0, r3) @ r0<- vB (object)
8180 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
8181 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
8184 /* continuation for OP_NEW_INSTANCE */
8186 .balign 32 @ minimize cache lines
8187 .LOP_NEW_INSTANCE_finish: @ r0=new object
8188 mov r3, rINST, lsr #8 @ r3<- AA
8189 cmp r0, #0 @ failed?
8190 beq common_exceptionThrown @ yes, handle the exception
8191 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8192 GET_INST_OPCODE(ip) @ extract opcode from rINST
8193 SET_VREG(r0, r3) @ vAA<- r0
8194 GOTO_OPCODE(ip) @ jump to next instruction
8197 * Class initialization required.
8199 * r0 holds class object
8201 .LOP_NEW_INSTANCE_needinit:
8202 mov r9, r0 @ save r0
8203 bl dvmInitClass @ initialize class
8204 cmp r0, #0 @ check boolean result
8205 mov r0, r9 @ restore r0
8206 bne .LOP_NEW_INSTANCE_initialized @ success, continue
8207 b common_exceptionThrown @ failed, deal with init exception
8210 * Resolution required. This is the least-likely path.
8214 .LOP_NEW_INSTANCE_resolve:
8215 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8216 mov r2, #0 @ r2<- false
8217 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8218 bl dvmResolveClass @ r0<- resolved ClassObject ptr
8219 cmp r0, #0 @ got null?
8220 bne .LOP_NEW_INSTANCE_resolved @ no, continue
8221 b common_exceptionThrown @ yes, handle exception
8223 .LstrInstantiationErrorPtr:
8224 .word .LstrInstantiationError
8227 /* continuation for OP_NEW_ARRAY */
8231 * Resolve class. (This is an uncommon case.)
8233 * r1 holds array length
8234 * r2 holds class ref CCCC
8236 .LOP_NEW_ARRAY_resolve:
8237 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8238 mov r9, r1 @ r9<- length (save)
8239 mov r1, r2 @ r1<- CCCC
8240 mov r2, #0 @ r2<- false
8241 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8242 bl dvmResolveClass @ r0<- call(clazz, ref)
8243 cmp r0, #0 @ got null?
8244 mov r1, r9 @ r1<- length (restore)
8245 beq common_exceptionThrown @ yes, handle exception
8246 @ fall through to OP_NEW_ARRAY_finish
8249 * Finish allocation.
8252 * r1 holds array length
8254 .LOP_NEW_ARRAY_finish:
8255 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
8256 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
8257 cmp r0, #0 @ failed?
8258 mov r2, rINST, lsr #8 @ r2<- A+
8259 beq common_exceptionThrown @ yes, handle the exception
8260 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8261 and r2, r2, #15 @ r2<- A
8262 GET_INST_OPCODE(ip) @ extract opcode from rINST
8263 SET_VREG(r0, r2) @ vA<- r0
8264 GOTO_OPCODE(ip) @ jump to next instruction
8267 /* continuation for OP_FILLED_NEW_ARRAY */
8271 * r0 holds array class
8272 * r10 holds AA or BA
8274 .LOP_FILLED_NEW_ARRAY_continue:
8275 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8276 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8277 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8279 mov r1, r10 @ r1<- AA (length)
8281 mov r1, r10, lsr #4 @ r1<- B (length)
8283 cmp r3, #'I' @ array of ints?
8284 cmpne r3, #'L' @ array of objects?
8285 cmpne r3, #'[' @ array of arrays?
8286 mov r9, r1 @ save length in r9
8287 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
8288 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8289 cmp r0, #0 @ null return?
8290 beq common_exceptionThrown @ alloc failed, handle exception
8292 FETCH(r1, 2) @ r1<- FEDC or CCCC
8293 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8294 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8295 subs r9, r9, #1 @ length--, check for neg
8296 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8297 bmi 2f @ was zero, bail
8299 @ copy values from registers into the array
8300 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8302 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8303 1: ldr r3, [r2], #4 @ r3<- *r2++
8304 subs r9, r9, #1 @ count--
8305 str r3, [r0], #4 @ *contents++ = vX
8309 cmp r9, #4 @ length was initially 5?
8310 and r2, r10, #15 @ r2<- A
8311 bne 1f @ <= 4 args, branch
8312 GET_VREG(r3, r2) @ r3<- vA
8313 sub r9, r9, #1 @ count--
8314 str r3, [r0, #16] @ contents[4] = vA
8315 1: and r2, r1, #15 @ r2<- F/E/D/C
8316 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8317 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8318 subs r9, r9, #1 @ count--
8319 str r3, [r0], #4 @ *contents++ = vX
8325 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8326 GOTO_OPCODE(ip) @ execute it
8329 * Throw an exception indicating that we have not implemented this
8330 * mode of filled-new-array.
8332 .LOP_FILLED_NEW_ARRAY_notimpl:
8333 ldr r0, .L_strInternalError
8334 ldr r1, .L_strFilledNewArrayNotImpl
8335 bl dvmThrowException
8336 b common_exceptionThrown
8338 .if (!0) @ define in one or the other, not both
8339 .L_strFilledNewArrayNotImpl:
8340 .word .LstrFilledNewArrayNotImpl
8341 .L_strInternalError:
8342 .word .LstrInternalError
8346 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8350 * r0 holds array class
8351 * r10 holds AA or BA
8353 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8354 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8355 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8356 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8358 mov r1, r10 @ r1<- AA (length)
8360 mov r1, r10, lsr #4 @ r1<- B (length)
8362 cmp r3, #'I' @ array of ints?
8363 cmpne r3, #'L' @ array of objects?
8364 cmpne r3, #'[' @ array of arrays?
8365 mov r9, r1 @ save length in r9
8366 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
8367 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8368 cmp r0, #0 @ null return?
8369 beq common_exceptionThrown @ alloc failed, handle exception
8371 FETCH(r1, 2) @ r1<- FEDC or CCCC
8372 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8373 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8374 subs r9, r9, #1 @ length--, check for neg
8375 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8376 bmi 2f @ was zero, bail
8378 @ copy values from registers into the array
8379 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8381 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8382 1: ldr r3, [r2], #4 @ r3<- *r2++
8383 subs r9, r9, #1 @ count--
8384 str r3, [r0], #4 @ *contents++ = vX
8388 cmp r9, #4 @ length was initially 5?
8389 and r2, r10, #15 @ r2<- A
8390 bne 1f @ <= 4 args, branch
8391 GET_VREG(r3, r2) @ r3<- vA
8392 sub r9, r9, #1 @ count--
8393 str r3, [r0, #16] @ contents[4] = vA
8394 1: and r2, r1, #15 @ r2<- F/E/D/C
8395 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8396 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8397 subs r9, r9, #1 @ count--
8398 str r3, [r0], #4 @ *contents++ = vX
8404 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8405 GOTO_OPCODE(ip) @ execute it
8408 * Throw an exception indicating that we have not implemented this
8409 * mode of filled-new-array.
8411 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8412 ldr r0, .L_strInternalError
8413 ldr r1, .L_strFilledNewArrayNotImpl
8414 bl dvmThrowException
8415 b common_exceptionThrown
8417 .if (!1) @ define in one or the other, not both
8418 .L_strFilledNewArrayNotImpl:
8419 .word .LstrFilledNewArrayNotImpl
8420 .L_strInternalError:
8421 .word .LstrInternalError
8425 /* continuation for OP_CMPL_FLOAT */
8427 @ Test for NaN with a second comparison. EABI forbids testing bit
8428 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8429 @ make the library call.
8430 .LOP_CMPL_FLOAT_gt_or_nan:
8431 mov r1, r9 @ reverse order
8433 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8435 movcc r1, #1 @ (greater than) r1<- 1
8436 bcc .LOP_CMPL_FLOAT_finish
8437 mvn r1, #0 @ r1<- 1 or -1 for NaN
8438 b .LOP_CMPL_FLOAT_finish
8441 #if 0 /* "clasic" form */
8442 FETCH(r0, 1) @ r0<- CCBB
8443 and r2, r0, #255 @ r2<- BB
8444 mov r3, r0, lsr #8 @ r3<- CC
8445 GET_VREG(r9, r2) @ r9<- vBB
8446 GET_VREG(r10, r3) @ r10<- vCC
8447 mov r0, r9 @ r0<- vBB
8448 mov r1, r10 @ r1<- vCC
8449 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8451 movne r1, #0 @ yes, result is 0
8452 bne OP_CMPL_FLOAT_finish
8453 mov r0, r9 @ r0<- vBB
8454 mov r1, r10 @ r1<- vCC
8455 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8456 cmp r0, #0 @ less than?
8457 b OP_CMPL_FLOAT_continue
8460 OP_CMPL_FLOAT_continue:
8461 mvnne r1, #0 @ yes, result is -1
8462 bne OP_CMPL_FLOAT_finish
8463 mov r0, r9 @ r0<- vBB
8464 mov r1, r10 @ r1<- vCC
8465 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8466 cmp r0, #0 @ greater than?
8467 beq OP_CMPL_FLOAT_nan @ no, must be NaN
8468 mov r1, #1 @ yes, result is 1
8469 @ fall through to _finish
8471 OP_CMPL_FLOAT_finish:
8472 mov r3, rINST, lsr #8 @ r3<- AA
8473 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8474 SET_VREG(r1, r3) @ vAA<- r1
8475 GET_INST_OPCODE(ip) @ extract opcode from rINST
8476 GOTO_OPCODE(ip) @ jump to next instruction
8479 * This is expected to be uncommon, so we double-branch (once to here,
8480 * again back to _finish).
8483 mvn r1, #0 @ r1<- 1 or -1 for NaN
8484 b OP_CMPL_FLOAT_finish
8489 /* continuation for OP_CMPG_FLOAT */
8491 @ Test for NaN with a second comparison. EABI forbids testing bit
8492 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8493 @ make the library call.
8494 .LOP_CMPG_FLOAT_gt_or_nan:
8495 mov r1, r9 @ reverse order
8497 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8499 movcc r1, #1 @ (greater than) r1<- 1
8500 bcc .LOP_CMPG_FLOAT_finish
8501 mov r1, #1 @ r1<- 1 or -1 for NaN
8502 b .LOP_CMPG_FLOAT_finish
8505 #if 0 /* "clasic" form */
8506 FETCH(r0, 1) @ r0<- CCBB
8507 and r2, r0, #255 @ r2<- BB
8508 mov r3, r0, lsr #8 @ r3<- CC
8509 GET_VREG(r9, r2) @ r9<- vBB
8510 GET_VREG(r10, r3) @ r10<- vCC
8511 mov r0, r9 @ r0<- vBB
8512 mov r1, r10 @ r1<- vCC
8513 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8515 movne r1, #0 @ yes, result is 0
8516 bne OP_CMPG_FLOAT_finish
8517 mov r0, r9 @ r0<- vBB
8518 mov r1, r10 @ r1<- vCC
8519 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8520 cmp r0, #0 @ less than?
8521 b OP_CMPG_FLOAT_continue
8524 OP_CMPG_FLOAT_continue:
8525 mvnne r1, #0 @ yes, result is -1
8526 bne OP_CMPG_FLOAT_finish
8527 mov r0, r9 @ r0<- vBB
8528 mov r1, r10 @ r1<- vCC
8529 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8530 cmp r0, #0 @ greater than?
8531 beq OP_CMPG_FLOAT_nan @ no, must be NaN
8532 mov r1, #1 @ yes, result is 1
8533 @ fall through to _finish
8535 OP_CMPG_FLOAT_finish:
8536 mov r3, rINST, lsr #8 @ r3<- AA
8537 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8538 SET_VREG(r1, r3) @ vAA<- r1
8539 GET_INST_OPCODE(ip) @ extract opcode from rINST
8540 GOTO_OPCODE(ip) @ jump to next instruction
8543 * This is expected to be uncommon, so we double-branch (once to here,
8544 * again back to _finish).
8547 mov r1, #1 @ r1<- 1 or -1 for NaN
8548 b OP_CMPG_FLOAT_finish
8553 /* continuation for OP_CMPL_DOUBLE */
8555 @ Test for NaN with a second comparison. EABI forbids testing bit
8556 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8557 @ make the library call.
8558 .LOP_CMPL_DOUBLE_gt_or_nan:
8559 ldmia r10, {r0-r1} @ reverse order
8561 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8563 movcc r1, #1 @ (greater than) r1<- 1
8564 bcc .LOP_CMPL_DOUBLE_finish
8565 mvn r1, #0 @ r1<- 1 or -1 for NaN
8566 b .LOP_CMPL_DOUBLE_finish
8569 /* continuation for OP_CMPG_DOUBLE */
8571 @ Test for NaN with a second comparison. EABI forbids testing bit
8572 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8573 @ make the library call.
8574 .LOP_CMPG_DOUBLE_gt_or_nan:
8575 ldmia r10, {r0-r1} @ reverse order
8577 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8579 movcc r1, #1 @ (greater than) r1<- 1
8580 bcc .LOP_CMPG_DOUBLE_finish
8581 mov r1, #1 @ r1<- 1 or -1 for NaN
8582 b .LOP_CMPG_DOUBLE_finish
8585 /* continuation for OP_CMP_LONG */
8588 mvn r1, #0 @ r1<- -1
8589 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8590 @ instead, we just replicate the tail end.
8591 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8592 SET_VREG(r1, r9) @ vAA<- r1
8593 GET_INST_OPCODE(ip) @ extract opcode from rINST
8594 GOTO_OPCODE(ip) @ jump to next instruction
8596 .LOP_CMP_LONG_greater:
8598 @ fall through to _finish
8600 .LOP_CMP_LONG_finish:
8601 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8602 SET_VREG(r1, r9) @ vAA<- r1
8603 GET_INST_OPCODE(ip) @ extract opcode from rINST
8604 GOTO_OPCODE(ip) @ jump to next instruction
8607 /* continuation for OP_AGET_WIDE */
8609 .LOP_AGET_WIDE_finish:
8610 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8611 add r0, r0, #offArrayObject_contents
8612 ldmia r0, {r2-r3} @ r2/r3 <- vBB[vCC]
8613 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8614 GET_INST_OPCODE(ip) @ extract opcode from rINST
8615 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8616 GOTO_OPCODE(ip) @ jump to next instruction
8619 /* continuation for OP_APUT_WIDE */
8621 .LOP_APUT_WIDE_finish:
8622 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8623 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8624 GET_INST_OPCODE(ip) @ extract opcode from rINST
8625 add r0, #offArrayObject_contents
8626 stmia r0, {r2-r3} @ vBB[vCC] <- r2/r3
8627 GOTO_OPCODE(ip) @ jump to next instruction
8630 /* continuation for OP_APUT_OBJECT */
8633 * r1 = vBB (arrayObj)
8635 * r10 = offset into array (vBB + vCC * width)
8637 .LOP_APUT_OBJECT_finish:
8638 cmp r9, #0 @ storing null reference?
8639 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8640 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8641 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz
8642 bl dvmCanPutArrayElement @ test object type vs. array type
8644 beq common_errArrayStore @ no
8645 .LOP_APUT_OBJECT_skip_check:
8646 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8647 GET_INST_OPCODE(ip) @ extract opcode from rINST
8648 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8649 GOTO_OPCODE(ip) @ jump to next instruction
8652 /* continuation for OP_IGET */
8656 * r0 holds resolved field
8661 cmp r9, #0 @ check object for null
8662 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8663 beq common_errNullObject @ object was null
8664 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8665 mov r2, rINST, lsr #8 @ r2<- A+
8666 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8667 and r2, r2, #15 @ r2<- A
8668 GET_INST_OPCODE(ip) @ extract opcode from rINST
8669 SET_VREG(r0, r2) @ fp[A]<- r0
8670 GOTO_OPCODE(ip) @ jump to next instruction
8673 /* continuation for OP_IGET_WIDE */
8677 * r0 holds resolved field
8680 .LOP_IGET_WIDE_finish:
8681 cmp r9, #0 @ check object for null
8682 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8683 beq common_errNullObject @ object was null
8684 mov r2, rINST, lsr #8 @ r2<- A+
8685 add r9, r9, r3 @ r9<- obj + field offset
8686 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok)
8687 and r2, r2, #15 @ r2<- A
8688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8689 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8690 GET_INST_OPCODE(ip) @ extract opcode from rINST
8691 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8692 GOTO_OPCODE(ip) @ jump to next instruction
8695 /* continuation for OP_IGET_OBJECT */
8699 * r0 holds resolved field
8702 .LOP_IGET_OBJECT_finish:
8704 cmp r9, #0 @ check object for null
8705 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8706 beq common_errNullObject @ object was null
8707 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8708 mov r2, rINST, lsr #8 @ r2<- A+
8709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8710 and r2, r2, #15 @ r2<- A
8711 GET_INST_OPCODE(ip) @ extract opcode from rINST
8712 SET_VREG(r0, r2) @ fp[A]<- r0
8713 GOTO_OPCODE(ip) @ jump to next instruction
8716 /* continuation for OP_IGET_BOOLEAN */
8720 * r0 holds resolved field
8723 .LOP_IGET_BOOLEAN_finish:
8725 cmp r9, #0 @ check object for null
8726 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8727 beq common_errNullObject @ object was null
8728 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8729 mov r2, rINST, lsr #8 @ r2<- A+
8730 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8731 and r2, r2, #15 @ r2<- A
8732 GET_INST_OPCODE(ip) @ extract opcode from rINST
8733 SET_VREG(r0, r2) @ fp[A]<- r0
8734 GOTO_OPCODE(ip) @ jump to next instruction
8737 /* continuation for OP_IGET_BYTE */
8741 * r0 holds resolved field
8744 .LOP_IGET_BYTE_finish:
8746 cmp r9, #0 @ check object for null
8747 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8748 beq common_errNullObject @ object was null
8749 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8750 mov r2, rINST, lsr #8 @ r2<- A+
8751 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8752 and r2, r2, #15 @ r2<- A
8753 GET_INST_OPCODE(ip) @ extract opcode from rINST
8754 SET_VREG(r0, r2) @ fp[A]<- r0
8755 GOTO_OPCODE(ip) @ jump to next instruction
8758 /* continuation for OP_IGET_CHAR */
8762 * r0 holds resolved field
8765 .LOP_IGET_CHAR_finish:
8767 cmp r9, #0 @ check object for null
8768 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8769 beq common_errNullObject @ object was null
8770 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8771 mov r2, rINST, lsr #8 @ r2<- A+
8772 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8773 and r2, r2, #15 @ r2<- A
8774 GET_INST_OPCODE(ip) @ extract opcode from rINST
8775 SET_VREG(r0, r2) @ fp[A]<- r0
8776 GOTO_OPCODE(ip) @ jump to next instruction
8779 /* continuation for OP_IGET_SHORT */
8783 * r0 holds resolved field
8786 .LOP_IGET_SHORT_finish:
8788 cmp r9, #0 @ check object for null
8789 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8790 beq common_errNullObject @ object was null
8791 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8792 mov r2, rINST, lsr #8 @ r2<- A+
8793 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8794 and r2, r2, #15 @ r2<- A
8795 GET_INST_OPCODE(ip) @ extract opcode from rINST
8796 SET_VREG(r0, r2) @ fp[A]<- r0
8797 GOTO_OPCODE(ip) @ jump to next instruction
8800 /* continuation for OP_IPUT */
8804 * r0 holds resolved field
8809 mov r1, rINST, lsr #8 @ r1<- A+
8810 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8811 and r1, r1, #15 @ r1<- A
8812 cmp r9, #0 @ check object for null
8813 GET_VREG(r0, r1) @ r0<- fp[A]
8814 beq common_errNullObject @ object was null
8815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8816 GET_INST_OPCODE(ip) @ extract opcode from rINST
8817 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8818 GOTO_OPCODE(ip) @ jump to next instruction
8821 /* continuation for OP_IPUT_WIDE */
8825 * r0 holds resolved field
8828 .LOP_IPUT_WIDE_finish:
8829 mov r2, rINST, lsr #8 @ r2<- A+
8830 cmp r9, #0 @ check object for null
8831 and r2, r2, #15 @ r2<- A
8832 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8833 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8834 beq common_errNullObject @ object was null
8835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8836 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8837 GET_INST_OPCODE(ip) @ extract opcode from rINST
8838 add r9, r9, r3 @ r9<- object + byte offset
8839 stmia r9, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
8840 GOTO_OPCODE(ip) @ jump to next instruction
8843 /* continuation for OP_IPUT_OBJECT */
8847 * r0 holds resolved field
8850 .LOP_IPUT_OBJECT_finish:
8852 mov r1, rINST, lsr #8 @ r1<- A+
8853 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8854 and r1, r1, #15 @ r1<- A
8855 cmp r9, #0 @ check object for null
8856 GET_VREG(r0, r1) @ r0<- fp[A]
8857 beq common_errNullObject @ object was null
8858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8859 GET_INST_OPCODE(ip) @ extract opcode from rINST
8860 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8861 GOTO_OPCODE(ip) @ jump to next instruction
8864 /* continuation for OP_IPUT_BOOLEAN */
8868 * r0 holds resolved field
8871 .LOP_IPUT_BOOLEAN_finish:
8873 mov r1, rINST, lsr #8 @ r1<- A+
8874 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8875 and r1, r1, #15 @ r1<- A
8876 cmp r9, #0 @ check object for null
8877 GET_VREG(r0, r1) @ r0<- fp[A]
8878 beq common_errNullObject @ object was null
8879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8880 GET_INST_OPCODE(ip) @ extract opcode from rINST
8881 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8882 GOTO_OPCODE(ip) @ jump to next instruction
8885 /* continuation for OP_IPUT_BYTE */
8889 * r0 holds resolved field
8892 .LOP_IPUT_BYTE_finish:
8894 mov r1, rINST, lsr #8 @ r1<- A+
8895 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8896 and r1, r1, #15 @ r1<- A
8897 cmp r9, #0 @ check object for null
8898 GET_VREG(r0, r1) @ r0<- fp[A]
8899 beq common_errNullObject @ object was null
8900 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8901 GET_INST_OPCODE(ip) @ extract opcode from rINST
8902 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8903 GOTO_OPCODE(ip) @ jump to next instruction
8906 /* continuation for OP_IPUT_CHAR */
8910 * r0 holds resolved field
8913 .LOP_IPUT_CHAR_finish:
8915 mov r1, rINST, lsr #8 @ r1<- A+
8916 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8917 and r1, r1, #15 @ r1<- A
8918 cmp r9, #0 @ check object for null
8919 GET_VREG(r0, r1) @ r0<- fp[A]
8920 beq common_errNullObject @ object was null
8921 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8922 GET_INST_OPCODE(ip) @ extract opcode from rINST
8923 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8924 GOTO_OPCODE(ip) @ jump to next instruction
8927 /* continuation for OP_IPUT_SHORT */
8931 * r0 holds resolved field
8934 .LOP_IPUT_SHORT_finish:
8936 mov r1, rINST, lsr #8 @ r1<- A+
8937 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8938 and r1, r1, #15 @ r1<- A
8939 cmp r9, #0 @ check object for null
8940 GET_VREG(r0, r1) @ r0<- fp[A]
8941 beq common_errNullObject @ object was null
8942 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8943 GET_INST_OPCODE(ip) @ extract opcode from rINST
8944 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8945 GOTO_OPCODE(ip) @ jump to next instruction
8948 /* continuation for OP_SGET */
8951 * Continuation if the field has not yet been resolved.
8952 * r1: BBBB field ref
8955 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8956 EXPORT_PC() @ resolve() could throw, so export now
8957 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8958 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8959 cmp r0, #0 @ success?
8960 bne .LOP_SGET_finish @ yes, finish
8961 b common_exceptionThrown @ no, handle exception
8964 /* continuation for OP_SGET_WIDE */
8967 * Continuation if the field has not yet been resolved.
8968 * r1: BBBB field ref
8970 .LOP_SGET_WIDE_resolve:
8971 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8972 EXPORT_PC() @ resolve() could throw, so export now
8973 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8974 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8975 cmp r0, #0 @ success?
8976 bne .LOP_SGET_WIDE_finish @ yes, finish
8977 b common_exceptionThrown @ no, handle exception
8980 /* continuation for OP_SGET_OBJECT */
8983 * Continuation if the field has not yet been resolved.
8984 * r1: BBBB field ref
8986 .LOP_SGET_OBJECT_resolve:
8987 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8988 EXPORT_PC() @ resolve() could throw, so export now
8989 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8990 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8991 cmp r0, #0 @ success?
8992 bne .LOP_SGET_OBJECT_finish @ yes, finish
8993 b common_exceptionThrown @ no, handle exception
8996 /* continuation for OP_SGET_BOOLEAN */
8999 * Continuation if the field has not yet been resolved.
9000 * r1: BBBB field ref
9002 .LOP_SGET_BOOLEAN_resolve:
9003 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9004 EXPORT_PC() @ resolve() could throw, so export now
9005 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9006 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9007 cmp r0, #0 @ success?
9008 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
9009 b common_exceptionThrown @ no, handle exception
9012 /* continuation for OP_SGET_BYTE */
9015 * Continuation if the field has not yet been resolved.
9016 * r1: BBBB field ref
9018 .LOP_SGET_BYTE_resolve:
9019 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9020 EXPORT_PC() @ resolve() could throw, so export now
9021 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9022 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9023 cmp r0, #0 @ success?
9024 bne .LOP_SGET_BYTE_finish @ yes, finish
9025 b common_exceptionThrown @ no, handle exception
9028 /* continuation for OP_SGET_CHAR */
9031 * Continuation if the field has not yet been resolved.
9032 * r1: BBBB field ref
9034 .LOP_SGET_CHAR_resolve:
9035 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9036 EXPORT_PC() @ resolve() could throw, so export now
9037 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9038 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9039 cmp r0, #0 @ success?
9040 bne .LOP_SGET_CHAR_finish @ yes, finish
9041 b common_exceptionThrown @ no, handle exception
9044 /* continuation for OP_SGET_SHORT */
9047 * Continuation if the field has not yet been resolved.
9048 * r1: BBBB field ref
9050 .LOP_SGET_SHORT_resolve:
9051 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9052 EXPORT_PC() @ resolve() could throw, so export now
9053 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9054 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9055 cmp r0, #0 @ success?
9056 bne .LOP_SGET_SHORT_finish @ yes, finish
9057 b common_exceptionThrown @ no, handle exception
9060 /* continuation for OP_SPUT */
9063 * Continuation if the field has not yet been resolved.
9064 * r1: BBBB field ref
9067 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9068 EXPORT_PC() @ resolve() could throw, so export now
9069 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9070 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9071 cmp r0, #0 @ success?
9072 bne .LOP_SPUT_finish @ yes, finish
9073 b common_exceptionThrown @ no, handle exception
9076 /* continuation for OP_SPUT_WIDE */
9079 * Continuation if the field has not yet been resolved.
9080 * r1: BBBB field ref
9083 .LOP_SPUT_WIDE_resolve:
9084 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9085 EXPORT_PC() @ resolve() could throw, so export now
9086 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9087 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9088 cmp r0, #0 @ success?
9089 bne .LOP_SPUT_WIDE_finish @ yes, finish
9090 b common_exceptionThrown @ no, handle exception
9093 /* continuation for OP_SPUT_OBJECT */
9096 * Continuation if the field has not yet been resolved.
9097 * r1: BBBB field ref
9099 .LOP_SPUT_OBJECT_resolve:
9100 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9101 EXPORT_PC() @ resolve() could throw, so export now
9102 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9103 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9104 cmp r0, #0 @ success?
9105 bne .LOP_SPUT_OBJECT_finish @ yes, finish
9106 b common_exceptionThrown @ no, handle exception
9109 /* continuation for OP_SPUT_BOOLEAN */
9112 * Continuation if the field has not yet been resolved.
9113 * r1: BBBB field ref
9115 .LOP_SPUT_BOOLEAN_resolve:
9116 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9117 EXPORT_PC() @ resolve() could throw, so export now
9118 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9119 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9120 cmp r0, #0 @ success?
9121 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
9122 b common_exceptionThrown @ no, handle exception
9125 /* continuation for OP_SPUT_BYTE */
9128 * Continuation if the field has not yet been resolved.
9129 * r1: BBBB field ref
9131 .LOP_SPUT_BYTE_resolve:
9132 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9133 EXPORT_PC() @ resolve() could throw, so export now
9134 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9135 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9136 cmp r0, #0 @ success?
9137 bne .LOP_SPUT_BYTE_finish @ yes, finish
9138 b common_exceptionThrown @ no, handle exception
9141 /* continuation for OP_SPUT_CHAR */
9144 * Continuation if the field has not yet been resolved.
9145 * r1: BBBB field ref
9147 .LOP_SPUT_CHAR_resolve:
9148 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9149 EXPORT_PC() @ resolve() could throw, so export now
9150 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9151 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9152 cmp r0, #0 @ success?
9153 bne .LOP_SPUT_CHAR_finish @ yes, finish
9154 b common_exceptionThrown @ no, handle exception
9157 /* continuation for OP_SPUT_SHORT */
9160 * Continuation if the field has not yet been resolved.
9161 * r1: BBBB field ref
9163 .LOP_SPUT_SHORT_resolve:
9164 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9165 EXPORT_PC() @ resolve() could throw, so export now
9166 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9167 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9168 cmp r0, #0 @ success?
9169 bne .LOP_SPUT_SHORT_finish @ yes, finish
9170 b common_exceptionThrown @ no, handle exception
9173 /* continuation for OP_INVOKE_VIRTUAL */
9177 * r0 = resolved base method
9178 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
9180 .LOP_INVOKE_VIRTUAL_continue:
9181 GET_VREG(r1, r10) @ r1<- "this" ptr
9182 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9183 cmp r1, #0 @ is "this" null?
9184 beq common_errNullObject @ null "this", throw exception
9185 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
9186 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
9187 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
9188 bl common_invokeMethodNoRange @ continue on
9191 /* continuation for OP_INVOKE_SUPER */
9195 * r0 = resolved base method
9196 * r9 = method->clazz
9198 .LOP_INVOKE_SUPER_continue:
9199 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
9200 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9201 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
9202 EXPORT_PC() @ must export for invoke
9203 cmp r2, r3 @ compare (methodIndex, vtableCount)
9204 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
9205 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
9206 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
9207 bl common_invokeMethodNoRange @ continue on
9209 .LOP_INVOKE_SUPER_resolve:
9210 mov r0, r9 @ r0<- method->clazz
9211 mov r2, #METHOD_VIRTUAL @ resolver method type
9212 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9213 cmp r0, #0 @ got null?
9214 bne .LOP_INVOKE_SUPER_continue @ no, continue
9215 b common_exceptionThrown @ yes, handle exception
9218 * Throw a NoSuchMethodError with the method name as the message.
9219 * r0 = resolved base method
9221 .LOP_INVOKE_SUPER_nsm:
9222 ldr r1, [r0, #offMethod_name] @ r1<- method name
9223 b common_errNoSuchMethod
9226 /* continuation for OP_INVOKE_DIRECT */
9230 * r1 = reference (BBBB or CCCC)
9231 * r10 = "this" register
9233 .LOP_INVOKE_DIRECT_resolve:
9234 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9235 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9236 mov r2, #METHOD_DIRECT @ resolver method type
9237 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9238 cmp r0, #0 @ got null?
9239 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9240 bne .LOP_INVOKE_DIRECT_finish @ no, continue
9241 b common_exceptionThrown @ yes, handle exception
9244 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9248 * r0 = resolved base method
9249 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
9251 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9252 GET_VREG(r1, r10) @ r1<- "this" ptr
9253 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9254 cmp r1, #0 @ is "this" null?
9255 beq common_errNullObject @ null "this", throw exception
9256 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
9257 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
9258 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
9259 bl common_invokeMethodRange @ continue on
9262 /* continuation for OP_INVOKE_SUPER_RANGE */
9266 * r0 = resolved base method
9267 * r9 = method->clazz
9269 .LOP_INVOKE_SUPER_RANGE_continue:
9270 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
9271 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9272 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
9273 EXPORT_PC() @ must export for invoke
9274 cmp r2, r3 @ compare (methodIndex, vtableCount)
9275 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
9276 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
9277 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
9278 bl common_invokeMethodRange @ continue on
9280 .LOP_INVOKE_SUPER_RANGE_resolve:
9281 mov r0, r9 @ r0<- method->clazz
9282 mov r2, #METHOD_VIRTUAL @ resolver method type
9283 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9284 cmp r0, #0 @ got null?
9285 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
9286 b common_exceptionThrown @ yes, handle exception
9289 * Throw a NoSuchMethodError with the method name as the message.
9290 * r0 = resolved base method
9292 .LOP_INVOKE_SUPER_RANGE_nsm:
9293 ldr r1, [r0, #offMethod_name] @ r1<- method name
9294 b common_errNoSuchMethod
9297 /* continuation for OP_INVOKE_DIRECT_RANGE */
9301 * r1 = reference (BBBB or CCCC)
9302 * r10 = "this" register
9304 .LOP_INVOKE_DIRECT_RANGE_resolve:
9305 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9306 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9307 mov r2, #METHOD_DIRECT @ resolver method type
9308 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9309 cmp r0, #0 @ got null?
9310 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9311 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
9312 b common_exceptionThrown @ yes, handle exception
9315 /* continuation for OP_FLOAT_TO_LONG */
9317 * Convert the float in r0 to a long in r0/r1.
9319 * We have to clip values to long min/max per the specification. The
9320 * expected common case is a "reasonable" value that converts directly
9321 * to modest integer. The EABI convert function isn't doing this for us.
9325 mov r1, #0x5f000000 @ (float)maxlong
9327 bl __aeabi_fcmpge @ is arg >= maxlong?
9328 cmp r0, #0 @ nonzero == yes
9329 mvnne r0, #0 @ return maxlong (7fffffff)
9330 mvnne r1, #0x80000000
9331 ldmnefd sp!, {r4, pc}
9333 mov r0, r4 @ recover arg
9334 mov r1, #0xdf000000 @ (float)minlong
9335 bl __aeabi_fcmple @ is arg <= minlong?
9336 cmp r0, #0 @ nonzero == yes
9337 movne r0, #0 @ return minlong (80000000)
9338 movne r1, #0x80000000
9339 ldmnefd sp!, {r4, pc}
9341 mov r0, r4 @ recover arg
9343 bl __aeabi_fcmpeq @ is arg == self?
9344 cmp r0, #0 @ zero == no
9345 moveq r1, #0 @ return zero for NaN
9346 ldmeqfd sp!, {r4, pc}
9348 mov r0, r4 @ recover arg
9349 bl __aeabi_f2lz @ convert float to long
9353 /* continuation for OP_DOUBLE_TO_LONG */
9355 * Convert the double in r0/r1 to a long in r0/r1.
9357 * We have to clip values to long min/max per the specification. The
9358 * expected common case is a "reasonable" value that converts directly
9359 * to modest integer. The EABI convert function isn't doing this for us.
9362 stmfd sp!, {r4, r5, lr} @ save regs
9363 mov r3, #0x43000000 @ maxlong, as a double (high word)
9364 add r3, #0x00e00000 @ 0x43e00000
9365 mov r2, #0 @ maxlong, as a double (low word)
9366 sub sp, sp, #4 @ align for EABI
9367 mov r4, r0 @ save a copy of r0
9369 bl __aeabi_dcmpge @ is arg >= maxlong?
9370 cmp r0, #0 @ nonzero == yes
9371 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
9372 mvnne r1, #0x80000000
9375 mov r0, r4 @ recover arg
9377 mov r3, #0xc3000000 @ minlong, as a double (high word)
9378 add r3, #0x00e00000 @ 0xc3e00000
9379 mov r2, #0 @ minlong, as a double (low word)
9380 bl __aeabi_dcmple @ is arg <= minlong?
9381 cmp r0, #0 @ nonzero == yes
9382 movne r0, #0 @ return minlong (8000000000000000)
9383 movne r1, #0x80000000
9386 mov r0, r4 @ recover arg
9388 mov r2, r4 @ compare against self
9390 bl __aeabi_dcmpeq @ is arg == self?
9391 cmp r0, #0 @ zero == no
9392 moveq r1, #0 @ return zero for NaN
9395 mov r0, r4 @ recover arg
9397 bl __aeabi_d2lz @ convert double to long
9401 ldmfd sp!, {r4, r5, pc}
9404 /* continuation for OP_MUL_LONG */
9406 .LOP_MUL_LONG_finish:
9407 GET_INST_OPCODE(ip) @ extract opcode from rINST
9408 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
9409 GOTO_OPCODE(ip) @ jump to next instruction
9412 /* continuation for OP_SHL_LONG */
9414 .LOP_SHL_LONG_finish:
9415 mov r0, r0, asl r2 @ r0<- r0 << r2
9416 GET_INST_OPCODE(ip) @ extract opcode from rINST
9417 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9418 GOTO_OPCODE(ip) @ jump to next instruction
9421 /* continuation for OP_SHR_LONG */
9423 .LOP_SHR_LONG_finish:
9424 mov r1, r1, asr r2 @ r1<- r1 >> r2
9425 GET_INST_OPCODE(ip) @ extract opcode from rINST
9426 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9427 GOTO_OPCODE(ip) @ jump to next instruction
9430 /* continuation for OP_USHR_LONG */
9432 .LOP_USHR_LONG_finish:
9433 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
9434 GET_INST_OPCODE(ip) @ extract opcode from rINST
9435 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9436 GOTO_OPCODE(ip) @ jump to next instruction
9439 /* continuation for OP_SHL_LONG_2ADDR */
9441 .LOP_SHL_LONG_2ADDR_finish:
9442 GET_INST_OPCODE(ip) @ extract opcode from rINST
9443 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9444 GOTO_OPCODE(ip) @ jump to next instruction
9447 /* continuation for OP_SHR_LONG_2ADDR */
9449 .LOP_SHR_LONG_2ADDR_finish:
9450 GET_INST_OPCODE(ip) @ extract opcode from rINST
9451 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9452 GOTO_OPCODE(ip) @ jump to next instruction
9455 /* continuation for OP_USHR_LONG_2ADDR */
9457 .LOP_USHR_LONG_2ADDR_finish:
9458 GET_INST_OPCODE(ip) @ extract opcode from rINST
9459 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9460 GOTO_OPCODE(ip) @ jump to next instruction
9463 /* continuation for OP_EXECUTE_INLINE */
9466 * Extract args, call function.
9467 * r0 = #of args (0-4)
9469 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9472 * - Use a jump table from the main piece to jump directly into the
9473 * AND/LDR pairs. Costs a data load, saves a branch.
9474 * - Have five separate pieces that do the loading, so we can work the
9475 * interleave a little better. Increases code size.
9477 .LOP_EXECUTE_INLINE_continue:
9478 rsb r0, r0, #4 @ r0<- 4-r0
9479 FETCH(r9, 2) @ r9<- FEDC
9480 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9481 bl common_abort @ (skipped due to ARM prefetch)
9482 4: and ip, r9, #0xf000 @ isolate F
9483 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
9484 3: and ip, r9, #0x0f00 @ isolate E
9485 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
9486 2: and ip, r9, #0x00f0 @ isolate D
9487 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
9488 1: and ip, r9, #0x000f @ isolate C
9489 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
9491 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
9492 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9495 .LOP_EXECUTE_INLINE_table:
9496 .word gDvmInlineOpsTable
9499 /* continuation for OP_EXECUTE_INLINE_RANGE */
9502 * Extract args, call function.
9503 * r0 = #of args (0-4)
9505 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9507 .LOP_EXECUTE_INLINE_RANGE_continue:
9508 rsb r0, r0, #4 @ r0<- 4-r0
9509 FETCH(r9, 2) @ r9<- CCCC
9510 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9511 bl common_abort @ (skipped due to ARM prefetch)
9512 4: add ip, r9, #3 @ base+3
9513 GET_VREG(r3, ip) @ r3<- vBase[3]
9514 3: add ip, r9, #2 @ base+2
9515 GET_VREG(r2, ip) @ r2<- vBase[2]
9516 2: add ip, r9, #1 @ base+1
9517 GET_VREG(r1, ip) @ r1<- vBase[1]
9518 1: add ip, r9, #0 @ (nop)
9519 GET_VREG(r0, ip) @ r0<- vBase[0]
9521 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation
9522 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9525 .LOP_EXECUTE_INLINE_RANGE_table:
9526 .word gDvmInlineOpsTable
9529 .size dvmAsmSisterStart, .-dvmAsmSisterStart
9530 .global dvmAsmSisterEnd
9533 /* File: armv5te/footer.S */
9536 * ===========================================================================
9537 * Common subroutines and data
9538 * ===========================================================================
9546 #if defined(WITH_JIT)
9547 #if defined(WITH_SELF_VERIFICATION)
9548 .global dvmJitToInterpPunt
9550 mov r2,#kSVSPunt @ r2<- interpreter entry point
9551 b dvmJitSelfVerificationEnd @ doesn't return
9553 .global dvmJitToInterpSingleStep
9554 dvmJitToInterpSingleStep:
9555 mov r2,#kSVSSingleStep @ r2<- interpreter entry point
9556 b dvmJitSelfVerificationEnd @ doesn't return
9558 .global dvmJitToTraceSelect
9559 dvmJitToTraceSelect:
9560 ldr r0,[lr, #-1] @ pass our target PC
9561 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
9562 b dvmJitSelfVerificationEnd @ doesn't return
9564 .global dvmJitToBackwardBranch
9565 dvmJitToBackwardBranch:
9566 ldr r0,[lr, #-1] @ pass our target PC
9567 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
9568 b dvmJitSelfVerificationEnd @ doesn't return
9570 .global dvmJitToInterpNormal
9571 dvmJitToInterpNormal:
9572 ldr r0,[lr, #-1] @ pass our target PC
9573 mov r2,#kSVSNormal @ r2<- interpreter entry point
9574 b dvmJitSelfVerificationEnd @ doesn't return
9576 .global dvmJitToInterpNoChain
9577 dvmJitToInterpNoChain:
9578 mov r0,rPC @ pass our target PC
9579 mov r2,#kSVSNoChain @ r2<- interpreter entry point
9580 b dvmJitSelfVerificationEnd @ doesn't return
9583 * Return from the translation cache to the interpreter when the compiler is
9584 * having issues translating/executing a Dalvik instruction. We have to skip
9585 * the code cache lookup otherwise it is possible to indefinitely bouce
9586 * between the interpreter and the code cache if the instruction that fails
9587 * to be compiled happens to be at a trace start.
9589 .global dvmJitToInterpPunt
9591 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9599 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9600 adrl rIBASE, dvmAsmInstructionStart
9606 * Return to the interpreter to handle a single instruction.
9609 * r1 <= PC of resume instruction
9610 * lr <= resume point in translation
9612 .global dvmJitToInterpSingleStep
9613 dvmJitToInterpSingleStep:
9614 str lr,[rGLUE,#offGlue_jitResume]
9615 str r1,[rGLUE,#offGlue_jitResumePC]
9616 mov r1,#kInterpEntryInstr
9617 @ enum is 4 byte in aapcs-EABI
9618 str r1, [rGLUE, #offGlue_entryPoint]
9622 adrl rIBASE, dvmAsmInstructionStart
9623 mov r2,#kJitSingleStep @ Ask for single step and then revert
9624 str r2,[rGLUE,#offGlue_jitState]
9625 mov r1,#1 @ set changeInterp to bail to debug interp
9630 * Return from the translation cache and immediately request
9631 * a translation for the exit target. Commonly used following
9634 .global dvmJitToTraceSelect
9635 dvmJitToTraceSelect:
9636 ldr rPC,[lr, #-1] @ get our target PC
9637 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9638 add rINST,lr,#-5 @ save start of chain branch
9640 bl dvmJitGetCodeAddr @ Is there a translation?
9641 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9645 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9646 mov r1, rPC @ arg1 of translation may need this
9647 mov lr, #0 @ in case target is HANDLER_INTERPRET
9648 cmp r0,#0 @ successful chain?
9649 bxne r0 @ continue native execution
9650 b toInterpreter @ didn't chain - resume with interpreter
9652 /* No translation, so request one if profiling isn't disabled*/
9654 adrl rIBASE, dvmAsmInstructionStart
9655 GET_JIT_PROF_TABLE(r0)
9658 bne common_selectTrace
9663 * Return from the translation cache to the interpreter.
9664 * The return was done with a BLX from thumb mode, and
9665 * the following 32-bit word contains the target rPC value.
9666 * Note that lr (r14) will have its low-order bit set to denote
9667 * its thumb-mode origin.
9669 * We'll need to stash our lr origin away, recover the new
9670 * target and then check to see if there is a translation available
9671 * for our new target. If so, we do a translation chain and
9672 * go back to native execution. Otherwise, it's back to the
9673 * interpreter (after treating this entry as a potential
9676 .global dvmJitToInterpNormal
9677 dvmJitToInterpNormal:
9678 ldr rPC,[lr, #-1] @ get our target PC
9679 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9680 add rINST,lr,#-5 @ save start of chain branch
9685 bl dvmJitGetCodeAddr @ Is there a translation?
9686 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9688 beq toInterpreter @ go if not, otherwise do chain
9690 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
9691 mov r1, rPC @ arg1 of translation may need this
9692 mov lr, #0 @ in case target is HANDLER_INTERPRET
9693 cmp r0,#0 @ successful chain?
9694 bxne r0 @ continue native execution
9695 b toInterpreter @ didn't chain - resume with interpreter
9698 * Return from the translation cache to the interpreter to do method invocation.
9699 * Check if translation exists for the callee, but don't chain to it.
9701 .global dvmJitToInterpNoChain
9702 dvmJitToInterpNoChain:
9706 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9708 bl dvmJitGetCodeAddr @ Is there a translation?
9709 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9710 mov r1, rPC @ arg1 of translation may need this
9711 mov lr, #0 @ in case target is HANDLER_INTERPRET
9713 bxne r0 @ continue native execution if so
9717 * No translation, restore interpreter regs and start interpreting.
9718 * rGLUE & rFP were preserved in the translated code, and rPC has
9719 * already been restored by the time we get here. We'll need to set
9720 * up rIBASE & rINST, and load the address of the JitTable into r0.
9724 adrl rIBASE, dvmAsmInstructionStart
9726 GET_JIT_PROF_TABLE(r0)
9727 @ NOTE: intended fallthrough
9729 * Common code to update potential trace start counter, and initiate
9730 * a trace-build if appropriate. On entry, rPC should point to the
9731 * next instruction to execute, and rINST should be already loaded with
9732 * the next opcode word, and r0 holds a pointer to the jit profile
9733 * table (pJitProfTable).
9735 common_testUpdateProfile:
9738 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */
9740 common_updateProfile:
9741 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9742 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits
9743 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9745 subs r1,r1,#1 @ decrement counter
9746 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9747 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
9750 * Here, we switch to the debug interpreter to request
9751 * trace selection. First, though, check to see if there
9752 * is already a native translation in place (and, if so,
9755 GET_JIT_THRESHOLD(r1)
9756 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9757 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9760 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
9761 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9762 mov r1, rPC @ arg1 of translation may need this
9763 mov lr, #0 @ in case target is HANDLER_INTERPRET
9765 #if !defined(WITH_SELF_VERIFICATION)
9766 bxne r0 @ jump to the translation
9768 beq common_selectTrace
9770 * At this point, we have a target translation. However, if
9771 * that translation is actually the interpret-only pseudo-translation
9772 * we want to treat it the same as no translation.
9774 mov r10, r0 @ save target
9775 bl dvmCompilerGetInterpretTemplate
9776 cmp r0, r10 @ special case?
9777 bne dvmJitSelfVerificationStart @ set up self verification
9784 mov r2,#kJitTSelectRequest @ ask for trace selection
9785 str r2,[rGLUE,#offGlue_jitState]
9786 mov r2,#kInterpEntryInstr @ normal entry reason
9787 str r2,[rGLUE,#offGlue_entryPoint]
9788 mov r1,#1 @ set changeInterp
9791 #if defined(WITH_SELF_VERIFICATION)
9793 * Save PC and registers to shadow memory for self verification mode
9794 * before jumping to native translation.
9795 * On entry, r10 contains the address of the target translation.
9797 dvmJitSelfVerificationStart:
9798 mov r0,rPC @ r0<- program counter
9799 mov r1,rFP @ r1<- frame pointer
9800 mov r2,rGLUE @ r2<- InterpState pointer
9801 mov r3,r10 @ r3<- target translation
9802 bl dvmSelfVerificationSaveState @ save registers to shadow space
9803 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9804 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9805 bx r10 @ jump to the translation
9808 * Restore PC, registers, and interpState to original values
9809 * before jumping back to the interpreter.
9811 dvmJitSelfVerificationEnd:
9812 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9814 str r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9815 mov r1,rFP @ pass ending fp
9816 bl dvmSelfVerificationRestoreState @ restore pc and fp values
9817 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
9818 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
9819 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9820 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
9821 cmp r1,#0 @ check for punt condition
9823 mov r2,#kJitSelfVerification @ ask for self verification
9824 str r2,[rGLUE,#offGlue_jitState]
9825 mov r2,#kInterpEntryInstr @ normal entry reason
9826 str r2,[rGLUE,#offGlue_entryPoint]
9827 mov r1,#1 @ set changeInterp
9830 1: @ exit to interpreter without check
9832 adrl rIBASE, dvmAsmInstructionStart
9841 * Common code when a backward branch is taken.
9844 * r9 is PC adjustment *in bytes*
9846 common_backwardBranch:
9847 mov r0, #kInterpEntryInstr
9848 bl common_periodicChecks
9849 #if defined(WITH_JIT)
9850 GET_JIT_PROF_TABLE(r0)
9851 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9853 bne common_updateProfile
9857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9858 GET_INST_OPCODE(ip) @ extract opcode from rINST
9859 GOTO_OPCODE(ip) @ jump to next instruction
9864 * Need to see if the thread needs to be suspended or debugger/profiler
9865 * activity has begun.
9867 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9868 * have to do the second ldr.
9870 * TODO: reduce this so we're just checking a single location.
9873 * r0 is reentry type, e.g. kInterpEntryInstr
9874 * r9 is trampoline PC adjustment *in bytes*
9876 common_periodicChecks:
9877 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9879 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9880 str r0, [rGLUE, #offGlue_entryPoint]
9882 #if defined(WITH_DEBUGGER)
9883 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9885 #if defined(WITH_PROFILER)
9886 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9889 ldr r3, [r3] @ r3<- suspendCount (int)
9891 #if defined(WITH_DEBUGGER)
9892 ldrb r1, [r1] @ r1<- debuggerActive (boolean)
9894 #if defined (WITH_PROFILER)
9895 ldr r2, [r2] @ r2<- activeProfilers (int)
9898 cmp r3, #0 @ suspend pending?
9899 bne 2f @ yes, do full suspension check
9901 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9902 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9903 orrs r1, r1, r2 @ r1<- r1 | r2
9904 cmp r1, #0 @ debugger attached or profiler started?
9905 # elif defined(WITH_DEBUGGER)
9906 cmp r1, #0 @ debugger attached?
9907 # elif defined(WITH_PROFILER)
9908 cmp r2, #0 @ profiler started?
9910 bne 3f @ debugger/profiler, switch interp
9913 bx lr @ nothing to do, return
9916 #if defined(WITH_JIT)
9918 * Refresh the Jit's cached copy of profile table pointer. This pointer
9919 * doubles as the Jit's on/off switch.
9921 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9922 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9923 ldr r3, [r3] @ r10 <- pJitProfTable
9924 EXPORT_PC() @ need for precise GC
9925 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9927 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9928 EXPORT_PC() @ need for precise GC
9930 b dvmCheckSuspendPending @ suspend if necessary, then return
9932 3: @ debugger/profiler enabled, bail out
9933 add rPC, rPC, r9 @ update rPC
9934 mov r1, #1 @ "want switch" = true
9939 * The equivalent of "goto bail", this calls through the "bail handler".
9941 * State registers will be saved to the "glue" area before bailing.
9944 * r1 is "bool changeInterp", indicating if we want to switch to the
9945 * other interpreter or just bail all the way out
9948 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9949 mov r0, rGLUE @ r0<- glue ptr
9950 b dvmMterpStdBail @ call(glue, changeInterp)
9952 @add r1, r1, #1 @ using (boolean+1)
9953 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9954 @bl _longjmp @ does not return
9959 * Common code for method invocation with range.
9962 * r0 is "Method* methodToCall", the method we're trying to call
9964 common_invokeMethodRange:
9966 @ prepare to copy args to "outs" area of current frame
9967 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9968 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9969 beq .LinvokeArgsDone @ if no args, skip the rest
9970 FETCH(r1, 2) @ r1<- CCCC
9972 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9973 @ (very few methods have > 10 args; could unroll for common cases)
9974 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9975 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9976 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9977 1: ldr r1, [r3], #4 @ val = *fp++
9978 subs r2, r2, #1 @ count--
9979 str r1, [r10], #4 @ *outs++ = val
9980 bne 1b @ ...while count != 0
9981 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9985 * Common code for method invocation without range.
9988 * r0 is "Method* methodToCall", the method we're trying to call
9990 common_invokeMethodNoRange:
9992 @ prepare to copy args to "outs" area of current frame
9993 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9994 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9995 FETCH(r1, 2) @ r1<- GFED (load here to hide latency)
9996 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9997 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9998 beq .LinvokeArgsDone
10000 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
10002 rsb r2, r2, #5 @ r2<- 5-r2
10003 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
10004 bl common_abort @ (skipped due to ARM prefetch)
10005 5: and ip, rINST, #0x0f00 @ isolate A
10006 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2)
10008 str r2, [r10, #-4]! @ *--outs = vA
10009 4: and ip, r1, #0xf000 @ isolate G
10010 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2)
10012 str r2, [r10, #-4]! @ *--outs = vG
10013 3: and ip, r1, #0x0f00 @ isolate F
10014 ldr r2, [rFP, ip, lsr #6] @ r2<- vF
10016 str r2, [r10, #-4]! @ *--outs = vF
10017 2: and ip, r1, #0x00f0 @ isolate E
10018 ldr r2, [rFP, ip, lsr #2] @ r2<- vE
10020 str r2, [r10, #-4]! @ *--outs = vE
10021 1: and ip, r1, #0x000f @ isolate D
10022 ldr r2, [rFP, ip, lsl #2] @ r2<- vD
10024 str r2, [r10, #-4]! @ *--outs = vD
10025 0: @ fall through to .LinvokeArgsDone
10027 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
10028 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns
10029 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz
10030 @ find space for the new stack frame, check for overflow
10031 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
10032 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize)
10033 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
10034 @ bl common_dumpRegs
10035 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
10036 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
10037 cmp r3, r9 @ bottom < interpStackEnd?
10038 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10039 blt .LstackOverflow @ yes, this frame will overflow stack
10041 @ set up newSaveArea
10043 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
10044 str ip, [r10, #offStackSaveArea_prevSave]
10046 str rFP, [r10, #offStackSaveArea_prevFrame]
10047 str rPC, [r10, #offStackSaveArea_savedPc]
10048 #if defined(WITH_JIT)
10050 str r9, [r10, #offStackSaveArea_returnAddr]
10052 str r0, [r10, #offStackSaveArea_method]
10053 tst r3, #ACC_NATIVE
10058 bl common_printNewline
10067 bl common_printNewline
10071 ldrh r9, [r2] @ r9 <- load INST from new PC
10072 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10073 mov rPC, r2 @ publish new rPC
10074 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
10076 @ Update "glue" values for the new method
10077 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10078 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
10079 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10080 #if defined(WITH_JIT)
10081 GET_JIT_PROF_TABLE(r0)
10082 mov rFP, r1 @ fp = newFp
10083 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
10084 mov rINST, r9 @ publish new rINST
10085 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
10087 bne common_updateProfile
10088 GOTO_OPCODE(ip) @ jump to next instruction
10090 mov rFP, r1 @ fp = newFp
10091 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
10092 mov rINST, r9 @ publish new rINST
10093 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
10094 GOTO_OPCODE(ip) @ jump to next instruction
10098 @ Prep for the native call
10099 @ r0=methodToCall, r1=newFp, r10=newSaveArea
10100 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
10101 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10102 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
10103 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10104 mov r9, r3 @ r9<- glue->self (preserve)
10106 mov r2, r0 @ r2<- methodToCall
10107 mov r0, r1 @ r0<- newFp (points to args)
10108 add r1, rGLUE, #offGlue_retval @ r1<- &retval
10110 #ifdef ASSIST_DEBUGGER
10111 /* insert fake function header to help gdb find the stack frame */
10113 .type dalvik_mterp, %function
10121 @mov lr, pc @ set return addr
10122 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10123 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10125 #if defined(WITH_JIT)
10126 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10129 @ native return; r9=self, r10=newSaveArea
10130 @ equivalent to dvmPopJniLocals
10131 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10132 ldr r1, [r9, #offThread_exception] @ check for exception
10133 #if defined(WITH_JIT)
10134 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable
10136 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
10138 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10139 #if defined(WITH_JIT)
10140 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10142 bne common_exceptionThrown @ no, handle exception
10144 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
10145 GET_INST_OPCODE(ip) @ extract opcode from rINST
10146 GOTO_OPCODE(ip) @ jump to next instruction
10148 .LstackOverflow: @ r0=methodToCall
10149 mov r1, r0 @ r1<- methodToCall
10150 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
10151 bl dvmHandleStackOverflow
10152 b common_exceptionThrown
10153 #ifdef ASSIST_DEBUGGER
10159 * Common code for method invocation, calling through "glue code".
10161 * TODO: now that we have range and non-range invoke handlers, this
10162 * needs to be split into two. Maybe just create entry points
10163 * that set r9 and jump here?
10166 * r0 is "Method* methodToCall", the method we're trying to call
10167 * r9 is "bool methodCallRange", indicating if this is a /range variant
10171 sub sp, sp, #8 @ space for args + pad
10172 FETCH(ip, 2) @ ip<- FEDC or CCCC
10173 mov r2, r0 @ A2<- methodToCall
10174 mov r0, rGLUE @ A0<- glue
10175 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
10176 mov r1, r9 @ A1<- methodCallRange
10177 mov r3, rINST, lsr #8 @ A3<- AA
10178 str ip, [sp, #0] @ A4<- ip
10179 bl dvmMterp_invokeMethod @ call the C invokeMethod
10180 add sp, sp, #8 @ remove arg area
10181 b common_resumeAfterGlueCall @ continue to next instruction
10187 * Common code for handling a return instruction.
10189 * This does not return.
10191 common_returnFromMethod:
10193 mov r0, #kInterpEntryReturn
10195 bl common_periodicChecks
10197 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
10198 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10199 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10200 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10201 @ r2<- method we're returning to
10202 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
10203 cmp r2, #0 @ is this a break frame?
10204 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10205 mov r1, #0 @ "want switch" = false
10206 beq common_gotoBail @ break frame, bail out completely
10208 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10209 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10210 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
10211 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
10212 #if defined(WITH_JIT)
10213 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10214 GET_JIT_PROF_TABLE(r0)
10215 mov rPC, r9 @ publish new rPC
10216 str r1, [rGLUE, #offGlue_methodClassDex]
10217 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land
10218 cmp r10, #0 @ caller is compiled code
10220 GET_INST_OPCODE(ip) @ extract opcode from rINST
10222 bne common_updateProfile
10223 GOTO_OPCODE(ip) @ jump to next instruction
10225 GET_INST_OPCODE(ip) @ extract opcode from rINST
10226 mov rPC, r9 @ publish new rPC
10227 str r1, [rGLUE, #offGlue_methodClassDex]
10228 GOTO_OPCODE(ip) @ jump to next instruction
10232 * Return handling, calls through "glue code".
10236 SAVE_PC_FP_TO_GLUE() @ export state
10237 mov r0, rGLUE @ arg to function
10238 bl dvmMterp_returnFromMethod
10239 b common_resumeAfterGlueCall
10244 * Somebody has thrown an exception. Handle it.
10246 * If the exception processing code returns to us (instead of falling
10247 * out of the interpreter), continue with whatever the next instruction
10248 * now happens to be.
10250 * This does not return.
10252 .global dvmMterpCommonExceptionThrown
10253 dvmMterpCommonExceptionThrown:
10254 common_exceptionThrown:
10256 mov r0, #kInterpEntryThrow
10258 bl common_periodicChecks
10260 #if defined(WITH_JIT)
10261 mov r2,#kJitTSelectAbort @ abandon trace selection in progress
10262 str r2,[rGLUE,#offGlue_jitState]
10265 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10266 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
10267 mov r1, r10 @ r1<- self
10268 mov r0, r9 @ r0<- exception
10269 bl dvmAddTrackedAlloc @ don't let the exception be GCed
10270 mov r3, #0 @ r3<- NULL
10271 str r3, [r10, #offThread_exception] @ self->exception = NULL
10273 /* set up args and a local for "&fp" */
10274 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
10275 str rFP, [sp, #-4]! @ *--sp = fp
10276 mov ip, sp @ ip<- &fp
10277 mov r3, #0 @ r3<- false
10278 str ip, [sp, #-4]! @ *--sp = &fp
10279 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10280 mov r0, r10 @ r0<- self
10281 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
10282 mov r2, r9 @ r2<- exception
10283 sub r1, rPC, r1 @ r1<- pc - method->insns
10284 mov r1, r1, asr #1 @ r1<- offset in code units
10286 /* call, r0 gets catchRelPc (a code-unit offset) */
10287 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
10289 /* fix earlier stack overflow if necessary; may trash rFP */
10290 ldrb r1, [r10, #offThread_stackOverflowed]
10291 cmp r1, #0 @ did we overflow earlier?
10292 beq 1f @ no, skip ahead
10293 mov rFP, r0 @ save relPc result in rFP
10294 mov r0, r10 @ r0<- self
10295 mov r1, r9 @ r1<- exception
10296 bl dvmCleanupStackOverflow @ call(self)
10297 mov r0, rFP @ restore result
10300 /* update frame pointer and check result from dvmFindCatchBlock */
10301 ldr rFP, [sp, #4] @ retrieve the updated rFP
10302 cmp r0, #0 @ is catchRelPc < 0?
10303 add sp, sp, #8 @ restore stack
10304 bmi .LnotCaughtLocally
10306 /* adjust locals to match self->curFrame and updated PC */
10307 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
10308 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
10309 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
10310 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
10311 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
10312 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10313 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
10314 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10316 /* release the tracked alloc on the exception */
10317 mov r0, r9 @ r0<- exception
10318 mov r1, r10 @ r1<- self
10319 bl dvmReleaseTrackedAlloc @ release the exception
10321 /* restore the exception if the handler wants it */
10322 FETCH_INST() @ load rINST from rPC
10323 GET_INST_OPCODE(ip) @ extract opcode from rINST
10324 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
10325 streq r9, [r10, #offThread_exception] @ yes, restore the exception
10326 GOTO_OPCODE(ip) @ jump to next instruction
10328 .LnotCaughtLocally: @ r9=exception, r10=self
10329 /* fix stack overflow if necessary */
10330 ldrb r1, [r10, #offThread_stackOverflowed]
10331 cmp r1, #0 @ did we overflow earlier?
10332 movne r0, r10 @ if yes: r0<- self
10333 movne r1, r9 @ if yes: r1<- exception
10334 blne dvmCleanupStackOverflow @ if yes: call(self)
10336 @ may want to show "not caught locally" debug messages here
10337 #if DVM_SHOW_EXCEPTION >= 2
10338 /* call __android_log_print(prio, tag, format, ...) */
10339 /* "Exception %s from %s:%d not caught locally" */
10340 @ dvmLineNumFromPC(method, pc - method->insns)
10341 ldr r0, [rGLUE, #offGlue_method]
10342 ldr r1, [r0, #offMethod_insns]
10345 bl dvmLineNumFromPC
10347 @ dvmGetMethodSourceFile(method)
10348 ldr r0, [rGLUE, #offGlue_method]
10349 bl dvmGetMethodSourceFile
10351 @ exception->clazz->descriptor
10352 ldr r3, [r9, #offObject_clazz]
10353 ldr r3, [r3, #offClassObject_descriptor]
10355 ldr r2, strExceptionNotCaughtLocally
10357 mov r0, #3 @ LOG_DEBUG
10358 bl __android_log_print
10360 str r9, [r10, #offThread_exception] @ restore exception
10361 mov r0, r9 @ r0<- exception
10362 mov r1, r10 @ r1<- self
10363 bl dvmReleaseTrackedAlloc @ release the exception
10364 mov r1, #0 @ "want switch" = false
10365 b common_gotoBail @ bail out
10369 * Exception handling, calls through "glue code".
10373 SAVE_PC_FP_TO_GLUE() @ export state
10374 mov r0, rGLUE @ arg to function
10375 bl dvmMterp_exceptionThrown
10376 b common_resumeAfterGlueCall
10381 * After returning from a "glued" function, pull out the updated
10382 * values and start executing at the next instruction.
10384 common_resumeAfterGlueCall:
10385 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
10386 FETCH_INST() @ load rINST from rPC
10387 GET_INST_OPCODE(ip) @ extract opcode from rINST
10388 GOTO_OPCODE(ip) @ jump to next instruction
10391 * Invalid array index.
10393 common_errArrayIndex:
10395 ldr r0, strArrayIndexException
10397 bl dvmThrowException
10398 b common_exceptionThrown
10401 * Invalid array value.
10403 common_errArrayStore:
10405 ldr r0, strArrayStoreException
10407 bl dvmThrowException
10408 b common_exceptionThrown
10411 * Integer divide or mod by zero.
10413 common_errDivideByZero:
10415 ldr r0, strArithmeticException
10416 ldr r1, strDivideByZero
10417 bl dvmThrowException
10418 b common_exceptionThrown
10421 * Attempt to allocate an array with a negative size.
10423 common_errNegativeArraySize:
10425 ldr r0, strNegativeArraySizeException
10427 bl dvmThrowException
10428 b common_exceptionThrown
10431 * Invocation of a non-existent method.
10433 common_errNoSuchMethod:
10435 ldr r0, strNoSuchMethodError
10437 bl dvmThrowException
10438 b common_exceptionThrown
10441 * We encountered a null object when we weren't expecting one. We
10442 * export the PC, throw a NullPointerException, and goto the exception
10445 common_errNullObject:
10447 ldr r0, strNullPointerException
10449 bl dvmThrowException
10450 b common_exceptionThrown
10453 * For debugging, cause an immediate fault. The source address will
10454 * be in lr (use a bl instruction to jump here).
10462 * Spit out a "we were here", preserving all registers. (The attempt
10463 * to save ip won't work, but we need to save an even number of
10464 * registers for EABI 64-bit stack alignment.)
10468 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10472 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10484 * Spit out the number in r0, preserving registers.
10487 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10491 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10495 * Print a newline, preserving registers.
10497 common_printNewline:
10498 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10501 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10505 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10508 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10510 ldr r0, strPrintHex
10512 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10516 * Print the 64-bit quantity in r0-r1, preserving registers.
10519 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10522 ldr r0, strPrintLong
10524 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10528 * Print full method info. Pass the Method* in r0. Preserves regs.
10530 common_printMethod:
10531 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10532 bl dvmMterpPrintMethod
10533 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10537 * Call a C helper function that dumps regs and possibly some
10538 * additional info. Requires the C function to be compiled in.
10542 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10543 bl dvmMterpDumpArmRegs
10544 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10550 * Experiment on VFP mode.
10552 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10554 * Updates the bits specified by "mask", setting them to the values in "val".
10557 and r0, r0, r1 @ make sure no stray bits are set
10558 fmrx r2, fpscr @ get VFP reg
10559 mvn r1, r1 @ bit-invert mask
10560 and r2, r2, r1 @ clear masked bits
10561 orr r2, r2, r0 @ set specified bits
10562 fmxr fpscr, r2 @ set VFP reg
10563 mov r0, r2 @ return new value
10567 .global dvmConfigureFP
10568 .type dvmConfigureFP, %function
10570 stmfd sp!, {ip, lr}
10571 /* 0x03000000 sets DN/FZ */
10572 /* 0x00009f00 clears the six exception enable flags */
10574 mov r0, #0x03000000 @ r0<- 0x03000000
10575 add r1, r0, #0x9f00 @ r1<- 0x03009f00
10577 ldmfd sp!, {ip, pc}
10582 * String references, must be close to the code that uses them.
10585 strArithmeticException:
10586 .word .LstrArithmeticException
10587 strArrayIndexException:
10588 .word .LstrArrayIndexException
10589 strArrayStoreException:
10590 .word .LstrArrayStoreException
10592 .word .LstrDivideByZero
10593 strNegativeArraySizeException:
10594 .word .LstrNegativeArraySizeException
10595 strNoSuchMethodError:
10596 .word .LstrNoSuchMethodError
10597 strNullPointerException:
10598 .word .LstrNullPointerException
10602 strExceptionNotCaughtLocally:
10603 .word .LstrExceptionNotCaughtLocally
10610 .word .LstrPrintHex
10612 .word .LstrPrintLong
10615 * Zero-terminated ASCII string data.
10617 * On ARM we have two choices: do like gcc does, and LDR from a .word
10618 * with the address, or use an ADR pseudo-op to get the address
10619 * directly. ADR saves 4 bytes and an indirection, but it's using a
10620 * PC-relative addressing mode and hence has a limited range, which
10621 * makes it not work well with mergeable string sections.
10623 .section .rodata.str1.4,"aMS",%progbits,1
10625 .LstrBadEntryPoint:
10626 .asciz "Bad entry point %d\n"
10627 .LstrArithmeticException:
10628 .asciz "Ljava/lang/ArithmeticException;"
10629 .LstrArrayIndexException:
10630 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
10631 .LstrArrayStoreException:
10632 .asciz "Ljava/lang/ArrayStoreException;"
10633 .LstrClassCastException:
10634 .asciz "Ljava/lang/ClassCastException;"
10636 .asciz "divide by zero"
10637 .LstrFilledNewArrayNotImpl:
10638 .asciz "filled-new-array only implemented for objects and 'int'"
10639 .LstrInternalError:
10640 .asciz "Ljava/lang/InternalError;"
10641 .LstrInstantiationError:
10642 .asciz "Ljava/lang/InstantiationError;"
10643 .LstrNegativeArraySizeException:
10644 .asciz "Ljava/lang/NegativeArraySizeException;"
10645 .LstrNoSuchMethodError:
10646 .asciz "Ljava/lang/NoSuchMethodError;"
10647 .LstrNullPointerException:
10648 .asciz "Ljava/lang/NullPointerException;"
10652 .LstrExceptionNotCaughtLocally:
10653 .asciz "Exception %s from %s:%d not caught locally\n"