2 * This file was generated automatically by gen-mterp.py for 'armv4'.
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.
45 Stack is "full descending". Only the arguments that don't fit in the first 4
46 registers are placed on the stack. "sp" points at the first stacked argument
49 VFP: single-precision results in s0, double-precision results in d0.
51 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
52 64-bit quantities (long long, double) must be 64-bit aligned.
58 The following registers have fixed assignments:
61 r4 rPC interpreted program counter, used for fetching instructions
62 r5 rFP interpreted frame pointer, used for accessing locals and args
63 r6 rGLUE MterpGlue pointer
64 r7 rIBASE interpreted instruction base pointer, used for computed goto
65 r8 rINST first 16-bit code unit of current instruction
67 Macros are provided for common operations. Each macro MUST emit only
68 one instruction to make instruction-counting easier. They MUST NOT alter
69 unspecified registers or condition codes.
72 /* single-purpose registers, given names for clarity */
79 /* save/restore the PC and/or FP from the glue struct */
80 #define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc]
81 #define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc]
82 #define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp]
83 #define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp]
84 #define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP}
85 #define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP}
88 * "export" the PC to the stack frame, f/b/o future exception objects. Must
89 * be done *before* something calls dvmThrowException.
91 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
92 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
94 * It's okay to do this more than once.
97 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100 * Given a frame pointer, find the stack save area.
102 * In C this is "((StackSaveArea*)(_fp) -1)".
104 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
105 sub _reg, _fpreg, #sizeofStackSaveArea
108 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
110 #define FETCH_INST() ldrh rINST, [rPC]
113 * Fetch the next instruction from the specified offset. Advances rPC
114 * to point to the next instruction. "_count" is in 16-bit code units.
116 * Because of the limited size of immediate constants on ARM, this is only
117 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * This must come AFTER anything that can throw an exception, or the
121 * exception catch may miss. (This also implies that it must come after
124 #define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]!
127 * Fetch the next instruction from an offset specified by _reg. Updates
128 * rPC to point to the next instruction. "_reg" must specify the distance
129 * in bytes, *not* 16-bit code units, and may be a signed value.
131 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
132 * bits that hold the shift distance are used for the half/byte/sign flags.
133 * In some cases we can pre-double _reg for free, so we require a byte offset
136 #define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]!
139 * Fetch a half-word code unit from an offset past the current PC. The
140 * "_count" value is in 16-bit code units. Does not advance rPC.
142 * The "_S" variant works the same but treats the value as signed.
144 #define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)]
145 #define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)]
148 * Fetch one byte from an offset past the current PC. Pass in the same
149 * "_count" as you would for FETCH, and an additional 0/1 indicating which
150 * byte of the halfword you want (lo/hi).
152 #define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)]
155 * Put the instruction's opcode field into the specified register.
157 #define GET_INST_OPCODE(_reg) and _reg, rINST, #255
160 * Begin executing the opcode in _reg. Because this only jumps within the
161 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
163 #define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6
166 * Get/set the 32-bit value from a Dalvik register.
168 #define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2]
169 #define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2]
172 * This is a #include, not a %include, because we want the C pre-processor
173 * to expand the macros into assembler assignment statements.
175 #include "../common/asm-constants.h"
178 /* File: armv5te/platform.S */
180 * ===========================================================================
181 * CPU-version-specific defines
182 * ===========================================================================
186 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a
189 * May modify IP. Does not modify LR.
196 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
197 * Jump to subroutine.
199 * May modify IP and LR.
201 .macro LDR_PC_LR source
207 * Macro for "LDMFD SP!, {...regs...,PC}".
209 * May modify IP and LR.
212 ldmfd sp!, {\regs,pc}
216 /* File: armv5te/entry.S */
218 * Copyright (C) 2008 The Android Open Source Project
220 * Licensed under the Apache License, Version 2.0 (the "License");
221 * you may not use this file except in compliance with the License.
222 * You may obtain a copy of the License at
224 * http://www.apache.org/licenses/LICENSE-2.0
226 * Unless required by applicable law or agreed to in writing, software
227 * distributed under the License is distributed on an "AS IS" BASIS,
228 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
229 * See the License for the specific language governing permissions and
230 * limitations under the License.
233 * Interpreter entry point.
237 * We don't have formal stack frames, so gdb scans upward in the code
238 * to find the start of the function (a label with the %function type),
239 * and then looks at the next few instructions to figure out what
240 * got pushed onto the stack. From this it figures out how to restore
241 * the registers, including PC, for the previous stack frame. If gdb
242 * sees a non-function label, it stops scanning, so either we need to
243 * have nothing but assembler-local labels between the entry point and
244 * the break, or we need to fake it out.
246 * When this is defined, we add some stuff to make gdb less confused.
248 #define ASSIST_DEBUGGER 1
252 .global dvmMterpStdRun
253 .type dvmMterpStdRun, %function
259 * This function returns a boolean "changeInterp" value. The return comes
260 * via a call to dvmMterpStdBail().
263 #define MTERP_ENTRY1 \
264 .save {r4-r10,fp,lr}; \
265 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs
266 #define MTERP_ENTRY2 \
268 sub sp, sp, #4 @ align 64
274 /* save stack pointer, add magic word for debuggerd */
275 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return
277 /* set up "named" registers, figure out entry point */
278 mov rGLUE, r0 @ set rGLUE
279 ldrb r1, [r0, #offGlue_entryPoint] @ InterpEntry enum is char
280 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue"
281 adr rIBASE, dvmAsmInstructionStart @ set rIBASE
282 cmp r1, #kInterpEntryInstr @ usual case?
283 bne .Lnot_instr @ no, handle it
285 /* start executing the instruction at rPC */
286 FETCH_INST() @ load rINST from rPC
287 GET_INST_OPCODE(ip) @ extract opcode from rINST
288 GOTO_OPCODE(ip) @ jump to next instruction
291 cmp r1, #kInterpEntryReturn @ were we returning from a method?
292 beq common_returnFromMethod
295 cmp r1, #kInterpEntryThrow @ were we throwing an exception?
296 beq common_exceptionThrown
299 ldr r0, strBadEntryPoint
300 @ r1 holds value of entryPoint
306 .global dvmMterpStdBail
307 .type dvmMterpStdBail, %function
310 * Restore the stack pointer and PC from the save point established on entry.
311 * This is essentially the same as a longjmp, but should be cheaper. The
312 * last instruction causes us to return to whoever called dvmMterpStdRun.
314 * We pushed some registers on the stack in dvmMterpStdRun, then saved
315 * SP and LR. Here we restore SP, restore the registers, and then restore
320 * r1 bool changeInterp
323 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP
324 mov r0, r1 @ return the changeInterp value
325 add sp, sp, #4 @ un-align 64
326 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return
333 .word .LstrBadEntryPoint
337 .global dvmAsmInstructionStart
338 .type dvmAsmInstructionStart, %function
339 dvmAsmInstructionStart = .L_OP_NOP
342 /* ------------------------------ */
344 .L_OP_NOP: /* 0x00 */
345 /* File: armv5te/OP_NOP.S */
346 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST
347 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
348 GOTO_OPCODE(ip) @ execute it
350 #ifdef ASSIST_DEBUGGER
351 /* insert fake function header to help gdb find the stack frame */
352 .type dalvik_inst, %function
361 /* ------------------------------ */
363 .L_OP_MOVE: /* 0x01 */
364 /* File: armv5te/OP_MOVE.S */
365 /* for move, move-object, long-to-int */
367 mov r1, rINST, lsr #12 @ r1<- B from 15:12
368 mov r0, rINST, lsr #8 @ r0<- A from 11:8
369 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
370 GET_VREG(r2, r1) @ r2<- fp[B]
372 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
373 SET_VREG(r2, r0) @ fp[A]<- r2
374 GOTO_OPCODE(ip) @ execute next instruction
377 /* ------------------------------ */
379 .L_OP_MOVE_FROM16: /* 0x02 */
380 /* File: armv5te/OP_MOVE_FROM16.S */
381 /* for: move/from16, move-object/from16 */
383 FETCH(r1, 1) @ r1<- BBBB
384 mov r0, rINST, lsr #8 @ r0<- AA
385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
386 GET_VREG(r2, r1) @ r2<- fp[BBBB]
387 GET_INST_OPCODE(ip) @ extract opcode from rINST
388 SET_VREG(r2, r0) @ fp[AA]<- r2
389 GOTO_OPCODE(ip) @ jump to next instruction
392 /* ------------------------------ */
394 .L_OP_MOVE_16: /* 0x03 */
395 /* File: armv5te/OP_MOVE_16.S */
396 /* for: move/16, move-object/16 */
397 /* op vAAAA, vBBBB */
398 FETCH(r1, 2) @ r1<- BBBB
399 FETCH(r0, 1) @ r0<- AAAA
400 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
401 GET_VREG(r2, r1) @ r2<- fp[BBBB]
402 GET_INST_OPCODE(ip) @ extract opcode from rINST
403 SET_VREG(r2, r0) @ fp[AAAA]<- r2
404 GOTO_OPCODE(ip) @ jump to next instruction
407 /* ------------------------------ */
409 .L_OP_MOVE_WIDE: /* 0x04 */
410 /* File: armv5te/OP_MOVE_WIDE.S */
411 /* move-wide vA, vB */
412 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
413 mov r2, rINST, lsr #8 @ r2<- A(+)
414 mov r3, rINST, lsr #12 @ r3<- B
416 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
417 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
418 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
419 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
420 GET_INST_OPCODE(ip) @ extract opcode from rINST
421 stmia r2, {r0-r1} @ fp[A]<- r0/r1
422 GOTO_OPCODE(ip) @ jump to next instruction
425 /* ------------------------------ */
427 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
428 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
429 /* move-wide/from16 vAA, vBBBB */
430 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
431 FETCH(r3, 1) @ r3<- BBBB
432 mov r2, rINST, lsr #8 @ r2<- AA
433 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
434 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
435 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
437 GET_INST_OPCODE(ip) @ extract opcode from rINST
438 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
439 GOTO_OPCODE(ip) @ jump to next instruction
442 /* ------------------------------ */
444 .L_OP_MOVE_WIDE_16: /* 0x06 */
445 /* File: armv5te/OP_MOVE_WIDE_16.S */
446 /* move-wide/16 vAAAA, vBBBB */
447 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
448 FETCH(r3, 2) @ r3<- BBBB
449 FETCH(r2, 1) @ r2<- AAAA
450 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
451 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
452 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
454 GET_INST_OPCODE(ip) @ extract opcode from rINST
455 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
456 GOTO_OPCODE(ip) @ jump to next instruction
459 /* ------------------------------ */
461 .L_OP_MOVE_OBJECT: /* 0x07 */
462 /* File: armv5te/OP_MOVE_OBJECT.S */
463 /* File: armv5te/OP_MOVE.S */
464 /* for move, move-object, long-to-int */
466 mov r1, rINST, lsr #12 @ r1<- B from 15:12
467 mov r0, rINST, lsr #8 @ r0<- A from 11:8
468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
469 GET_VREG(r2, r1) @ r2<- fp[B]
471 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
472 SET_VREG(r2, r0) @ fp[A]<- r2
473 GOTO_OPCODE(ip) @ execute next instruction
477 /* ------------------------------ */
479 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
480 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
481 /* File: armv5te/OP_MOVE_FROM16.S */
482 /* for: move/from16, move-object/from16 */
484 FETCH(r1, 1) @ r1<- BBBB
485 mov r0, rINST, lsr #8 @ r0<- AA
486 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
487 GET_VREG(r2, r1) @ r2<- fp[BBBB]
488 GET_INST_OPCODE(ip) @ extract opcode from rINST
489 SET_VREG(r2, r0) @ fp[AA]<- r2
490 GOTO_OPCODE(ip) @ jump to next instruction
494 /* ------------------------------ */
496 .L_OP_MOVE_OBJECT_16: /* 0x09 */
497 /* File: armv5te/OP_MOVE_OBJECT_16.S */
498 /* File: armv5te/OP_MOVE_16.S */
499 /* for: move/16, move-object/16 */
500 /* op vAAAA, vBBBB */
501 FETCH(r1, 2) @ r1<- BBBB
502 FETCH(r0, 1) @ r0<- AAAA
503 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
504 GET_VREG(r2, r1) @ r2<- fp[BBBB]
505 GET_INST_OPCODE(ip) @ extract opcode from rINST
506 SET_VREG(r2, r0) @ fp[AAAA]<- r2
507 GOTO_OPCODE(ip) @ jump to next instruction
511 /* ------------------------------ */
513 .L_OP_MOVE_RESULT: /* 0x0a */
514 /* File: armv5te/OP_MOVE_RESULT.S */
515 /* for: move-result, move-result-object */
517 mov r2, rINST, lsr #8 @ r2<- AA
518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
519 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
520 GET_INST_OPCODE(ip) @ extract opcode from rINST
521 SET_VREG(r0, r2) @ fp[AA]<- r0
522 GOTO_OPCODE(ip) @ jump to next instruction
525 /* ------------------------------ */
527 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
528 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
529 /* move-result-wide vAA */
530 mov r2, rINST, lsr #8 @ r2<- AA
531 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
532 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
533 ldmia r3, {r0-r1} @ r0/r1<- retval.j
534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
535 GET_INST_OPCODE(ip) @ extract opcode from rINST
536 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
537 GOTO_OPCODE(ip) @ jump to next instruction
540 /* ------------------------------ */
542 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
543 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
544 /* File: armv5te/OP_MOVE_RESULT.S */
545 /* for: move-result, move-result-object */
547 mov r2, rINST, lsr #8 @ r2<- AA
548 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
549 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
550 GET_INST_OPCODE(ip) @ extract opcode from rINST
551 SET_VREG(r0, r2) @ fp[AA]<- r0
552 GOTO_OPCODE(ip) @ jump to next instruction
556 /* ------------------------------ */
558 .L_OP_MOVE_EXCEPTION: /* 0x0d */
559 /* File: armv5te/OP_MOVE_EXCEPTION.S */
560 /* move-exception vAA */
561 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
562 mov r2, rINST, lsr #8 @ r2<- AA
563 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
565 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
566 SET_VREG(r3, r2) @ fp[AA]<- exception obj
567 GET_INST_OPCODE(ip) @ extract opcode from rINST
568 str r1, [r0, #offThread_exception] @ dvmClearException bypass
569 GOTO_OPCODE(ip) @ jump to next instruction
572 /* ------------------------------ */
574 .L_OP_RETURN_VOID: /* 0x0e */
575 /* File: armv5te/OP_RETURN_VOID.S */
576 b common_returnFromMethod
579 /* ------------------------------ */
581 .L_OP_RETURN: /* 0x0f */
582 /* File: armv5te/OP_RETURN.S */
584 * Return a 32-bit value. Copies the return value into the "glue"
585 * structure, then jumps to the return handler.
587 * for: return, return-object
590 mov r2, rINST, lsr #8 @ r2<- AA
591 GET_VREG(r0, r2) @ r0<- vAA
592 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
593 b common_returnFromMethod
596 /* ------------------------------ */
598 .L_OP_RETURN_WIDE: /* 0x10 */
599 /* File: armv5te/OP_RETURN_WIDE.S */
601 * Return a 64-bit value. Copies the return value into the "glue"
602 * structure, then jumps to the return handler.
604 /* return-wide vAA */
605 mov r2, rINST, lsr #8 @ r2<- AA
606 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
607 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
608 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
609 stmia r3, {r0-r1} @ retval<- r0/r1
610 b common_returnFromMethod
613 /* ------------------------------ */
615 .L_OP_RETURN_OBJECT: /* 0x11 */
616 /* File: armv5te/OP_RETURN_OBJECT.S */
617 /* File: armv5te/OP_RETURN.S */
619 * Return a 32-bit value. Copies the return value into the "glue"
620 * structure, then jumps to the return handler.
622 * for: return, return-object
625 mov r2, rINST, lsr #8 @ r2<- AA
626 GET_VREG(r0, r2) @ r0<- vAA
627 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
628 b common_returnFromMethod
632 /* ------------------------------ */
634 .L_OP_CONST_4: /* 0x12 */
635 /* File: armv5te/OP_CONST_4.S */
636 /* const/4 vA, #+B */
637 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
638 mov r0, rINST, lsr #8 @ r0<- A+
639 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
640 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
642 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
643 SET_VREG(r1, r0) @ fp[A]<- r1
644 GOTO_OPCODE(ip) @ execute next instruction
647 /* ------------------------------ */
649 .L_OP_CONST_16: /* 0x13 */
650 /* File: armv5te/OP_CONST_16.S */
651 /* const/16 vAA, #+BBBB */
652 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
653 mov r3, rINST, lsr #8 @ r3<- AA
654 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
655 SET_VREG(r0, r3) @ vAA<- r0
656 GET_INST_OPCODE(ip) @ extract opcode from rINST
657 GOTO_OPCODE(ip) @ jump to next instruction
660 /* ------------------------------ */
662 .L_OP_CONST: /* 0x14 */
663 /* File: armv5te/OP_CONST.S */
664 /* const vAA, #+BBBBbbbb */
665 mov r3, rINST, lsr #8 @ r3<- AA
666 FETCH(r0, 1) @ r0<- bbbb (low)
667 FETCH(r1, 2) @ r1<- BBBB (high)
668 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
669 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
670 GET_INST_OPCODE(ip) @ extract opcode from rINST
671 SET_VREG(r0, r3) @ vAA<- r0
672 GOTO_OPCODE(ip) @ jump to next instruction
675 /* ------------------------------ */
677 .L_OP_CONST_HIGH16: /* 0x15 */
678 /* File: armv5te/OP_CONST_HIGH16.S */
679 /* const/high16 vAA, #+BBBB0000 */
680 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
681 mov r3, rINST, lsr #8 @ r3<- AA
682 mov r0, r0, lsl #16 @ r0<- BBBB0000
683 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
684 SET_VREG(r0, r3) @ vAA<- r0
685 GET_INST_OPCODE(ip) @ extract opcode from rINST
686 GOTO_OPCODE(ip) @ jump to next instruction
689 /* ------------------------------ */
691 .L_OP_CONST_WIDE_16: /* 0x16 */
692 /* File: armv5te/OP_CONST_WIDE_16.S */
693 /* const-wide/16 vAA, #+BBBB */
694 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
695 mov r3, rINST, lsr #8 @ r3<- AA
696 mov r1, r0, asr #31 @ r1<- ssssssss
697 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
698 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
699 GET_INST_OPCODE(ip) @ extract opcode from rINST
700 stmia r3, {r0-r1} @ vAA<- r0/r1
701 GOTO_OPCODE(ip) @ jump to next instruction
704 /* ------------------------------ */
706 .L_OP_CONST_WIDE_32: /* 0x17 */
707 /* File: armv5te/OP_CONST_WIDE_32.S */
708 /* const-wide/32 vAA, #+BBBBbbbb */
709 FETCH(r0, 1) @ r0<- 0000bbbb (low)
710 mov r3, rINST, lsr #8 @ r3<- AA
711 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
712 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
713 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
714 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
715 mov r1, r0, asr #31 @ r1<- ssssssss
716 GET_INST_OPCODE(ip) @ extract opcode from rINST
717 stmia r3, {r0-r1} @ vAA<- r0/r1
718 GOTO_OPCODE(ip) @ jump to next instruction
721 /* ------------------------------ */
723 .L_OP_CONST_WIDE: /* 0x18 */
724 /* File: armv5te/OP_CONST_WIDE.S */
725 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
726 FETCH(r0, 1) @ r0<- bbbb (low)
727 FETCH(r1, 2) @ r1<- BBBB (low middle)
728 FETCH(r2, 3) @ r2<- hhhh (high middle)
729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
730 FETCH(r3, 4) @ r3<- HHHH (high)
731 mov r9, rINST, lsr #8 @ r9<- AA
732 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
733 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
734 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
735 GET_INST_OPCODE(ip) @ extract opcode from rINST
736 stmia r9, {r0-r1} @ vAA<- r0/r1
737 GOTO_OPCODE(ip) @ jump to next instruction
740 /* ------------------------------ */
742 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
743 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
744 /* const-wide/high16 vAA, #+BBBB000000000000 */
745 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
746 mov r3, rINST, lsr #8 @ r3<- AA
747 mov r0, #0 @ r0<- 00000000
748 mov r1, r1, lsl #16 @ r1<- BBBB0000
749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
750 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
751 GET_INST_OPCODE(ip) @ extract opcode from rINST
752 stmia r3, {r0-r1} @ vAA<- r0/r1
753 GOTO_OPCODE(ip) @ jump to next instruction
756 /* ------------------------------ */
758 .L_OP_CONST_STRING: /* 0x1a */
759 /* File: armv5te/OP_CONST_STRING.S */
760 /* const/string vAA, String@BBBB */
761 FETCH(r1, 1) @ r1<- BBBB
762 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
763 mov r9, rINST, lsr #8 @ r9<- AA
764 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
765 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
766 cmp r0, #0 @ not yet resolved?
767 beq .LOP_CONST_STRING_resolve
768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
769 GET_INST_OPCODE(ip) @ extract opcode from rINST
770 SET_VREG(r0, r9) @ vAA<- r0
771 GOTO_OPCODE(ip) @ jump to next instruction
773 /* ------------------------------ */
775 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
776 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
777 /* const/string vAA, String@BBBBBBBB */
778 FETCH(r0, 1) @ r0<- bbbb (low)
779 FETCH(r1, 2) @ r1<- BBBB (high)
780 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
781 mov r9, rINST, lsr #8 @ r9<- AA
782 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
783 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
784 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
786 beq .LOP_CONST_STRING_JUMBO_resolve
787 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
788 GET_INST_OPCODE(ip) @ extract opcode from rINST
789 SET_VREG(r0, r9) @ vAA<- r0
790 GOTO_OPCODE(ip) @ jump to next instruction
792 /* ------------------------------ */
794 .L_OP_CONST_CLASS: /* 0x1c */
795 /* File: armv5te/OP_CONST_CLASS.S */
796 /* const/class vAA, Class@BBBB */
797 FETCH(r1, 1) @ r1<- BBBB
798 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
799 mov r9, rINST, lsr #8 @ r9<- AA
800 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
801 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
802 cmp r0, #0 @ not yet resolved?
803 beq .LOP_CONST_CLASS_resolve
804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
805 GET_INST_OPCODE(ip) @ extract opcode from rINST
806 SET_VREG(r0, r9) @ vAA<- r0
807 GOTO_OPCODE(ip) @ jump to next instruction
809 /* ------------------------------ */
811 .L_OP_MONITOR_ENTER: /* 0x1d */
812 /* File: armv5te/OP_MONITOR_ENTER.S */
814 * Synchronize on an object.
816 /* monitor-enter vAA */
817 mov r2, rINST, lsr #8 @ r2<- AA
818 GET_VREG(r1, r2) @ r1<- vAA (object)
819 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
820 cmp r1, #0 @ null object?
821 #ifdef WITH_MONITOR_TRACKING
822 EXPORT_PC() @ export PC so we can grab stack trace
824 beq common_errNullObject @ null object, throw an exception
825 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
826 bl dvmLockObject @ call(self, obj)
827 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
828 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
829 ldr r1, [r0, #offThread_exception] @ check for exception
831 bne common_exceptionThrown @ exception raised, bail out
833 GET_INST_OPCODE(ip) @ extract opcode from rINST
834 GOTO_OPCODE(ip) @ jump to next instruction
837 /* ------------------------------ */
839 .L_OP_MONITOR_EXIT: /* 0x1e */
840 /* File: armv5te/OP_MONITOR_EXIT.S */
844 * Exceptions that occur when unlocking a monitor need to appear as
845 * if they happened at the following instruction. See the Dalvik
848 /* monitor-exit vAA */
849 mov r2, rINST, lsr #8 @ r2<- AA
850 EXPORT_PC() @ before fetch: export the PC
851 GET_VREG(r1, r2) @ r1<- vAA (object)
852 cmp r1, #0 @ null object?
853 beq common_errNullObject @ yes
854 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
855 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
857 beq common_exceptionThrown @ yes, exception is pending
858 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
859 GET_INST_OPCODE(ip) @ extract opcode from rINST
860 GOTO_OPCODE(ip) @ jump to next instruction
863 /* ------------------------------ */
865 .L_OP_CHECK_CAST: /* 0x1f */
866 /* File: armv5te/OP_CHECK_CAST.S */
868 * Check to see if a cast from one class to another is allowed.
870 /* check-cast vAA, class@BBBB */
871 mov r3, rINST, lsr #8 @ r3<- AA
872 FETCH(r2, 1) @ r2<- BBBB
873 GET_VREG(r9, r3) @ r9<- object
874 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
875 cmp r9, #0 @ is object null?
876 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
877 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
878 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
879 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
880 cmp r1, #0 @ have we resolved this before?
881 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
882 .LOP_CHECK_CAST_resolved:
883 cmp r0, r1 @ same class (trivial success)?
884 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
885 .LOP_CHECK_CAST_okay:
886 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
887 GET_INST_OPCODE(ip) @ extract opcode from rINST
888 GOTO_OPCODE(ip) @ jump to next instruction
890 /* ------------------------------ */
892 .L_OP_INSTANCE_OF: /* 0x20 */
893 /* File: armv5te/OP_INSTANCE_OF.S */
895 * Check to see if an object reference is an instance of a class.
897 * Most common situation is a non-null object, being compared against
898 * an already-resolved class.
900 /* instance-of vA, vB, class@CCCC */
901 mov r3, rINST, lsr #12 @ r3<- B
902 mov r9, rINST, lsr #8 @ r9<- A+
903 GET_VREG(r0, r3) @ r0<- vB (object)
904 and r9, r9, #15 @ r9<- A
905 cmp r0, #0 @ is object null?
906 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
907 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
908 FETCH(r3, 1) @ r3<- CCCC
909 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
910 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
911 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
912 cmp r1, #0 @ have we resolved this before?
913 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
914 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
915 cmp r0, r1 @ same class (trivial success)?
916 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
917 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
919 /* ------------------------------ */
921 .L_OP_ARRAY_LENGTH: /* 0x21 */
922 /* File: armv5te/OP_ARRAY_LENGTH.S */
924 * Return the length of an array.
926 mov r1, rINST, lsr #12 @ r1<- B
927 mov r2, rINST, lsr #8 @ r2<- A+
928 GET_VREG(r0, r1) @ r0<- vB (object ref)
929 and r2, r2, #15 @ r2<- A
930 cmp r0, #0 @ is object null?
931 beq common_errNullObject @ yup, fail
932 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
933 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
934 GET_INST_OPCODE(ip) @ extract opcode from rINST
935 SET_VREG(r3, r2) @ vB<- length
936 GOTO_OPCODE(ip) @ jump to next instruction
939 /* ------------------------------ */
941 .L_OP_NEW_INSTANCE: /* 0x22 */
942 /* File: armv5te/OP_NEW_INSTANCE.S */
944 * Create a new instance of a class.
946 /* new-instance vAA, class@BBBB */
947 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
948 FETCH(r1, 1) @ r1<- BBBB
949 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
950 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
951 EXPORT_PC() @ req'd for init, resolve, alloc
952 cmp r0, #0 @ already resolved?
953 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
954 .LOP_NEW_INSTANCE_resolved: @ r0=class
955 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
956 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
957 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
958 .LOP_NEW_INSTANCE_initialized: @ r0=class
959 ldr r3, [r0, #offClassObject_accessFlags] @ r3<- clazz->accessFlags
960 tst r3, #(ACC_INTERFACE|ACC_ABSTRACT) @ abstract or interface?
961 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
962 beq .LOP_NEW_INSTANCE_finish @ concrete class, continue
963 b .LOP_NEW_INSTANCE_abstract @ fail
965 /* ------------------------------ */
967 .L_OP_NEW_ARRAY: /* 0x23 */
968 /* File: armv5te/OP_NEW_ARRAY.S */
970 * Allocate an array of objects, specified with the array class
973 * The verifier guarantees that this is an array class, so we don't
976 /* new-array vA, vB, class@CCCC */
977 mov r0, rINST, lsr #12 @ r0<- B
978 FETCH(r2, 1) @ r2<- CCCC
979 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
980 GET_VREG(r1, r0) @ r1<- vB (array length)
981 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
982 cmp r1, #0 @ check length
983 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
984 bmi common_errNegativeArraySize @ negative length, bail
985 cmp r0, #0 @ already resolved?
986 EXPORT_PC() @ req'd for resolve, alloc
987 bne .LOP_NEW_ARRAY_finish @ resolved, continue
988 b .LOP_NEW_ARRAY_resolve @ do resolve now
990 /* ------------------------------ */
992 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
993 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
995 * Create a new array with elements filled from registers.
997 * for: filled-new-array, filled-new-array/range
999 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1000 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1001 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1002 FETCH(r1, 1) @ r1<- BBBB
1003 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1004 EXPORT_PC() @ need for resolve and alloc
1005 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1006 mov r10, rINST, lsr #8 @ r10<- AA or BA
1007 cmp r0, #0 @ already resolved?
1008 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
1009 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1010 mov r2, #0 @ r2<- false
1011 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1012 bl dvmResolveClass @ r0<- call(clazz, ref)
1013 cmp r0, #0 @ got null?
1014 beq common_exceptionThrown @ yes, handle exception
1015 b .LOP_FILLED_NEW_ARRAY_continue
1017 /* ------------------------------ */
1019 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1020 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1021 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1023 * Create a new array with elements filled from registers.
1025 * for: filled-new-array, filled-new-array/range
1027 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1028 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1029 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1030 FETCH(r1, 1) @ r1<- BBBB
1031 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1032 EXPORT_PC() @ need for resolve and alloc
1033 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1034 mov r10, rINST, lsr #8 @ r10<- AA or BA
1035 cmp r0, #0 @ already resolved?
1036 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
1037 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1038 mov r2, #0 @ r2<- false
1039 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1040 bl dvmResolveClass @ r0<- call(clazz, ref)
1041 cmp r0, #0 @ got null?
1042 beq common_exceptionThrown @ yes, handle exception
1043 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1046 /* ------------------------------ */
1048 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1049 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1050 /* fill-array-data vAA, +BBBBBBBB */
1051 FETCH(r0, 1) @ r0<- bbbb (lo)
1052 FETCH(r1, 2) @ r1<- BBBB (hi)
1053 mov r3, rINST, lsr #8 @ r3<- AA
1054 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1055 GET_VREG(r0, r3) @ r0<- vAA (array object)
1056 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1058 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1059 cmp r0, #0 @ 0 means an exception is thrown
1060 beq common_exceptionThrown @ has exception
1061 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1062 GET_INST_OPCODE(ip) @ extract opcode from rINST
1063 GOTO_OPCODE(ip) @ jump to next instruction
1065 /* ------------------------------ */
1067 .L_OP_THROW: /* 0x27 */
1068 /* File: armv5te/OP_THROW.S */
1070 * Throw an exception object in the current thread.
1073 mov r2, rINST, lsr #8 @ r2<- AA
1074 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1075 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1076 cmp r1, #0 @ null object?
1077 beq common_errNullObject @ yes, throw an NPE instead
1078 @ bypass dvmSetException, just store it
1079 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1080 b common_exceptionThrown
1083 /* ------------------------------ */
1085 .L_OP_GOTO: /* 0x28 */
1086 /* File: armv5te/OP_GOTO.S */
1088 * Unconditional branch, 8-bit offset.
1090 * The branch distance is a signed code-unit offset, which we need to
1091 * double to get a byte offset.
1094 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1095 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1096 mov r9, r9, lsl #1 @ r9<- byte offset
1097 bmi common_backwardBranch @ backward branch, do periodic checks
1098 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1099 GET_INST_OPCODE(ip) @ extract opcode from rINST
1100 GOTO_OPCODE(ip) @ jump to next instruction
1103 /* ------------------------------ */
1105 .L_OP_GOTO_16: /* 0x29 */
1106 /* File: armv5te/OP_GOTO_16.S */
1108 * Unconditional branch, 16-bit offset.
1110 * The branch distance is a signed code-unit offset, which we need to
1111 * double to get a byte offset.
1114 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1115 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1116 bmi common_backwardBranch @ backward branch, do periodic checks
1117 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1118 GET_INST_OPCODE(ip) @ extract opcode from rINST
1119 GOTO_OPCODE(ip) @ jump to next instruction
1122 /* ------------------------------ */
1124 .L_OP_GOTO_32: /* 0x2a */
1125 /* File: armv5te/OP_GOTO_32.S */
1127 * Unconditional branch, 32-bit offset.
1129 * The branch distance is a signed code-unit offset, which we need to
1130 * double to get a byte offset.
1132 * Unlike most opcodes, this one is allowed to branch to itself, so
1133 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1134 * instruction doesn't affect the V flag, so we need to clear it
1137 /* goto/32 +AAAAAAAA */
1138 FETCH(r0, 1) @ r0<- aaaa (lo)
1139 FETCH(r1, 2) @ r1<- AAAA (hi)
1140 cmp ip, ip @ (clear V flag during stall)
1141 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1142 mov r9, r0, asl #1 @ r9<- byte offset
1143 ble common_backwardBranch @ backward branch, do periodic checks
1144 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1145 GET_INST_OPCODE(ip) @ extract opcode from rINST
1146 GOTO_OPCODE(ip) @ jump to next instruction
1149 /* ------------------------------ */
1151 .L_OP_PACKED_SWITCH: /* 0x2b */
1152 /* File: armv5te/OP_PACKED_SWITCH.S */
1154 * Handle a packed-switch or sparse-switch instruction. In both cases
1155 * we decode it and hand it off to a helper function.
1157 * We don't really expect backward branches in a switch statement, but
1158 * they're perfectly legal, so we check for them here.
1160 * for: packed-switch, sparse-switch
1163 FETCH(r0, 1) @ r0<- bbbb (lo)
1164 FETCH(r1, 2) @ r1<- BBBB (hi)
1165 mov r3, rINST, lsr #8 @ r3<- AA
1166 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1167 GET_VREG(r1, r3) @ r1<- vAA
1168 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1169 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1170 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1171 bmi common_backwardBranch @ backward branch, do periodic checks
1172 beq common_backwardBranch @ (want to use BLE but V is unknown)
1173 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1174 GET_INST_OPCODE(ip) @ extract opcode from rINST
1175 GOTO_OPCODE(ip) @ jump to next instruction
1178 /* ------------------------------ */
1180 .L_OP_SPARSE_SWITCH: /* 0x2c */
1181 /* File: armv5te/OP_SPARSE_SWITCH.S */
1182 /* File: armv5te/OP_PACKED_SWITCH.S */
1184 * Handle a packed-switch or sparse-switch instruction. In both cases
1185 * we decode it and hand it off to a helper function.
1187 * We don't really expect backward branches in a switch statement, but
1188 * they're perfectly legal, so we check for them here.
1190 * for: packed-switch, sparse-switch
1193 FETCH(r0, 1) @ r0<- bbbb (lo)
1194 FETCH(r1, 2) @ r1<- BBBB (hi)
1195 mov r3, rINST, lsr #8 @ r3<- AA
1196 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1197 GET_VREG(r1, r3) @ r1<- vAA
1198 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1199 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1200 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1201 bmi common_backwardBranch @ backward branch, do periodic checks
1202 beq common_backwardBranch @ (want to use BLE but V is unknown)
1203 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1204 GET_INST_OPCODE(ip) @ extract opcode from rINST
1205 GOTO_OPCODE(ip) @ jump to next instruction
1209 /* ------------------------------ */
1211 .L_OP_CMPL_FLOAT: /* 0x2d */
1212 /* File: armv5te/OP_CMPL_FLOAT.S */
1214 * Compare two floating-point values. Puts 0, 1, or -1 into the
1215 * destination register based on the results of the comparison.
1217 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1218 * on what value we'd like to return when one of the operands is NaN.
1220 * The operation we're implementing is:
1228 * return {-1,1}; // one or both operands was NaN
1230 * The straightforward implementation requires 3 calls to functions
1231 * that return a result in r0. We can do it with two calls if our
1232 * EABI library supports __aeabi_cfcmple (only one if we want to check
1233 * for NaN directly):
1241 * for: cmpl-float, cmpg-float
1243 /* op vAA, vBB, vCC */
1244 FETCH(r0, 1) @ r0<- CCBB
1245 and r2, r0, #255 @ r2<- BB
1246 mov r3, r0, lsr #8 @ r3<- CC
1247 GET_VREG(r9, r2) @ r9<- vBB
1248 GET_VREG(r10, r3) @ r10<- vCC
1249 mov r0, r9 @ copy to arg registers
1251 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1252 bhi .LOP_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1253 mvncc r1, #0 @ (less than) r1<- -1
1254 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1255 .LOP_CMPL_FLOAT_finish:
1256 mov r3, rINST, lsr #8 @ r3<- AA
1257 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1258 SET_VREG(r1, r3) @ vAA<- r1
1259 GET_INST_OPCODE(ip) @ extract opcode from rINST
1260 GOTO_OPCODE(ip) @ jump to next instruction
1262 /* ------------------------------ */
1264 .L_OP_CMPG_FLOAT: /* 0x2e */
1265 /* File: armv5te/OP_CMPG_FLOAT.S */
1266 /* File: armv5te/OP_CMPL_FLOAT.S */
1268 * Compare two floating-point values. Puts 0, 1, or -1 into the
1269 * destination register based on the results of the comparison.
1271 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1272 * on what value we'd like to return when one of the operands is NaN.
1274 * The operation we're implementing is:
1282 * return {-1,1}; // one or both operands was NaN
1284 * The straightforward implementation requires 3 calls to functions
1285 * that return a result in r0. We can do it with two calls if our
1286 * EABI library supports __aeabi_cfcmple (only one if we want to check
1287 * for NaN directly):
1295 * for: cmpl-float, cmpg-float
1297 /* op vAA, vBB, vCC */
1298 FETCH(r0, 1) @ r0<- CCBB
1299 and r2, r0, #255 @ r2<- BB
1300 mov r3, r0, lsr #8 @ r3<- CC
1301 GET_VREG(r9, r2) @ r9<- vBB
1302 GET_VREG(r10, r3) @ r10<- vCC
1303 mov r0, r9 @ copy to arg registers
1305 bl __aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq
1306 bhi .LOP_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
1307 mvncc r1, #0 @ (less than) r1<- -1
1308 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1309 .LOP_CMPG_FLOAT_finish:
1310 mov r3, rINST, lsr #8 @ r3<- AA
1311 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1312 SET_VREG(r1, r3) @ vAA<- r1
1313 GET_INST_OPCODE(ip) @ extract opcode from rINST
1314 GOTO_OPCODE(ip) @ jump to next instruction
1317 /* ------------------------------ */
1319 .L_OP_CMPL_DOUBLE: /* 0x2f */
1320 /* File: armv5te/OP_CMPL_DOUBLE.S */
1322 * Compare two floating-point values. Puts 0, 1, or -1 into the
1323 * destination register based on the results of the comparison.
1325 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1326 * on what value we'd like to return when one of the operands is NaN.
1328 * See OP_CMPL_FLOAT for an explanation.
1330 * For: cmpl-double, cmpg-double
1332 /* op vAA, vBB, vCC */
1333 FETCH(r0, 1) @ r0<- CCBB
1334 and r9, r0, #255 @ r9<- BB
1335 mov r10, r0, lsr #8 @ r10<- CC
1336 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1337 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1338 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1339 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1340 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1341 bhi .LOP_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1342 mvncc r1, #0 @ (less than) r1<- -1
1343 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1344 .LOP_CMPL_DOUBLE_finish:
1345 mov r3, rINST, lsr #8 @ r3<- AA
1346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1347 SET_VREG(r1, r3) @ vAA<- r1
1348 GET_INST_OPCODE(ip) @ extract opcode from rINST
1349 GOTO_OPCODE(ip) @ jump to next instruction
1351 /* ------------------------------ */
1353 .L_OP_CMPG_DOUBLE: /* 0x30 */
1354 /* File: armv5te/OP_CMPG_DOUBLE.S */
1355 /* File: armv5te/OP_CMPL_DOUBLE.S */
1357 * Compare two floating-point values. Puts 0, 1, or -1 into the
1358 * destination register based on the results of the comparison.
1360 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1361 * on what value we'd like to return when one of the operands is NaN.
1363 * See OP_CMPL_FLOAT for an explanation.
1365 * For: cmpl-double, cmpg-double
1367 /* op vAA, vBB, vCC */
1368 FETCH(r0, 1) @ r0<- CCBB
1369 and r9, r0, #255 @ r9<- BB
1370 mov r10, r0, lsr #8 @ r10<- CC
1371 add r9, rFP, r9, lsl #2 @ r9<- &fp[BB]
1372 add r10, rFP, r10, lsl #2 @ r10<- &fp[CC]
1373 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
1374 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
1375 bl __aeabi_cdcmple @ cmp <=: C clear if <, Z set if eq
1376 bhi .LOP_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
1377 mvncc r1, #0 @ (less than) r1<- -1
1378 moveq r1, #0 @ (equal) r1<- 0, trumps less than
1379 .LOP_CMPG_DOUBLE_finish:
1380 mov r3, rINST, lsr #8 @ r3<- AA
1381 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1382 SET_VREG(r1, r3) @ vAA<- r1
1383 GET_INST_OPCODE(ip) @ extract opcode from rINST
1384 GOTO_OPCODE(ip) @ jump to next instruction
1387 /* ------------------------------ */
1389 .L_OP_CMP_LONG: /* 0x31 */
1390 /* File: armv5te/OP_CMP_LONG.S */
1392 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1393 * register based on the results of the comparison.
1395 * We load the full values with LDM, but in practice many values could
1396 * be resolved by only looking at the high word. This could be made
1397 * faster or slower by splitting the LDM into a pair of LDRs.
1399 * If we just wanted to set condition flags, we could do this:
1403 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1404 * integer value, which we can do with 2 conditional mov/mvn instructions
1405 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1406 * us a constant 5-cycle path plus a branch at the end to the
1407 * instruction epilogue code. The multi-compare approach below needs
1408 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1409 * in the worst case (the 64-bit values are equal).
1411 /* cmp-long vAA, vBB, vCC */
1412 FETCH(r0, 1) @ r0<- CCBB
1413 mov r9, rINST, lsr #8 @ r9<- AA
1414 and r2, r0, #255 @ r2<- BB
1415 mov r3, r0, lsr #8 @ r3<- CC
1416 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1417 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1418 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1419 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1420 cmp r1, r3 @ compare (vBB+1, vCC+1)
1421 blt .LOP_CMP_LONG_less @ signed compare on high part
1422 bgt .LOP_CMP_LONG_greater
1423 subs r1, r0, r2 @ r1<- r0 - r2
1424 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1425 bne .LOP_CMP_LONG_less
1426 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1428 /* ------------------------------ */
1430 .L_OP_IF_EQ: /* 0x32 */
1431 /* File: armv5te/OP_IF_EQ.S */
1432 /* File: armv5te/bincmp.S */
1434 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1435 * fragment that specifies the *reverse* comparison to perform, e.g.
1436 * for "if-le" you would use "gt".
1438 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1440 /* if-cmp vA, vB, +CCCC */
1441 mov r0, rINST, lsr #8 @ r0<- A+
1442 mov r1, rINST, lsr #12 @ r1<- B
1444 GET_VREG(r3, r1) @ r3<- vB
1445 GET_VREG(r2, r0) @ r2<- vA
1446 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1447 cmp r2, r3 @ compare (vA, vB)
1448 bne 1f @ branch to 1 if comparison failed
1449 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1450 movs r9, r9, asl #1 @ convert to bytes, check sign
1451 bmi common_backwardBranch @ yes, do periodic checks
1452 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1453 GET_INST_OPCODE(ip) @ extract opcode from rINST
1454 GOTO_OPCODE(ip) @ jump to next instruction
1458 /* ------------------------------ */
1460 .L_OP_IF_NE: /* 0x33 */
1461 /* File: armv5te/OP_IF_NE.S */
1462 /* File: armv5te/bincmp.S */
1464 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1465 * fragment that specifies the *reverse* comparison to perform, e.g.
1466 * for "if-le" you would use "gt".
1468 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1470 /* if-cmp vA, vB, +CCCC */
1471 mov r0, rINST, lsr #8 @ r0<- A+
1472 mov r1, rINST, lsr #12 @ r1<- B
1474 GET_VREG(r3, r1) @ r3<- vB
1475 GET_VREG(r2, r0) @ r2<- vA
1476 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1477 cmp r2, r3 @ compare (vA, vB)
1478 beq 1f @ branch to 1 if comparison failed
1479 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1480 movs r9, r9, asl #1 @ convert to bytes, check sign
1481 bmi common_backwardBranch @ yes, do periodic checks
1482 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1483 GET_INST_OPCODE(ip) @ extract opcode from rINST
1484 GOTO_OPCODE(ip) @ jump to next instruction
1488 /* ------------------------------ */
1490 .L_OP_IF_LT: /* 0x34 */
1491 /* File: armv5te/OP_IF_LT.S */
1492 /* File: armv5te/bincmp.S */
1494 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1495 * fragment that specifies the *reverse* comparison to perform, e.g.
1496 * for "if-le" you would use "gt".
1498 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1500 /* if-cmp vA, vB, +CCCC */
1501 mov r0, rINST, lsr #8 @ r0<- A+
1502 mov r1, rINST, lsr #12 @ r1<- B
1504 GET_VREG(r3, r1) @ r3<- vB
1505 GET_VREG(r2, r0) @ r2<- vA
1506 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1507 cmp r2, r3 @ compare (vA, vB)
1508 bge 1f @ branch to 1 if comparison failed
1509 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1510 movs r9, r9, asl #1 @ convert to bytes, check sign
1511 bmi common_backwardBranch @ yes, do periodic checks
1512 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1513 GET_INST_OPCODE(ip) @ extract opcode from rINST
1514 GOTO_OPCODE(ip) @ jump to next instruction
1518 /* ------------------------------ */
1520 .L_OP_IF_GE: /* 0x35 */
1521 /* File: armv5te/OP_IF_GE.S */
1522 /* File: armv5te/bincmp.S */
1524 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1525 * fragment that specifies the *reverse* comparison to perform, e.g.
1526 * for "if-le" you would use "gt".
1528 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1530 /* if-cmp vA, vB, +CCCC */
1531 mov r0, rINST, lsr #8 @ r0<- A+
1532 mov r1, rINST, lsr #12 @ r1<- B
1534 GET_VREG(r3, r1) @ r3<- vB
1535 GET_VREG(r2, r0) @ r2<- vA
1536 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1537 cmp r2, r3 @ compare (vA, vB)
1538 blt 1f @ branch to 1 if comparison failed
1539 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1540 movs r9, r9, asl #1 @ convert to bytes, check sign
1541 bmi common_backwardBranch @ yes, do periodic checks
1542 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1543 GET_INST_OPCODE(ip) @ extract opcode from rINST
1544 GOTO_OPCODE(ip) @ jump to next instruction
1548 /* ------------------------------ */
1550 .L_OP_IF_GT: /* 0x36 */
1551 /* File: armv5te/OP_IF_GT.S */
1552 /* File: armv5te/bincmp.S */
1554 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1555 * fragment that specifies the *reverse* comparison to perform, e.g.
1556 * for "if-le" you would use "gt".
1558 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1560 /* if-cmp vA, vB, +CCCC */
1561 mov r0, rINST, lsr #8 @ r0<- A+
1562 mov r1, rINST, lsr #12 @ r1<- B
1564 GET_VREG(r3, r1) @ r3<- vB
1565 GET_VREG(r2, r0) @ r2<- vA
1566 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1567 cmp r2, r3 @ compare (vA, vB)
1568 ble 1f @ branch to 1 if comparison failed
1569 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1570 movs r9, r9, asl #1 @ convert to bytes, check sign
1571 bmi common_backwardBranch @ yes, do periodic checks
1572 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1573 GET_INST_OPCODE(ip) @ extract opcode from rINST
1574 GOTO_OPCODE(ip) @ jump to next instruction
1578 /* ------------------------------ */
1580 .L_OP_IF_LE: /* 0x37 */
1581 /* File: armv5te/OP_IF_LE.S */
1582 /* File: armv5te/bincmp.S */
1584 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1585 * fragment that specifies the *reverse* comparison to perform, e.g.
1586 * for "if-le" you would use "gt".
1588 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1590 /* if-cmp vA, vB, +CCCC */
1591 mov r0, rINST, lsr #8 @ r0<- A+
1592 mov r1, rINST, lsr #12 @ r1<- B
1594 GET_VREG(r3, r1) @ r3<- vB
1595 GET_VREG(r2, r0) @ r2<- vA
1596 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1597 cmp r2, r3 @ compare (vA, vB)
1598 bgt 1f @ branch to 1 if comparison failed
1599 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1600 movs r9, r9, asl #1 @ convert to bytes, check sign
1601 bmi common_backwardBranch @ yes, do periodic checks
1602 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1603 GET_INST_OPCODE(ip) @ extract opcode from rINST
1604 GOTO_OPCODE(ip) @ jump to next instruction
1608 /* ------------------------------ */
1610 .L_OP_IF_EQZ: /* 0x38 */
1611 /* File: armv5te/OP_IF_EQZ.S */
1612 /* File: armv5te/zcmp.S */
1614 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1615 * fragment that specifies the *reverse* comparison to perform, e.g.
1616 * for "if-le" you would use "gt".
1618 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1620 /* if-cmp vAA, +BBBB */
1621 mov r0, rINST, lsr #8 @ r0<- AA
1622 GET_VREG(r2, r0) @ r2<- vAA
1623 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1624 cmp r2, #0 @ compare (vA, 0)
1625 bne 1f @ branch to 1 if comparison failed
1626 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1627 movs r9, r9, asl #1 @ convert to bytes, check sign
1628 bmi common_backwardBranch @ backward branch, do periodic checks
1629 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1630 GET_INST_OPCODE(ip) @ extract opcode from rINST
1631 GOTO_OPCODE(ip) @ jump to next instruction
1635 /* ------------------------------ */
1637 .L_OP_IF_NEZ: /* 0x39 */
1638 /* File: armv5te/OP_IF_NEZ.S */
1639 /* File: armv5te/zcmp.S */
1641 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1642 * fragment that specifies the *reverse* comparison to perform, e.g.
1643 * for "if-le" you would use "gt".
1645 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1647 /* if-cmp vAA, +BBBB */
1648 mov r0, rINST, lsr #8 @ r0<- AA
1649 GET_VREG(r2, r0) @ r2<- vAA
1650 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1651 cmp r2, #0 @ compare (vA, 0)
1652 beq 1f @ branch to 1 if comparison failed
1653 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1654 movs r9, r9, asl #1 @ convert to bytes, check sign
1655 bmi common_backwardBranch @ backward branch, do periodic checks
1656 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1657 GET_INST_OPCODE(ip) @ extract opcode from rINST
1658 GOTO_OPCODE(ip) @ jump to next instruction
1662 /* ------------------------------ */
1664 .L_OP_IF_LTZ: /* 0x3a */
1665 /* File: armv5te/OP_IF_LTZ.S */
1666 /* File: armv5te/zcmp.S */
1668 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1669 * fragment that specifies the *reverse* comparison to perform, e.g.
1670 * for "if-le" you would use "gt".
1672 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1674 /* if-cmp vAA, +BBBB */
1675 mov r0, rINST, lsr #8 @ r0<- AA
1676 GET_VREG(r2, r0) @ r2<- vAA
1677 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1678 cmp r2, #0 @ compare (vA, 0)
1679 bge 1f @ branch to 1 if comparison failed
1680 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1681 movs r9, r9, asl #1 @ convert to bytes, check sign
1682 bmi common_backwardBranch @ backward branch, do periodic checks
1683 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1684 GET_INST_OPCODE(ip) @ extract opcode from rINST
1685 GOTO_OPCODE(ip) @ jump to next instruction
1689 /* ------------------------------ */
1691 .L_OP_IF_GEZ: /* 0x3b */
1692 /* File: armv5te/OP_IF_GEZ.S */
1693 /* File: armv5te/zcmp.S */
1695 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1696 * fragment that specifies the *reverse* comparison to perform, e.g.
1697 * for "if-le" you would use "gt".
1699 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1701 /* if-cmp vAA, +BBBB */
1702 mov r0, rINST, lsr #8 @ r0<- AA
1703 GET_VREG(r2, r0) @ r2<- vAA
1704 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1705 cmp r2, #0 @ compare (vA, 0)
1706 blt 1f @ branch to 1 if comparison failed
1707 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1708 movs r9, r9, asl #1 @ convert to bytes, check sign
1709 bmi common_backwardBranch @ backward branch, do periodic checks
1710 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1711 GET_INST_OPCODE(ip) @ extract opcode from rINST
1712 GOTO_OPCODE(ip) @ jump to next instruction
1716 /* ------------------------------ */
1718 .L_OP_IF_GTZ: /* 0x3c */
1719 /* File: armv5te/OP_IF_GTZ.S */
1720 /* File: armv5te/zcmp.S */
1722 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1723 * fragment that specifies the *reverse* comparison to perform, e.g.
1724 * for "if-le" you would use "gt".
1726 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1728 /* if-cmp vAA, +BBBB */
1729 mov r0, rINST, lsr #8 @ r0<- AA
1730 GET_VREG(r2, r0) @ r2<- vAA
1731 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1732 cmp r2, #0 @ compare (vA, 0)
1733 ble 1f @ branch to 1 if comparison failed
1734 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1735 movs r9, r9, asl #1 @ convert to bytes, check sign
1736 bmi common_backwardBranch @ backward branch, do periodic checks
1737 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1738 GET_INST_OPCODE(ip) @ extract opcode from rINST
1739 GOTO_OPCODE(ip) @ jump to next instruction
1743 /* ------------------------------ */
1745 .L_OP_IF_LEZ: /* 0x3d */
1746 /* File: armv5te/OP_IF_LEZ.S */
1747 /* File: armv5te/zcmp.S */
1749 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1750 * fragment that specifies the *reverse* comparison to perform, e.g.
1751 * for "if-le" you would use "gt".
1753 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1755 /* if-cmp vAA, +BBBB */
1756 mov r0, rINST, lsr #8 @ r0<- AA
1757 GET_VREG(r2, r0) @ r2<- vAA
1758 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1759 cmp r2, #0 @ compare (vA, 0)
1760 bgt 1f @ branch to 1 if comparison failed
1761 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1762 movs r9, r9, asl #1 @ convert to bytes, check sign
1763 bmi common_backwardBranch @ backward branch, do periodic checks
1764 1: FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1765 GET_INST_OPCODE(ip) @ extract opcode from rINST
1766 GOTO_OPCODE(ip) @ jump to next instruction
1770 /* ------------------------------ */
1772 .L_OP_UNUSED_3E: /* 0x3e */
1773 /* File: armv5te/OP_UNUSED_3E.S */
1774 /* File: armv5te/unused.S */
1779 /* ------------------------------ */
1781 .L_OP_UNUSED_3F: /* 0x3f */
1782 /* File: armv5te/OP_UNUSED_3F.S */
1783 /* File: armv5te/unused.S */
1788 /* ------------------------------ */
1790 .L_OP_UNUSED_40: /* 0x40 */
1791 /* File: armv5te/OP_UNUSED_40.S */
1792 /* File: armv5te/unused.S */
1797 /* ------------------------------ */
1799 .L_OP_UNUSED_41: /* 0x41 */
1800 /* File: armv5te/OP_UNUSED_41.S */
1801 /* File: armv5te/unused.S */
1806 /* ------------------------------ */
1808 .L_OP_UNUSED_42: /* 0x42 */
1809 /* File: armv5te/OP_UNUSED_42.S */
1810 /* File: armv5te/unused.S */
1815 /* ------------------------------ */
1817 .L_OP_UNUSED_43: /* 0x43 */
1818 /* File: armv5te/OP_UNUSED_43.S */
1819 /* File: armv5te/unused.S */
1824 /* ------------------------------ */
1826 .L_OP_AGET: /* 0x44 */
1827 /* File: armv5te/OP_AGET.S */
1829 * Array get, 32 bits or less. vAA <- vBB[vCC].
1831 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1832 * instructions. We use a pair of FETCH_Bs instead.
1834 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1836 /* op vAA, vBB, vCC */
1837 FETCH_B(r2, 1, 0) @ r2<- BB
1838 mov r9, rINST, lsr #8 @ r9<- AA
1839 FETCH_B(r3, 1, 1) @ r3<- CC
1840 GET_VREG(r0, r2) @ r0<- vBB (array object)
1841 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1842 cmp r0, #0 @ null array object?
1843 beq common_errNullObject @ yes, bail
1844 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1845 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
1846 cmp r1, r3 @ compare unsigned index, length
1847 bcs common_errArrayIndex @ index >= length, bail
1848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1849 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
1850 GET_INST_OPCODE(ip) @ extract opcode from rINST
1851 SET_VREG(r2, r9) @ vAA<- r2
1852 GOTO_OPCODE(ip) @ jump to next instruction
1855 /* ------------------------------ */
1857 .L_OP_AGET_WIDE: /* 0x45 */
1858 /* File: armv4/OP_AGET_WIDE.S */
1860 * Array get, 64 bits. vAA <- vBB[vCC].
1862 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1864 /* aget-wide vAA, vBB, vCC */
1865 FETCH(r0, 1) @ r0<- CCBB
1866 mov r9, rINST, lsr #8 @ r9<- AA
1867 and r2, r0, #255 @ r2<- BB
1868 mov r3, r0, lsr #8 @ r3<- CC
1869 GET_VREG(r0, r2) @ r0<- vBB (array object)
1870 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1871 cmp r0, #0 @ null array object?
1872 beq common_errNullObject @ yes, bail
1873 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1874 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
1875 cmp r1, r3 @ compare unsigned index, length
1876 bcc .LOP_AGET_WIDE_finish @ okay, continue below
1877 b common_errArrayIndex @ index >= length, bail
1878 @ May want to swap the order of these two branches depending on how the
1879 @ branch prediction (if any) handles conditional forward branches vs.
1880 @ unconditional forward branches.
1882 /* ------------------------------ */
1884 .L_OP_AGET_OBJECT: /* 0x46 */
1885 /* File: armv5te/OP_AGET_OBJECT.S */
1886 /* File: armv5te/OP_AGET.S */
1888 * Array get, 32 bits or less. vAA <- vBB[vCC].
1890 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1891 * instructions. We use a pair of FETCH_Bs instead.
1893 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1895 /* op vAA, vBB, vCC */
1896 FETCH_B(r2, 1, 0) @ r2<- BB
1897 mov r9, rINST, lsr #8 @ r9<- AA
1898 FETCH_B(r3, 1, 1) @ r3<- CC
1899 GET_VREG(r0, r2) @ r0<- vBB (array object)
1900 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1901 cmp r0, #0 @ null array object?
1902 beq common_errNullObject @ yes, bail
1903 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1904 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
1905 cmp r1, r3 @ compare unsigned index, length
1906 bcs common_errArrayIndex @ index >= length, bail
1907 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1908 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
1909 GET_INST_OPCODE(ip) @ extract opcode from rINST
1910 SET_VREG(r2, r9) @ vAA<- r2
1911 GOTO_OPCODE(ip) @ jump to next instruction
1915 /* ------------------------------ */
1917 .L_OP_AGET_BOOLEAN: /* 0x47 */
1918 /* File: armv5te/OP_AGET_BOOLEAN.S */
1919 /* File: armv5te/OP_AGET.S */
1921 * Array get, 32 bits or less. vAA <- vBB[vCC].
1923 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1924 * instructions. We use a pair of FETCH_Bs instead.
1926 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1928 /* op vAA, vBB, vCC */
1929 FETCH_B(r2, 1, 0) @ r2<- BB
1930 mov r9, rINST, lsr #8 @ r9<- AA
1931 FETCH_B(r3, 1, 1) @ r3<- CC
1932 GET_VREG(r0, r2) @ r0<- vBB (array object)
1933 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1934 cmp r0, #0 @ null array object?
1935 beq common_errNullObject @ yes, bail
1936 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1937 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
1938 cmp r1, r3 @ compare unsigned index, length
1939 bcs common_errArrayIndex @ index >= length, bail
1940 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1941 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
1942 GET_INST_OPCODE(ip) @ extract opcode from rINST
1943 SET_VREG(r2, r9) @ vAA<- r2
1944 GOTO_OPCODE(ip) @ jump to next instruction
1948 /* ------------------------------ */
1950 .L_OP_AGET_BYTE: /* 0x48 */
1951 /* File: armv5te/OP_AGET_BYTE.S */
1952 /* File: armv5te/OP_AGET.S */
1954 * Array get, 32 bits or less. vAA <- vBB[vCC].
1956 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1957 * instructions. We use a pair of FETCH_Bs instead.
1959 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1961 /* op vAA, vBB, vCC */
1962 FETCH_B(r2, 1, 0) @ r2<- BB
1963 mov r9, rINST, lsr #8 @ r9<- AA
1964 FETCH_B(r3, 1, 1) @ r3<- CC
1965 GET_VREG(r0, r2) @ r0<- vBB (array object)
1966 GET_VREG(r1, r3) @ r1<- vCC (requested index)
1967 cmp r0, #0 @ null array object?
1968 beq common_errNullObject @ yes, bail
1969 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
1970 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
1971 cmp r1, r3 @ compare unsigned index, length
1972 bcs common_errArrayIndex @ index >= length, bail
1973 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1974 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
1975 GET_INST_OPCODE(ip) @ extract opcode from rINST
1976 SET_VREG(r2, r9) @ vAA<- r2
1977 GOTO_OPCODE(ip) @ jump to next instruction
1981 /* ------------------------------ */
1983 .L_OP_AGET_CHAR: /* 0x49 */
1984 /* File: armv5te/OP_AGET_CHAR.S */
1985 /* File: armv5te/OP_AGET.S */
1987 * Array get, 32 bits or less. vAA <- vBB[vCC].
1989 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1990 * instructions. We use a pair of FETCH_Bs instead.
1992 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1994 /* op vAA, vBB, vCC */
1995 FETCH_B(r2, 1, 0) @ r2<- BB
1996 mov r9, rINST, lsr #8 @ r9<- AA
1997 FETCH_B(r3, 1, 1) @ r3<- CC
1998 GET_VREG(r0, r2) @ r0<- vBB (array object)
1999 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2000 cmp r0, #0 @ null array object?
2001 beq common_errNullObject @ yes, bail
2002 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2003 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2004 cmp r1, r3 @ compare unsigned index, length
2005 bcs common_errArrayIndex @ index >= length, bail
2006 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2007 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2008 GET_INST_OPCODE(ip) @ extract opcode from rINST
2009 SET_VREG(r2, r9) @ vAA<- r2
2010 GOTO_OPCODE(ip) @ jump to next instruction
2014 /* ------------------------------ */
2016 .L_OP_AGET_SHORT: /* 0x4a */
2017 /* File: armv5te/OP_AGET_SHORT.S */
2018 /* File: armv5te/OP_AGET.S */
2020 * Array get, 32 bits or less. vAA <- vBB[vCC].
2022 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2023 * instructions. We use a pair of FETCH_Bs instead.
2025 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2027 /* op vAA, vBB, vCC */
2028 FETCH_B(r2, 1, 0) @ r2<- BB
2029 mov r9, rINST, lsr #8 @ r9<- AA
2030 FETCH_B(r3, 1, 1) @ r3<- CC
2031 GET_VREG(r0, r2) @ r0<- vBB (array object)
2032 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2033 cmp r0, #0 @ null array object?
2034 beq common_errNullObject @ yes, bail
2035 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2036 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2037 cmp r1, r3 @ compare unsigned index, length
2038 bcs common_errArrayIndex @ index >= length, bail
2039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2040 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2041 GET_INST_OPCODE(ip) @ extract opcode from rINST
2042 SET_VREG(r2, r9) @ vAA<- r2
2043 GOTO_OPCODE(ip) @ jump to next instruction
2047 /* ------------------------------ */
2049 .L_OP_APUT: /* 0x4b */
2050 /* File: armv5te/OP_APUT.S */
2052 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2054 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2055 * instructions. We use a pair of FETCH_Bs instead.
2057 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2059 /* op vAA, vBB, vCC */
2060 FETCH_B(r2, 1, 0) @ r2<- BB
2061 mov r9, rINST, lsr #8 @ r9<- AA
2062 FETCH_B(r3, 1, 1) @ r3<- CC
2063 GET_VREG(r0, r2) @ r0<- vBB (array object)
2064 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2065 cmp r0, #0 @ null array object?
2066 beq common_errNullObject @ yes, bail
2067 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2068 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2069 cmp r1, r3 @ compare unsigned index, length
2070 bcs common_errArrayIndex @ index >= length, bail
2071 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2072 GET_VREG(r2, r9) @ r2<- vAA
2073 GET_INST_OPCODE(ip) @ extract opcode from rINST
2074 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2075 GOTO_OPCODE(ip) @ jump to next instruction
2078 /* ------------------------------ */
2080 .L_OP_APUT_WIDE: /* 0x4c */
2081 /* File: armv4/OP_APUT_WIDE.S */
2083 * Array put, 64 bits. vBB[vCC] <- vAA.
2085 /* aput-wide vAA, vBB, vCC */
2086 FETCH(r0, 1) @ r0<- CCBB
2087 mov r9, rINST, lsr #8 @ r9<- AA
2088 and r2, r0, #255 @ r2<- BB
2089 mov r3, r0, lsr #8 @ r3<- CC
2090 GET_VREG(r0, r2) @ r0<- vBB (array object)
2091 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2092 cmp r0, #0 @ null array object?
2093 beq common_errNullObject @ yes, bail
2094 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2095 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2096 cmp r1, r3 @ compare unsigned index, length
2097 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2098 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2099 b common_errArrayIndex @ index >= length, bail
2100 @ May want to swap the order of these two branches depending on how the
2101 @ branch prediction (if any) handles conditional forward branches vs.
2102 @ unconditional forward branches.
2104 /* ------------------------------ */
2106 .L_OP_APUT_OBJECT: /* 0x4d */
2107 /* File: armv5te/OP_APUT_OBJECT.S */
2109 * Store an object into an array. vBB[vCC] <- vAA.
2111 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2112 * instructions. We use a pair of FETCH_Bs instead.
2114 /* op vAA, vBB, vCC */
2115 FETCH(r0, 1) @ r0<- CCBB
2116 mov r9, rINST, lsr #8 @ r9<- AA
2117 and r2, r0, #255 @ r2<- BB
2118 mov r3, r0, lsr #8 @ r3<- CC
2119 GET_VREG(r1, r2) @ r1<- vBB (array object)
2120 GET_VREG(r0, r3) @ r0<- vCC (requested index)
2121 cmp r1, #0 @ null array object?
2122 GET_VREG(r9, r9) @ r9<- vAA
2123 beq common_errNullObject @ yes, bail
2124 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length
2125 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width
2126 cmp r0, r3 @ compare unsigned index, length
2127 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2128 b common_errArrayIndex @ index >= length, bail
2131 /* ------------------------------ */
2133 .L_OP_APUT_BOOLEAN: /* 0x4e */
2134 /* File: armv5te/OP_APUT_BOOLEAN.S */
2135 /* File: armv5te/OP_APUT.S */
2137 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2139 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2140 * instructions. We use a pair of FETCH_Bs instead.
2142 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2144 /* op vAA, vBB, vCC */
2145 FETCH_B(r2, 1, 0) @ r2<- BB
2146 mov r9, rINST, lsr #8 @ r9<- AA
2147 FETCH_B(r3, 1, 1) @ r3<- CC
2148 GET_VREG(r0, r2) @ r0<- vBB (array object)
2149 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2150 cmp r0, #0 @ null array object?
2151 beq common_errNullObject @ yes, bail
2152 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2153 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2154 cmp r1, r3 @ compare unsigned index, length
2155 bcs common_errArrayIndex @ index >= length, bail
2156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2157 GET_VREG(r2, r9) @ r2<- vAA
2158 GET_INST_OPCODE(ip) @ extract opcode from rINST
2159 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2160 GOTO_OPCODE(ip) @ jump to next instruction
2164 /* ------------------------------ */
2166 .L_OP_APUT_BYTE: /* 0x4f */
2167 /* File: armv5te/OP_APUT_BYTE.S */
2168 /* File: armv5te/OP_APUT.S */
2170 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2172 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2173 * instructions. We use a pair of FETCH_Bs instead.
2175 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2177 /* op vAA, vBB, vCC */
2178 FETCH_B(r2, 1, 0) @ r2<- BB
2179 mov r9, rINST, lsr #8 @ r9<- AA
2180 FETCH_B(r3, 1, 1) @ r3<- CC
2181 GET_VREG(r0, r2) @ r0<- vBB (array object)
2182 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2183 cmp r0, #0 @ null array object?
2184 beq common_errNullObject @ yes, bail
2185 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2186 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2187 cmp r1, r3 @ compare unsigned index, length
2188 bcs common_errArrayIndex @ index >= length, bail
2189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2190 GET_VREG(r2, r9) @ r2<- vAA
2191 GET_INST_OPCODE(ip) @ extract opcode from rINST
2192 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2193 GOTO_OPCODE(ip) @ jump to next instruction
2197 /* ------------------------------ */
2199 .L_OP_APUT_CHAR: /* 0x50 */
2200 /* File: armv5te/OP_APUT_CHAR.S */
2201 /* File: armv5te/OP_APUT.S */
2203 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2205 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2206 * instructions. We use a pair of FETCH_Bs instead.
2208 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2210 /* op vAA, vBB, vCC */
2211 FETCH_B(r2, 1, 0) @ r2<- BB
2212 mov r9, rINST, lsr #8 @ r9<- AA
2213 FETCH_B(r3, 1, 1) @ r3<- CC
2214 GET_VREG(r0, r2) @ r0<- vBB (array object)
2215 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2216 cmp r0, #0 @ null array object?
2217 beq common_errNullObject @ yes, bail
2218 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2219 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2220 cmp r1, r3 @ compare unsigned index, length
2221 bcs common_errArrayIndex @ index >= length, bail
2222 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2223 GET_VREG(r2, r9) @ r2<- vAA
2224 GET_INST_OPCODE(ip) @ extract opcode from rINST
2225 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2226 GOTO_OPCODE(ip) @ jump to next instruction
2230 /* ------------------------------ */
2232 .L_OP_APUT_SHORT: /* 0x51 */
2233 /* File: armv5te/OP_APUT_SHORT.S */
2234 /* File: armv5te/OP_APUT.S */
2236 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2238 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2239 * instructions. We use a pair of FETCH_Bs instead.
2241 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2243 /* op vAA, vBB, vCC */
2244 FETCH_B(r2, 1, 0) @ r2<- BB
2245 mov r9, rINST, lsr #8 @ r9<- AA
2246 FETCH_B(r3, 1, 1) @ r3<- CC
2247 GET_VREG(r0, r2) @ r0<- vBB (array object)
2248 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2249 cmp r0, #0 @ null array object?
2250 beq common_errNullObject @ yes, bail
2251 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2252 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2253 cmp r1, r3 @ compare unsigned index, length
2254 bcs common_errArrayIndex @ index >= length, bail
2255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2256 GET_VREG(r2, r9) @ r2<- vAA
2257 GET_INST_OPCODE(ip) @ extract opcode from rINST
2258 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2259 GOTO_OPCODE(ip) @ jump to next instruction
2263 /* ------------------------------ */
2265 .L_OP_IGET: /* 0x52 */
2266 /* File: armv5te/OP_IGET.S */
2268 * General 32-bit instance field get.
2270 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2272 /* op vA, vB, field@CCCC */
2273 mov r0, rINST, lsr #12 @ r0<- B
2274 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2275 FETCH(r1, 1) @ r1<- field ref CCCC
2276 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2277 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2278 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2279 cmp r0, #0 @ is resolved entry null?
2280 bne .LOP_IGET_finish @ no, already resolved
2281 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2282 EXPORT_PC() @ resolve() could throw
2283 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2284 bl dvmResolveInstField @ r0<- resolved InstField ptr
2286 bne .LOP_IGET_finish
2287 b common_exceptionThrown
2289 /* ------------------------------ */
2291 .L_OP_IGET_WIDE: /* 0x53 */
2292 /* File: armv4/OP_IGET_WIDE.S */
2294 * Wide 32-bit instance field get.
2296 /* iget-wide vA, vB, field@CCCC */
2297 mov r0, rINST, lsr #12 @ r0<- B
2298 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2299 FETCH(r1, 1) @ r1<- field ref CCCC
2300 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2301 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2302 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2303 cmp r0, #0 @ is resolved entry null?
2304 bne .LOP_IGET_WIDE_finish @ no, already resolved
2305 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2306 EXPORT_PC() @ resolve() could throw
2307 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2308 bl dvmResolveInstField @ r0<- resolved InstField ptr
2310 bne .LOP_IGET_WIDE_finish
2311 b common_exceptionThrown
2313 /* ------------------------------ */
2315 .L_OP_IGET_OBJECT: /* 0x54 */
2316 /* File: armv5te/OP_IGET_OBJECT.S */
2317 /* File: armv5te/OP_IGET.S */
2319 * General 32-bit instance field get.
2321 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2323 /* op vA, vB, field@CCCC */
2324 mov r0, rINST, lsr #12 @ r0<- B
2325 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2326 FETCH(r1, 1) @ r1<- field ref CCCC
2327 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2328 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2329 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2330 cmp r0, #0 @ is resolved entry null?
2331 bne .LOP_IGET_OBJECT_finish @ no, already resolved
2332 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2333 EXPORT_PC() @ resolve() could throw
2334 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2335 bl dvmResolveInstField @ r0<- resolved InstField ptr
2337 bne .LOP_IGET_OBJECT_finish
2338 b common_exceptionThrown
2341 /* ------------------------------ */
2343 .L_OP_IGET_BOOLEAN: /* 0x55 */
2344 /* File: armv5te/OP_IGET_BOOLEAN.S */
2345 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2346 /* File: armv5te/OP_IGET.S */
2348 * General 32-bit instance field get.
2350 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2352 /* op vA, vB, field@CCCC */
2353 mov r0, rINST, lsr #12 @ r0<- B
2354 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2355 FETCH(r1, 1) @ r1<- field ref CCCC
2356 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2357 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2358 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2359 cmp r0, #0 @ is resolved entry null?
2360 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved
2361 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2362 EXPORT_PC() @ resolve() could throw
2363 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2364 bl dvmResolveInstField @ r0<- resolved InstField ptr
2366 bne .LOP_IGET_BOOLEAN_finish
2367 b common_exceptionThrown
2370 /* ------------------------------ */
2372 .L_OP_IGET_BYTE: /* 0x56 */
2373 /* File: armv5te/OP_IGET_BYTE.S */
2374 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2375 /* File: armv5te/OP_IGET.S */
2377 * General 32-bit instance field get.
2379 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2381 /* op vA, vB, field@CCCC */
2382 mov r0, rINST, lsr #12 @ r0<- B
2383 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2384 FETCH(r1, 1) @ r1<- field ref CCCC
2385 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2386 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2387 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2388 cmp r0, #0 @ is resolved entry null?
2389 bne .LOP_IGET_BYTE_finish @ no, already resolved
2390 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2391 EXPORT_PC() @ resolve() could throw
2392 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2393 bl dvmResolveInstField @ r0<- resolved InstField ptr
2395 bne .LOP_IGET_BYTE_finish
2396 b common_exceptionThrown
2399 /* ------------------------------ */
2401 .L_OP_IGET_CHAR: /* 0x57 */
2402 /* File: armv5te/OP_IGET_CHAR.S */
2403 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2404 /* File: armv5te/OP_IGET.S */
2406 * General 32-bit instance field get.
2408 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2410 /* op vA, vB, field@CCCC */
2411 mov r0, rINST, lsr #12 @ r0<- B
2412 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2413 FETCH(r1, 1) @ r1<- field ref CCCC
2414 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2415 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2416 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2417 cmp r0, #0 @ is resolved entry null?
2418 bne .LOP_IGET_CHAR_finish @ no, already resolved
2419 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2420 EXPORT_PC() @ resolve() could throw
2421 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2422 bl dvmResolveInstField @ r0<- resolved InstField ptr
2424 bne .LOP_IGET_CHAR_finish
2425 b common_exceptionThrown
2428 /* ------------------------------ */
2430 .L_OP_IGET_SHORT: /* 0x58 */
2431 /* File: armv5te/OP_IGET_SHORT.S */
2432 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2433 /* File: armv5te/OP_IGET.S */
2435 * General 32-bit instance field get.
2437 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2439 /* op vA, vB, field@CCCC */
2440 mov r0, rINST, lsr #12 @ r0<- B
2441 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2442 FETCH(r1, 1) @ r1<- field ref CCCC
2443 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2444 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2445 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2446 cmp r0, #0 @ is resolved entry null?
2447 bne .LOP_IGET_SHORT_finish @ no, already resolved
2448 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2449 EXPORT_PC() @ resolve() could throw
2450 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2451 bl dvmResolveInstField @ r0<- resolved InstField ptr
2453 bne .LOP_IGET_SHORT_finish
2454 b common_exceptionThrown
2457 /* ------------------------------ */
2459 .L_OP_IPUT: /* 0x59 */
2460 /* File: armv5te/OP_IPUT.S */
2462 * General 32-bit instance field put.
2464 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2466 /* op vA, vB, field@CCCC */
2467 mov r0, rINST, lsr #12 @ r0<- B
2468 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2469 FETCH(r1, 1) @ r1<- field ref CCCC
2470 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2471 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2472 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2473 cmp r0, #0 @ is resolved entry null?
2474 bne .LOP_IPUT_finish @ no, already resolved
2475 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2476 EXPORT_PC() @ resolve() could throw
2477 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2478 bl dvmResolveInstField @ r0<- resolved InstField ptr
2479 cmp r0, #0 @ success?
2480 bne .LOP_IPUT_finish @ yes, finish up
2481 b common_exceptionThrown
2483 /* ------------------------------ */
2485 .L_OP_IPUT_WIDE: /* 0x5a */
2486 /* File: armv4/OP_IPUT_WIDE.S */
2487 /* iput-wide vA, vB, field@CCCC */
2488 mov r0, rINST, lsr #12 @ r0<- B
2489 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2490 FETCH(r1, 1) @ r1<- field ref CCCC
2491 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2492 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2493 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2494 cmp r0, #0 @ is resolved entry null?
2495 bne .LOP_IPUT_WIDE_finish @ no, already resolved
2496 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2497 EXPORT_PC() @ resolve() could throw
2498 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2499 bl dvmResolveInstField @ r0<- resolved InstField ptr
2500 cmp r0, #0 @ success?
2501 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2502 b common_exceptionThrown
2504 /* ------------------------------ */
2506 .L_OP_IPUT_OBJECT: /* 0x5b */
2507 /* File: armv5te/OP_IPUT_OBJECT.S */
2508 /* File: armv5te/OP_IPUT.S */
2510 * General 32-bit instance field put.
2512 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2514 /* op vA, vB, field@CCCC */
2515 mov r0, rINST, lsr #12 @ r0<- B
2516 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2517 FETCH(r1, 1) @ r1<- field ref CCCC
2518 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2519 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2520 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2521 cmp r0, #0 @ is resolved entry null?
2522 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
2523 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2524 EXPORT_PC() @ resolve() could throw
2525 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2526 bl dvmResolveInstField @ r0<- resolved InstField ptr
2527 cmp r0, #0 @ success?
2528 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2529 b common_exceptionThrown
2532 /* ------------------------------ */
2534 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2535 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2536 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2537 /* File: armv5te/OP_IPUT.S */
2539 * General 32-bit instance field put.
2541 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2543 /* op vA, vB, field@CCCC */
2544 mov r0, rINST, lsr #12 @ r0<- B
2545 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2546 FETCH(r1, 1) @ r1<- field ref CCCC
2547 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2548 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2549 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2550 cmp r0, #0 @ is resolved entry null?
2551 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
2552 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2553 EXPORT_PC() @ resolve() could throw
2554 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2555 bl dvmResolveInstField @ r0<- resolved InstField ptr
2556 cmp r0, #0 @ success?
2557 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2558 b common_exceptionThrown
2561 /* ------------------------------ */
2563 .L_OP_IPUT_BYTE: /* 0x5d */
2564 /* File: armv5te/OP_IPUT_BYTE.S */
2565 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2566 /* File: armv5te/OP_IPUT.S */
2568 * General 32-bit instance field put.
2570 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2572 /* op vA, vB, field@CCCC */
2573 mov r0, rINST, lsr #12 @ r0<- B
2574 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2575 FETCH(r1, 1) @ r1<- field ref CCCC
2576 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2577 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2578 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2579 cmp r0, #0 @ is resolved entry null?
2580 bne .LOP_IPUT_BYTE_finish @ no, already resolved
2581 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2582 EXPORT_PC() @ resolve() could throw
2583 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2584 bl dvmResolveInstField @ r0<- resolved InstField ptr
2585 cmp r0, #0 @ success?
2586 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2587 b common_exceptionThrown
2590 /* ------------------------------ */
2592 .L_OP_IPUT_CHAR: /* 0x5e */
2593 /* File: armv5te/OP_IPUT_CHAR.S */
2594 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2595 /* File: armv5te/OP_IPUT.S */
2597 * General 32-bit instance field put.
2599 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2601 /* op vA, vB, field@CCCC */
2602 mov r0, rINST, lsr #12 @ r0<- B
2603 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2604 FETCH(r1, 1) @ r1<- field ref CCCC
2605 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2606 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2607 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2608 cmp r0, #0 @ is resolved entry null?
2609 bne .LOP_IPUT_CHAR_finish @ no, already resolved
2610 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2611 EXPORT_PC() @ resolve() could throw
2612 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2613 bl dvmResolveInstField @ r0<- resolved InstField ptr
2614 cmp r0, #0 @ success?
2615 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2616 b common_exceptionThrown
2619 /* ------------------------------ */
2621 .L_OP_IPUT_SHORT: /* 0x5f */
2622 /* File: armv5te/OP_IPUT_SHORT.S */
2623 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2624 /* File: armv5te/OP_IPUT.S */
2626 * General 32-bit instance field put.
2628 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2630 /* op vA, vB, field@CCCC */
2631 mov r0, rINST, lsr #12 @ r0<- B
2632 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2633 FETCH(r1, 1) @ r1<- field ref CCCC
2634 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2636 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2637 cmp r0, #0 @ is resolved entry null?
2638 bne .LOP_IPUT_SHORT_finish @ no, already resolved
2639 8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2640 EXPORT_PC() @ resolve() could throw
2641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2642 bl dvmResolveInstField @ r0<- resolved InstField ptr
2643 cmp r0, #0 @ success?
2644 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2645 b common_exceptionThrown
2648 /* ------------------------------ */
2650 .L_OP_SGET: /* 0x60 */
2651 /* File: armv5te/OP_SGET.S */
2653 * General 32-bit SGET handler.
2655 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2657 /* op vAA, field@BBBB */
2658 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2659 FETCH(r1, 1) @ r1<- field ref BBBB
2660 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2661 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2662 cmp r0, #0 @ is resolved entry null?
2663 beq .LOP_SGET_resolve @ yes, do resolve
2664 .LOP_SGET_finish: @ field ptr in r0
2665 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2666 mov r2, rINST, lsr #8 @ r2<- AA
2667 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2668 SET_VREG(r1, r2) @ fp[AA]<- r1
2669 GET_INST_OPCODE(ip) @ extract opcode from rINST
2670 GOTO_OPCODE(ip) @ jump to next instruction
2672 /* ------------------------------ */
2674 .L_OP_SGET_WIDE: /* 0x61 */
2675 /* File: armv4/OP_SGET_WIDE.S */
2677 * 64-bit SGET handler.
2679 /* sget-wide vAA, field@BBBB */
2680 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2681 FETCH(r1, 1) @ r1<- field ref BBBB
2682 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2683 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2684 cmp r0, #0 @ is resolved entry null?
2685 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2686 .LOP_SGET_WIDE_finish:
2687 mov r1, rINST, lsr #8 @ r1<- AA
2688 add r0, r0, #offStaticField_value
2689 ldmia r0, {r2-r3} @ r2/r3<- field value (aligned)
2690 add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
2691 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2692 stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
2693 GET_INST_OPCODE(ip) @ extract opcode from rINST
2694 GOTO_OPCODE(ip) @ jump to next instruction
2696 /* ------------------------------ */
2698 .L_OP_SGET_OBJECT: /* 0x62 */
2699 /* File: armv5te/OP_SGET_OBJECT.S */
2700 /* File: armv5te/OP_SGET.S */
2702 * General 32-bit SGET handler.
2704 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2706 /* op vAA, field@BBBB */
2707 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2708 FETCH(r1, 1) @ r1<- field ref BBBB
2709 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2710 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2711 cmp r0, #0 @ is resolved entry null?
2712 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2713 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2714 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2715 mov r2, rINST, lsr #8 @ r2<- AA
2716 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2717 SET_VREG(r1, r2) @ fp[AA]<- r1
2718 GET_INST_OPCODE(ip) @ extract opcode from rINST
2719 GOTO_OPCODE(ip) @ jump to next instruction
2722 /* ------------------------------ */
2724 .L_OP_SGET_BOOLEAN: /* 0x63 */
2725 /* File: armv5te/OP_SGET_BOOLEAN.S */
2726 /* File: armv5te/OP_SGET.S */
2728 * General 32-bit SGET handler.
2730 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2732 /* op vAA, field@BBBB */
2733 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2734 FETCH(r1, 1) @ r1<- field ref BBBB
2735 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2736 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2737 cmp r0, #0 @ is resolved entry null?
2738 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2739 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2740 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2741 mov r2, rINST, lsr #8 @ r2<- AA
2742 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2743 SET_VREG(r1, r2) @ fp[AA]<- r1
2744 GET_INST_OPCODE(ip) @ extract opcode from rINST
2745 GOTO_OPCODE(ip) @ jump to next instruction
2748 /* ------------------------------ */
2750 .L_OP_SGET_BYTE: /* 0x64 */
2751 /* File: armv5te/OP_SGET_BYTE.S */
2752 /* File: armv5te/OP_SGET.S */
2754 * General 32-bit SGET handler.
2756 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2758 /* op vAA, field@BBBB */
2759 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2760 FETCH(r1, 1) @ r1<- field ref BBBB
2761 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2762 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2763 cmp r0, #0 @ is resolved entry null?
2764 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2765 .LOP_SGET_BYTE_finish: @ field ptr in r0
2766 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2767 mov r2, rINST, lsr #8 @ r2<- AA
2768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2769 SET_VREG(r1, r2) @ fp[AA]<- r1
2770 GET_INST_OPCODE(ip) @ extract opcode from rINST
2771 GOTO_OPCODE(ip) @ jump to next instruction
2774 /* ------------------------------ */
2776 .L_OP_SGET_CHAR: /* 0x65 */
2777 /* File: armv5te/OP_SGET_CHAR.S */
2778 /* File: armv5te/OP_SGET.S */
2780 * General 32-bit SGET handler.
2782 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2784 /* op vAA, field@BBBB */
2785 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2786 FETCH(r1, 1) @ r1<- field ref BBBB
2787 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2788 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2789 cmp r0, #0 @ is resolved entry null?
2790 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2791 .LOP_SGET_CHAR_finish: @ field ptr in r0
2792 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2793 mov r2, rINST, lsr #8 @ r2<- AA
2794 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2795 SET_VREG(r1, r2) @ fp[AA]<- r1
2796 GET_INST_OPCODE(ip) @ extract opcode from rINST
2797 GOTO_OPCODE(ip) @ jump to next instruction
2800 /* ------------------------------ */
2802 .L_OP_SGET_SHORT: /* 0x66 */
2803 /* File: armv5te/OP_SGET_SHORT.S */
2804 /* File: armv5te/OP_SGET.S */
2806 * General 32-bit SGET handler.
2808 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2810 /* op vAA, field@BBBB */
2811 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2812 FETCH(r1, 1) @ r1<- field ref BBBB
2813 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2814 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2815 cmp r0, #0 @ is resolved entry null?
2816 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
2817 .LOP_SGET_SHORT_finish: @ field ptr in r0
2818 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2819 mov r2, rINST, lsr #8 @ r2<- AA
2820 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2821 SET_VREG(r1, r2) @ fp[AA]<- r1
2822 GET_INST_OPCODE(ip) @ extract opcode from rINST
2823 GOTO_OPCODE(ip) @ jump to next instruction
2826 /* ------------------------------ */
2828 .L_OP_SPUT: /* 0x67 */
2829 /* File: armv5te/OP_SPUT.S */
2831 * General 32-bit SPUT handler.
2833 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2835 /* op vAA, field@BBBB */
2836 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2837 FETCH(r1, 1) @ r1<- field ref BBBB
2838 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2839 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2840 cmp r0, #0 @ is resolved entry null?
2841 beq .LOP_SPUT_resolve @ yes, do resolve
2842 .LOP_SPUT_finish: @ field ptr in r0
2843 mov r2, rINST, lsr #8 @ r2<- AA
2844 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2845 GET_VREG(r1, r2) @ r1<- fp[AA]
2846 GET_INST_OPCODE(ip) @ extract opcode from rINST
2847 str r1, [r0, #offStaticField_value] @ field<- vAA
2848 GOTO_OPCODE(ip) @ jump to next instruction
2850 /* ------------------------------ */
2852 .L_OP_SPUT_WIDE: /* 0x68 */
2853 /* File: armv4/OP_SPUT_WIDE.S */
2855 * 64-bit SPUT handler.
2857 /* sput-wide vAA, field@BBBB */
2858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2859 FETCH(r1, 1) @ r1<- field ref BBBB
2860 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2861 mov r9, rINST, lsr #8 @ r9<- AA
2862 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2863 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2864 cmp r0, #0 @ is resolved entry null?
2865 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
2866 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
2867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2868 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
2869 GET_INST_OPCODE(ip) @ extract opcode from rINST
2870 add r0, r0, #offStaticField_value
2871 stmia r0, {r2-r3} @ field<- vAA/vAA+1
2872 GOTO_OPCODE(ip) @ jump to next instruction
2874 /* ------------------------------ */
2876 .L_OP_SPUT_OBJECT: /* 0x69 */
2877 /* File: armv5te/OP_SPUT_OBJECT.S */
2878 /* File: armv5te/OP_SPUT.S */
2880 * General 32-bit SPUT handler.
2882 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2884 /* op vAA, field@BBBB */
2885 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2886 FETCH(r1, 1) @ r1<- field ref BBBB
2887 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2888 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2889 cmp r0, #0 @ is resolved entry null?
2890 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
2891 .LOP_SPUT_OBJECT_finish: @ field ptr in r0
2892 mov r2, rINST, lsr #8 @ r2<- AA
2893 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2894 GET_VREG(r1, r2) @ r1<- fp[AA]
2895 GET_INST_OPCODE(ip) @ extract opcode from rINST
2896 str r1, [r0, #offStaticField_value] @ field<- vAA
2897 GOTO_OPCODE(ip) @ jump to next instruction
2900 /* ------------------------------ */
2902 .L_OP_SPUT_BOOLEAN: /* 0x6a */
2903 /* File: armv5te/OP_SPUT_BOOLEAN.S */
2904 /* File: armv5te/OP_SPUT.S */
2906 * General 32-bit SPUT handler.
2908 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_BOOLEAN_resolve @ yes, do resolve
2917 .LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
2918 mov r2, rINST, lsr #8 @ r2<- AA
2919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2920 GET_VREG(r1, r2) @ r1<- fp[AA]
2921 GET_INST_OPCODE(ip) @ extract opcode from rINST
2922 str r1, [r0, #offStaticField_value] @ field<- vAA
2923 GOTO_OPCODE(ip) @ jump to next instruction
2926 /* ------------------------------ */
2928 .L_OP_SPUT_BYTE: /* 0x6b */
2929 /* File: armv5te/OP_SPUT_BYTE.S */
2930 /* File: armv5te/OP_SPUT.S */
2932 * General 32-bit SPUT handler.
2934 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_BYTE_resolve @ yes, do resolve
2943 .LOP_SPUT_BYTE_finish: @ field ptr in r0
2944 mov r2, rINST, lsr #8 @ r2<- AA
2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2946 GET_VREG(r1, r2) @ r1<- fp[AA]
2947 GET_INST_OPCODE(ip) @ extract opcode from rINST
2948 str r1, [r0, #offStaticField_value] @ field<- vAA
2949 GOTO_OPCODE(ip) @ jump to next instruction
2952 /* ------------------------------ */
2954 .L_OP_SPUT_CHAR: /* 0x6c */
2955 /* File: armv5te/OP_SPUT_CHAR.S */
2956 /* File: armv5te/OP_SPUT.S */
2958 * General 32-bit SPUT handler.
2960 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_CHAR_resolve @ yes, do resolve
2969 .LOP_SPUT_CHAR_finish: @ field ptr in r0
2970 mov r2, rINST, lsr #8 @ r2<- AA
2971 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2972 GET_VREG(r1, r2) @ r1<- fp[AA]
2973 GET_INST_OPCODE(ip) @ extract opcode from rINST
2974 str r1, [r0, #offStaticField_value] @ field<- vAA
2975 GOTO_OPCODE(ip) @ jump to next instruction
2978 /* ------------------------------ */
2980 .L_OP_SPUT_SHORT: /* 0x6d */
2981 /* File: armv5te/OP_SPUT_SHORT.S */
2982 /* File: armv5te/OP_SPUT.S */
2984 * General 32-bit SPUT handler.
2986 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_SHORT_resolve @ yes, do resolve
2995 .LOP_SPUT_SHORT_finish: @ field ptr in r0
2996 mov r2, rINST, lsr #8 @ r2<- AA
2997 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2998 GET_VREG(r1, r2) @ r1<- fp[AA]
2999 GET_INST_OPCODE(ip) @ extract opcode from rINST
3000 str r1, [r0, #offStaticField_value] @ field<- vAA
3001 GOTO_OPCODE(ip) @ jump to next instruction
3004 /* ------------------------------ */
3006 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3007 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3009 * Handle a virtual method call.
3011 * for: invoke-virtual, invoke-virtual/range
3013 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3014 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3015 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3016 FETCH(r1, 1) @ r1<- BBBB
3017 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3018 FETCH(r10, 2) @ r10<- GFED or CCCC
3019 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3021 and r10, r10, #15 @ r10<- D (or stays CCCC)
3023 cmp r0, #0 @ already resolved?
3024 EXPORT_PC() @ must export for invoke
3025 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3026 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3027 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3028 mov r2, #METHOD_VIRTUAL @ resolver method type
3029 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3030 cmp r0, #0 @ got null?
3031 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3032 b common_exceptionThrown @ yes, handle exception
3034 /* ------------------------------ */
3036 .L_OP_INVOKE_SUPER: /* 0x6f */
3037 /* File: armv5te/OP_INVOKE_SUPER.S */
3039 * Handle a "super" method call.
3041 * for: invoke-super, invoke-super/range
3043 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3044 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3045 FETCH(r10, 2) @ r10<- GFED or CCCC
3046 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3048 and r10, r10, #15 @ r10<- D (or stays CCCC)
3050 FETCH(r1, 1) @ r1<- BBBB
3051 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3052 GET_VREG(r2, r10) @ r2<- "this" ptr
3053 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3054 cmp r2, #0 @ null "this"?
3055 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3056 beq common_errNullObject @ null "this", throw exception
3057 cmp r0, #0 @ already resolved?
3058 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3059 EXPORT_PC() @ must export for invoke
3060 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3061 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3063 /* ------------------------------ */
3065 .L_OP_INVOKE_DIRECT: /* 0x70 */
3066 /* File: armv5te/OP_INVOKE_DIRECT.S */
3068 * Handle a direct method call.
3070 * (We could defer the "is 'this' pointer null" test to the common
3071 * method invocation code, and use a flag to indicate that static
3072 * calls don't count. If we do this as part of copying the arguments
3073 * out we could avoiding loading the first arg twice.)
3075 * for: invoke-direct, invoke-direct/range
3077 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3078 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3079 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3080 FETCH(r1, 1) @ r1<- BBBB
3081 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3082 FETCH(r10, 2) @ r10<- GFED or CCCC
3083 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3085 and r10, r10, #15 @ r10<- D (or stays CCCC)
3087 cmp r0, #0 @ already resolved?
3088 EXPORT_PC() @ must export for invoke
3089 GET_VREG(r2, r10) @ r2<- "this" ptr
3090 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3091 .LOP_INVOKE_DIRECT_finish:
3092 cmp r2, #0 @ null "this" ref?
3093 bne common_invokeMethodNoRange @ no, continue on
3094 b common_errNullObject @ yes, throw exception
3096 /* ------------------------------ */
3098 .L_OP_INVOKE_STATIC: /* 0x71 */
3099 /* File: armv5te/OP_INVOKE_STATIC.S */
3101 * Handle a static method call.
3103 * for: invoke-static, invoke-static/range
3105 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3106 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3107 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3108 FETCH(r1, 1) @ r1<- BBBB
3109 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3110 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3111 cmp r0, #0 @ already resolved?
3112 EXPORT_PC() @ must export for invoke
3113 bne common_invokeMethodNoRange @ yes, continue on
3114 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3115 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3116 mov r2, #METHOD_STATIC @ resolver method type
3117 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3118 cmp r0, #0 @ got null?
3119 bne common_invokeMethodNoRange @ no, continue
3120 b common_exceptionThrown @ yes, handle exception
3123 /* ------------------------------ */
3125 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3126 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3128 * Handle an interface method call.
3130 * for: invoke-interface, invoke-interface/range
3132 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3133 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3134 FETCH(r2, 2) @ r2<- FEDC or CCCC
3135 FETCH(r1, 1) @ r1<- BBBB
3137 and r2, r2, #15 @ r2<- C (or stays CCCC)
3139 EXPORT_PC() @ must export for invoke
3140 GET_VREG(r0, r2) @ r0<- first arg ("this")
3141 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3142 cmp r0, #0 @ null obj?
3143 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3144 beq common_errNullObject @ yes, fail
3145 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3146 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3147 cmp r0, #0 @ failed?
3148 beq common_exceptionThrown @ yes, handle exception
3149 b common_invokeMethodNoRange @ jump to common handler
3152 /* ------------------------------ */
3154 .L_OP_UNUSED_73: /* 0x73 */
3155 /* File: armv5te/OP_UNUSED_73.S */
3156 /* File: armv5te/unused.S */
3161 /* ------------------------------ */
3163 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3164 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3165 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3167 * Handle a virtual method call.
3169 * for: invoke-virtual, invoke-virtual/range
3171 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3172 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3173 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3174 FETCH(r1, 1) @ r1<- BBBB
3175 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3176 FETCH(r10, 2) @ r10<- GFED or CCCC
3177 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3179 and r10, r10, #15 @ r10<- D (or stays CCCC)
3181 cmp r0, #0 @ already resolved?
3182 EXPORT_PC() @ must export for invoke
3183 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3184 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3185 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3186 mov r2, #METHOD_VIRTUAL @ resolver method type
3187 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3188 cmp r0, #0 @ got null?
3189 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3190 b common_exceptionThrown @ yes, handle exception
3193 /* ------------------------------ */
3195 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3196 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3197 /* File: armv5te/OP_INVOKE_SUPER.S */
3199 * Handle a "super" method call.
3201 * for: invoke-super, invoke-super/range
3203 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3204 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3205 FETCH(r10, 2) @ r10<- GFED or CCCC
3206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3208 and r10, r10, #15 @ r10<- D (or stays CCCC)
3210 FETCH(r1, 1) @ r1<- BBBB
3211 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3212 GET_VREG(r2, r10) @ r2<- "this" ptr
3213 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3214 cmp r2, #0 @ null "this"?
3215 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3216 beq common_errNullObject @ null "this", throw exception
3217 cmp r0, #0 @ already resolved?
3218 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3219 EXPORT_PC() @ must export for invoke
3220 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3221 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3224 /* ------------------------------ */
3226 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3227 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3228 /* File: armv5te/OP_INVOKE_DIRECT.S */
3230 * Handle a direct method call.
3232 * (We could defer the "is 'this' pointer null" test to the common
3233 * method invocation code, and use a flag to indicate that static
3234 * calls don't count. If we do this as part of copying the arguments
3235 * out we could avoiding loading the first arg twice.)
3237 * for: invoke-direct, invoke-direct/range
3239 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3240 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3241 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3242 FETCH(r1, 1) @ r1<- BBBB
3243 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3244 FETCH(r10, 2) @ r10<- GFED or CCCC
3245 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3247 and r10, r10, #15 @ r10<- D (or stays CCCC)
3249 cmp r0, #0 @ already resolved?
3250 EXPORT_PC() @ must export for invoke
3251 GET_VREG(r2, r10) @ r2<- "this" ptr
3252 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3253 .LOP_INVOKE_DIRECT_RANGE_finish:
3254 cmp r2, #0 @ null "this" ref?
3255 bne common_invokeMethodRange @ no, continue on
3256 b common_errNullObject @ yes, throw exception
3259 /* ------------------------------ */
3261 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3262 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3263 /* File: armv5te/OP_INVOKE_STATIC.S */
3265 * Handle a static method call.
3267 * for: invoke-static, invoke-static/range
3269 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3270 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3271 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3272 FETCH(r1, 1) @ r1<- BBBB
3273 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3274 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3275 cmp r0, #0 @ already resolved?
3276 EXPORT_PC() @ must export for invoke
3277 bne common_invokeMethodRange @ yes, continue on
3278 0: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3279 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3280 mov r2, #METHOD_STATIC @ resolver method type
3281 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3282 cmp r0, #0 @ got null?
3283 bne common_invokeMethodRange @ no, continue
3284 b common_exceptionThrown @ yes, handle exception
3288 /* ------------------------------ */
3290 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3291 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3292 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3294 * Handle an interface method call.
3296 * for: invoke-interface, invoke-interface/range
3298 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3299 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3300 FETCH(r2, 2) @ r2<- FEDC or CCCC
3301 FETCH(r1, 1) @ r1<- BBBB
3303 and r2, r2, #15 @ r2<- C (or stays CCCC)
3305 EXPORT_PC() @ must export for invoke
3306 GET_VREG(r0, r2) @ r0<- first arg ("this")
3307 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3308 cmp r0, #0 @ null obj?
3309 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3310 beq common_errNullObject @ yes, fail
3311 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3312 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3313 cmp r0, #0 @ failed?
3314 beq common_exceptionThrown @ yes, handle exception
3315 b common_invokeMethodRange @ jump to common handler
3319 /* ------------------------------ */
3321 .L_OP_UNUSED_79: /* 0x79 */
3322 /* File: armv5te/OP_UNUSED_79.S */
3323 /* File: armv5te/unused.S */
3328 /* ------------------------------ */
3330 .L_OP_UNUSED_7A: /* 0x7a */
3331 /* File: armv5te/OP_UNUSED_7A.S */
3332 /* File: armv5te/unused.S */
3337 /* ------------------------------ */
3339 .L_OP_NEG_INT: /* 0x7b */
3340 /* File: armv5te/OP_NEG_INT.S */
3341 /* File: armv5te/unop.S */
3343 * Generic 32-bit unary operation. Provide an "instr" line that
3344 * specifies an instruction that performs "result = op r0".
3345 * This could be an ARM instruction or a function call.
3347 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3348 * int-to-byte, int-to-char, int-to-short
3351 mov r3, rINST, lsr #12 @ r3<- B
3352 mov r9, rINST, lsr #8 @ r9<- A+
3353 GET_VREG(r0, r3) @ r0<- vB
3355 @ optional op; may set condition codes
3356 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3357 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3358 GET_INST_OPCODE(ip) @ extract opcode from rINST
3359 SET_VREG(r0, r9) @ vAA<- r0
3360 GOTO_OPCODE(ip) @ jump to next instruction
3361 /* 9-10 instructions */
3364 /* ------------------------------ */
3366 .L_OP_NOT_INT: /* 0x7c */
3367 /* File: armv5te/OP_NOT_INT.S */
3368 /* File: armv5te/unop.S */
3370 * Generic 32-bit unary operation. Provide an "instr" line that
3371 * specifies an instruction that performs "result = op r0".
3372 * This could be an ARM instruction or a function call.
3374 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3375 * int-to-byte, int-to-char, int-to-short
3378 mov r3, rINST, lsr #12 @ r3<- B
3379 mov r9, rINST, lsr #8 @ r9<- A+
3380 GET_VREG(r0, r3) @ r0<- vB
3382 @ optional op; may set condition codes
3383 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3384 mvn r0, r0 @ r0<- op, r0-r3 changed
3385 GET_INST_OPCODE(ip) @ extract opcode from rINST
3386 SET_VREG(r0, r9) @ vAA<- r0
3387 GOTO_OPCODE(ip) @ jump to next instruction
3388 /* 9-10 instructions */
3391 /* ------------------------------ */
3393 .L_OP_NEG_LONG: /* 0x7d */
3394 /* File: armv5te/OP_NEG_LONG.S */
3395 /* File: armv5te/unopWide.S */
3397 * Generic 64-bit unary operation. Provide an "instr" line that
3398 * specifies an instruction that performs "result = op r0/r1".
3399 * This could be an ARM instruction or a function call.
3401 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3404 mov r9, rINST, lsr #8 @ r9<- A+
3405 mov r3, rINST, lsr #12 @ r3<- B
3407 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3408 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3409 ldmia r3, {r0-r1} @ r0/r1<- vAA
3410 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3411 rsbs r0, r0, #0 @ optional op; may set condition codes
3412 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3413 GET_INST_OPCODE(ip) @ extract opcode from rINST
3414 stmia r9, {r0-r1} @ vAA<- r0/r1
3415 GOTO_OPCODE(ip) @ jump to next instruction
3416 /* 12-13 instructions */
3420 /* ------------------------------ */
3422 .L_OP_NOT_LONG: /* 0x7e */
3423 /* File: armv5te/OP_NOT_LONG.S */
3424 /* File: armv5te/unopWide.S */
3426 * Generic 64-bit unary operation. Provide an "instr" line that
3427 * specifies an instruction that performs "result = op r0/r1".
3428 * This could be an ARM instruction or a function call.
3430 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3433 mov r9, rINST, lsr #8 @ r9<- A+
3434 mov r3, rINST, lsr #12 @ r3<- B
3436 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3437 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3438 ldmia r3, {r0-r1} @ r0/r1<- vAA
3439 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3440 mvn r0, r0 @ optional op; may set condition codes
3441 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3442 GET_INST_OPCODE(ip) @ extract opcode from rINST
3443 stmia r9, {r0-r1} @ vAA<- r0/r1
3444 GOTO_OPCODE(ip) @ jump to next instruction
3445 /* 12-13 instructions */
3449 /* ------------------------------ */
3451 .L_OP_NEG_FLOAT: /* 0x7f */
3452 /* File: armv5te/OP_NEG_FLOAT.S */
3453 /* File: armv5te/unop.S */
3455 * Generic 32-bit unary operation. Provide an "instr" line that
3456 * specifies an instruction that performs "result = op r0".
3457 * This could be an ARM instruction or a function call.
3459 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3460 * int-to-byte, int-to-char, int-to-short
3463 mov r3, rINST, lsr #12 @ r3<- B
3464 mov r9, rINST, lsr #8 @ r9<- A+
3465 GET_VREG(r0, r3) @ r0<- vB
3467 @ optional op; may set condition codes
3468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3469 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3470 GET_INST_OPCODE(ip) @ extract opcode from rINST
3471 SET_VREG(r0, r9) @ vAA<- r0
3472 GOTO_OPCODE(ip) @ jump to next instruction
3473 /* 9-10 instructions */
3476 /* ------------------------------ */
3478 .L_OP_NEG_DOUBLE: /* 0x80 */
3479 /* File: armv5te/OP_NEG_DOUBLE.S */
3480 /* File: armv5te/unopWide.S */
3482 * Generic 64-bit unary operation. Provide an "instr" line that
3483 * specifies an instruction that performs "result = op r0/r1".
3484 * This could be an ARM instruction or a function call.
3486 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3489 mov r9, rINST, lsr #8 @ r9<- A+
3490 mov r3, rINST, lsr #12 @ r3<- B
3492 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3493 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3494 ldmia r3, {r0-r1} @ r0/r1<- vAA
3495 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3496 @ optional op; may set condition codes
3497 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed
3498 GET_INST_OPCODE(ip) @ extract opcode from rINST
3499 stmia r9, {r0-r1} @ vAA<- r0/r1
3500 GOTO_OPCODE(ip) @ jump to next instruction
3501 /* 12-13 instructions */
3505 /* ------------------------------ */
3507 .L_OP_INT_TO_LONG: /* 0x81 */
3508 /* File: armv5te/OP_INT_TO_LONG.S */
3509 /* File: armv5te/unopWider.S */
3511 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3512 * that specifies an instruction that performs "result = op r0", where
3513 * "result" is a 64-bit quantity in r0/r1.
3515 * For: int-to-long, int-to-double, float-to-long, float-to-double
3518 mov r9, rINST, lsr #8 @ r9<- A+
3519 mov r3, rINST, lsr #12 @ r3<- B
3521 GET_VREG(r0, r3) @ r0<- vB
3522 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3523 @ optional op; may set condition codes
3524 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3525 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3526 GET_INST_OPCODE(ip) @ extract opcode from rINST
3527 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3528 GOTO_OPCODE(ip) @ jump to next instruction
3529 /* 10-11 instructions */
3532 /* ------------------------------ */
3534 .L_OP_INT_TO_FLOAT: /* 0x82 */
3535 /* File: armv5te/OP_INT_TO_FLOAT.S */
3536 /* File: armv5te/unop.S */
3538 * Generic 32-bit unary operation. Provide an "instr" line that
3539 * specifies an instruction that performs "result = op r0".
3540 * This could be an ARM instruction or a function call.
3542 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543 * int-to-byte, int-to-char, int-to-short
3546 mov r3, rINST, lsr #12 @ r3<- B
3547 mov r9, rINST, lsr #8 @ r9<- A+
3548 GET_VREG(r0, r3) @ r0<- vB
3550 @ optional op; may set condition codes
3551 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3552 bl __aeabi_i2f @ r0<- op, r0-r3 changed
3553 GET_INST_OPCODE(ip) @ extract opcode from rINST
3554 SET_VREG(r0, r9) @ vAA<- r0
3555 GOTO_OPCODE(ip) @ jump to next instruction
3556 /* 9-10 instructions */
3559 /* ------------------------------ */
3561 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3562 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3563 /* File: armv5te/unopWider.S */
3565 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3566 * that specifies an instruction that performs "result = op r0", where
3567 * "result" is a 64-bit quantity in r0/r1.
3569 * For: int-to-long, int-to-double, float-to-long, float-to-double
3572 mov r9, rINST, lsr #8 @ r9<- A+
3573 mov r3, rINST, lsr #12 @ r3<- B
3575 GET_VREG(r0, r3) @ r0<- vB
3576 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3577 @ optional op; may set condition codes
3578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3579 bl __aeabi_i2d @ r0<- op, r0-r3 changed
3580 GET_INST_OPCODE(ip) @ extract opcode from rINST
3581 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3582 GOTO_OPCODE(ip) @ jump to next instruction
3583 /* 10-11 instructions */
3586 /* ------------------------------ */
3588 .L_OP_LONG_TO_INT: /* 0x84 */
3589 /* File: armv5te/OP_LONG_TO_INT.S */
3590 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3591 /* File: armv5te/OP_MOVE.S */
3592 /* for move, move-object, long-to-int */
3594 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3595 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3596 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3597 GET_VREG(r2, r1) @ r2<- fp[B]
3599 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3600 SET_VREG(r2, r0) @ fp[A]<- r2
3601 GOTO_OPCODE(ip) @ execute next instruction
3605 /* ------------------------------ */
3607 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3608 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3609 /* File: armv5te/unopNarrower.S */
3611 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3612 * that specifies an instruction that performs "result = op r0/r1", where
3613 * "result" is a 32-bit quantity in r0.
3615 * For: long-to-float, double-to-int, double-to-float
3617 * (This would work for long-to-int, but that instruction is actually
3618 * an exact match for OP_MOVE.)
3621 mov r3, rINST, lsr #12 @ r3<- B
3622 mov r9, rINST, lsr #8 @ r9<- A+
3623 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3625 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3626 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3627 @ optional op; may set condition codes
3628 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3629 GET_INST_OPCODE(ip) @ extract opcode from rINST
3630 SET_VREG(r0, r9) @ vA<- r0
3631 GOTO_OPCODE(ip) @ jump to next instruction
3632 /* 10-11 instructions */
3635 /* ------------------------------ */
3637 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3638 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3639 /* File: armv5te/unopWide.S */
3641 * Generic 64-bit unary operation. Provide an "instr" line that
3642 * specifies an instruction that performs "result = op r0/r1".
3643 * This could be an ARM instruction or a function call.
3645 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3648 mov r9, rINST, lsr #8 @ r9<- A+
3649 mov r3, rINST, lsr #12 @ r3<- B
3651 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3652 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3653 ldmia r3, {r0-r1} @ r0/r1<- vAA
3654 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3655 @ optional op; may set condition codes
3656 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3657 GET_INST_OPCODE(ip) @ extract opcode from rINST
3658 stmia r9, {r0-r1} @ vAA<- r0/r1
3659 GOTO_OPCODE(ip) @ jump to next instruction
3660 /* 12-13 instructions */
3664 /* ------------------------------ */
3666 .L_OP_FLOAT_TO_INT: /* 0x87 */
3667 /* File: armv5te/OP_FLOAT_TO_INT.S */
3668 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3669 /* File: armv5te/unop.S */
3671 * Generic 32-bit unary operation. Provide an "instr" line that
3672 * specifies an instruction that performs "result = op r0".
3673 * This could be an ARM instruction or a function call.
3675 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3676 * int-to-byte, int-to-char, int-to-short
3679 mov r3, rINST, lsr #12 @ r3<- B
3680 mov r9, rINST, lsr #8 @ r9<- A+
3681 GET_VREG(r0, r3) @ r0<- vB
3683 @ optional op; may set condition codes
3684 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3685 bl __aeabi_f2iz @ r0<- op, r0-r3 changed
3686 GET_INST_OPCODE(ip) @ extract opcode from rINST
3687 SET_VREG(r0, r9) @ vAA<- r0
3688 GOTO_OPCODE(ip) @ jump to next instruction
3689 /* 9-10 instructions */
3693 @include "armv5te/unop.S" {"instr":"bl f2i_doconv"}
3696 * Convert the float in r0 to an int in r0.
3698 * We have to clip values to int min/max per the specification. The
3699 * expected common case is a "reasonable" value that converts directly
3700 * to modest integer. The EABI convert function isn't doing this for us.
3704 mov r1, #0x4f000000 @ (float)maxint
3706 bl __aeabi_fcmpge @ is arg >= maxint?
3707 cmp r0, #0 @ nonzero == yes
3708 mvnne r0, #0x80000000 @ return maxint (7fffffff)
3709 ldmnefd sp!, {r4, pc}
3711 mov r0, r4 @ recover arg
3712 mov r1, #0xcf000000 @ (float)minint
3713 bl __aeabi_fcmple @ is arg <= minint?
3714 cmp r0, #0 @ nonzero == yes
3715 movne r0, #0x80000000 @ return minint (80000000)
3716 ldmnefd sp!, {r4, pc}
3718 mov r0, r4 @ recover arg
3720 bl __aeabi_fcmpeq @ is arg == self?
3721 cmp r0, #0 @ zero == no
3722 ldmeqfd sp!, {r4, pc} @ return zero for NaN
3724 mov r0, r4 @ recover arg
3725 bl __aeabi_f2iz @ convert float to int
3730 /* ------------------------------ */
3732 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3733 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3734 @include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3735 /* File: armv5te/unopWider.S */
3737 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3738 * that specifies an instruction that performs "result = op r0", where
3739 * "result" is a 64-bit quantity in r0/r1.
3741 * For: int-to-long, int-to-double, float-to-long, float-to-double
3744 mov r9, rINST, lsr #8 @ r9<- A+
3745 mov r3, rINST, lsr #12 @ r3<- B
3747 GET_VREG(r0, r3) @ r0<- vB
3748 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3749 @ optional op; may set condition codes
3750 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3751 bl f2l_doconv @ r0<- op, r0-r3 changed
3752 GET_INST_OPCODE(ip) @ extract opcode from rINST
3753 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3754 GOTO_OPCODE(ip) @ jump to next instruction
3755 /* 10-11 instructions */
3759 /* ------------------------------ */
3761 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3762 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3763 /* File: armv5te/unopWider.S */
3765 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3766 * that specifies an instruction that performs "result = op r0", where
3767 * "result" is a 64-bit quantity in r0/r1.
3769 * For: int-to-long, int-to-double, float-to-long, float-to-double
3772 mov r9, rINST, lsr #8 @ r9<- A+
3773 mov r3, rINST, lsr #12 @ r3<- B
3775 GET_VREG(r0, r3) @ r0<- vB
3776 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3777 @ optional op; may set condition codes
3778 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3779 bl __aeabi_f2d @ r0<- op, r0-r3 changed
3780 GET_INST_OPCODE(ip) @ extract opcode from rINST
3781 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3782 GOTO_OPCODE(ip) @ jump to next instruction
3783 /* 10-11 instructions */
3786 /* ------------------------------ */
3788 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3789 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3790 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3791 /* File: armv5te/unopNarrower.S */
3793 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3794 * that specifies an instruction that performs "result = op r0/r1", where
3795 * "result" is a 32-bit quantity in r0.
3797 * For: long-to-float, double-to-int, double-to-float
3799 * (This would work for long-to-int, but that instruction is actually
3800 * an exact match for OP_MOVE.)
3803 mov r3, rINST, lsr #12 @ r3<- B
3804 mov r9, rINST, lsr #8 @ r9<- A+
3805 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3807 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3808 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3809 @ optional op; may set condition codes
3810 bl __aeabi_d2iz @ r0<- op, r0-r3 changed
3811 GET_INST_OPCODE(ip) @ extract opcode from rINST
3812 SET_VREG(r0, r9) @ vA<- r0
3813 GOTO_OPCODE(ip) @ jump to next instruction
3814 /* 10-11 instructions */
3818 @include "armv5te/unopNarrower.S" {"instr":"bl d2i_doconv"}
3821 * Convert the double in r0/r1 to an int in r0.
3823 * We have to clip values to int min/max per the specification. The
3824 * expected common case is a "reasonable" value that converts directly
3825 * to modest integer. The EABI convert function isn't doing this for us.
3828 stmfd sp!, {r4, r5, lr} @ save regs
3829 ldr r2, .LOP_DOUBLE_TO_INT_maxlo @ (double)maxint, lo
3830 ldr r3, .LOP_DOUBLE_TO_INT_maxhi @ (double)maxint, hi
3831 sub sp, sp, #4 @ align for EABI
3832 mov r4, r0 @ save r0
3834 bl __aeabi_dcmpge @ is arg >= maxint?
3835 cmp r0, #0 @ nonzero == yes
3836 mvnne r0, #0x80000000 @ return maxint (7fffffff)
3839 mov r0, r4 @ recover arg
3841 ldr r3, .LOP_DOUBLE_TO_INT_min @ (double)minint, hi
3842 mov r2, #0 @ (double)minint, lo
3843 bl __aeabi_dcmple @ is arg <= minint?
3844 cmp r0, #0 @ nonzero == yes
3845 movne r0, #0x80000000 @ return minint (80000000)
3848 mov r0, r4 @ recover arg
3850 mov r2, r4 @ compare against self
3852 bl __aeabi_dcmpeq @ is arg == self?
3853 cmp r0, #0 @ zero == no
3854 beq 1f @ return zero for NaN
3856 mov r0, r4 @ recover arg
3858 bl __aeabi_d2iz @ convert double to int
3862 ldmfd sp!, {r4, r5, pc}
3864 .LOP_DOUBLE_TO_INT_maxlo:
3865 .word 0xffc00000 @ maxint, as a double (low word)
3866 .LOP_DOUBLE_TO_INT_maxhi:
3867 .word 0x41dfffff @ maxint, as a double (high word)
3868 .LOP_DOUBLE_TO_INT_min:
3869 .word 0xc1e00000 @ minint, as a double (high word)
3873 /* ------------------------------ */
3875 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3876 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
3877 @include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"}
3878 /* File: armv5te/unopWide.S */
3880 * Generic 64-bit unary operation. Provide an "instr" line that
3881 * specifies an instruction that performs "result = op r0/r1".
3882 * This could be an ARM instruction or a function call.
3884 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3887 mov r9, rINST, lsr #8 @ r9<- A+
3888 mov r3, rINST, lsr #12 @ r3<- B
3890 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3891 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3892 ldmia r3, {r0-r1} @ r0/r1<- vAA
3893 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3894 @ optional op; may set condition codes
3895 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
3896 GET_INST_OPCODE(ip) @ extract opcode from rINST
3897 stmia r9, {r0-r1} @ vAA<- r0/r1
3898 GOTO_OPCODE(ip) @ jump to next instruction
3899 /* 12-13 instructions */
3904 /* ------------------------------ */
3906 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3907 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
3908 /* File: armv5te/unopNarrower.S */
3910 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3911 * that specifies an instruction that performs "result = op r0/r1", where
3912 * "result" is a 32-bit quantity in r0.
3914 * For: long-to-float, double-to-int, double-to-float
3916 * (This would work for long-to-int, but that instruction is actually
3917 * an exact match for OP_MOVE.)
3920 mov r3, rINST, lsr #12 @ r3<- B
3921 mov r9, rINST, lsr #8 @ r9<- A+
3922 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3924 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3925 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3926 @ optional op; may set condition codes
3927 bl __aeabi_d2f @ r0<- op, r0-r3 changed
3928 GET_INST_OPCODE(ip) @ extract opcode from rINST
3929 SET_VREG(r0, r9) @ vA<- r0
3930 GOTO_OPCODE(ip) @ jump to next instruction
3931 /* 10-11 instructions */
3934 /* ------------------------------ */
3936 .L_OP_INT_TO_BYTE: /* 0x8d */
3937 /* File: armv5te/OP_INT_TO_BYTE.S */
3938 /* File: armv5te/unop.S */
3940 * Generic 32-bit unary operation. Provide an "instr" line that
3941 * specifies an instruction that performs "result = op r0".
3942 * This could be an ARM instruction or a function call.
3944 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3945 * int-to-byte, int-to-char, int-to-short
3948 mov r3, rINST, lsr #12 @ r3<- B
3949 mov r9, rINST, lsr #8 @ r9<- A+
3950 GET_VREG(r0, r3) @ r0<- vB
3952 mov r0, r0, asl #24 @ optional op; may set condition codes
3953 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3954 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed
3955 GET_INST_OPCODE(ip) @ extract opcode from rINST
3956 SET_VREG(r0, r9) @ vAA<- r0
3957 GOTO_OPCODE(ip) @ jump to next instruction
3958 /* 9-10 instructions */
3961 /* ------------------------------ */
3963 .L_OP_INT_TO_CHAR: /* 0x8e */
3964 /* File: armv5te/OP_INT_TO_CHAR.S */
3965 /* File: armv5te/unop.S */
3967 * Generic 32-bit unary operation. Provide an "instr" line that
3968 * specifies an instruction that performs "result = op r0".
3969 * This could be an ARM instruction or a function call.
3971 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3972 * int-to-byte, int-to-char, int-to-short
3975 mov r3, rINST, lsr #12 @ r3<- B
3976 mov r9, rINST, lsr #8 @ r9<- A+
3977 GET_VREG(r0, r3) @ r0<- vB
3979 mov r0, r0, asl #16 @ optional op; may set condition codes
3980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3981 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed
3982 GET_INST_OPCODE(ip) @ extract opcode from rINST
3983 SET_VREG(r0, r9) @ vAA<- r0
3984 GOTO_OPCODE(ip) @ jump to next instruction
3985 /* 9-10 instructions */
3988 /* ------------------------------ */
3990 .L_OP_INT_TO_SHORT: /* 0x8f */
3991 /* File: armv5te/OP_INT_TO_SHORT.S */
3992 /* File: armv5te/unop.S */
3994 * Generic 32-bit unary operation. Provide an "instr" line that
3995 * specifies an instruction that performs "result = op r0".
3996 * This could be an ARM instruction or a function call.
3998 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3999 * int-to-byte, int-to-char, int-to-short
4002 mov r3, rINST, lsr #12 @ r3<- B
4003 mov r9, rINST, lsr #8 @ r9<- A+
4004 GET_VREG(r0, r3) @ r0<- vB
4006 mov r0, r0, asl #16 @ optional op; may set condition codes
4007 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4008 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed
4009 GET_INST_OPCODE(ip) @ extract opcode from rINST
4010 SET_VREG(r0, r9) @ vAA<- r0
4011 GOTO_OPCODE(ip) @ jump to next instruction
4012 /* 9-10 instructions */
4015 /* ------------------------------ */
4017 .L_OP_ADD_INT: /* 0x90 */
4018 /* File: armv5te/OP_ADD_INT.S */
4019 /* File: armv5te/binop.S */
4021 * Generic 32-bit binary operation. Provide an "instr" line that
4022 * specifies an instruction that performs "result = r0 op r1".
4023 * This could be an ARM instruction or a function call. (If the result
4024 * comes back in a register other than r0, you can override "result".)
4026 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4027 * vCC (r1). Useful for integer division and modulus. Note that we
4028 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4029 * handles it correctly.
4031 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4032 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4033 * mul-float, div-float, rem-float
4035 /* binop vAA, vBB, vCC */
4036 FETCH(r0, 1) @ r0<- CCBB
4037 mov r9, rINST, lsr #8 @ r9<- AA
4038 mov r3, r0, lsr #8 @ r3<- CC
4039 and r2, r0, #255 @ r2<- BB
4040 GET_VREG(r1, r3) @ r1<- vCC
4041 GET_VREG(r0, r2) @ r0<- vBB
4043 cmp r1, #0 @ is second operand zero?
4044 beq common_errDivideByZero
4047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4048 @ optional op; may set condition codes
4049 add r0, r0, r1 @ r0<- op, r0-r3 changed
4050 GET_INST_OPCODE(ip) @ extract opcode from rINST
4051 SET_VREG(r0, r9) @ vAA<- r0
4052 GOTO_OPCODE(ip) @ jump to next instruction
4053 /* 11-14 instructions */
4057 /* ------------------------------ */
4059 .L_OP_SUB_INT: /* 0x91 */
4060 /* File: armv5te/OP_SUB_INT.S */
4061 /* File: armv5te/binop.S */
4063 * Generic 32-bit binary operation. Provide an "instr" line that
4064 * specifies an instruction that performs "result = r0 op r1".
4065 * This could be an ARM instruction or a function call. (If the result
4066 * comes back in a register other than r0, you can override "result".)
4068 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4069 * vCC (r1). Useful for integer division and modulus. Note that we
4070 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4071 * handles it correctly.
4073 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4074 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4075 * mul-float, div-float, rem-float
4077 /* binop vAA, vBB, vCC */
4078 FETCH(r0, 1) @ r0<- CCBB
4079 mov r9, rINST, lsr #8 @ r9<- AA
4080 mov r3, r0, lsr #8 @ r3<- CC
4081 and r2, r0, #255 @ r2<- BB
4082 GET_VREG(r1, r3) @ r1<- vCC
4083 GET_VREG(r0, r2) @ r0<- vBB
4085 cmp r1, #0 @ is second operand zero?
4086 beq common_errDivideByZero
4089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4090 @ optional op; may set condition codes
4091 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4092 GET_INST_OPCODE(ip) @ extract opcode from rINST
4093 SET_VREG(r0, r9) @ vAA<- r0
4094 GOTO_OPCODE(ip) @ jump to next instruction
4095 /* 11-14 instructions */
4099 /* ------------------------------ */
4101 .L_OP_MUL_INT: /* 0x92 */
4102 /* File: armv5te/OP_MUL_INT.S */
4103 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4104 /* File: armv5te/binop.S */
4106 * Generic 32-bit binary operation. Provide an "instr" line that
4107 * specifies an instruction that performs "result = r0 op r1".
4108 * This could be an ARM instruction or a function call. (If the result
4109 * comes back in a register other than r0, you can override "result".)
4111 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4112 * vCC (r1). Useful for integer division and modulus. Note that we
4113 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4114 * handles it correctly.
4116 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4117 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4118 * mul-float, div-float, rem-float
4120 /* binop vAA, vBB, vCC */
4121 FETCH(r0, 1) @ r0<- CCBB
4122 mov r9, rINST, lsr #8 @ r9<- AA
4123 mov r3, r0, lsr #8 @ r3<- CC
4124 and r2, r0, #255 @ r2<- BB
4125 GET_VREG(r1, r3) @ r1<- vCC
4126 GET_VREG(r0, r2) @ r0<- vBB
4128 cmp r1, #0 @ is second operand zero?
4129 beq common_errDivideByZero
4132 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4133 @ optional op; may set condition codes
4134 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4135 GET_INST_OPCODE(ip) @ extract opcode from rINST
4136 SET_VREG(r0, r9) @ vAA<- r0
4137 GOTO_OPCODE(ip) @ jump to next instruction
4138 /* 11-14 instructions */
4142 /* ------------------------------ */
4144 .L_OP_DIV_INT: /* 0x93 */
4145 /* File: armv5te/OP_DIV_INT.S */
4146 /* File: armv5te/binop.S */
4148 * Generic 32-bit binary operation. Provide an "instr" line that
4149 * specifies an instruction that performs "result = r0 op r1".
4150 * This could be an ARM instruction or a function call. (If the result
4151 * comes back in a register other than r0, you can override "result".)
4153 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4154 * vCC (r1). Useful for integer division and modulus. Note that we
4155 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4156 * handles it correctly.
4158 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4159 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4160 * mul-float, div-float, rem-float
4162 /* binop vAA, vBB, vCC */
4163 FETCH(r0, 1) @ r0<- CCBB
4164 mov r9, rINST, lsr #8 @ r9<- AA
4165 mov r3, r0, lsr #8 @ r3<- CC
4166 and r2, r0, #255 @ r2<- BB
4167 GET_VREG(r1, r3) @ r1<- vCC
4168 GET_VREG(r0, r2) @ r0<- vBB
4170 cmp r1, #0 @ is second operand zero?
4171 beq common_errDivideByZero
4174 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4175 @ optional op; may set condition codes
4176 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4177 GET_INST_OPCODE(ip) @ extract opcode from rINST
4178 SET_VREG(r0, r9) @ vAA<- r0
4179 GOTO_OPCODE(ip) @ jump to next instruction
4180 /* 11-14 instructions */
4184 /* ------------------------------ */
4186 .L_OP_REM_INT: /* 0x94 */
4187 /* File: armv5te/OP_REM_INT.S */
4188 /* idivmod returns quotient in r0 and remainder in r1 */
4189 /* File: armv5te/binop.S */
4191 * Generic 32-bit binary operation. Provide an "instr" line that
4192 * specifies an instruction that performs "result = r0 op r1".
4193 * This could be an ARM instruction or a function call. (If the result
4194 * comes back in a register other than r0, you can override "result".)
4196 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4197 * vCC (r1). Useful for integer division and modulus. Note that we
4198 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4199 * handles it correctly.
4201 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4202 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4203 * mul-float, div-float, rem-float
4205 /* binop vAA, vBB, vCC */
4206 FETCH(r0, 1) @ r0<- CCBB
4207 mov r9, rINST, lsr #8 @ r9<- AA
4208 mov r3, r0, lsr #8 @ r3<- CC
4209 and r2, r0, #255 @ r2<- BB
4210 GET_VREG(r1, r3) @ r1<- vCC
4211 GET_VREG(r0, r2) @ r0<- vBB
4213 cmp r1, #0 @ is second operand zero?
4214 beq common_errDivideByZero
4217 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4218 @ optional op; may set condition codes
4219 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4220 GET_INST_OPCODE(ip) @ extract opcode from rINST
4221 SET_VREG(r1, r9) @ vAA<- r1
4222 GOTO_OPCODE(ip) @ jump to next instruction
4223 /* 11-14 instructions */
4227 /* ------------------------------ */
4229 .L_OP_AND_INT: /* 0x95 */
4230 /* File: armv5te/OP_AND_INT.S */
4231 /* File: armv5te/binop.S */
4233 * Generic 32-bit binary operation. Provide an "instr" line that
4234 * specifies an instruction that performs "result = r0 op r1".
4235 * This could be an ARM instruction or a function call. (If the result
4236 * comes back in a register other than r0, you can override "result".)
4238 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4239 * vCC (r1). Useful for integer division and modulus. Note that we
4240 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4241 * handles it correctly.
4243 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4244 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4245 * mul-float, div-float, rem-float
4247 /* binop vAA, vBB, vCC */
4248 FETCH(r0, 1) @ r0<- CCBB
4249 mov r9, rINST, lsr #8 @ r9<- AA
4250 mov r3, r0, lsr #8 @ r3<- CC
4251 and r2, r0, #255 @ r2<- BB
4252 GET_VREG(r1, r3) @ r1<- vCC
4253 GET_VREG(r0, r2) @ r0<- vBB
4255 cmp r1, #0 @ is second operand zero?
4256 beq common_errDivideByZero
4259 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4260 @ optional op; may set condition codes
4261 and r0, r0, r1 @ r0<- op, r0-r3 changed
4262 GET_INST_OPCODE(ip) @ extract opcode from rINST
4263 SET_VREG(r0, r9) @ vAA<- r0
4264 GOTO_OPCODE(ip) @ jump to next instruction
4265 /* 11-14 instructions */
4269 /* ------------------------------ */
4271 .L_OP_OR_INT: /* 0x96 */
4272 /* File: armv5te/OP_OR_INT.S */
4273 /* File: armv5te/binop.S */
4275 * Generic 32-bit binary operation. Provide an "instr" line that
4276 * specifies an instruction that performs "result = r0 op r1".
4277 * This could be an ARM instruction or a function call. (If the result
4278 * comes back in a register other than r0, you can override "result".)
4280 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281 * vCC (r1). Useful for integer division and modulus. Note that we
4282 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283 * handles it correctly.
4285 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287 * mul-float, div-float, rem-float
4289 /* binop vAA, vBB, vCC */
4290 FETCH(r0, 1) @ r0<- CCBB
4291 mov r9, rINST, lsr #8 @ r9<- AA
4292 mov r3, r0, lsr #8 @ r3<- CC
4293 and r2, r0, #255 @ r2<- BB
4294 GET_VREG(r1, r3) @ r1<- vCC
4295 GET_VREG(r0, r2) @ r0<- vBB
4297 cmp r1, #0 @ is second operand zero?
4298 beq common_errDivideByZero
4301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4302 @ optional op; may set condition codes
4303 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4304 GET_INST_OPCODE(ip) @ extract opcode from rINST
4305 SET_VREG(r0, r9) @ vAA<- r0
4306 GOTO_OPCODE(ip) @ jump to next instruction
4307 /* 11-14 instructions */
4311 /* ------------------------------ */
4313 .L_OP_XOR_INT: /* 0x97 */
4314 /* File: armv5te/OP_XOR_INT.S */
4315 /* File: armv5te/binop.S */
4317 * Generic 32-bit binary operation. Provide an "instr" line that
4318 * specifies an instruction that performs "result = r0 op r1".
4319 * This could be an ARM instruction or a function call. (If the result
4320 * comes back in a register other than r0, you can override "result".)
4322 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4323 * vCC (r1). Useful for integer division and modulus. Note that we
4324 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4325 * handles it correctly.
4327 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4328 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4329 * mul-float, div-float, rem-float
4331 /* binop vAA, vBB, vCC */
4332 FETCH(r0, 1) @ r0<- CCBB
4333 mov r9, rINST, lsr #8 @ r9<- AA
4334 mov r3, r0, lsr #8 @ r3<- CC
4335 and r2, r0, #255 @ r2<- BB
4336 GET_VREG(r1, r3) @ r1<- vCC
4337 GET_VREG(r0, r2) @ r0<- vBB
4339 cmp r1, #0 @ is second operand zero?
4340 beq common_errDivideByZero
4343 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4344 @ optional op; may set condition codes
4345 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4346 GET_INST_OPCODE(ip) @ extract opcode from rINST
4347 SET_VREG(r0, r9) @ vAA<- r0
4348 GOTO_OPCODE(ip) @ jump to next instruction
4349 /* 11-14 instructions */
4353 /* ------------------------------ */
4355 .L_OP_SHL_INT: /* 0x98 */
4356 /* File: armv5te/OP_SHL_INT.S */
4357 /* File: armv5te/binop.S */
4359 * Generic 32-bit binary operation. Provide an "instr" line that
4360 * specifies an instruction that performs "result = r0 op r1".
4361 * This could be an ARM instruction or a function call. (If the result
4362 * comes back in a register other than r0, you can override "result".)
4364 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4365 * vCC (r1). Useful for integer division and modulus. Note that we
4366 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4367 * handles it correctly.
4369 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4370 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4371 * mul-float, div-float, rem-float
4373 /* binop vAA, vBB, vCC */
4374 FETCH(r0, 1) @ r0<- CCBB
4375 mov r9, rINST, lsr #8 @ r9<- AA
4376 mov r3, r0, lsr #8 @ r3<- CC
4377 and r2, r0, #255 @ r2<- BB
4378 GET_VREG(r1, r3) @ r1<- vCC
4379 GET_VREG(r0, r2) @ r0<- vBB
4381 cmp r1, #0 @ is second operand zero?
4382 beq common_errDivideByZero
4385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4386 and r1, r1, #31 @ optional op; may set condition codes
4387 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4388 GET_INST_OPCODE(ip) @ extract opcode from rINST
4389 SET_VREG(r0, r9) @ vAA<- r0
4390 GOTO_OPCODE(ip) @ jump to next instruction
4391 /* 11-14 instructions */
4395 /* ------------------------------ */
4397 .L_OP_SHR_INT: /* 0x99 */
4398 /* File: armv5te/OP_SHR_INT.S */
4399 /* File: armv5te/binop.S */
4401 * Generic 32-bit binary operation. Provide an "instr" line that
4402 * specifies an instruction that performs "result = r0 op r1".
4403 * This could be an ARM instruction or a function call. (If the result
4404 * comes back in a register other than r0, you can override "result".)
4406 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4407 * vCC (r1). Useful for integer division and modulus. Note that we
4408 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4409 * handles it correctly.
4411 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4412 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4413 * mul-float, div-float, rem-float
4415 /* binop vAA, vBB, vCC */
4416 FETCH(r0, 1) @ r0<- CCBB
4417 mov r9, rINST, lsr #8 @ r9<- AA
4418 mov r3, r0, lsr #8 @ r3<- CC
4419 and r2, r0, #255 @ r2<- BB
4420 GET_VREG(r1, r3) @ r1<- vCC
4421 GET_VREG(r0, r2) @ r0<- vBB
4423 cmp r1, #0 @ is second operand zero?
4424 beq common_errDivideByZero
4427 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4428 and r1, r1, #31 @ optional op; may set condition codes
4429 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4430 GET_INST_OPCODE(ip) @ extract opcode from rINST
4431 SET_VREG(r0, r9) @ vAA<- r0
4432 GOTO_OPCODE(ip) @ jump to next instruction
4433 /* 11-14 instructions */
4437 /* ------------------------------ */
4439 .L_OP_USHR_INT: /* 0x9a */
4440 /* File: armv5te/OP_USHR_INT.S */
4441 /* File: armv5te/binop.S */
4443 * Generic 32-bit binary operation. Provide an "instr" line that
4444 * specifies an instruction that performs "result = r0 op r1".
4445 * This could be an ARM instruction or a function call. (If the result
4446 * comes back in a register other than r0, you can override "result".)
4448 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4449 * vCC (r1). Useful for integer division and modulus. Note that we
4450 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4451 * handles it correctly.
4453 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4454 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4455 * mul-float, div-float, rem-float
4457 /* binop vAA, vBB, vCC */
4458 FETCH(r0, 1) @ r0<- CCBB
4459 mov r9, rINST, lsr #8 @ r9<- AA
4460 mov r3, r0, lsr #8 @ r3<- CC
4461 and r2, r0, #255 @ r2<- BB
4462 GET_VREG(r1, r3) @ r1<- vCC
4463 GET_VREG(r0, r2) @ r0<- vBB
4465 cmp r1, #0 @ is second operand zero?
4466 beq common_errDivideByZero
4469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4470 and r1, r1, #31 @ optional op; may set condition codes
4471 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4472 GET_INST_OPCODE(ip) @ extract opcode from rINST
4473 SET_VREG(r0, r9) @ vAA<- r0
4474 GOTO_OPCODE(ip) @ jump to next instruction
4475 /* 11-14 instructions */
4479 /* ------------------------------ */
4481 .L_OP_ADD_LONG: /* 0x9b */
4482 /* File: armv5te/OP_ADD_LONG.S */
4483 /* File: armv5te/binopWide.S */
4485 * Generic 64-bit binary operation. Provide an "instr" line that
4486 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4487 * This could be an ARM instruction or a function call. (If the result
4488 * comes back in a register other than r0, you can override "result".)
4490 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4491 * vCC (r1). Useful for integer division and modulus.
4493 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4494 * xor-long, add-double, sub-double, mul-double, div-double,
4497 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4499 /* binop vAA, vBB, vCC */
4500 FETCH(r0, 1) @ r0<- CCBB
4501 mov r9, rINST, lsr #8 @ r9<- AA
4502 and r2, r0, #255 @ r2<- BB
4503 mov r3, r0, lsr #8 @ r3<- CC
4504 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4505 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4506 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4507 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4508 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4510 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4511 beq common_errDivideByZero
4513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4515 adds r0, r0, r2 @ optional op; may set condition codes
4516 adc r1, r1, r3 @ result<- op, r0-r3 changed
4517 GET_INST_OPCODE(ip) @ extract opcode from rINST
4518 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4519 GOTO_OPCODE(ip) @ jump to next instruction
4520 /* 14-17 instructions */
4524 /* ------------------------------ */
4526 .L_OP_SUB_LONG: /* 0x9c */
4527 /* File: armv5te/OP_SUB_LONG.S */
4528 /* File: armv5te/binopWide.S */
4530 * Generic 64-bit binary operation. Provide an "instr" line that
4531 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4532 * This could be an ARM instruction or a function call. (If the result
4533 * comes back in a register other than r0, you can override "result".)
4535 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4536 * vCC (r1). Useful for integer division and modulus.
4538 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4539 * xor-long, add-double, sub-double, mul-double, div-double,
4542 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4544 /* binop vAA, vBB, vCC */
4545 FETCH(r0, 1) @ r0<- CCBB
4546 mov r9, rINST, lsr #8 @ r9<- AA
4547 and r2, r0, #255 @ r2<- BB
4548 mov r3, r0, lsr #8 @ r3<- CC
4549 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4550 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4551 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4552 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4553 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4555 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4556 beq common_errDivideByZero
4558 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4560 subs r0, r0, r2 @ optional op; may set condition codes
4561 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4562 GET_INST_OPCODE(ip) @ extract opcode from rINST
4563 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4564 GOTO_OPCODE(ip) @ jump to next instruction
4565 /* 14-17 instructions */
4569 /* ------------------------------ */
4571 .L_OP_MUL_LONG: /* 0x9d */
4572 /* File: armv5te/OP_MUL_LONG.S */
4574 * Signed 64-bit integer multiply.
4576 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4583 * The low word of the result holds ZX, the high word holds
4584 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4585 * it doesn't fit in the low 64 bits.
4587 * Unlike most ARM math operations, multiply instructions have
4588 * restrictions on using the same register more than once (Rd and Rm
4589 * cannot be the same).
4591 /* mul-long vAA, vBB, vCC */
4592 FETCH(r0, 1) @ r0<- CCBB
4593 and r2, r0, #255 @ r2<- BB
4594 mov r3, r0, lsr #8 @ r3<- CC
4595 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4596 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4597 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4598 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4599 mul ip, r2, r1 @ ip<- ZxW
4600 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4601 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4602 mov r0, rINST, lsr #8 @ r0<- AA
4603 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4604 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4605 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4606 b .LOP_MUL_LONG_finish
4608 /* ------------------------------ */
4610 .L_OP_DIV_LONG: /* 0x9e */
4611 /* File: armv5te/OP_DIV_LONG.S */
4612 /* File: armv5te/binopWide.S */
4614 * Generic 64-bit binary operation. Provide an "instr" line that
4615 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4616 * This could be an ARM instruction or a function call. (If the result
4617 * comes back in a register other than r0, you can override "result".)
4619 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4620 * vCC (r1). Useful for integer division and modulus.
4622 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4623 * xor-long, add-double, sub-double, mul-double, div-double,
4626 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4628 /* binop vAA, vBB, vCC */
4629 FETCH(r0, 1) @ r0<- CCBB
4630 mov r9, rINST, lsr #8 @ r9<- AA
4631 and r2, r0, #255 @ r2<- BB
4632 mov r3, r0, lsr #8 @ r3<- CC
4633 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4634 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4635 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4636 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4637 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4639 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4640 beq common_errDivideByZero
4642 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4644 @ optional op; may set condition codes
4645 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4646 GET_INST_OPCODE(ip) @ extract opcode from rINST
4647 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4648 GOTO_OPCODE(ip) @ jump to next instruction
4649 /* 14-17 instructions */
4653 /* ------------------------------ */
4655 .L_OP_REM_LONG: /* 0x9f */
4656 /* File: armv5te/OP_REM_LONG.S */
4657 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4658 /* File: armv5te/binopWide.S */
4660 * Generic 64-bit binary operation. Provide an "instr" line that
4661 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4662 * This could be an ARM instruction or a function call. (If the result
4663 * comes back in a register other than r0, you can override "result".)
4665 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4666 * vCC (r1). Useful for integer division and modulus.
4668 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4669 * xor-long, add-double, sub-double, mul-double, div-double,
4672 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4674 /* binop vAA, vBB, vCC */
4675 FETCH(r0, 1) @ r0<- CCBB
4676 mov r9, rINST, lsr #8 @ r9<- AA
4677 and r2, r0, #255 @ r2<- BB
4678 mov r3, r0, lsr #8 @ r3<- CC
4679 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4680 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4681 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4682 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4683 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4685 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4686 beq common_errDivideByZero
4688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4690 @ optional op; may set condition codes
4691 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4692 GET_INST_OPCODE(ip) @ extract opcode from rINST
4693 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4694 GOTO_OPCODE(ip) @ jump to next instruction
4695 /* 14-17 instructions */
4699 /* ------------------------------ */
4701 .L_OP_AND_LONG: /* 0xa0 */
4702 /* File: armv5te/OP_AND_LONG.S */
4703 /* File: armv5te/binopWide.S */
4705 * Generic 64-bit binary operation. Provide an "instr" line that
4706 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4707 * This could be an ARM instruction or a function call. (If the result
4708 * comes back in a register other than r0, you can override "result".)
4710 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4711 * vCC (r1). Useful for integer division and modulus.
4713 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4714 * xor-long, add-double, sub-double, mul-double, div-double,
4717 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4719 /* binop vAA, vBB, vCC */
4720 FETCH(r0, 1) @ r0<- CCBB
4721 mov r9, rINST, lsr #8 @ r9<- AA
4722 and r2, r0, #255 @ r2<- BB
4723 mov r3, r0, lsr #8 @ r3<- CC
4724 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4725 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4726 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4727 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4728 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4730 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4731 beq common_errDivideByZero
4733 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4735 and r0, r0, r2 @ optional op; may set condition codes
4736 and r1, r1, r3 @ result<- op, r0-r3 changed
4737 GET_INST_OPCODE(ip) @ extract opcode from rINST
4738 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4739 GOTO_OPCODE(ip) @ jump to next instruction
4740 /* 14-17 instructions */
4744 /* ------------------------------ */
4746 .L_OP_OR_LONG: /* 0xa1 */
4747 /* File: armv5te/OP_OR_LONG.S */
4748 /* File: armv5te/binopWide.S */
4750 * Generic 64-bit binary operation. Provide an "instr" line that
4751 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4752 * This could be an ARM instruction or a function call. (If the result
4753 * comes back in a register other than r0, you can override "result".)
4755 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4756 * vCC (r1). Useful for integer division and modulus.
4758 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4759 * xor-long, add-double, sub-double, mul-double, div-double,
4762 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4764 /* binop vAA, vBB, vCC */
4765 FETCH(r0, 1) @ r0<- CCBB
4766 mov r9, rINST, lsr #8 @ r9<- AA
4767 and r2, r0, #255 @ r2<- BB
4768 mov r3, r0, lsr #8 @ r3<- CC
4769 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4770 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4771 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4772 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4773 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4775 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4776 beq common_errDivideByZero
4778 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4780 orr r0, r0, r2 @ optional op; may set condition codes
4781 orr r1, r1, r3 @ result<- op, r0-r3 changed
4782 GET_INST_OPCODE(ip) @ extract opcode from rINST
4783 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4784 GOTO_OPCODE(ip) @ jump to next instruction
4785 /* 14-17 instructions */
4789 /* ------------------------------ */
4791 .L_OP_XOR_LONG: /* 0xa2 */
4792 /* File: armv5te/OP_XOR_LONG.S */
4793 /* File: armv5te/binopWide.S */
4795 * Generic 64-bit binary operation. Provide an "instr" line that
4796 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4797 * This could be an ARM instruction or a function call. (If the result
4798 * comes back in a register other than r0, you can override "result".)
4800 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4801 * vCC (r1). Useful for integer division and modulus.
4803 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4804 * xor-long, add-double, sub-double, mul-double, div-double,
4807 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4809 /* binop vAA, vBB, vCC */
4810 FETCH(r0, 1) @ r0<- CCBB
4811 mov r9, rINST, lsr #8 @ r9<- AA
4812 and r2, r0, #255 @ r2<- BB
4813 mov r3, r0, lsr #8 @ r3<- CC
4814 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4815 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4816 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4817 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4818 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4820 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4821 beq common_errDivideByZero
4823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4825 eor r0, r0, r2 @ optional op; may set condition codes
4826 eor r1, r1, r3 @ result<- op, r0-r3 changed
4827 GET_INST_OPCODE(ip) @ extract opcode from rINST
4828 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4829 GOTO_OPCODE(ip) @ jump to next instruction
4830 /* 14-17 instructions */
4834 /* ------------------------------ */
4836 .L_OP_SHL_LONG: /* 0xa3 */
4837 /* File: armv5te/OP_SHL_LONG.S */
4839 * Long integer shift. This is different from the generic 32/64-bit
4840 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4841 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4842 * 6 bits of the shift distance.
4844 /* shl-long vAA, vBB, vCC */
4845 FETCH(r0, 1) @ r0<- CCBB
4846 mov r9, rINST, lsr #8 @ r9<- AA
4847 and r3, r0, #255 @ r3<- BB
4848 mov r0, r0, lsr #8 @ r0<- CC
4849 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4850 GET_VREG(r2, r0) @ r2<- vCC
4851 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4852 and r2, r2, #63 @ r2<- r2 & 0x3f
4853 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4855 mov r1, r1, asl r2 @ r1<- r1 << r2
4856 rsb r3, r2, #32 @ r3<- 32 - r2
4857 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
4858 subs ip, r2, #32 @ ip<- r2 - 32
4859 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
4860 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4861 b .LOP_SHL_LONG_finish
4863 /* ------------------------------ */
4865 .L_OP_SHR_LONG: /* 0xa4 */
4866 /* File: armv5te/OP_SHR_LONG.S */
4868 * Long integer shift. This is different from the generic 32/64-bit
4869 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4870 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4871 * 6 bits of the shift distance.
4873 /* shr-long vAA, vBB, vCC */
4874 FETCH(r0, 1) @ r0<- CCBB
4875 mov r9, rINST, lsr #8 @ r9<- AA
4876 and r3, r0, #255 @ r3<- BB
4877 mov r0, r0, lsr #8 @ r0<- CC
4878 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4879 GET_VREG(r2, r0) @ r2<- vCC
4880 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4881 and r2, r2, #63 @ r0<- r0 & 0x3f
4882 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4884 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4885 rsb r3, r2, #32 @ r3<- 32 - r2
4886 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4887 subs ip, r2, #32 @ ip<- r2 - 32
4888 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
4889 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4890 b .LOP_SHR_LONG_finish
4892 /* ------------------------------ */
4894 .L_OP_USHR_LONG: /* 0xa5 */
4895 /* File: armv5te/OP_USHR_LONG.S */
4897 * Long integer shift. This is different from the generic 32/64-bit
4898 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4899 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4900 * 6 bits of the shift distance.
4902 /* ushr-long vAA, vBB, vCC */
4903 FETCH(r0, 1) @ r0<- CCBB
4904 mov r9, rINST, lsr #8 @ r9<- AA
4905 and r3, r0, #255 @ r3<- BB
4906 mov r0, r0, lsr #8 @ r0<- CC
4907 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4908 GET_VREG(r2, r0) @ r2<- vCC
4909 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4910 and r2, r2, #63 @ r0<- r0 & 0x3f
4911 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4913 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4914 rsb r3, r2, #32 @ r3<- 32 - r2
4915 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4916 subs ip, r2, #32 @ ip<- r2 - 32
4917 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
4918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4919 b .LOP_USHR_LONG_finish
4921 /* ------------------------------ */
4923 .L_OP_ADD_FLOAT: /* 0xa6 */
4924 /* File: armv5te/OP_ADD_FLOAT.S */
4925 /* File: armv5te/binop.S */
4927 * Generic 32-bit binary operation. Provide an "instr" line that
4928 * specifies an instruction that performs "result = r0 op r1".
4929 * This could be an ARM instruction or a function call. (If the result
4930 * comes back in a register other than r0, you can override "result".)
4932 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4933 * vCC (r1). Useful for integer division and modulus. Note that we
4934 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4935 * handles it correctly.
4937 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4938 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4939 * mul-float, div-float, rem-float
4941 /* binop vAA, vBB, vCC */
4942 FETCH(r0, 1) @ r0<- CCBB
4943 mov r9, rINST, lsr #8 @ r9<- AA
4944 mov r3, r0, lsr #8 @ r3<- CC
4945 and r2, r0, #255 @ r2<- BB
4946 GET_VREG(r1, r3) @ r1<- vCC
4947 GET_VREG(r0, r2) @ r0<- vBB
4949 cmp r1, #0 @ is second operand zero?
4950 beq common_errDivideByZero
4953 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4954 @ optional op; may set condition codes
4955 bl __aeabi_fadd @ r0<- op, r0-r3 changed
4956 GET_INST_OPCODE(ip) @ extract opcode from rINST
4957 SET_VREG(r0, r9) @ vAA<- r0
4958 GOTO_OPCODE(ip) @ jump to next instruction
4959 /* 11-14 instructions */
4963 /* ------------------------------ */
4965 .L_OP_SUB_FLOAT: /* 0xa7 */
4966 /* File: armv5te/OP_SUB_FLOAT.S */
4967 /* File: armv5te/binop.S */
4969 * Generic 32-bit binary operation. Provide an "instr" line that
4970 * specifies an instruction that performs "result = r0 op r1".
4971 * This could be an ARM instruction or a function call. (If the result
4972 * comes back in a register other than r0, you can override "result".)
4974 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4975 * vCC (r1). Useful for integer division and modulus. Note that we
4976 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4977 * handles it correctly.
4979 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4980 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4981 * mul-float, div-float, rem-float
4983 /* binop vAA, vBB, vCC */
4984 FETCH(r0, 1) @ r0<- CCBB
4985 mov r9, rINST, lsr #8 @ r9<- AA
4986 mov r3, r0, lsr #8 @ r3<- CC
4987 and r2, r0, #255 @ r2<- BB
4988 GET_VREG(r1, r3) @ r1<- vCC
4989 GET_VREG(r0, r2) @ r0<- vBB
4991 cmp r1, #0 @ is second operand zero?
4992 beq common_errDivideByZero
4995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4996 @ optional op; may set condition codes
4997 bl __aeabi_fsub @ r0<- op, r0-r3 changed
4998 GET_INST_OPCODE(ip) @ extract opcode from rINST
4999 SET_VREG(r0, r9) @ vAA<- r0
5000 GOTO_OPCODE(ip) @ jump to next instruction
5001 /* 11-14 instructions */
5005 /* ------------------------------ */
5007 .L_OP_MUL_FLOAT: /* 0xa8 */
5008 /* File: armv5te/OP_MUL_FLOAT.S */
5009 /* File: armv5te/binop.S */
5011 * Generic 32-bit binary operation. Provide an "instr" line that
5012 * specifies an instruction that performs "result = r0 op r1".
5013 * This could be an ARM instruction or a function call. (If the result
5014 * comes back in a register other than r0, you can override "result".)
5016 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5017 * vCC (r1). Useful for integer division and modulus. Note that we
5018 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5019 * handles it correctly.
5021 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5022 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5023 * mul-float, div-float, rem-float
5025 /* binop vAA, vBB, vCC */
5026 FETCH(r0, 1) @ r0<- CCBB
5027 mov r9, rINST, lsr #8 @ r9<- AA
5028 mov r3, r0, lsr #8 @ r3<- CC
5029 and r2, r0, #255 @ r2<- BB
5030 GET_VREG(r1, r3) @ r1<- vCC
5031 GET_VREG(r0, r2) @ r0<- vBB
5033 cmp r1, #0 @ is second operand zero?
5034 beq common_errDivideByZero
5037 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5038 @ optional op; may set condition codes
5039 bl __aeabi_fmul @ r0<- op, r0-r3 changed
5040 GET_INST_OPCODE(ip) @ extract opcode from rINST
5041 SET_VREG(r0, r9) @ vAA<- r0
5042 GOTO_OPCODE(ip) @ jump to next instruction
5043 /* 11-14 instructions */
5047 /* ------------------------------ */
5049 .L_OP_DIV_FLOAT: /* 0xa9 */
5050 /* File: armv5te/OP_DIV_FLOAT.S */
5051 /* File: armv5te/binop.S */
5053 * Generic 32-bit binary operation. Provide an "instr" line that
5054 * specifies an instruction that performs "result = r0 op r1".
5055 * This could be an ARM instruction or a function call. (If the result
5056 * comes back in a register other than r0, you can override "result".)
5058 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5059 * vCC (r1). Useful for integer division and modulus. Note that we
5060 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5061 * handles it correctly.
5063 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5064 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5065 * mul-float, div-float, rem-float
5067 /* binop vAA, vBB, vCC */
5068 FETCH(r0, 1) @ r0<- CCBB
5069 mov r9, rINST, lsr #8 @ r9<- AA
5070 mov r3, r0, lsr #8 @ r3<- CC
5071 and r2, r0, #255 @ r2<- BB
5072 GET_VREG(r1, r3) @ r1<- vCC
5073 GET_VREG(r0, r2) @ r0<- vBB
5075 cmp r1, #0 @ is second operand zero?
5076 beq common_errDivideByZero
5079 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5080 @ optional op; may set condition codes
5081 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
5082 GET_INST_OPCODE(ip) @ extract opcode from rINST
5083 SET_VREG(r0, r9) @ vAA<- r0
5084 GOTO_OPCODE(ip) @ jump to next instruction
5085 /* 11-14 instructions */
5089 /* ------------------------------ */
5091 .L_OP_REM_FLOAT: /* 0xaa */
5092 /* File: armv5te/OP_REM_FLOAT.S */
5093 /* EABI doesn't define a float remainder function, but libm does */
5094 /* File: armv5te/binop.S */
5096 * Generic 32-bit binary operation. Provide an "instr" line that
5097 * specifies an instruction that performs "result = r0 op r1".
5098 * This could be an ARM instruction or a function call. (If the result
5099 * comes back in a register other than r0, you can override "result".)
5101 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5102 * vCC (r1). Useful for integer division and modulus. Note that we
5103 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5104 * handles it correctly.
5106 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5107 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5108 * mul-float, div-float, rem-float
5110 /* binop vAA, vBB, vCC */
5111 FETCH(r0, 1) @ r0<- CCBB
5112 mov r9, rINST, lsr #8 @ r9<- AA
5113 mov r3, r0, lsr #8 @ r3<- CC
5114 and r2, r0, #255 @ r2<- BB
5115 GET_VREG(r1, r3) @ r1<- vCC
5116 GET_VREG(r0, r2) @ r0<- vBB
5118 cmp r1, #0 @ is second operand zero?
5119 beq common_errDivideByZero
5122 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5123 @ optional op; may set condition codes
5124 bl fmodf @ r0<- op, r0-r3 changed
5125 GET_INST_OPCODE(ip) @ extract opcode from rINST
5126 SET_VREG(r0, r9) @ vAA<- r0
5127 GOTO_OPCODE(ip) @ jump to next instruction
5128 /* 11-14 instructions */
5132 /* ------------------------------ */
5134 .L_OP_ADD_DOUBLE: /* 0xab */
5135 /* File: armv5te/OP_ADD_DOUBLE.S */
5136 /* File: armv5te/binopWide.S */
5138 * Generic 64-bit binary operation. Provide an "instr" line that
5139 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5140 * This could be an ARM instruction or a function call. (If the result
5141 * comes back in a register other than r0, you can override "result".)
5143 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5144 * vCC (r1). Useful for integer division and modulus.
5146 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5147 * xor-long, add-double, sub-double, mul-double, div-double,
5150 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5152 /* binop vAA, vBB, vCC */
5153 FETCH(r0, 1) @ r0<- CCBB
5154 mov r9, rINST, lsr #8 @ r9<- AA
5155 and r2, r0, #255 @ r2<- BB
5156 mov r3, r0, lsr #8 @ r3<- CC
5157 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5158 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5159 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5160 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5161 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5163 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5164 beq common_errDivideByZero
5166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5168 @ optional op; may set condition codes
5169 bl __aeabi_dadd @ result<- op, r0-r3 changed
5170 GET_INST_OPCODE(ip) @ extract opcode from rINST
5171 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5172 GOTO_OPCODE(ip) @ jump to next instruction
5173 /* 14-17 instructions */
5177 /* ------------------------------ */
5179 .L_OP_SUB_DOUBLE: /* 0xac */
5180 /* File: armv5te/OP_SUB_DOUBLE.S */
5181 /* File: armv5te/binopWide.S */
5183 * Generic 64-bit binary operation. Provide an "instr" line that
5184 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5185 * This could be an ARM instruction or a function call. (If the result
5186 * comes back in a register other than r0, you can override "result".)
5188 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5189 * vCC (r1). Useful for integer division and modulus.
5191 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5192 * xor-long, add-double, sub-double, mul-double, div-double,
5195 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5197 /* binop vAA, vBB, vCC */
5198 FETCH(r0, 1) @ r0<- CCBB
5199 mov r9, rINST, lsr #8 @ r9<- AA
5200 and r2, r0, #255 @ r2<- BB
5201 mov r3, r0, lsr #8 @ r3<- CC
5202 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5203 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5204 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5205 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5206 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5208 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5209 beq common_errDivideByZero
5211 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5213 @ optional op; may set condition codes
5214 bl __aeabi_dsub @ result<- op, r0-r3 changed
5215 GET_INST_OPCODE(ip) @ extract opcode from rINST
5216 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5217 GOTO_OPCODE(ip) @ jump to next instruction
5218 /* 14-17 instructions */
5222 /* ------------------------------ */
5224 .L_OP_MUL_DOUBLE: /* 0xad */
5225 /* File: armv5te/OP_MUL_DOUBLE.S */
5226 /* File: armv5te/binopWide.S */
5228 * Generic 64-bit binary operation. Provide an "instr" line that
5229 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5230 * This could be an ARM instruction or a function call. (If the result
5231 * comes back in a register other than r0, you can override "result".)
5233 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5234 * vCC (r1). Useful for integer division and modulus.
5236 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5237 * xor-long, add-double, sub-double, mul-double, div-double,
5240 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5242 /* binop vAA, vBB, vCC */
5243 FETCH(r0, 1) @ r0<- CCBB
5244 mov r9, rINST, lsr #8 @ r9<- AA
5245 and r2, r0, #255 @ r2<- BB
5246 mov r3, r0, lsr #8 @ r3<- CC
5247 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5248 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5249 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5250 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5251 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5253 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5254 beq common_errDivideByZero
5256 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5258 @ optional op; may set condition codes
5259 bl __aeabi_dmul @ result<- op, r0-r3 changed
5260 GET_INST_OPCODE(ip) @ extract opcode from rINST
5261 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5262 GOTO_OPCODE(ip) @ jump to next instruction
5263 /* 14-17 instructions */
5267 /* ------------------------------ */
5269 .L_OP_DIV_DOUBLE: /* 0xae */
5270 /* File: armv5te/OP_DIV_DOUBLE.S */
5271 /* File: armv5te/binopWide.S */
5273 * Generic 64-bit binary operation. Provide an "instr" line that
5274 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5275 * This could be an ARM instruction or a function call. (If the result
5276 * comes back in a register other than r0, you can override "result".)
5278 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5279 * vCC (r1). Useful for integer division and modulus.
5281 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5282 * xor-long, add-double, sub-double, mul-double, div-double,
5285 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5287 /* binop vAA, vBB, vCC */
5288 FETCH(r0, 1) @ r0<- CCBB
5289 mov r9, rINST, lsr #8 @ r9<- AA
5290 and r2, r0, #255 @ r2<- BB
5291 mov r3, r0, lsr #8 @ r3<- CC
5292 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5293 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5294 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5295 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5296 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5298 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5299 beq common_errDivideByZero
5301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5303 @ optional op; may set condition codes
5304 bl __aeabi_ddiv @ result<- op, r0-r3 changed
5305 GET_INST_OPCODE(ip) @ extract opcode from rINST
5306 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5307 GOTO_OPCODE(ip) @ jump to next instruction
5308 /* 14-17 instructions */
5312 /* ------------------------------ */
5314 .L_OP_REM_DOUBLE: /* 0xaf */
5315 /* File: armv5te/OP_REM_DOUBLE.S */
5316 /* EABI doesn't define a double remainder function, but libm does */
5317 /* File: armv5te/binopWide.S */
5319 * Generic 64-bit binary operation. Provide an "instr" line that
5320 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5321 * This could be an ARM instruction or a function call. (If the result
5322 * comes back in a register other than r0, you can override "result".)
5324 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5325 * vCC (r1). Useful for integer division and modulus.
5327 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5328 * xor-long, add-double, sub-double, mul-double, div-double,
5331 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5333 /* binop vAA, vBB, vCC */
5334 FETCH(r0, 1) @ r0<- CCBB
5335 mov r9, rINST, lsr #8 @ r9<- AA
5336 and r2, r0, #255 @ r2<- BB
5337 mov r3, r0, lsr #8 @ r3<- CC
5338 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5339 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5340 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5341 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5342 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5344 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5345 beq common_errDivideByZero
5347 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5349 @ optional op; may set condition codes
5350 bl fmod @ result<- op, r0-r3 changed
5351 GET_INST_OPCODE(ip) @ extract opcode from rINST
5352 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5353 GOTO_OPCODE(ip) @ jump to next instruction
5354 /* 14-17 instructions */
5358 /* ------------------------------ */
5360 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5361 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5362 /* File: armv5te/binop2addr.S */
5364 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5365 * that specifies an instruction that performs "result = r0 op r1".
5366 * This could be an ARM instruction or a function call. (If the result
5367 * comes back in a register other than r0, you can override "result".)
5369 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5370 * vCC (r1). Useful for integer division and modulus.
5372 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5373 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5374 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5375 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5377 /* binop/2addr vA, vB */
5378 mov r9, rINST, lsr #8 @ r9<- A+
5379 mov r3, rINST, lsr #12 @ r3<- B
5381 GET_VREG(r0, r9) @ r0<- vA
5382 GET_VREG(r1, r3) @ r1<- vB
5384 cmp r1, #0 @ is second operand zero?
5385 beq common_errDivideByZero
5387 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5389 @ optional op; may set condition codes
5390 add r0, r0, r1 @ r0<- op, r0-r3 changed
5391 GET_INST_OPCODE(ip) @ extract opcode from rINST
5392 SET_VREG(r0, r9) @ vAA<- r0
5393 GOTO_OPCODE(ip) @ jump to next instruction
5394 /* 10-13 instructions */
5398 /* ------------------------------ */
5400 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5401 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5402 /* File: armv5te/binop2addr.S */
5404 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5405 * that specifies an instruction that performs "result = r0 op r1".
5406 * This could be an ARM instruction or a function call. (If the result
5407 * comes back in a register other than r0, you can override "result".)
5409 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5410 * vCC (r1). Useful for integer division and modulus.
5412 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5413 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5414 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5415 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5417 /* binop/2addr vA, vB */
5418 mov r9, rINST, lsr #8 @ r9<- A+
5419 mov r3, rINST, lsr #12 @ r3<- B
5421 GET_VREG(r0, r9) @ r0<- vA
5422 GET_VREG(r1, r3) @ r1<- vB
5424 cmp r1, #0 @ is second operand zero?
5425 beq common_errDivideByZero
5427 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5429 @ optional op; may set condition codes
5430 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5431 GET_INST_OPCODE(ip) @ extract opcode from rINST
5432 SET_VREG(r0, r9) @ vAA<- r0
5433 GOTO_OPCODE(ip) @ jump to next instruction
5434 /* 10-13 instructions */
5438 /* ------------------------------ */
5440 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5441 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5442 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5443 /* File: armv5te/binop2addr.S */
5445 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5446 * that specifies an instruction that performs "result = r0 op r1".
5447 * This could be an ARM instruction or a function call. (If the result
5448 * comes back in a register other than r0, you can override "result".)
5450 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5451 * vCC (r1). Useful for integer division and modulus.
5453 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5454 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5455 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5456 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5458 /* binop/2addr vA, vB */
5459 mov r9, rINST, lsr #8 @ r9<- A+
5460 mov r3, rINST, lsr #12 @ r3<- B
5462 GET_VREG(r0, r9) @ r0<- vA
5463 GET_VREG(r1, r3) @ r1<- vB
5465 cmp r1, #0 @ is second operand zero?
5466 beq common_errDivideByZero
5468 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5470 @ optional op; may set condition codes
5471 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5472 GET_INST_OPCODE(ip) @ extract opcode from rINST
5473 SET_VREG(r0, r9) @ vAA<- r0
5474 GOTO_OPCODE(ip) @ jump to next instruction
5475 /* 10-13 instructions */
5479 /* ------------------------------ */
5481 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5482 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5483 /* File: armv5te/binop2addr.S */
5485 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5486 * that specifies an instruction that performs "result = r0 op r1".
5487 * This could be an ARM instruction or a function call. (If the result
5488 * comes back in a register other than r0, you can override "result".)
5490 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5491 * vCC (r1). Useful for integer division and modulus.
5493 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5494 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5495 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5496 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5498 /* binop/2addr vA, vB */
5499 mov r9, rINST, lsr #8 @ r9<- A+
5500 mov r3, rINST, lsr #12 @ r3<- B
5502 GET_VREG(r0, r9) @ r0<- vA
5503 GET_VREG(r1, r3) @ r1<- vB
5505 cmp r1, #0 @ is second operand zero?
5506 beq common_errDivideByZero
5508 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5510 @ optional op; may set condition codes
5511 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5512 GET_INST_OPCODE(ip) @ extract opcode from rINST
5513 SET_VREG(r0, r9) @ vAA<- r0
5514 GOTO_OPCODE(ip) @ jump to next instruction
5515 /* 10-13 instructions */
5519 /* ------------------------------ */
5521 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5522 /* File: armv5te/OP_REM_INT_2ADDR.S */
5523 /* idivmod returns quotient in r0 and remainder in r1 */
5524 /* File: armv5te/binop2addr.S */
5526 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5527 * that specifies an instruction that performs "result = r0 op r1".
5528 * This could be an ARM instruction or a function call. (If the result
5529 * comes back in a register other than r0, you can override "result".)
5531 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5532 * vCC (r1). Useful for integer division and modulus.
5534 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5535 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5536 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5537 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5539 /* binop/2addr vA, vB */
5540 mov r9, rINST, lsr #8 @ r9<- A+
5541 mov r3, rINST, lsr #12 @ r3<- B
5543 GET_VREG(r0, r9) @ r0<- vA
5544 GET_VREG(r1, r3) @ r1<- vB
5546 cmp r1, #0 @ is second operand zero?
5547 beq common_errDivideByZero
5549 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5551 @ optional op; may set condition codes
5552 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5553 GET_INST_OPCODE(ip) @ extract opcode from rINST
5554 SET_VREG(r1, r9) @ vAA<- r1
5555 GOTO_OPCODE(ip) @ jump to next instruction
5556 /* 10-13 instructions */
5560 /* ------------------------------ */
5562 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5563 /* File: armv5te/OP_AND_INT_2ADDR.S */
5564 /* File: armv5te/binop2addr.S */
5566 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5567 * that specifies an instruction that performs "result = r0 op r1".
5568 * This could be an ARM instruction or a function call. (If the result
5569 * comes back in a register other than r0, you can override "result".)
5571 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572 * vCC (r1). Useful for integer division and modulus.
5574 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5579 /* binop/2addr vA, vB */
5580 mov r9, rINST, lsr #8 @ r9<- A+
5581 mov r3, rINST, lsr #12 @ r3<- B
5583 GET_VREG(r0, r9) @ r0<- vA
5584 GET_VREG(r1, r3) @ r1<- vB
5586 cmp r1, #0 @ is second operand zero?
5587 beq common_errDivideByZero
5589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5591 @ optional op; may set condition codes
5592 and r0, r0, r1 @ r0<- op, r0-r3 changed
5593 GET_INST_OPCODE(ip) @ extract opcode from rINST
5594 SET_VREG(r0, r9) @ vAA<- r0
5595 GOTO_OPCODE(ip) @ jump to next instruction
5596 /* 10-13 instructions */
5600 /* ------------------------------ */
5602 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5603 /* File: armv5te/OP_OR_INT_2ADDR.S */
5604 /* File: armv5te/binop2addr.S */
5606 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5607 * that specifies an instruction that performs "result = r0 op r1".
5608 * This could be an ARM instruction or a function call. (If the result
5609 * comes back in a register other than r0, you can override "result".)
5611 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5612 * vCC (r1). Useful for integer division and modulus.
5614 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5615 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5616 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5617 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5619 /* binop/2addr vA, vB */
5620 mov r9, rINST, lsr #8 @ r9<- A+
5621 mov r3, rINST, lsr #12 @ r3<- B
5623 GET_VREG(r0, r9) @ r0<- vA
5624 GET_VREG(r1, r3) @ r1<- vB
5626 cmp r1, #0 @ is second operand zero?
5627 beq common_errDivideByZero
5629 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5631 @ optional op; may set condition codes
5632 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5633 GET_INST_OPCODE(ip) @ extract opcode from rINST
5634 SET_VREG(r0, r9) @ vAA<- r0
5635 GOTO_OPCODE(ip) @ jump to next instruction
5636 /* 10-13 instructions */
5640 /* ------------------------------ */
5642 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5643 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5644 /* File: armv5te/binop2addr.S */
5646 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5647 * that specifies an instruction that performs "result = r0 op r1".
5648 * This could be an ARM instruction or a function call. (If the result
5649 * comes back in a register other than r0, you can override "result".)
5651 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5652 * vCC (r1). Useful for integer division and modulus.
5654 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5655 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5656 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5657 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5659 /* binop/2addr vA, vB */
5660 mov r9, rINST, lsr #8 @ r9<- A+
5661 mov r3, rINST, lsr #12 @ r3<- B
5663 GET_VREG(r0, r9) @ r0<- vA
5664 GET_VREG(r1, r3) @ r1<- vB
5666 cmp r1, #0 @ is second operand zero?
5667 beq common_errDivideByZero
5669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5671 @ optional op; may set condition codes
5672 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5673 GET_INST_OPCODE(ip) @ extract opcode from rINST
5674 SET_VREG(r0, r9) @ vAA<- r0
5675 GOTO_OPCODE(ip) @ jump to next instruction
5676 /* 10-13 instructions */
5680 /* ------------------------------ */
5682 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5683 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5684 /* File: armv5te/binop2addr.S */
5686 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5687 * that specifies an instruction that performs "result = r0 op r1".
5688 * This could be an ARM instruction or a function call. (If the result
5689 * comes back in a register other than r0, you can override "result".)
5691 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5692 * vCC (r1). Useful for integer division and modulus.
5694 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5695 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5696 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5697 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5699 /* binop/2addr vA, vB */
5700 mov r9, rINST, lsr #8 @ r9<- A+
5701 mov r3, rINST, lsr #12 @ r3<- B
5703 GET_VREG(r0, r9) @ r0<- vA
5704 GET_VREG(r1, r3) @ r1<- vB
5706 cmp r1, #0 @ is second operand zero?
5707 beq common_errDivideByZero
5709 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5711 and r1, r1, #31 @ optional op; may set condition codes
5712 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
5713 GET_INST_OPCODE(ip) @ extract opcode from rINST
5714 SET_VREG(r0, r9) @ vAA<- r0
5715 GOTO_OPCODE(ip) @ jump to next instruction
5716 /* 10-13 instructions */
5720 /* ------------------------------ */
5722 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5723 /* File: armv5te/OP_SHR_INT_2ADDR.S */
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(r0, r9) @ r0<- vA
5744 GET_VREG(r1, r3) @ r1<- vB
5746 cmp r1, #0 @ is second operand zero?
5747 beq common_errDivideByZero
5749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5751 and r1, r1, #31 @ optional op; may set condition codes
5752 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
5753 GET_INST_OPCODE(ip) @ extract opcode from rINST
5754 SET_VREG(r0, r9) @ vAA<- r0
5755 GOTO_OPCODE(ip) @ jump to next instruction
5756 /* 10-13 instructions */
5760 /* ------------------------------ */
5762 .L_OP_USHR_INT_2ADDR: /* 0xba */
5763 /* File: armv5te/OP_USHR_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(r0, r9) @ r0<- vA
5784 GET_VREG(r1, r3) @ r1<- vB
5786 cmp r1, #0 @ is second operand zero?
5787 beq common_errDivideByZero
5789 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5791 and r1, r1, #31 @ optional op; may set condition codes
5792 mov r0, r0, lsr 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_ADD_LONG_2ADDR: /* 0xbb */
5803 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5804 /* File: armv5te/binopWide2addr.S */
5806 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5807 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5815 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5816 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5819 /* binop/2addr vA, vB */
5820 mov r9, rINST, lsr #8 @ r9<- A+
5821 mov r1, rINST, lsr #12 @ r1<- B
5823 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5825 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5826 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5828 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5829 beq common_errDivideByZero
5831 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5833 adds r0, r0, r2 @ optional op; may set condition codes
5834 adc r1, r1, r3 @ result<- op, r0-r3 changed
5835 GET_INST_OPCODE(ip) @ extract opcode from rINST
5836 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5837 GOTO_OPCODE(ip) @ jump to next instruction
5838 /* 12-15 instructions */
5842 /* ------------------------------ */
5844 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5845 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
5846 /* File: armv5te/binopWide2addr.S */
5848 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5849 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5850 * This could be an ARM instruction or a function call. (If the result
5851 * comes back in a register other than r0, you can override "result".)
5853 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5854 * vCC (r1). Useful for integer division and modulus.
5856 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5857 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5858 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5861 /* binop/2addr vA, vB */
5862 mov r9, rINST, lsr #8 @ r9<- A+
5863 mov r1, rINST, lsr #12 @ r1<- B
5865 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5866 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5867 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5868 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5870 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5871 beq common_errDivideByZero
5873 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5875 subs r0, r0, r2 @ optional op; may set condition codes
5876 sbc r1, r1, r3 @ result<- op, r0-r3 changed
5877 GET_INST_OPCODE(ip) @ extract opcode from rINST
5878 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5879 GOTO_OPCODE(ip) @ jump to next instruction
5880 /* 12-15 instructions */
5884 /* ------------------------------ */
5886 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5887 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
5889 * Signed 64-bit integer multiply, "/2addr" version.
5891 * See OP_MUL_LONG for an explanation.
5893 * We get a little tight on registers, so to avoid looking up &fp[A]
5894 * again we stuff it into rINST.
5896 /* mul-long/2addr vA, vB */
5897 mov r9, rINST, lsr #8 @ r9<- A+
5898 mov r1, rINST, lsr #12 @ r1<- B
5900 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5901 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
5902 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5903 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
5904 mul ip, r2, r1 @ ip<- ZxW
5905 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
5906 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
5907 mov r0, rINST @ r0<- &fp[A] (free up rINST)
5908 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5909 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
5910 GET_INST_OPCODE(ip) @ extract opcode from rINST
5911 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
5912 GOTO_OPCODE(ip) @ jump to next instruction
5915 /* ------------------------------ */
5917 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5918 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
5919 /* File: armv5te/binopWide2addr.S */
5921 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5922 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5923 * This could be an ARM instruction or a function call. (If the result
5924 * comes back in a register other than r0, you can override "result".)
5926 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5927 * vCC (r1). Useful for integer division and modulus.
5929 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5930 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5931 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5934 /* binop/2addr vA, vB */
5935 mov r9, rINST, lsr #8 @ r9<- A+
5936 mov r1, rINST, lsr #12 @ r1<- B
5938 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5939 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5940 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5941 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5943 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5944 beq common_errDivideByZero
5946 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5948 @ optional op; may set condition codes
5949 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5950 GET_INST_OPCODE(ip) @ extract opcode from rINST
5951 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5952 GOTO_OPCODE(ip) @ jump to next instruction
5953 /* 12-15 instructions */
5957 /* ------------------------------ */
5959 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5960 /* File: armv5te/OP_REM_LONG_2ADDR.S */
5961 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5962 /* File: armv5te/binopWide2addr.S */
5964 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5965 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5966 * This could be an ARM instruction or a function call. (If the result
5967 * comes back in a register other than r0, you can override "result".)
5969 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5970 * vCC (r1). Useful for integer division and modulus.
5972 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5973 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5974 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5977 /* binop/2addr vA, vB */
5978 mov r9, rINST, lsr #8 @ r9<- A+
5979 mov r1, rINST, lsr #12 @ r1<- B
5981 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5982 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5983 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5984 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5986 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5987 beq common_errDivideByZero
5989 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5991 @ optional op; may set condition codes
5992 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5993 GET_INST_OPCODE(ip) @ extract opcode from rINST
5994 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
5995 GOTO_OPCODE(ip) @ jump to next instruction
5996 /* 12-15 instructions */
6000 /* ------------------------------ */
6002 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6003 /* File: armv5te/OP_AND_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 and r0, r0, r2 @ optional op; may set condition codes
6034 and 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_OR_LONG_2ADDR: /* 0xc1 */
6045 /* File: armv5te/OP_OR_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 orr r0, r0, r2 @ optional op; may set condition codes
6076 orr 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_XOR_LONG_2ADDR: /* 0xc2 */
6087 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6088 /* File: armv5te/binopWide2addr.S */
6090 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6091 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6092 * This could be an ARM instruction or a function call. (If the result
6093 * comes back in a register other than r0, you can override "result".)
6095 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6096 * vCC (r1). Useful for integer division and modulus.
6098 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6099 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6100 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6103 /* binop/2addr vA, vB */
6104 mov r9, rINST, lsr #8 @ r9<- A+
6105 mov r1, rINST, lsr #12 @ r1<- B
6107 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6108 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6109 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6110 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6112 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6113 beq common_errDivideByZero
6115 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6117 eor r0, r0, r2 @ optional op; may set condition codes
6118 eor r1, r1, r3 @ result<- op, r0-r3 changed
6119 GET_INST_OPCODE(ip) @ extract opcode from rINST
6120 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6121 GOTO_OPCODE(ip) @ jump to next instruction
6122 /* 12-15 instructions */
6126 /* ------------------------------ */
6128 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6129 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6131 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6132 * 32-bit shift distance.
6134 /* shl-long/2addr vA, vB */
6135 mov r9, rINST, lsr #8 @ r9<- A+
6136 mov r3, rINST, lsr #12 @ r3<- B
6138 GET_VREG(r2, r3) @ r2<- vB
6139 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6140 and r2, r2, #63 @ r2<- r2 & 0x3f
6141 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6143 mov r1, r1, asl r2 @ r1<- r1 << r2
6144 rsb r3, r2, #32 @ r3<- 32 - r2
6145 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6146 subs ip, r2, #32 @ ip<- r2 - 32
6147 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6148 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6149 mov r0, r0, asl r2 @ r0<- r0 << r2
6150 b .LOP_SHL_LONG_2ADDR_finish
6152 /* ------------------------------ */
6154 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6155 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6157 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6158 * 32-bit shift distance.
6160 /* shr-long/2addr vA, vB */
6161 mov r9, rINST, lsr #8 @ r9<- A+
6162 mov r3, rINST, lsr #12 @ r3<- B
6164 GET_VREG(r2, r3) @ r2<- vB
6165 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6166 and r2, r2, #63 @ r2<- r2 & 0x3f
6167 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6169 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6170 rsb r3, r2, #32 @ r3<- 32 - r2
6171 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6172 subs ip, r2, #32 @ ip<- r2 - 32
6173 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6174 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6175 mov r1, r1, asr r2 @ r1<- r1 >> r2
6176 b .LOP_SHR_LONG_2ADDR_finish
6178 /* ------------------------------ */
6180 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6181 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6183 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6184 * 32-bit shift distance.
6186 /* ushr-long/2addr vA, vB */
6187 mov r9, rINST, lsr #8 @ r9<- A+
6188 mov r3, rINST, lsr #12 @ r3<- B
6190 GET_VREG(r2, r3) @ r2<- vB
6191 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6192 and r2, r2, #63 @ r2<- r2 & 0x3f
6193 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6195 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6196 rsb r3, r2, #32 @ r3<- 32 - r2
6197 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6198 subs ip, r2, #32 @ ip<- r2 - 32
6199 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6200 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6201 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6202 b .LOP_USHR_LONG_2ADDR_finish
6204 /* ------------------------------ */
6206 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6207 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6208 /* File: armv5te/binop2addr.S */
6210 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6211 * that specifies an instruction that performs "result = r0 op r1".
6212 * This could be an ARM instruction or a function call. (If the result
6213 * comes back in a register other than r0, you can override "result".)
6215 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6216 * vCC (r1). Useful for integer division and modulus.
6218 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6219 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6220 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6221 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6223 /* binop/2addr vA, vB */
6224 mov r9, rINST, lsr #8 @ r9<- A+
6225 mov r3, rINST, lsr #12 @ r3<- B
6227 GET_VREG(r0, r9) @ r0<- vA
6228 GET_VREG(r1, r3) @ r1<- vB
6230 cmp r1, #0 @ is second operand zero?
6231 beq common_errDivideByZero
6233 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6235 @ optional op; may set condition codes
6236 bl __aeabi_fadd @ r0<- op, r0-r3 changed
6237 GET_INST_OPCODE(ip) @ extract opcode from rINST
6238 SET_VREG(r0, r9) @ vAA<- r0
6239 GOTO_OPCODE(ip) @ jump to next instruction
6240 /* 10-13 instructions */
6244 /* ------------------------------ */
6246 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6247 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6248 /* File: armv5te/binop2addr.S */
6250 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6251 * that specifies an instruction that performs "result = r0 op r1".
6252 * This could be an ARM instruction or a function call. (If the result
6253 * comes back in a register other than r0, you can override "result".)
6255 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6256 * vCC (r1). Useful for integer division and modulus.
6258 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6259 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6260 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6261 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6263 /* binop/2addr vA, vB */
6264 mov r9, rINST, lsr #8 @ r9<- A+
6265 mov r3, rINST, lsr #12 @ r3<- B
6267 GET_VREG(r0, r9) @ r0<- vA
6268 GET_VREG(r1, r3) @ r1<- vB
6270 cmp r1, #0 @ is second operand zero?
6271 beq common_errDivideByZero
6273 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6275 @ optional op; may set condition codes
6276 bl __aeabi_fsub @ r0<- op, r0-r3 changed
6277 GET_INST_OPCODE(ip) @ extract opcode from rINST
6278 SET_VREG(r0, r9) @ vAA<- r0
6279 GOTO_OPCODE(ip) @ jump to next instruction
6280 /* 10-13 instructions */
6284 /* ------------------------------ */
6286 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6287 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6288 /* File: armv5te/binop2addr.S */
6290 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6291 * that specifies an instruction that performs "result = r0 op r1".
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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6299 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6300 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6301 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6303 /* binop/2addr vA, vB */
6304 mov r9, rINST, lsr #8 @ r9<- A+
6305 mov r3, rINST, lsr #12 @ r3<- B
6307 GET_VREG(r0, r9) @ r0<- vA
6308 GET_VREG(r1, r3) @ r1<- vB
6310 cmp r1, #0 @ is second operand zero?
6311 beq common_errDivideByZero
6313 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6315 @ optional op; may set condition codes
6316 bl __aeabi_fmul @ r0<- op, r0-r3 changed
6317 GET_INST_OPCODE(ip) @ extract opcode from rINST
6318 SET_VREG(r0, r9) @ vAA<- r0
6319 GOTO_OPCODE(ip) @ jump to next instruction
6320 /* 10-13 instructions */
6324 /* ------------------------------ */
6326 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6327 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6328 /* File: armv5te/binop2addr.S */
6330 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6331 * that specifies an instruction that performs "result = r0 op r1".
6332 * This could be an ARM instruction or a function call. (If the result
6333 * comes back in a register other than r0, you can override "result".)
6335 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6336 * vCC (r1). Useful for integer division and modulus.
6338 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6339 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6340 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6341 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6343 /* binop/2addr vA, vB */
6344 mov r9, rINST, lsr #8 @ r9<- A+
6345 mov r3, rINST, lsr #12 @ r3<- B
6347 GET_VREG(r0, r9) @ r0<- vA
6348 GET_VREG(r1, r3) @ r1<- vB
6350 cmp r1, #0 @ is second operand zero?
6351 beq common_errDivideByZero
6353 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6355 @ optional op; may set condition codes
6356 bl __aeabi_fdiv @ r0<- op, r0-r3 changed
6357 GET_INST_OPCODE(ip) @ extract opcode from rINST
6358 SET_VREG(r0, r9) @ vAA<- r0
6359 GOTO_OPCODE(ip) @ jump to next instruction
6360 /* 10-13 instructions */
6364 /* ------------------------------ */
6366 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6367 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6368 /* EABI doesn't define a float remainder function, but libm does */
6369 /* File: armv5te/binop2addr.S */
6371 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6372 * that specifies an instruction that performs "result = r0 op r1".
6373 * This could be an ARM instruction or a function call. (If the result
6374 * comes back in a register other than r0, you can override "result".)
6376 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6377 * vCC (r1). Useful for integer division and modulus.
6379 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6380 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6381 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6382 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6384 /* binop/2addr vA, vB */
6385 mov r9, rINST, lsr #8 @ r9<- A+
6386 mov r3, rINST, lsr #12 @ r3<- B
6388 GET_VREG(r0, r9) @ r0<- vA
6389 GET_VREG(r1, r3) @ r1<- vB
6391 cmp r1, #0 @ is second operand zero?
6392 beq common_errDivideByZero
6394 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6396 @ optional op; may set condition codes
6397 bl fmodf @ r0<- op, r0-r3 changed
6398 GET_INST_OPCODE(ip) @ extract opcode from rINST
6399 SET_VREG(r0, r9) @ vAA<- r0
6400 GOTO_OPCODE(ip) @ jump to next instruction
6401 /* 10-13 instructions */
6405 /* ------------------------------ */
6407 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6408 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6409 /* File: armv5te/binopWide2addr.S */
6411 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6412 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6413 * This could be an ARM instruction or a function call. (If the result
6414 * comes back in a register other than r0, you can override "result".)
6416 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6417 * vCC (r1). Useful for integer division and modulus.
6419 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6420 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6421 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6424 /* binop/2addr vA, vB */
6425 mov r9, rINST, lsr #8 @ r9<- A+
6426 mov r1, rINST, lsr #12 @ r1<- B
6428 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6429 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6430 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6431 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6433 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6434 beq common_errDivideByZero
6436 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6438 @ optional op; may set condition codes
6439 bl __aeabi_dadd @ result<- op, r0-r3 changed
6440 GET_INST_OPCODE(ip) @ extract opcode from rINST
6441 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6442 GOTO_OPCODE(ip) @ jump to next instruction
6443 /* 12-15 instructions */
6447 /* ------------------------------ */
6449 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6450 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6451 /* File: armv5te/binopWide2addr.S */
6453 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6454 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6455 * This could be an ARM instruction or a function call. (If the result
6456 * comes back in a register other than r0, you can override "result".)
6458 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459 * vCC (r1). Useful for integer division and modulus.
6461 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6462 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6463 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6466 /* binop/2addr vA, vB */
6467 mov r9, rINST, lsr #8 @ r9<- A+
6468 mov r1, rINST, lsr #12 @ r1<- B
6470 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6471 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6472 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6473 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6475 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6476 beq common_errDivideByZero
6478 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6480 @ optional op; may set condition codes
6481 bl __aeabi_dsub @ result<- op, r0-r3 changed
6482 GET_INST_OPCODE(ip) @ extract opcode from rINST
6483 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6484 GOTO_OPCODE(ip) @ jump to next instruction
6485 /* 12-15 instructions */
6489 /* ------------------------------ */
6491 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6492 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6493 /* File: armv5te/binopWide2addr.S */
6495 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6496 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6497 * This could be an ARM instruction or a function call. (If the result
6498 * comes back in a register other than r0, you can override "result".)
6500 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6501 * vCC (r1). Useful for integer division and modulus.
6503 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6504 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6505 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6508 /* binop/2addr vA, vB */
6509 mov r9, rINST, lsr #8 @ r9<- A+
6510 mov r1, rINST, lsr #12 @ r1<- B
6512 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6513 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6514 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6515 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6517 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6518 beq common_errDivideByZero
6520 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6522 @ optional op; may set condition codes
6523 bl __aeabi_dmul @ result<- op, r0-r3 changed
6524 GET_INST_OPCODE(ip) @ extract opcode from rINST
6525 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6526 GOTO_OPCODE(ip) @ jump to next instruction
6527 /* 12-15 instructions */
6531 /* ------------------------------ */
6533 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6534 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6535 /* File: armv5te/binopWide2addr.S */
6537 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6538 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6539 * This could be an ARM instruction or a function call. (If the result
6540 * comes back in a register other than r0, you can override "result".)
6542 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6543 * vCC (r1). Useful for integer division and modulus.
6545 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6546 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6547 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6550 /* binop/2addr vA, vB */
6551 mov r9, rINST, lsr #8 @ r9<- A+
6552 mov r1, rINST, lsr #12 @ r1<- B
6554 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6555 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6556 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6557 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6559 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6560 beq common_errDivideByZero
6562 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6564 @ optional op; may set condition codes
6565 bl __aeabi_ddiv @ result<- op, r0-r3 changed
6566 GET_INST_OPCODE(ip) @ extract opcode from rINST
6567 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6568 GOTO_OPCODE(ip) @ jump to next instruction
6569 /* 12-15 instructions */
6573 /* ------------------------------ */
6575 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6576 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6577 /* EABI doesn't define a double remainder function, but libm does */
6578 /* File: armv5te/binopWide2addr.S */
6580 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6581 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6582 * This could be an ARM instruction or a function call. (If the result
6583 * comes back in a register other than r0, you can override "result".)
6585 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6586 * vCC (r1). Useful for integer division and modulus.
6588 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6589 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6590 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6593 /* binop/2addr vA, vB */
6594 mov r9, rINST, lsr #8 @ r9<- A+
6595 mov r1, rINST, lsr #12 @ r1<- B
6597 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6598 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6599 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6600 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6602 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6603 beq common_errDivideByZero
6605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6607 @ optional op; may set condition codes
6608 bl fmod @ result<- op, r0-r3 changed
6609 GET_INST_OPCODE(ip) @ extract opcode from rINST
6610 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6611 GOTO_OPCODE(ip) @ jump to next instruction
6612 /* 12-15 instructions */
6616 /* ------------------------------ */
6618 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6619 /* File: armv5te/OP_ADD_INT_LIT16.S */
6620 /* File: armv5te/binopLit16.S */
6622 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6623 * that specifies an instruction that performs "result = r0 op r1".
6624 * This could be an ARM instruction or a function call. (If the result
6625 * comes back in a register other than r0, you can override "result".)
6627 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6628 * vCC (r1). Useful for integer division and modulus.
6630 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6631 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6633 /* binop/lit16 vA, vB, #+CCCC */
6634 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6635 mov r2, rINST, lsr #12 @ r2<- B
6636 mov r9, rINST, lsr #8 @ r9<- A+
6637 GET_VREG(r0, r2) @ r0<- vB
6640 cmp r1, #0 @ is second operand zero?
6641 beq common_errDivideByZero
6643 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6645 add r0, r0, r1 @ r0<- op, r0-r3 changed
6646 GET_INST_OPCODE(ip) @ extract opcode from rINST
6647 SET_VREG(r0, r9) @ vAA<- r0
6648 GOTO_OPCODE(ip) @ jump to next instruction
6649 /* 10-13 instructions */
6653 /* ------------------------------ */
6655 .L_OP_RSUB_INT: /* 0xd1 */
6656 /* File: armv5te/OP_RSUB_INT.S */
6657 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6658 /* File: armv5te/binopLit16.S */
6660 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6661 * that specifies an instruction that performs "result = r0 op r1".
6662 * This could be an ARM instruction or a function call. (If the result
6663 * comes back in a register other than r0, you can override "result".)
6665 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6666 * vCC (r1). Useful for integer division and modulus.
6668 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6669 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6671 /* binop/lit16 vA, vB, #+CCCC */
6672 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6673 mov r2, rINST, lsr #12 @ r2<- B
6674 mov r9, rINST, lsr #8 @ r9<- A+
6675 GET_VREG(r0, r2) @ r0<- vB
6678 cmp r1, #0 @ is second operand zero?
6679 beq common_errDivideByZero
6681 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6683 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6684 GET_INST_OPCODE(ip) @ extract opcode from rINST
6685 SET_VREG(r0, r9) @ vAA<- r0
6686 GOTO_OPCODE(ip) @ jump to next instruction
6687 /* 10-13 instructions */
6691 /* ------------------------------ */
6693 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6694 /* File: armv5te/OP_MUL_INT_LIT16.S */
6695 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6696 /* File: armv5te/binopLit16.S */
6698 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6699 * that specifies an instruction that performs "result = r0 op r1".
6700 * This could be an ARM instruction or a function call. (If the result
6701 * comes back in a register other than r0, you can override "result".)
6703 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6704 * vCC (r1). Useful for integer division and modulus.
6706 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6707 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6709 /* binop/lit16 vA, vB, #+CCCC */
6710 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6711 mov r2, rINST, lsr #12 @ r2<- B
6712 mov r9, rINST, lsr #8 @ r9<- A+
6713 GET_VREG(r0, r2) @ r0<- vB
6716 cmp r1, #0 @ is second operand zero?
6717 beq common_errDivideByZero
6719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6721 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6722 GET_INST_OPCODE(ip) @ extract opcode from rINST
6723 SET_VREG(r0, r9) @ vAA<- r0
6724 GOTO_OPCODE(ip) @ jump to next instruction
6725 /* 10-13 instructions */
6729 /* ------------------------------ */
6731 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6732 /* File: armv5te/OP_DIV_INT_LIT16.S */
6733 /* File: armv5te/binopLit16.S */
6735 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6736 * that specifies an instruction that performs "result = r0 op r1".
6737 * This could be an ARM instruction or a function call. (If the result
6738 * comes back in a register other than r0, you can override "result".)
6740 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6741 * vCC (r1). Useful for integer division and modulus.
6743 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6744 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6746 /* binop/lit16 vA, vB, #+CCCC */
6747 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6748 mov r2, rINST, lsr #12 @ r2<- B
6749 mov r9, rINST, lsr #8 @ r9<- A+
6750 GET_VREG(r0, r2) @ r0<- vB
6753 cmp r1, #0 @ is second operand zero?
6754 beq common_errDivideByZero
6756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6758 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6759 GET_INST_OPCODE(ip) @ extract opcode from rINST
6760 SET_VREG(r0, r9) @ vAA<- r0
6761 GOTO_OPCODE(ip) @ jump to next instruction
6762 /* 10-13 instructions */
6766 /* ------------------------------ */
6768 .L_OP_REM_INT_LIT16: /* 0xd4 */
6769 /* File: armv5te/OP_REM_INT_LIT16.S */
6770 /* idivmod returns quotient in r0 and remainder in r1 */
6771 /* File: armv5te/binopLit16.S */
6773 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6774 * that specifies an instruction that performs "result = r0 op r1".
6775 * This could be an ARM instruction or a function call. (If the result
6776 * comes back in a register other than r0, you can override "result".)
6778 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6779 * vCC (r1). Useful for integer division and modulus.
6781 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6782 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6784 /* binop/lit16 vA, vB, #+CCCC */
6785 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6786 mov r2, rINST, lsr #12 @ r2<- B
6787 mov r9, rINST, lsr #8 @ r9<- A+
6788 GET_VREG(r0, r2) @ r0<- vB
6791 cmp r1, #0 @ is second operand zero?
6792 beq common_errDivideByZero
6794 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6796 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6797 GET_INST_OPCODE(ip) @ extract opcode from rINST
6798 SET_VREG(r1, r9) @ vAA<- r1
6799 GOTO_OPCODE(ip) @ jump to next instruction
6800 /* 10-13 instructions */
6804 /* ------------------------------ */
6806 .L_OP_AND_INT_LIT16: /* 0xd5 */
6807 /* File: armv5te/OP_AND_INT_LIT16.S */
6808 /* File: armv5te/binopLit16.S */
6810 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6811 * that specifies an instruction that performs "result = r0 op r1".
6812 * This could be an ARM instruction or a function call. (If the result
6813 * comes back in a register other than r0, you can override "result".)
6815 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6816 * vCC (r1). Useful for integer division and modulus.
6818 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6819 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6821 /* binop/lit16 vA, vB, #+CCCC */
6822 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6823 mov r2, rINST, lsr #12 @ r2<- B
6824 mov r9, rINST, lsr #8 @ r9<- A+
6825 GET_VREG(r0, r2) @ r0<- vB
6828 cmp r1, #0 @ is second operand zero?
6829 beq common_errDivideByZero
6831 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6833 and r0, r0, r1 @ r0<- op, r0-r3 changed
6834 GET_INST_OPCODE(ip) @ extract opcode from rINST
6835 SET_VREG(r0, r9) @ vAA<- r0
6836 GOTO_OPCODE(ip) @ jump to next instruction
6837 /* 10-13 instructions */
6841 /* ------------------------------ */
6843 .L_OP_OR_INT_LIT16: /* 0xd6 */
6844 /* File: armv5te/OP_OR_INT_LIT16.S */
6845 /* File: armv5te/binopLit16.S */
6847 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6848 * that specifies an instruction that performs "result = r0 op r1".
6849 * This could be an ARM instruction or a function call. (If the result
6850 * comes back in a register other than r0, you can override "result".)
6852 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6853 * vCC (r1). Useful for integer division and modulus.
6855 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6856 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6858 /* binop/lit16 vA, vB, #+CCCC */
6859 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6860 mov r2, rINST, lsr #12 @ r2<- B
6861 mov r9, rINST, lsr #8 @ r9<- A+
6862 GET_VREG(r0, r2) @ r0<- vB
6865 cmp r1, #0 @ is second operand zero?
6866 beq common_errDivideByZero
6868 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6870 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6871 GET_INST_OPCODE(ip) @ extract opcode from rINST
6872 SET_VREG(r0, r9) @ vAA<- r0
6873 GOTO_OPCODE(ip) @ jump to next instruction
6874 /* 10-13 instructions */
6878 /* ------------------------------ */
6880 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6881 /* File: armv5te/OP_XOR_INT_LIT16.S */
6882 /* File: armv5te/binopLit16.S */
6884 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6885 * that specifies an instruction that performs "result = r0 op r1".
6886 * This could be an ARM instruction or a function call. (If the result
6887 * comes back in a register other than r0, you can override "result".)
6889 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6890 * vCC (r1). Useful for integer division and modulus.
6892 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6893 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6895 /* binop/lit16 vA, vB, #+CCCC */
6896 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6897 mov r2, rINST, lsr #12 @ r2<- B
6898 mov r9, rINST, lsr #8 @ r9<- A+
6899 GET_VREG(r0, r2) @ r0<- vB
6902 cmp r1, #0 @ is second operand zero?
6903 beq common_errDivideByZero
6905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6907 eor r0, r0, r1 @ r0<- op, r0-r3 changed
6908 GET_INST_OPCODE(ip) @ extract opcode from rINST
6909 SET_VREG(r0, r9) @ vAA<- r0
6910 GOTO_OPCODE(ip) @ jump to next instruction
6911 /* 10-13 instructions */
6915 /* ------------------------------ */
6917 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6918 /* File: armv5te/OP_ADD_INT_LIT8.S */
6919 /* File: armv5te/binopLit8.S */
6921 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6922 * that specifies an instruction that performs "result = r0 op r1".
6923 * This could be an ARM instruction or a function call. (If the result
6924 * comes back in a register other than r0, you can override "result".)
6926 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6927 * vCC (r1). Useful for integer division and modulus.
6929 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6930 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6931 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6933 /* binop/lit8 vAA, vBB, #+CC */
6934 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6935 mov r9, rINST, lsr #8 @ r9<- AA
6936 and r2, r3, #255 @ r2<- BB
6937 GET_VREG(r0, r2) @ r0<- vBB
6938 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6940 @cmp r1, #0 @ is second operand zero?
6941 beq common_errDivideByZero
6943 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6945 @ optional op; may set condition codes
6946 add r0, r0, r1 @ r0<- op, r0-r3 changed
6947 GET_INST_OPCODE(ip) @ extract opcode from rINST
6948 SET_VREG(r0, r9) @ vAA<- r0
6949 GOTO_OPCODE(ip) @ jump to next instruction
6950 /* 10-12 instructions */
6954 /* ------------------------------ */
6956 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6957 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6958 /* File: armv5te/binopLit8.S */
6960 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6961 * that specifies an instruction that performs "result = r0 op r1".
6962 * This could be an ARM instruction or a function call. (If the result
6963 * comes back in a register other than r0, you can override "result".)
6965 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6966 * vCC (r1). Useful for integer division and modulus.
6968 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6969 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6970 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6972 /* binop/lit8 vAA, vBB, #+CC */
6973 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6974 mov r9, rINST, lsr #8 @ r9<- AA
6975 and r2, r3, #255 @ r2<- BB
6976 GET_VREG(r0, r2) @ r0<- vBB
6977 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6979 @cmp r1, #0 @ is second operand zero?
6980 beq common_errDivideByZero
6982 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6984 @ optional op; may set condition codes
6985 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6986 GET_INST_OPCODE(ip) @ extract opcode from rINST
6987 SET_VREG(r0, r9) @ vAA<- r0
6988 GOTO_OPCODE(ip) @ jump to next instruction
6989 /* 10-12 instructions */
6993 /* ------------------------------ */
6995 .L_OP_MUL_INT_LIT8: /* 0xda */
6996 /* File: armv5te/OP_MUL_INT_LIT8.S */
6997 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6998 /* File: armv5te/binopLit8.S */
7000 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7001 * that specifies an instruction that performs "result = r0 op r1".
7002 * This could be an ARM instruction or a function call. (If the result
7003 * comes back in a register other than r0, you can override "result".)
7005 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7006 * vCC (r1). Useful for integer division and modulus.
7008 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7009 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7010 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7012 /* binop/lit8 vAA, vBB, #+CC */
7013 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7014 mov r9, rINST, lsr #8 @ r9<- AA
7015 and r2, r3, #255 @ r2<- BB
7016 GET_VREG(r0, r2) @ r0<- vBB
7017 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7019 @cmp r1, #0 @ is second operand zero?
7020 beq common_errDivideByZero
7022 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7024 @ optional op; may set condition codes
7025 mul r0, r1, r0 @ r0<- op, r0-r3 changed
7026 GET_INST_OPCODE(ip) @ extract opcode from rINST
7027 SET_VREG(r0, r9) @ vAA<- r0
7028 GOTO_OPCODE(ip) @ jump to next instruction
7029 /* 10-12 instructions */
7033 /* ------------------------------ */
7035 .L_OP_DIV_INT_LIT8: /* 0xdb */
7036 /* File: armv5te/OP_DIV_INT_LIT8.S */
7037 /* File: armv5te/binopLit8.S */
7039 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7040 * that specifies an instruction that performs "result = r0 op r1".
7041 * This could be an ARM instruction or a function call. (If the result
7042 * comes back in a register other than r0, you can override "result".)
7044 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7045 * vCC (r1). Useful for integer division and modulus.
7047 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7048 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7049 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7051 /* binop/lit8 vAA, vBB, #+CC */
7052 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7053 mov r9, rINST, lsr #8 @ r9<- AA
7054 and r2, r3, #255 @ r2<- BB
7055 GET_VREG(r0, r2) @ r0<- vBB
7056 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7058 @cmp r1, #0 @ is second operand zero?
7059 beq common_errDivideByZero
7061 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7063 @ optional op; may set condition codes
7064 bl __aeabi_idiv @ r0<- op, r0-r3 changed
7065 GET_INST_OPCODE(ip) @ extract opcode from rINST
7066 SET_VREG(r0, r9) @ vAA<- r0
7067 GOTO_OPCODE(ip) @ jump to next instruction
7068 /* 10-12 instructions */
7072 /* ------------------------------ */
7074 .L_OP_REM_INT_LIT8: /* 0xdc */
7075 /* File: armv5te/OP_REM_INT_LIT8.S */
7076 /* idivmod returns quotient in r0 and remainder in r1 */
7077 /* File: armv5te/binopLit8.S */
7079 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7080 * that specifies an instruction that performs "result = r0 op r1".
7081 * This could be an ARM instruction or a function call. (If the result
7082 * comes back in a register other than r0, you can override "result".)
7084 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7085 * vCC (r1). Useful for integer division and modulus.
7087 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7088 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7089 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7091 /* binop/lit8 vAA, vBB, #+CC */
7092 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7093 mov r9, rINST, lsr #8 @ r9<- AA
7094 and r2, r3, #255 @ r2<- BB
7095 GET_VREG(r0, r2) @ r0<- vBB
7096 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7098 @cmp r1, #0 @ is second operand zero?
7099 beq common_errDivideByZero
7101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7103 @ optional op; may set condition codes
7104 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
7105 GET_INST_OPCODE(ip) @ extract opcode from rINST
7106 SET_VREG(r1, r9) @ vAA<- r1
7107 GOTO_OPCODE(ip) @ jump to next instruction
7108 /* 10-12 instructions */
7112 /* ------------------------------ */
7114 .L_OP_AND_INT_LIT8: /* 0xdd */
7115 /* File: armv5te/OP_AND_INT_LIT8.S */
7116 /* File: armv5te/binopLit8.S */
7118 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7119 * that specifies an instruction that performs "result = r0 op r1".
7120 * This could be an ARM instruction or a function call. (If the result
7121 * comes back in a register other than r0, you can override "result".)
7123 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7124 * vCC (r1). Useful for integer division and modulus.
7126 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7127 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7128 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7130 /* binop/lit8 vAA, vBB, #+CC */
7131 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7132 mov r9, rINST, lsr #8 @ r9<- AA
7133 and r2, r3, #255 @ r2<- BB
7134 GET_VREG(r0, r2) @ r0<- vBB
7135 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7137 @cmp r1, #0 @ is second operand zero?
7138 beq common_errDivideByZero
7140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7142 @ optional op; may set condition codes
7143 and r0, r0, r1 @ r0<- op, r0-r3 changed
7144 GET_INST_OPCODE(ip) @ extract opcode from rINST
7145 SET_VREG(r0, r9) @ vAA<- r0
7146 GOTO_OPCODE(ip) @ jump to next instruction
7147 /* 10-12 instructions */
7151 /* ------------------------------ */
7153 .L_OP_OR_INT_LIT8: /* 0xde */
7154 /* File: armv5te/OP_OR_INT_LIT8.S */
7155 /* File: armv5te/binopLit8.S */
7157 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7158 * that specifies an instruction that performs "result = r0 op r1".
7159 * This could be an ARM instruction or a function call. (If the result
7160 * comes back in a register other than r0, you can override "result".)
7162 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7163 * vCC (r1). Useful for integer division and modulus.
7165 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7166 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7167 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7169 /* binop/lit8 vAA, vBB, #+CC */
7170 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7171 mov r9, rINST, lsr #8 @ r9<- AA
7172 and r2, r3, #255 @ r2<- BB
7173 GET_VREG(r0, r2) @ r0<- vBB
7174 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7176 @cmp r1, #0 @ is second operand zero?
7177 beq common_errDivideByZero
7179 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7181 @ optional op; may set condition codes
7182 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7183 GET_INST_OPCODE(ip) @ extract opcode from rINST
7184 SET_VREG(r0, r9) @ vAA<- r0
7185 GOTO_OPCODE(ip) @ jump to next instruction
7186 /* 10-12 instructions */
7190 /* ------------------------------ */
7192 .L_OP_XOR_INT_LIT8: /* 0xdf */
7193 /* File: armv5te/OP_XOR_INT_LIT8.S */
7194 /* File: armv5te/binopLit8.S */
7196 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7197 * that specifies an instruction that performs "result = r0 op r1".
7198 * This could be an ARM instruction or a function call. (If the result
7199 * comes back in a register other than r0, you can override "result".)
7201 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7202 * vCC (r1). Useful for integer division and modulus.
7204 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7205 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7206 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7208 /* binop/lit8 vAA, vBB, #+CC */
7209 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7210 mov r9, rINST, lsr #8 @ r9<- AA
7211 and r2, r3, #255 @ r2<- BB
7212 GET_VREG(r0, r2) @ r0<- vBB
7213 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7215 @cmp r1, #0 @ is second operand zero?
7216 beq common_errDivideByZero
7218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7220 @ optional op; may set condition codes
7221 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7222 GET_INST_OPCODE(ip) @ extract opcode from rINST
7223 SET_VREG(r0, r9) @ vAA<- r0
7224 GOTO_OPCODE(ip) @ jump to next instruction
7225 /* 10-12 instructions */
7229 /* ------------------------------ */
7231 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7232 /* File: armv5te/OP_SHL_INT_LIT8.S */
7233 /* File: armv5te/binopLit8.S */
7235 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7236 * that specifies an instruction that performs "result = r0 op r1".
7237 * This could be an ARM instruction or a function call. (If the result
7238 * comes back in a register other than r0, you can override "result".)
7240 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7241 * vCC (r1). Useful for integer division and modulus.
7243 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7244 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7245 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7247 /* binop/lit8 vAA, vBB, #+CC */
7248 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7249 mov r9, rINST, lsr #8 @ r9<- AA
7250 and r2, r3, #255 @ r2<- BB
7251 GET_VREG(r0, r2) @ r0<- vBB
7252 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7254 @cmp r1, #0 @ is second operand zero?
7255 beq common_errDivideByZero
7257 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7259 and r1, r1, #31 @ optional op; may set condition codes
7260 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7261 GET_INST_OPCODE(ip) @ extract opcode from rINST
7262 SET_VREG(r0, r9) @ vAA<- r0
7263 GOTO_OPCODE(ip) @ jump to next instruction
7264 /* 10-12 instructions */
7268 /* ------------------------------ */
7270 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7271 /* File: armv5te/OP_SHR_INT_LIT8.S */
7272 /* File: armv5te/binopLit8.S */
7274 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7275 * that specifies an instruction that performs "result = r0 op r1".
7276 * This could be an ARM instruction or a function call. (If the result
7277 * comes back in a register other than r0, you can override "result".)
7279 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7280 * vCC (r1). Useful for integer division and modulus.
7282 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7283 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7284 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7286 /* binop/lit8 vAA, vBB, #+CC */
7287 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7288 mov r9, rINST, lsr #8 @ r9<- AA
7289 and r2, r3, #255 @ r2<- BB
7290 GET_VREG(r0, r2) @ r0<- vBB
7291 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7293 @cmp r1, #0 @ is second operand zero?
7294 beq common_errDivideByZero
7296 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7298 and r1, r1, #31 @ optional op; may set condition codes
7299 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7300 GET_INST_OPCODE(ip) @ extract opcode from rINST
7301 SET_VREG(r0, r9) @ vAA<- r0
7302 GOTO_OPCODE(ip) @ jump to next instruction
7303 /* 10-12 instructions */
7307 /* ------------------------------ */
7309 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7310 /* File: armv5te/OP_USHR_INT_LIT8.S */
7311 /* File: armv5te/binopLit8.S */
7313 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7314 * that specifies an instruction that performs "result = r0 op r1".
7315 * This could be an ARM instruction or a function call. (If the result
7316 * comes back in a register other than r0, you can override "result".)
7318 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7319 * vCC (r1). Useful for integer division and modulus.
7321 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7322 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7323 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7325 /* binop/lit8 vAA, vBB, #+CC */
7326 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7327 mov r9, rINST, lsr #8 @ r9<- AA
7328 and r2, r3, #255 @ r2<- BB
7329 GET_VREG(r0, r2) @ r0<- vBB
7330 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7332 @cmp r1, #0 @ is second operand zero?
7333 beq common_errDivideByZero
7335 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7337 and r1, r1, #31 @ optional op; may set condition codes
7338 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7339 GET_INST_OPCODE(ip) @ extract opcode from rINST
7340 SET_VREG(r0, r9) @ vAA<- r0
7341 GOTO_OPCODE(ip) @ jump to next instruction
7342 /* 10-12 instructions */
7346 /* ------------------------------ */
7348 .L_OP_UNUSED_E3: /* 0xe3 */
7349 /* File: armv5te/OP_UNUSED_E3.S */
7350 /* File: armv5te/unused.S */
7355 /* ------------------------------ */
7357 .L_OP_UNUSED_E4: /* 0xe4 */
7358 /* File: armv5te/OP_UNUSED_E4.S */
7359 /* File: armv5te/unused.S */
7364 /* ------------------------------ */
7366 .L_OP_UNUSED_E5: /* 0xe5 */
7367 /* File: armv5te/OP_UNUSED_E5.S */
7368 /* File: armv5te/unused.S */
7373 /* ------------------------------ */
7375 .L_OP_UNUSED_E6: /* 0xe6 */
7376 /* File: armv5te/OP_UNUSED_E6.S */
7377 /* File: armv5te/unused.S */
7382 /* ------------------------------ */
7384 .L_OP_UNUSED_E7: /* 0xe7 */
7385 /* File: armv5te/OP_UNUSED_E7.S */
7386 /* File: armv5te/unused.S */
7391 /* ------------------------------ */
7393 .L_OP_UNUSED_E8: /* 0xe8 */
7394 /* File: armv5te/OP_UNUSED_E8.S */
7395 /* File: armv5te/unused.S */
7400 /* ------------------------------ */
7402 .L_OP_UNUSED_E9: /* 0xe9 */
7403 /* File: armv5te/OP_UNUSED_E9.S */
7404 /* File: armv5te/unused.S */
7409 /* ------------------------------ */
7411 .L_OP_UNUSED_EA: /* 0xea */
7412 /* File: armv5te/OP_UNUSED_EA.S */
7413 /* File: armv5te/unused.S */
7418 /* ------------------------------ */
7420 .L_OP_UNUSED_EB: /* 0xeb */
7421 /* File: armv5te/OP_UNUSED_EB.S */
7422 /* File: armv5te/unused.S */
7427 /* ------------------------------ */
7429 .L_OP_UNUSED_EC: /* 0xec */
7430 /* File: armv5te/OP_UNUSED_EC.S */
7431 /* File: armv5te/unused.S */
7436 /* ------------------------------ */
7438 .L_OP_UNUSED_ED: /* 0xed */
7439 /* File: armv5te/OP_UNUSED_ED.S */
7440 /* File: armv5te/unused.S */
7445 /* ------------------------------ */
7447 .L_OP_EXECUTE_INLINE: /* 0xee */
7448 /* File: armv5te/OP_EXECUTE_INLINE.S */
7450 * Execute a "native inline" instruction.
7453 * dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7455 * The first four args are in r0-r3, but the last two must be pushed
7458 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7459 FETCH(r10, 1) @ r10<- BBBB
7460 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7461 EXPORT_PC() @ can throw
7462 sub sp, sp, #8 @ make room for arg(s)
7463 mov r0, rINST, lsr #12 @ r0<- B
7464 str r1, [sp] @ push &glue->retval
7465 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7466 add sp, sp, #8 @ pop stack
7467 cmp r0, #0 @ test boolean result of inline
7468 beq common_exceptionThrown @ returned false, handle exception
7469 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7470 GET_INST_OPCODE(ip) @ extract opcode from rINST
7471 GOTO_OPCODE(ip) @ jump to next instruction
7473 /* ------------------------------ */
7475 .L_OP_UNUSED_EF: /* 0xef */
7476 /* File: armv5te/OP_UNUSED_EF.S */
7477 /* File: armv5te/unused.S */
7482 /* ------------------------------ */
7484 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7485 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7487 * invoke-direct-empty is a no-op in a "standard" interpreter.
7489 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7490 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7491 GOTO_OPCODE(ip) @ execute it
7493 /* ------------------------------ */
7495 .L_OP_UNUSED_F1: /* 0xf1 */
7496 /* File: armv5te/OP_UNUSED_F1.S */
7497 /* File: armv5te/unused.S */
7502 /* ------------------------------ */
7504 .L_OP_IGET_QUICK: /* 0xf2 */
7505 /* File: armv5te/OP_IGET_QUICK.S */
7506 /* For: iget-quick, iget-object-quick */
7507 /* op vA, vB, offset@CCCC */
7508 mov r2, rINST, lsr #12 @ r2<- B
7509 GET_VREG(r3, r2) @ r3<- object we're operating on
7510 FETCH(r1, 1) @ r1<- field byte offset
7511 cmp r3, #0 @ check object for null
7512 mov r2, rINST, lsr #8 @ r2<- A(+)
7513 beq common_errNullObject @ object was null
7514 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7515 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7517 GET_INST_OPCODE(ip) @ extract opcode from rINST
7518 SET_VREG(r0, r2) @ fp[A]<- r0
7519 GOTO_OPCODE(ip) @ jump to next instruction
7522 /* ------------------------------ */
7524 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7525 /* File: armv4/OP_IGET_WIDE_QUICK.S */
7526 /* iget-wide-quick vA, vB, offset@CCCC */
7527 mov r2, rINST, lsr #12 @ r2<- B
7528 GET_VREG(r3, r2) @ r3<- object we're operating on
7529 FETCH(r1, 1) @ r1<- field byte offset
7530 cmp r3, #0 @ check object for null
7531 mov r2, rINST, lsr #8 @ r2<- A(+)
7532 beq common_errNullObject @ object was null
7533 add r9, r3, r1 @ r9<- object + offset
7534 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64 bits, aligned)
7535 and r2, r2, #15 @ r2<- A
7536 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7537 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7538 GET_INST_OPCODE(ip) @ extract opcode from rINST
7539 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7540 GOTO_OPCODE(ip) @ jump to next instruction
7543 /* ------------------------------ */
7545 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7546 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7547 /* File: armv5te/OP_IGET_QUICK.S */
7548 /* For: iget-quick, iget-object-quick */
7549 /* op vA, vB, offset@CCCC */
7550 mov r2, rINST, lsr #12 @ r2<- B
7551 GET_VREG(r3, r2) @ r3<- object we're operating on
7552 FETCH(r1, 1) @ r1<- field byte offset
7553 cmp r3, #0 @ check object for null
7554 mov r2, rINST, lsr #8 @ r2<- A(+)
7555 beq common_errNullObject @ object was null
7556 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7557 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7559 GET_INST_OPCODE(ip) @ extract opcode from rINST
7560 SET_VREG(r0, r2) @ fp[A]<- r0
7561 GOTO_OPCODE(ip) @ jump to next instruction
7565 /* ------------------------------ */
7567 .L_OP_IPUT_QUICK: /* 0xf5 */
7568 /* File: armv5te/OP_IPUT_QUICK.S */
7569 /* For: iput-quick, iput-object-quick */
7570 /* op vA, vB, offset@CCCC */
7571 mov r2, rINST, lsr #12 @ r2<- B
7572 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7573 FETCH(r1, 1) @ r1<- field byte offset
7574 cmp r3, #0 @ check object for null
7575 mov r2, rINST, lsr #8 @ r2<- A(+)
7576 beq common_errNullObject @ object was null
7578 GET_VREG(r0, r2) @ r0<- fp[A]
7579 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7580 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7581 GET_INST_OPCODE(ip) @ extract opcode from rINST
7582 GOTO_OPCODE(ip) @ jump to next instruction
7585 /* ------------------------------ */
7587 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7588 /* File: armv4/OP_IPUT_WIDE_QUICK.S */
7589 /* iput-wide-quick vA, vB, offset@CCCC */
7590 mov r0, rINST, lsr #8 @ r0<- A(+)
7591 mov r1, rINST, lsr #12 @ r1<- B
7593 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7594 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7595 cmp r2, #0 @ check object for null
7596 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7597 beq common_errNullObject @ object was null
7598 FETCH(r3, 1) @ r3<- field byte offset
7599 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7600 add r2, r2, r3 @ r2<- object + byte offset
7601 stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
7602 GET_INST_OPCODE(ip) @ extract opcode from rINST
7603 GOTO_OPCODE(ip) @ jump to next instruction
7606 /* ------------------------------ */
7608 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7609 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7610 /* File: armv5te/OP_IPUT_QUICK.S */
7611 /* For: iput-quick, iput-object-quick */
7612 /* op vA, vB, offset@CCCC */
7613 mov r2, rINST, lsr #12 @ r2<- B
7614 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7615 FETCH(r1, 1) @ r1<- field byte offset
7616 cmp r3, #0 @ check object for null
7617 mov r2, rINST, lsr #8 @ r2<- A(+)
7618 beq common_errNullObject @ object was null
7620 GET_VREG(r0, r2) @ r0<- fp[A]
7621 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7622 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7623 GET_INST_OPCODE(ip) @ extract opcode from rINST
7624 GOTO_OPCODE(ip) @ jump to next instruction
7628 /* ------------------------------ */
7630 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7631 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7633 * Handle an optimized virtual method call.
7635 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7637 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7638 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7639 FETCH(r3, 2) @ r3<- FEDC or CCCC
7640 FETCH(r1, 1) @ r1<- BBBB
7642 and r3, r3, #15 @ r3<- C (or stays CCCC)
7644 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7645 cmp r2, #0 @ is "this" null?
7646 beq common_errNullObject @ null "this", throw exception
7647 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7648 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7649 EXPORT_PC() @ invoke must export
7650 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7651 bl common_invokeMethodNoRange @ continue on
7653 /* ------------------------------ */
7655 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7656 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7657 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7659 * Handle an optimized virtual method call.
7661 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7663 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7664 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7665 FETCH(r3, 2) @ r3<- FEDC or CCCC
7666 FETCH(r1, 1) @ r1<- BBBB
7668 and r3, r3, #15 @ r3<- C (or stays CCCC)
7670 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7671 cmp r2, #0 @ is "this" null?
7672 beq common_errNullObject @ null "this", throw exception
7673 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7674 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7675 EXPORT_PC() @ invoke must export
7676 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7677 bl common_invokeMethodRange @ continue on
7680 /* ------------------------------ */
7682 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7683 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7685 * Handle an optimized "super" method call.
7687 * for: [opt] invoke-super-quick, invoke-super-quick/range
7689 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7690 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7691 FETCH(r10, 2) @ r10<- GFED or CCCC
7692 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7694 and r10, r10, #15 @ r10<- D (or stays CCCC)
7696 FETCH(r1, 1) @ r1<- BBBB
7697 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7698 EXPORT_PC() @ must export for invoke
7699 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7700 GET_VREG(r3, r10) @ r3<- "this"
7701 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7702 cmp r3, #0 @ null "this" ref?
7703 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7704 beq common_errNullObject @ "this" is null, throw exception
7705 bl common_invokeMethodNoRange @ continue on
7708 /* ------------------------------ */
7710 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7711 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7712 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7714 * Handle an optimized "super" method call.
7716 * for: [opt] invoke-super-quick, invoke-super-quick/range
7718 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7719 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7720 FETCH(r10, 2) @ r10<- GFED or CCCC
7721 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7723 and r10, r10, #15 @ r10<- D (or stays CCCC)
7725 FETCH(r1, 1) @ r1<- BBBB
7726 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7727 EXPORT_PC() @ must export for invoke
7728 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7729 GET_VREG(r3, r10) @ r3<- "this"
7730 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7731 cmp r3, #0 @ null "this" ref?
7732 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7733 beq common_errNullObject @ "this" is null, throw exception
7734 bl common_invokeMethodRange @ continue on
7738 /* ------------------------------ */
7740 .L_OP_UNUSED_FC: /* 0xfc */
7741 /* File: armv5te/OP_UNUSED_FC.S */
7742 /* File: armv5te/unused.S */
7747 /* ------------------------------ */
7749 .L_OP_UNUSED_FD: /* 0xfd */
7750 /* File: armv5te/OP_UNUSED_FD.S */
7751 /* File: armv5te/unused.S */
7756 /* ------------------------------ */
7758 .L_OP_UNUSED_FE: /* 0xfe */
7759 /* File: armv5te/OP_UNUSED_FE.S */
7760 /* File: armv5te/unused.S */
7765 /* ------------------------------ */
7767 .L_OP_UNUSED_FF: /* 0xff */
7768 /* File: armv5te/OP_UNUSED_FF.S */
7769 /* File: armv5te/unused.S */
7776 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
7777 .global dvmAsmInstructionEnd
7778 dvmAsmInstructionEnd:
7781 * ===========================================================================
7782 * Sister implementations
7783 * ===========================================================================
7785 .global dvmAsmSisterStart
7786 .type dvmAsmSisterStart, %function
7791 /* continuation for OP_CONST_STRING */
7794 * Continuation if the String has not yet been resolved.
7795 * r1: BBBB (String ref)
7796 * r9: target register
7798 .LOP_CONST_STRING_resolve:
7800 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7801 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7802 bl dvmResolveString @ r0<- String reference
7803 cmp r0, #0 @ failed?
7804 beq common_exceptionThrown @ yup, handle the exception
7805 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7806 GET_INST_OPCODE(ip) @ extract opcode from rINST
7807 SET_VREG(r0, r9) @ vAA<- r0
7808 GOTO_OPCODE(ip) @ jump to next instruction
7811 /* continuation for OP_CONST_STRING_JUMBO */
7814 * Continuation if the String has not yet been resolved.
7815 * r1: BBBBBBBB (String ref)
7816 * r9: target register
7818 .LOP_CONST_STRING_JUMBO_resolve:
7820 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7821 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7822 bl dvmResolveString @ r0<- String reference
7823 cmp r0, #0 @ failed?
7824 beq common_exceptionThrown @ yup, handle the exception
7825 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7826 GET_INST_OPCODE(ip) @ extract opcode from rINST
7827 SET_VREG(r0, r9) @ vAA<- r0
7828 GOTO_OPCODE(ip) @ jump to next instruction
7831 /* continuation for OP_CONST_CLASS */
7834 * Continuation if the Class has not yet been resolved.
7835 * r1: BBBB (Class ref)
7836 * r9: target register
7838 .LOP_CONST_CLASS_resolve:
7840 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7841 mov r2, #1 @ r2<- true
7842 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7843 bl dvmResolveClass @ r0<- Class reference
7844 cmp r0, #0 @ failed?
7845 beq common_exceptionThrown @ yup, handle the exception
7846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7847 GET_INST_OPCODE(ip) @ extract opcode from rINST
7848 SET_VREG(r0, r9) @ vAA<- r0
7849 GOTO_OPCODE(ip) @ jump to next instruction
7852 /* continuation for OP_CHECK_CAST */
7855 * Trivial test failed, need to perform full check. This is common.
7856 * r0 holds obj->clazz
7857 * r1 holds class resolved from BBBB
7860 .LOP_CHECK_CAST_fullcheck:
7861 bl dvmInstanceofNonTrivial @ r0<- boolean result
7862 cmp r0, #0 @ failed?
7863 bne .LOP_CHECK_CAST_okay @ no, success
7865 @ A cast has failed. We need to throw a ClassCastException with the
7866 @ class of the object that failed to be cast.
7867 EXPORT_PC() @ about to throw
7868 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz
7869 ldr r0, .LstrClassCastExceptionPtr
7870 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7871 bl dvmThrowExceptionWithClassMessage
7872 b common_exceptionThrown
7875 * Resolution required. This is the least-likely path.
7880 .LOP_CHECK_CAST_resolve:
7881 EXPORT_PC() @ resolve() could throw
7882 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7883 mov r1, r2 @ r1<- BBBB
7884 mov r2, #0 @ r2<- false
7885 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7886 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7887 cmp r0, #0 @ got null?
7888 beq common_exceptionThrown @ yes, handle exception
7889 mov r1, r0 @ r1<- class resolved from BBB
7890 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
7891 b .LOP_CHECK_CAST_resolved @ pick up where we left off
7893 .LstrClassCastExceptionPtr:
7894 .word .LstrClassCastException
7897 /* continuation for OP_INSTANCE_OF */
7900 * Trivial test failed, need to perform full check. This is common.
7901 * r0 holds obj->clazz
7902 * r1 holds class resolved from BBBB
7905 .LOP_INSTANCE_OF_fullcheck:
7906 bl dvmInstanceofNonTrivial @ r0<- boolean result
7907 @ fall through to OP_INSTANCE_OF_store
7910 * r0 holds boolean result
7913 .LOP_INSTANCE_OF_store:
7914 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7915 SET_VREG(r0, r9) @ vA<- r0
7916 GET_INST_OPCODE(ip) @ extract opcode from rINST
7917 GOTO_OPCODE(ip) @ jump to next instruction
7920 * Trivial test succeeded, save and bail.
7923 .LOP_INSTANCE_OF_trivial:
7924 mov r0, #1 @ indicate success
7925 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7926 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7927 SET_VREG(r0, r9) @ vA<- r0
7928 GET_INST_OPCODE(ip) @ extract opcode from rINST
7929 GOTO_OPCODE(ip) @ jump to next instruction
7932 * Resolution required. This is the least-likely path.
7937 .LOP_INSTANCE_OF_resolve:
7938 EXPORT_PC() @ resolve() could throw
7939 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7940 mov r1, r3 @ r1<- BBBB
7941 mov r2, #1 @ r2<- true
7942 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7943 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7944 cmp r0, #0 @ got null?
7945 beq common_exceptionThrown @ yes, handle exception
7946 mov r1, r0 @ r1<- class resolved from BBB
7947 mov r3, rINST, lsr #12 @ r3<- B
7948 GET_VREG(r0, r3) @ r0<- vB (object)
7949 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
7950 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
7953 /* continuation for OP_NEW_INSTANCE */
7955 .balign 32 @ minimize cache lines
7956 .LOP_NEW_INSTANCE_finish: @ r0=class
7957 bl dvmAllocObject @ r0<- new object
7958 mov r3, rINST, lsr #8 @ r3<- AA
7959 cmp r0, #0 @ failed?
7960 beq common_exceptionThrown @ yes, handle the exception
7961 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7962 GET_INST_OPCODE(ip) @ extract opcode from rINST
7963 SET_VREG(r0, r3) @ vAA<- r0
7964 GOTO_OPCODE(ip) @ jump to next instruction
7967 * Class initialization required.
7969 * r0 holds class object
7971 .LOP_NEW_INSTANCE_needinit:
7972 mov r9, r0 @ save r0
7973 bl dvmInitClass @ initialize class
7974 cmp r0, #0 @ check boolean result
7975 mov r0, r9 @ restore r0
7976 bne .LOP_NEW_INSTANCE_initialized @ success, continue
7977 b common_exceptionThrown @ failed, deal with init exception
7980 * Resolution required. This is the least-likely path.
7984 .LOP_NEW_INSTANCE_resolve:
7985 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7986 mov r2, #0 @ r2<- false
7987 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7988 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7989 cmp r0, #0 @ got null?
7990 bne .LOP_NEW_INSTANCE_resolved @ no, continue
7991 b common_exceptionThrown @ yes, handle exception
7994 * We can't instantiate an abstract class or interface, so throw an
7995 * InstantiationError with the class descriptor as the message.
7997 * r0 holds class object
7999 .LOP_NEW_INSTANCE_abstract:
8000 ldr r1, [r0, #offClassObject_descriptor]
8001 ldr r0, .LstrInstantiationErrorPtr
8002 bl dvmThrowExceptionWithClassMessage
8003 b common_exceptionThrown
8005 .LstrInstantiationErrorPtr:
8006 .word .LstrInstantiationError
8009 /* continuation for OP_NEW_ARRAY */
8013 * Resolve class. (This is an uncommon case.)
8015 * r1 holds array length
8016 * r2 holds class ref CCCC
8018 .LOP_NEW_ARRAY_resolve:
8019 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8020 mov r9, r1 @ r9<- length (save)
8021 mov r1, r2 @ r1<- CCCC
8022 mov r2, #0 @ r2<- false
8023 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8024 bl dvmResolveClass @ r0<- call(clazz, ref)
8025 cmp r0, #0 @ got null?
8026 mov r1, r9 @ r1<- length (restore)
8027 beq common_exceptionThrown @ yes, handle exception
8028 @ fall through to OP_NEW_ARRAY_finish
8031 * Finish allocation.
8034 * r1 holds array length
8036 .LOP_NEW_ARRAY_finish:
8037 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
8038 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
8039 cmp r0, #0 @ failed?
8040 mov r2, rINST, lsr #8 @ r2<- A+
8041 beq common_exceptionThrown @ yes, handle the exception
8042 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8043 and r2, r2, #15 @ r2<- A
8044 GET_INST_OPCODE(ip) @ extract opcode from rINST
8045 SET_VREG(r0, r2) @ vA<- r0
8046 GOTO_OPCODE(ip) @ jump to next instruction
8049 /* continuation for OP_FILLED_NEW_ARRAY */
8053 * r0 holds array class
8054 * r10 holds AA or BA
8056 .LOP_FILLED_NEW_ARRAY_continue:
8057 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8058 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8059 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8061 mov r1, r10 @ r1<- AA (length)
8063 mov r1, r10, lsr #4 @ r1<- B (length)
8065 cmp r3, #'I' @ array of ints?
8066 cmpne r3, #'L' @ array of objects?
8067 cmpne r3, #'[' @ array of arrays?
8068 mov r9, r1 @ save length in r9
8069 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
8070 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8071 cmp r0, #0 @ null return?
8072 beq common_exceptionThrown @ alloc failed, handle exception
8074 FETCH(r1, 2) @ r1<- FEDC or CCCC
8075 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8076 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8077 subs r9, r9, #1 @ length--, check for neg
8078 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8079 bmi 2f @ was zero, bail
8081 @ copy values from registers into the array
8082 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8084 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8085 1: ldr r3, [r2], #4 @ r3<- *r2++
8086 subs r9, r9, #1 @ count--
8087 str r3, [r0], #4 @ *contents++ = vX
8091 cmp r9, #4 @ length was initially 5?
8092 and r2, r10, #15 @ r2<- A
8093 bne 1f @ <= 4 args, branch
8094 GET_VREG(r3, r2) @ r3<- vA
8095 sub r9, r9, #1 @ count--
8096 str r3, [r0, #16] @ contents[4] = vA
8097 1: and r2, r1, #15 @ r2<- F/E/D/C
8098 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8099 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8100 subs r9, r9, #1 @ count--
8101 str r3, [r0], #4 @ *contents++ = vX
8107 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8108 GOTO_OPCODE(ip) @ execute it
8111 * Throw an exception indicating that we have not implemented this
8112 * mode of filled-new-array.
8114 .LOP_FILLED_NEW_ARRAY_notimpl:
8115 ldr r0, .L_strInternalError
8116 ldr r1, .L_strFilledNewArrayNotImpl
8117 bl dvmThrowException
8118 b common_exceptionThrown
8120 .if (!0) @ define in one or the other, not both
8121 .L_strFilledNewArrayNotImpl:
8122 .word .LstrFilledNewArrayNotImpl
8123 .L_strInternalError:
8124 .word .LstrInternalError
8128 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8132 * r0 holds array class
8133 * r10 holds AA or BA
8135 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8136 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8137 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8138 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8140 mov r1, r10 @ r1<- AA (length)
8142 mov r1, r10, lsr #4 @ r1<- B (length)
8144 cmp r3, #'I' @ array of ints?
8145 cmpne r3, #'L' @ array of objects?
8146 cmpne r3, #'[' @ array of arrays?
8147 mov r9, r1 @ save length in r9
8148 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
8149 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8150 cmp r0, #0 @ null return?
8151 beq common_exceptionThrown @ alloc failed, handle exception
8153 FETCH(r1, 2) @ r1<- FEDC or CCCC
8154 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8155 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8156 subs r9, r9, #1 @ length--, check for neg
8157 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8158 bmi 2f @ was zero, bail
8160 @ copy values from registers into the array
8161 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8163 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
8164 1: ldr r3, [r2], #4 @ r3<- *r2++
8165 subs r9, r9, #1 @ count--
8166 str r3, [r0], #4 @ *contents++ = vX
8170 cmp r9, #4 @ length was initially 5?
8171 and r2, r10, #15 @ r2<- A
8172 bne 1f @ <= 4 args, branch
8173 GET_VREG(r3, r2) @ r3<- vA
8174 sub r9, r9, #1 @ count--
8175 str r3, [r0, #16] @ contents[4] = vA
8176 1: and r2, r1, #15 @ r2<- F/E/D/C
8177 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8178 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8179 subs r9, r9, #1 @ count--
8180 str r3, [r0], #4 @ *contents++ = vX
8186 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8187 GOTO_OPCODE(ip) @ execute it
8190 * Throw an exception indicating that we have not implemented this
8191 * mode of filled-new-array.
8193 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8194 ldr r0, .L_strInternalError
8195 ldr r1, .L_strFilledNewArrayNotImpl
8196 bl dvmThrowException
8197 b common_exceptionThrown
8199 .if (!1) @ define in one or the other, not both
8200 .L_strFilledNewArrayNotImpl:
8201 .word .LstrFilledNewArrayNotImpl
8202 .L_strInternalError:
8203 .word .LstrInternalError
8207 /* continuation for OP_CMPL_FLOAT */
8209 @ Test for NaN with a second comparison. EABI forbids testing bit
8210 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8211 @ make the library call.
8212 .LOP_CMPL_FLOAT_gt_or_nan:
8213 mov r1, r9 @ reverse order
8215 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8217 movcc r1, #1 @ (greater than) r1<- 1
8218 bcc .LOP_CMPL_FLOAT_finish
8219 mvn r1, #0 @ r1<- 1 or -1 for NaN
8220 b .LOP_CMPL_FLOAT_finish
8223 #if 0 /* "clasic" form */
8224 FETCH(r0, 1) @ r0<- CCBB
8225 and r2, r0, #255 @ r2<- BB
8226 mov r3, r0, lsr #8 @ r3<- CC
8227 GET_VREG(r9, r2) @ r9<- vBB
8228 GET_VREG(r10, r3) @ r10<- vCC
8229 mov r0, r9 @ r0<- vBB
8230 mov r1, r10 @ r1<- vCC
8231 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8233 movne r1, #0 @ yes, result is 0
8234 bne OP_CMPL_FLOAT_finish
8235 mov r0, r9 @ r0<- vBB
8236 mov r1, r10 @ r1<- vCC
8237 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8238 cmp r0, #0 @ less than?
8239 b OP_CMPL_FLOAT_continue
8242 OP_CMPL_FLOAT_continue:
8243 mvnne r1, #0 @ yes, result is -1
8244 bne OP_CMPL_FLOAT_finish
8245 mov r0, r9 @ r0<- vBB
8246 mov r1, r10 @ r1<- vCC
8247 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8248 cmp r0, #0 @ greater than?
8249 beq OP_CMPL_FLOAT_nan @ no, must be NaN
8250 mov r1, #1 @ yes, result is 1
8251 @ fall through to _finish
8253 OP_CMPL_FLOAT_finish:
8254 mov r3, rINST, lsr #8 @ r3<- AA
8255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8256 SET_VREG(r1, r3) @ vAA<- r1
8257 GET_INST_OPCODE(ip) @ extract opcode from rINST
8258 GOTO_OPCODE(ip) @ jump to next instruction
8261 * This is expected to be uncommon, so we double-branch (once to here,
8262 * again back to _finish).
8265 mvn r1, #0 @ r1<- 1 or -1 for NaN
8266 b OP_CMPL_FLOAT_finish
8271 /* continuation for OP_CMPG_FLOAT */
8273 @ Test for NaN with a second comparison. EABI forbids testing bit
8274 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8275 @ make the library call.
8276 .LOP_CMPG_FLOAT_gt_or_nan:
8277 mov r1, r9 @ reverse order
8279 bl __aeabi_cfcmple @ r0<- Z set if eq, C clear if <
8281 movcc r1, #1 @ (greater than) r1<- 1
8282 bcc .LOP_CMPG_FLOAT_finish
8283 mov r1, #1 @ r1<- 1 or -1 for NaN
8284 b .LOP_CMPG_FLOAT_finish
8287 #if 0 /* "clasic" form */
8288 FETCH(r0, 1) @ r0<- CCBB
8289 and r2, r0, #255 @ r2<- BB
8290 mov r3, r0, lsr #8 @ r3<- CC
8291 GET_VREG(r9, r2) @ r9<- vBB
8292 GET_VREG(r10, r3) @ r10<- vCC
8293 mov r0, r9 @ r0<- vBB
8294 mov r1, r10 @ r1<- vCC
8295 bl __aeabi_fcmpeq @ r0<- (vBB == vCC)
8297 movne r1, #0 @ yes, result is 0
8298 bne OP_CMPG_FLOAT_finish
8299 mov r0, r9 @ r0<- vBB
8300 mov r1, r10 @ r1<- vCC
8301 bl __aeabi_fcmplt @ r0<- (vBB < vCC)
8302 cmp r0, #0 @ less than?
8303 b OP_CMPG_FLOAT_continue
8306 OP_CMPG_FLOAT_continue:
8307 mvnne r1, #0 @ yes, result is -1
8308 bne OP_CMPG_FLOAT_finish
8309 mov r0, r9 @ r0<- vBB
8310 mov r1, r10 @ r1<- vCC
8311 bl __aeabi_fcmpgt @ r0<- (vBB > vCC)
8312 cmp r0, #0 @ greater than?
8313 beq OP_CMPG_FLOAT_nan @ no, must be NaN
8314 mov r1, #1 @ yes, result is 1
8315 @ fall through to _finish
8317 OP_CMPG_FLOAT_finish:
8318 mov r3, rINST, lsr #8 @ r3<- AA
8319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8320 SET_VREG(r1, r3) @ vAA<- r1
8321 GET_INST_OPCODE(ip) @ extract opcode from rINST
8322 GOTO_OPCODE(ip) @ jump to next instruction
8325 * This is expected to be uncommon, so we double-branch (once to here,
8326 * again back to _finish).
8329 mov r1, #1 @ r1<- 1 or -1 for NaN
8330 b OP_CMPG_FLOAT_finish
8335 /* continuation for OP_CMPL_DOUBLE */
8337 @ Test for NaN with a second comparison. EABI forbids testing bit
8338 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8339 @ make the library call.
8340 .LOP_CMPL_DOUBLE_gt_or_nan:
8341 ldmia r10, {r0-r1} @ reverse order
8343 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8345 movcc r1, #1 @ (greater than) r1<- 1
8346 bcc .LOP_CMPL_DOUBLE_finish
8347 mvn r1, #0 @ r1<- 1 or -1 for NaN
8348 b .LOP_CMPL_DOUBLE_finish
8351 /* continuation for OP_CMPG_DOUBLE */
8353 @ Test for NaN with a second comparison. EABI forbids testing bit
8354 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8355 @ make the library call.
8356 .LOP_CMPG_DOUBLE_gt_or_nan:
8357 ldmia r10, {r0-r1} @ reverse order
8359 bl __aeabi_cdcmple @ r0<- Z set if eq, C clear if <
8361 movcc r1, #1 @ (greater than) r1<- 1
8362 bcc .LOP_CMPG_DOUBLE_finish
8363 mov r1, #1 @ r1<- 1 or -1 for NaN
8364 b .LOP_CMPG_DOUBLE_finish
8367 /* continuation for OP_CMP_LONG */
8370 mvn r1, #0 @ r1<- -1
8371 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8372 @ instead, we just replicate the tail end.
8373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8374 SET_VREG(r1, r9) @ vAA<- r1
8375 GET_INST_OPCODE(ip) @ extract opcode from rINST
8376 GOTO_OPCODE(ip) @ jump to next instruction
8378 .LOP_CMP_LONG_greater:
8380 @ fall through to _finish
8382 .LOP_CMP_LONG_finish:
8383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8384 SET_VREG(r1, r9) @ vAA<- r1
8385 GET_INST_OPCODE(ip) @ extract opcode from rINST
8386 GOTO_OPCODE(ip) @ jump to next instruction
8389 /* continuation for OP_AGET_WIDE */
8391 .LOP_AGET_WIDE_finish:
8392 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8393 add r0, r0, #offArrayObject_contents
8394 ldmia r0, {r2-r3} @ r2/r3 <- vBB[vCC]
8395 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8396 GET_INST_OPCODE(ip) @ extract opcode from rINST
8397 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8398 GOTO_OPCODE(ip) @ jump to next instruction
8401 /* continuation for OP_APUT_WIDE */
8403 .LOP_APUT_WIDE_finish:
8404 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8405 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8406 GET_INST_OPCODE(ip) @ extract opcode from rINST
8407 add r0, #offArrayObject_contents
8408 stmia r0, {r2-r3} @ vBB[vCC] <- r2/r3
8409 GOTO_OPCODE(ip) @ jump to next instruction
8412 /* continuation for OP_APUT_OBJECT */
8415 * r1 = vBB (arrayObj)
8417 * r10 = offset into array (vBB + vCC * width)
8419 .LOP_APUT_OBJECT_finish:
8420 cmp r9, #0 @ storing null reference?
8421 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8422 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8423 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz
8424 bl dvmCanPutArrayElement @ test object type vs. array type
8426 beq common_errArrayStore @ no
8427 .LOP_APUT_OBJECT_skip_check:
8428 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8429 GET_INST_OPCODE(ip) @ extract opcode from rINST
8430 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8431 GOTO_OPCODE(ip) @ jump to next instruction
8434 /* continuation for OP_IGET */
8438 * r0 holds resolved field
8443 cmp r9, #0 @ check object for null
8444 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8445 beq common_errNullObject @ object was null
8446 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8447 mov r2, rINST, lsr #8 @ r2<- A+
8448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8449 and r2, r2, #15 @ r2<- A
8450 GET_INST_OPCODE(ip) @ extract opcode from rINST
8451 SET_VREG(r0, r2) @ fp[A]<- r0
8452 GOTO_OPCODE(ip) @ jump to next instruction
8455 /* continuation for OP_IGET_WIDE */
8459 * r0 holds resolved field
8462 .LOP_IGET_WIDE_finish:
8463 cmp r9, #0 @ check object for null
8464 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8465 beq common_errNullObject @ object was null
8466 mov r2, rINST, lsr #8 @ r2<- A+
8467 add r9, r9, r3 @ r9<- obj + field offset
8468 ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok)
8469 and r2, r2, #15 @ r2<- A
8470 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8471 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8472 GET_INST_OPCODE(ip) @ extract opcode from rINST
8473 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8474 GOTO_OPCODE(ip) @ jump to next instruction
8477 /* continuation for OP_IGET_OBJECT */
8481 * r0 holds resolved field
8484 .LOP_IGET_OBJECT_finish:
8486 cmp r9, #0 @ check object for null
8487 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8488 beq common_errNullObject @ object was null
8489 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8490 mov r2, rINST, lsr #8 @ r2<- A+
8491 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8492 and r2, r2, #15 @ r2<- A
8493 GET_INST_OPCODE(ip) @ extract opcode from rINST
8494 SET_VREG(r0, r2) @ fp[A]<- r0
8495 GOTO_OPCODE(ip) @ jump to next instruction
8498 /* continuation for OP_IGET_BOOLEAN */
8502 * r0 holds resolved field
8505 .LOP_IGET_BOOLEAN_finish:
8507 cmp r9, #0 @ check object for null
8508 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8509 beq common_errNullObject @ object was null
8510 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8511 mov r2, rINST, lsr #8 @ r2<- A+
8512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8513 and r2, r2, #15 @ r2<- A
8514 GET_INST_OPCODE(ip) @ extract opcode from rINST
8515 SET_VREG(r0, r2) @ fp[A]<- r0
8516 GOTO_OPCODE(ip) @ jump to next instruction
8519 /* continuation for OP_IGET_BYTE */
8523 * r0 holds resolved field
8526 .LOP_IGET_BYTE_finish:
8528 cmp r9, #0 @ check object for null
8529 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8530 beq common_errNullObject @ object was null
8531 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8532 mov r2, rINST, lsr #8 @ r2<- A+
8533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8534 and r2, r2, #15 @ r2<- A
8535 GET_INST_OPCODE(ip) @ extract opcode from rINST
8536 SET_VREG(r0, r2) @ fp[A]<- r0
8537 GOTO_OPCODE(ip) @ jump to next instruction
8540 /* continuation for OP_IGET_CHAR */
8544 * r0 holds resolved field
8547 .LOP_IGET_CHAR_finish:
8549 cmp r9, #0 @ check object for null
8550 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8551 beq common_errNullObject @ object was null
8552 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8553 mov r2, rINST, lsr #8 @ r2<- A+
8554 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8555 and r2, r2, #15 @ r2<- A
8556 GET_INST_OPCODE(ip) @ extract opcode from rINST
8557 SET_VREG(r0, r2) @ fp[A]<- r0
8558 GOTO_OPCODE(ip) @ jump to next instruction
8561 /* continuation for OP_IGET_SHORT */
8565 * r0 holds resolved field
8568 .LOP_IGET_SHORT_finish:
8570 cmp r9, #0 @ check object for null
8571 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8572 beq common_errNullObject @ object was null
8573 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8574 mov r2, rINST, lsr #8 @ r2<- A+
8575 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8576 and r2, r2, #15 @ r2<- A
8577 GET_INST_OPCODE(ip) @ extract opcode from rINST
8578 SET_VREG(r0, r2) @ fp[A]<- r0
8579 GOTO_OPCODE(ip) @ jump to next instruction
8582 /* continuation for OP_IPUT */
8586 * r0 holds resolved field
8591 mov r1, rINST, lsr #8 @ r1<- A+
8592 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8593 and r1, r1, #15 @ r1<- A
8594 cmp r9, #0 @ check object for null
8595 GET_VREG(r0, r1) @ r0<- fp[A]
8596 beq common_errNullObject @ object was null
8597 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8598 GET_INST_OPCODE(ip) @ extract opcode from rINST
8599 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8600 GOTO_OPCODE(ip) @ jump to next instruction
8603 /* continuation for OP_IPUT_WIDE */
8607 * r0 holds resolved field
8610 .LOP_IPUT_WIDE_finish:
8611 mov r2, rINST, lsr #8 @ r2<- A+
8612 cmp r9, #0 @ check object for null
8613 and r2, r2, #15 @ r2<- A
8614 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8615 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8616 beq common_errNullObject @ object was null
8617 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8618 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8619 GET_INST_OPCODE(ip) @ extract opcode from rINST
8620 add r9, r9, r3 @ r9<- object + byte offset
8621 stmia r9, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
8622 GOTO_OPCODE(ip) @ jump to next instruction
8625 /* continuation for OP_IPUT_OBJECT */
8629 * r0 holds resolved field
8632 .LOP_IPUT_OBJECT_finish:
8634 mov r1, rINST, lsr #8 @ r1<- A+
8635 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8636 and r1, r1, #15 @ r1<- A
8637 cmp r9, #0 @ check object for null
8638 GET_VREG(r0, r1) @ r0<- fp[A]
8639 beq common_errNullObject @ object was null
8640 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8641 GET_INST_OPCODE(ip) @ extract opcode from rINST
8642 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8643 GOTO_OPCODE(ip) @ jump to next instruction
8646 /* continuation for OP_IPUT_BOOLEAN */
8650 * r0 holds resolved field
8653 .LOP_IPUT_BOOLEAN_finish:
8655 mov r1, rINST, lsr #8 @ r1<- A+
8656 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8657 and r1, r1, #15 @ r1<- A
8658 cmp r9, #0 @ check object for null
8659 GET_VREG(r0, r1) @ r0<- fp[A]
8660 beq common_errNullObject @ object was null
8661 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8662 GET_INST_OPCODE(ip) @ extract opcode from rINST
8663 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8664 GOTO_OPCODE(ip) @ jump to next instruction
8667 /* continuation for OP_IPUT_BYTE */
8671 * r0 holds resolved field
8674 .LOP_IPUT_BYTE_finish:
8676 mov r1, rINST, lsr #8 @ r1<- A+
8677 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8678 and r1, r1, #15 @ r1<- A
8679 cmp r9, #0 @ check object for null
8680 GET_VREG(r0, r1) @ r0<- fp[A]
8681 beq common_errNullObject @ object was null
8682 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8683 GET_INST_OPCODE(ip) @ extract opcode from rINST
8684 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8685 GOTO_OPCODE(ip) @ jump to next instruction
8688 /* continuation for OP_IPUT_CHAR */
8692 * r0 holds resolved field
8695 .LOP_IPUT_CHAR_finish:
8697 mov r1, rINST, lsr #8 @ r1<- A+
8698 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8699 and r1, r1, #15 @ r1<- A
8700 cmp r9, #0 @ check object for null
8701 GET_VREG(r0, r1) @ r0<- fp[A]
8702 beq common_errNullObject @ object was null
8703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8704 GET_INST_OPCODE(ip) @ extract opcode from rINST
8705 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8706 GOTO_OPCODE(ip) @ jump to next instruction
8709 /* continuation for OP_IPUT_SHORT */
8713 * r0 holds resolved field
8716 .LOP_IPUT_SHORT_finish:
8718 mov r1, rINST, lsr #8 @ r1<- A+
8719 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8720 and r1, r1, #15 @ r1<- A
8721 cmp r9, #0 @ check object for null
8722 GET_VREG(r0, r1) @ r0<- fp[A]
8723 beq common_errNullObject @ object was null
8724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8725 GET_INST_OPCODE(ip) @ extract opcode from rINST
8726 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8727 GOTO_OPCODE(ip) @ jump to next instruction
8730 /* continuation for OP_SGET */
8733 * Continuation if the field has not yet been resolved.
8734 * r1: BBBB field ref
8737 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8738 EXPORT_PC() @ resolve() could throw, so export now
8739 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8740 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8741 cmp r0, #0 @ success?
8742 bne .LOP_SGET_finish @ yes, finish
8743 b common_exceptionThrown @ no, handle exception
8746 /* continuation for OP_SGET_WIDE */
8749 * Continuation if the field has not yet been resolved.
8750 * r1: BBBB field ref
8752 .LOP_SGET_WIDE_resolve:
8753 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8754 EXPORT_PC() @ resolve() could throw, so export now
8755 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8756 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8757 cmp r0, #0 @ success?
8758 bne .LOP_SGET_WIDE_finish @ yes, finish
8759 b common_exceptionThrown @ no, handle exception
8762 /* continuation for OP_SGET_OBJECT */
8765 * Continuation if the field has not yet been resolved.
8766 * r1: BBBB field ref
8768 .LOP_SGET_OBJECT_resolve:
8769 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8770 EXPORT_PC() @ resolve() could throw, so export now
8771 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8772 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8773 cmp r0, #0 @ success?
8774 bne .LOP_SGET_OBJECT_finish @ yes, finish
8775 b common_exceptionThrown @ no, handle exception
8778 /* continuation for OP_SGET_BOOLEAN */
8781 * Continuation if the field has not yet been resolved.
8782 * r1: BBBB field ref
8784 .LOP_SGET_BOOLEAN_resolve:
8785 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8786 EXPORT_PC() @ resolve() could throw, so export now
8787 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8788 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8789 cmp r0, #0 @ success?
8790 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
8791 b common_exceptionThrown @ no, handle exception
8794 /* continuation for OP_SGET_BYTE */
8797 * Continuation if the field has not yet been resolved.
8798 * r1: BBBB field ref
8800 .LOP_SGET_BYTE_resolve:
8801 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8802 EXPORT_PC() @ resolve() could throw, so export now
8803 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8804 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8805 cmp r0, #0 @ success?
8806 bne .LOP_SGET_BYTE_finish @ yes, finish
8807 b common_exceptionThrown @ no, handle exception
8810 /* continuation for OP_SGET_CHAR */
8813 * Continuation if the field has not yet been resolved.
8814 * r1: BBBB field ref
8816 .LOP_SGET_CHAR_resolve:
8817 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8818 EXPORT_PC() @ resolve() could throw, so export now
8819 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8820 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8821 cmp r0, #0 @ success?
8822 bne .LOP_SGET_CHAR_finish @ yes, finish
8823 b common_exceptionThrown @ no, handle exception
8826 /* continuation for OP_SGET_SHORT */
8829 * Continuation if the field has not yet been resolved.
8830 * r1: BBBB field ref
8832 .LOP_SGET_SHORT_resolve:
8833 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8834 EXPORT_PC() @ resolve() could throw, so export now
8835 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8836 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8837 cmp r0, #0 @ success?
8838 bne .LOP_SGET_SHORT_finish @ yes, finish
8839 b common_exceptionThrown @ no, handle exception
8842 /* continuation for OP_SPUT */
8845 * Continuation if the field has not yet been resolved.
8846 * r1: BBBB field ref
8849 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8850 EXPORT_PC() @ resolve() could throw, so export now
8851 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8852 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8853 cmp r0, #0 @ success?
8854 bne .LOP_SPUT_finish @ yes, finish
8855 b common_exceptionThrown @ no, handle exception
8858 /* continuation for OP_SPUT_WIDE */
8861 * Continuation if the field has not yet been resolved.
8862 * r1: BBBB field ref
8865 .LOP_SPUT_WIDE_resolve:
8866 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8867 EXPORT_PC() @ resolve() could throw, so export now
8868 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8869 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8870 cmp r0, #0 @ success?
8871 bne .LOP_SPUT_WIDE_finish @ yes, finish
8872 b common_exceptionThrown @ no, handle exception
8875 /* continuation for OP_SPUT_OBJECT */
8878 * Continuation if the field has not yet been resolved.
8879 * r1: BBBB field ref
8881 .LOP_SPUT_OBJECT_resolve:
8882 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8883 EXPORT_PC() @ resolve() could throw, so export now
8884 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8885 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8886 cmp r0, #0 @ success?
8887 bne .LOP_SPUT_OBJECT_finish @ yes, finish
8888 b common_exceptionThrown @ no, handle exception
8891 /* continuation for OP_SPUT_BOOLEAN */
8894 * Continuation if the field has not yet been resolved.
8895 * r1: BBBB field ref
8897 .LOP_SPUT_BOOLEAN_resolve:
8898 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8899 EXPORT_PC() @ resolve() could throw, so export now
8900 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8901 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8902 cmp r0, #0 @ success?
8903 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
8904 b common_exceptionThrown @ no, handle exception
8907 /* continuation for OP_SPUT_BYTE */
8910 * Continuation if the field has not yet been resolved.
8911 * r1: BBBB field ref
8913 .LOP_SPUT_BYTE_resolve:
8914 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8915 EXPORT_PC() @ resolve() could throw, so export now
8916 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8917 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8918 cmp r0, #0 @ success?
8919 bne .LOP_SPUT_BYTE_finish @ yes, finish
8920 b common_exceptionThrown @ no, handle exception
8923 /* continuation for OP_SPUT_CHAR */
8926 * Continuation if the field has not yet been resolved.
8927 * r1: BBBB field ref
8929 .LOP_SPUT_CHAR_resolve:
8930 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8931 EXPORT_PC() @ resolve() could throw, so export now
8932 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8933 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8934 cmp r0, #0 @ success?
8935 bne .LOP_SPUT_CHAR_finish @ yes, finish
8936 b common_exceptionThrown @ no, handle exception
8939 /* continuation for OP_SPUT_SHORT */
8942 * Continuation if the field has not yet been resolved.
8943 * r1: BBBB field ref
8945 .LOP_SPUT_SHORT_resolve:
8946 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8947 EXPORT_PC() @ resolve() could throw, so export now
8948 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8949 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8950 cmp r0, #0 @ success?
8951 bne .LOP_SPUT_SHORT_finish @ yes, finish
8952 b common_exceptionThrown @ no, handle exception
8955 /* continuation for OP_INVOKE_VIRTUAL */
8959 * r0 = resolved base method
8960 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8962 .LOP_INVOKE_VIRTUAL_continue:
8963 GET_VREG(r1, r10) @ r1<- "this" ptr
8964 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8965 cmp r1, #0 @ is "this" null?
8966 beq common_errNullObject @ null "this", throw exception
8967 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8968 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8969 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8970 bl common_invokeMethodNoRange @ continue on
8973 /* continuation for OP_INVOKE_SUPER */
8977 * r0 = resolved base method
8978 * r9 = method->clazz
8980 .LOP_INVOKE_SUPER_continue:
8981 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8982 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8983 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8984 EXPORT_PC() @ must export for invoke
8985 cmp r2, r3 @ compare (methodIndex, vtableCount)
8986 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
8987 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8988 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8989 bl common_invokeMethodNoRange @ continue on
8991 .LOP_INVOKE_SUPER_resolve:
8992 mov r0, r9 @ r0<- method->clazz
8993 mov r2, #METHOD_VIRTUAL @ resolver method type
8994 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8995 cmp r0, #0 @ got null?
8996 bne .LOP_INVOKE_SUPER_continue @ no, continue
8997 b common_exceptionThrown @ yes, handle exception
9000 * Throw a NoSuchMethodError with the method name as the message.
9001 * r0 = resolved base method
9003 .LOP_INVOKE_SUPER_nsm:
9004 ldr r1, [r0, #offMethod_name] @ r1<- method name
9005 b common_errNoSuchMethod
9008 /* continuation for OP_INVOKE_DIRECT */
9012 * r1 = reference (BBBB or CCCC)
9013 * r10 = "this" register
9015 .LOP_INVOKE_DIRECT_resolve:
9016 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9017 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9018 mov r2, #METHOD_DIRECT @ resolver method type
9019 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9020 cmp r0, #0 @ got null?
9021 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9022 bne .LOP_INVOKE_DIRECT_finish @ no, continue
9023 b common_exceptionThrown @ yes, handle exception
9026 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9030 * r0 = resolved base method
9031 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
9033 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9034 GET_VREG(r1, r10) @ r1<- "this" ptr
9035 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9036 cmp r1, #0 @ is "this" null?
9037 beq common_errNullObject @ null "this", throw exception
9038 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
9039 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
9040 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
9041 bl common_invokeMethodRange @ continue on
9044 /* continuation for OP_INVOKE_SUPER_RANGE */
9048 * r0 = resolved base method
9049 * r9 = method->clazz
9051 .LOP_INVOKE_SUPER_RANGE_continue:
9052 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
9053 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
9054 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
9055 EXPORT_PC() @ must export for invoke
9056 cmp r2, r3 @ compare (methodIndex, vtableCount)
9057 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
9058 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
9059 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
9060 bl common_invokeMethodRange @ continue on
9062 .LOP_INVOKE_SUPER_RANGE_resolve:
9063 mov r0, r9 @ r0<- method->clazz
9064 mov r2, #METHOD_VIRTUAL @ resolver method type
9065 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9066 cmp r0, #0 @ got null?
9067 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
9068 b common_exceptionThrown @ yes, handle exception
9071 * Throw a NoSuchMethodError with the method name as the message.
9072 * r0 = resolved base method
9074 .LOP_INVOKE_SUPER_RANGE_nsm:
9075 ldr r1, [r0, #offMethod_name] @ r1<- method name
9076 b common_errNoSuchMethod
9079 /* continuation for OP_INVOKE_DIRECT_RANGE */
9083 * r1 = reference (BBBB or CCCC)
9084 * r10 = "this" register
9086 .LOP_INVOKE_DIRECT_RANGE_resolve:
9087 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9088 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
9089 mov r2, #METHOD_DIRECT @ resolver method type
9090 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
9091 cmp r0, #0 @ got null?
9092 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
9093 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
9094 b common_exceptionThrown @ yes, handle exception
9097 /* continuation for OP_FLOAT_TO_LONG */
9099 * Convert the float in r0 to a long in r0/r1.
9101 * We have to clip values to long min/max per the specification. The
9102 * expected common case is a "reasonable" value that converts directly
9103 * to modest integer. The EABI convert function isn't doing this for us.
9107 mov r1, #0x5f000000 @ (float)maxlong
9109 bl __aeabi_fcmpge @ is arg >= maxlong?
9110 cmp r0, #0 @ nonzero == yes
9111 mvnne r0, #0 @ return maxlong (7fffffff)
9112 mvnne r1, #0x80000000
9113 ldmnefd sp!, {r4, pc}
9115 mov r0, r4 @ recover arg
9116 mov r1, #0xdf000000 @ (float)minlong
9117 bl __aeabi_fcmple @ is arg <= minlong?
9118 cmp r0, #0 @ nonzero == yes
9119 movne r0, #0 @ return minlong (80000000)
9120 movne r1, #0x80000000
9121 ldmnefd sp!, {r4, pc}
9123 mov r0, r4 @ recover arg
9125 bl __aeabi_fcmpeq @ is arg == self?
9126 cmp r0, #0 @ zero == no
9127 moveq r1, #0 @ return zero for NaN
9128 ldmeqfd sp!, {r4, pc}
9130 mov r0, r4 @ recover arg
9131 bl __aeabi_f2lz @ convert float to long
9135 /* continuation for OP_DOUBLE_TO_LONG */
9137 * Convert the double in r0/r1 to a long in r0/r1.
9139 * We have to clip values to long min/max per the specification. The
9140 * expected common case is a "reasonable" value that converts directly
9141 * to modest integer. The EABI convert function isn't doing this for us.
9144 stmfd sp!, {r4, r5, lr} @ save regs
9145 ldr r3, .LOP_DOUBLE_TO_LONG_max @ (double)maxlong, hi
9146 sub sp, sp, #4 @ align for EABI
9147 mov r2, #0 @ (double)maxlong, lo
9148 mov r4, r0 @ save r0
9150 bl __aeabi_dcmpge @ is arg >= maxlong?
9151 cmp r0, #0 @ nonzero == yes
9152 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
9153 mvnne r1, #0x80000000
9156 mov r0, r4 @ recover arg
9158 ldr r3, .LOP_DOUBLE_TO_LONG_min @ (double)minlong, hi
9159 mov r2, #0 @ (double)minlong, lo
9160 bl __aeabi_dcmple @ is arg <= minlong?
9161 cmp r0, #0 @ nonzero == yes
9162 movne r0, #0 @ return minlong (8000000000000000)
9163 movne r1, #0x80000000
9166 mov r0, r4 @ recover arg
9168 mov r2, r4 @ compare against self
9170 bl __aeabi_dcmpeq @ is arg == self?
9171 cmp r0, #0 @ zero == no
9172 moveq r1, #0 @ return zero for NaN
9175 mov r0, r4 @ recover arg
9177 bl __aeabi_d2lz @ convert double to long
9181 ldmfd sp!, {r4, r5, pc}
9183 .LOP_DOUBLE_TO_LONG_max:
9184 .word 0x43e00000 @ maxlong, as a double (high word)
9185 .LOP_DOUBLE_TO_LONG_min:
9186 .word 0xc3e00000 @ minlong, as a double (high word)
9189 /* continuation for OP_MUL_LONG */
9191 .LOP_MUL_LONG_finish:
9192 GET_INST_OPCODE(ip) @ extract opcode from rINST
9193 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
9194 GOTO_OPCODE(ip) @ jump to next instruction
9197 /* continuation for OP_SHL_LONG */
9199 .LOP_SHL_LONG_finish:
9200 mov r0, r0, asl r2 @ r0<- r0 << r2
9201 GET_INST_OPCODE(ip) @ extract opcode from rINST
9202 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9203 GOTO_OPCODE(ip) @ jump to next instruction
9206 /* continuation for OP_SHR_LONG */
9208 .LOP_SHR_LONG_finish:
9209 mov r1, r1, asr r2 @ r1<- r1 >> r2
9210 GET_INST_OPCODE(ip) @ extract opcode from rINST
9211 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9212 GOTO_OPCODE(ip) @ jump to next instruction
9215 /* continuation for OP_USHR_LONG */
9217 .LOP_USHR_LONG_finish:
9218 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
9219 GET_INST_OPCODE(ip) @ extract opcode from rINST
9220 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9221 GOTO_OPCODE(ip) @ jump to next instruction
9224 /* continuation for OP_SHL_LONG_2ADDR */
9226 .LOP_SHL_LONG_2ADDR_finish:
9227 GET_INST_OPCODE(ip) @ extract opcode from rINST
9228 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9229 GOTO_OPCODE(ip) @ jump to next instruction
9232 /* continuation for OP_SHR_LONG_2ADDR */
9234 .LOP_SHR_LONG_2ADDR_finish:
9235 GET_INST_OPCODE(ip) @ extract opcode from rINST
9236 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9237 GOTO_OPCODE(ip) @ jump to next instruction
9240 /* continuation for OP_USHR_LONG_2ADDR */
9242 .LOP_USHR_LONG_2ADDR_finish:
9243 GET_INST_OPCODE(ip) @ extract opcode from rINST
9244 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9245 GOTO_OPCODE(ip) @ jump to next instruction
9248 /* continuation for OP_EXECUTE_INLINE */
9251 * Extract args, call function.
9252 * r0 = #of args (0-4)
9254 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9257 * - Use a jump table from the main piece to jump directly into the
9258 * AND/LDR pairs. Costs a data load, saves a branch.
9259 * - Have five separate pieces that do the loading, so we can work the
9260 * interleave a little better. Increases code size.
9262 .LOP_EXECUTE_INLINE_continue:
9263 rsb r0, r0, #4 @ r0<- 4-r0
9264 FETCH(r9, 2) @ r9<- FEDC
9265 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9266 bl common_abort @ (skipped due to ARM prefetch)
9267 4: and ip, r9, #0xf000 @ isolate F
9268 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
9269 3: and ip, r9, #0x0f00 @ isolate E
9270 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
9271 2: and ip, r9, #0x00f0 @ isolate D
9272 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
9273 1: and ip, r9, #0x000f @ isolate C
9274 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
9276 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
9277 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9280 .LOP_EXECUTE_INLINE_table:
9281 .word gDvmInlineOpsTable
9284 .size dvmAsmSisterStart, .-dvmAsmSisterStart
9285 .global dvmAsmSisterEnd
9288 /* File: armv5te/footer.S */
9290 * ===========================================================================
9291 * Common subroutines and data
9292 * ===========================================================================
9299 * Common code when a backward branch is taken.
9302 * r9 is PC adjustment *in bytes*
9304 common_backwardBranch:
9305 mov r0, #kInterpEntryInstr
9306 bl common_periodicChecks
9307 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9308 GET_INST_OPCODE(ip) @ extract opcode from rINST
9309 GOTO_OPCODE(ip) @ jump to next instruction
9313 * Need to see if the thread needs to be suspended or debugger/profiler
9314 * activity has begun.
9316 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9317 * have to do the second ldr.
9319 * TODO: reduce this so we're just checking a single location.
9322 * r0 is reentry type, e.g. kInterpEntryInstr
9323 * r9 is trampoline PC adjustment *in bytes*
9325 common_periodicChecks:
9326 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9328 #if defined(WITH_DEBUGGER)
9329 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9331 #if defined(WITH_PROFILER)
9332 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9335 ldr r3, [r3] @ r3<- suspendCount (int)
9337 #if defined(WITH_DEBUGGER)
9338 ldrb r1, [r1] @ r1<- debuggerActive (boolean)
9340 #if defined (WITH_PROFILER)
9341 ldr r2, [r2] @ r2<- activeProfilers (int)
9344 cmp r3, #0 @ suspend pending?
9345 bne 2f @ yes, check suspend
9347 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9348 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9349 orrs r1, r1, r2 @ r1<- r1 | r2
9350 cmp r1, #0 @ debugger attached or profiler started?
9351 # elif defined(WITH_DEBUGGER)
9352 cmp r1, #0 @ debugger attached?
9353 # elif defined(WITH_PROFILER)
9354 cmp r2, #0 @ profiler started?
9356 bne 3f @ debugger/profiler, switch interp
9359 bx lr @ nothing to do, return
9362 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9363 b dvmCheckSuspendPending @ suspend if necessary, then return
9365 3: @ debugger/profiler enabled, bail out
9366 add rPC, rPC, r9 @ update rPC
9367 str r0, [rGLUE, #offGlue_entryPoint]
9368 mov r1, #1 @ "want switch" = true
9373 * The equivalent of "goto bail", this calls through the "bail handler".
9375 * State registers will be saved to the "glue" area before bailing.
9378 * r1 is "bool changeInterp", indicating if we want to switch to the
9379 * other interpreter or just bail all the way out
9382 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9383 mov r0, rGLUE @ r0<- glue ptr
9384 b dvmMterpStdBail @ call(glue, changeInterp)
9386 @add r1, r1, #1 @ using (boolean+1)
9387 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9388 @bl _longjmp @ does not return
9393 * Common code for method invocation with range.
9396 * r0 is "Method* methodToCall", the method we're trying to call
9398 common_invokeMethodRange:
9400 @ prepare to copy args to "outs" area of current frame
9401 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9402 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9403 beq .LinvokeArgsDone @ if no args, skip the rest
9404 FETCH(r1, 2) @ r1<- CCCC
9406 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9407 @ (very few methods have > 10 args; could unroll for common cases)
9408 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9409 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9410 1: ldr r1, [r3], #4 @ val = *fp++
9411 subs r2, r2, #1 @ count--
9412 str r1, [r10], #4 @ *outs++ = val
9413 bne 1b @ ...while count != 0
9417 * Common code for method invocation without range.
9420 * r0 is "Method* methodToCall", the method we're trying to call
9422 common_invokeMethodNoRange:
9424 @ prepare to copy args to "outs" area of current frame
9425 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9426 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9427 beq .LinvokeArgsDone @ if no args, skip the rest
9428 FETCH(r1, 2) @ r1<- GFED
9430 @ r0=methodToCall, r1=GFED, r2=count, r10=outs
9432 rsb r2, r2, #5 @ r2<- 5-r2
9433 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
9434 bl common_abort @ (skipped due to ARM prefetch)
9435 5: and ip, rINST, #0x0f00 @ isolate A
9436 ldr r3, [rFP, ip, lsr #6] @ r3<- vA (shift right 8, left 2)
9438 str r3, [r10, #-4]! @ *--outs = vA
9439 4: and ip, r1, #0xf000 @ isolate G
9440 ldr r3, [rFP, ip, lsr #10] @ r3<- vG (shift right 12, left 2)
9442 str r3, [r10, #-4]! @ *--outs = vG
9443 3: and ip, r1, #0x0f00 @ isolate F
9444 ldr r3, [rFP, ip, lsr #6] @ r3<- vF
9446 str r3, [r10, #-4]! @ *--outs = vF
9447 2: and ip, r1, #0x00f0 @ isolate E
9448 ldr r3, [rFP, ip, lsr #2] @ r3<- vE
9450 str r3, [r10, #-4]! @ *--outs = vE
9451 1: and ip, r1, #0x000f @ isolate D
9452 ldr r3, [rFP, ip, lsl #2] @ r3<- vD
9454 str r3, [r10, #-4]! @ *--outs = vD
9455 0: @ fall through to .LinvokeArgsDone
9457 .LinvokeArgsDone: @ r0=methodToCall
9458 @ find space for the new stack frame, check for overflow
9459 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
9460 ldrh r2, [r0, #offMethod_registersSize] @ r2<- methodToCall->regsSize
9461 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9462 sub r1, r1, r2, lsl #2 @ r1<- newFp (old savearea - regsSize)
9463 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
9464 @ bl common_dumpRegs
9465 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
9466 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
9467 cmp r3, r9 @ bottom < interpStackEnd?
9468 blt .LstackOverflow @ yes, this frame will overflow stack
9470 @ set up newSaveArea
9472 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
9473 str ip, [r10, #offStackSaveArea_prevSave]
9475 str rFP, [r10, #offStackSaveArea_prevFrame]
9476 str rPC, [r10, #offStackSaveArea_savedPc]
9477 str r0, [r10, #offStackSaveArea_method]
9479 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9485 bl common_printNewline
9494 bl common_printNewline
9498 @ Update "glue" values for the new method
9499 @ r0=methodToCall, r1=newFp
9500 ldr r3, [r0, #offMethod_clazz] @ r3<- method->clazz
9501 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
9502 ldr r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9503 ldr rPC, [r0, #offMethod_insns] @ rPC<- method->insns
9504 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9505 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
9506 FETCH_INST() @ load rINST from rPC
9507 mov rFP, r1 @ fp = newFp
9508 GET_INST_OPCODE(ip) @ extract opcode from rINST
9509 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9510 GOTO_OPCODE(ip) @ jump to next instruction
9513 @ Prep for the native call
9514 @ r0=methodToCall, r1=newFp, r10=newSaveArea
9515 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9516 ldr r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9517 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
9518 str r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9519 mov r9, r3 @ r9<- glue->self (preserve)
9521 mov r2, r0 @ r2<- methodToCall
9522 mov r0, r1 @ r0<- newFp (points to args)
9523 add r1, rGLUE, #offGlue_retval @ r1<- &retval
9525 #ifdef ASSIST_DEBUGGER
9526 /* insert fake function header to help gdb find the stack frame */
9528 .type dalvik_mterp, %function
9536 @mov lr, pc @ set return addr
9537 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9538 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9540 @ native return; r9=self, r10=newSaveArea
9541 @ equivalent to dvmPopJniLocals
9542 ldr r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9543 ldr r1, [r9, #offThread_exception] @ check for exception
9544 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
9546 str r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9547 bne common_exceptionThrown @ no, handle exception
9549 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
9550 GET_INST_OPCODE(ip) @ extract opcode from rINST
9551 GOTO_OPCODE(ip) @ jump to next instruction
9554 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
9555 bl dvmHandleStackOverflow
9556 b common_exceptionThrown
9557 #ifdef ASSIST_DEBUGGER
9563 * Common code for method invocation, calling through "glue code".
9565 * TODO: now that we have range and non-range invoke handlers, this
9566 * needs to be split into two. Maybe just create entry points
9567 * that set r9 and jump here?
9570 * r0 is "Method* methodToCall", the method we're trying to call
9571 * r9 is "bool methodCallRange", indicating if this is a /range variant
9575 sub sp, sp, #8 @ space for args + pad
9576 FETCH(ip, 2) @ ip<- FEDC or CCCC
9577 mov r2, r0 @ A2<- methodToCall
9578 mov r0, rGLUE @ A0<- glue
9579 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9580 mov r1, r9 @ A1<- methodCallRange
9581 mov r3, rINST, lsr #8 @ A3<- AA
9582 str ip, [sp, #0] @ A4<- ip
9583 bl dvmMterp_invokeMethod @ call the C invokeMethod
9584 add sp, sp, #8 @ remove arg area
9585 b common_resumeAfterGlueCall @ continue to next instruction
9591 * Common code for handling a return instruction.
9593 * This does not return.
9595 common_returnFromMethod:
9597 mov r0, #kInterpEntryReturn
9599 bl common_periodicChecks
9601 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
9602 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9603 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9604 @ r2<- method we're returning to
9605 cmp r2, #0 @ is this a break frame?
9606 mov r1, #0 @ "want switch" = false
9607 beq common_gotoBail @ break frame, bail out completely
9609 ldr rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
9610 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9611 str r2, [rGLUE, #offGlue_method] @ glue->method = newSave->method
9612 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
9613 ldr r1, [r2, #offMethod_clazz] @ r1<- method->clazz
9614 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
9615 ldr r1, [r1, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
9616 GET_INST_OPCODE(ip) @ extract opcode from rINST
9617 str r1, [rGLUE, #offGlue_methodClassDex]
9618 GOTO_OPCODE(ip) @ jump to next instruction
9621 * Return handling, calls through "glue code".
9625 SAVE_PC_FP_TO_GLUE() @ export state
9626 mov r0, rGLUE @ arg to function
9627 bl dvmMterp_returnFromMethod
9628 b common_resumeAfterGlueCall
9633 * Somebody has thrown an exception. Handle it.
9635 * If the exception processing code returns to us (instead of falling
9636 * out of the interpreter), continue with whatever the next instruction
9637 * now happens to be.
9639 * This does not return.
9641 common_exceptionThrown:
9643 mov r0, #kInterpEntryThrow
9645 bl common_periodicChecks
9647 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9648 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
9649 mov r1, r10 @ r1<- self
9650 mov r0, r9 @ r0<- exception
9651 bl dvmAddTrackedAlloc @ don't let the exception be GCed
9652 mov r3, #0 @ r3<- NULL
9653 str r3, [r10, #offThread_exception] @ self->exception = NULL
9655 /* set up args and a local for "&fp" */
9656 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
9657 str rFP, [sp, #-4]! @ *--sp = fp
9658 mov ip, sp @ ip<- &fp
9659 mov r3, #0 @ r3<- false
9660 str ip, [sp, #-4]! @ *--sp = &fp
9661 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9662 mov r0, r10 @ r0<- self
9663 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
9664 mov r2, r9 @ r2<- exception
9665 sub r1, rPC, r1 @ r1<- pc - method->insns
9666 mov r1, r1, asr #1 @ r1<- offset in code units
9668 /* call, r0 gets catchRelPc (a code-unit offset) */
9669 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
9671 /* fix earlier stack overflow if necessary; may trash rFP */
9672 ldrb r1, [r10, #offThread_stackOverflowed]
9673 cmp r1, #0 @ did we overflow earlier?
9674 beq 1f @ no, skip ahead
9675 mov rFP, r0 @ save relPc result in rFP
9676 mov r0, r10 @ r0<- self
9677 bl dvmCleanupStackOverflow @ call(self)
9678 mov r0, rFP @ restore result
9681 /* update frame pointer and check result from dvmFindCatchBlock */
9682 ldr rFP, [sp, #4] @ retrieve the updated rFP
9683 cmp r0, #0 @ is catchRelPc < 0?
9684 add sp, sp, #8 @ restore stack
9685 bmi .LnotCaughtLocally
9687 /* adjust locals to match self->curFrame and updated PC */
9688 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
9689 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
9690 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
9691 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
9692 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
9693 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9694 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
9695 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9697 /* release the tracked alloc on the exception */
9698 mov r0, r9 @ r0<- exception
9699 mov r1, r10 @ r1<- self
9700 bl dvmReleaseTrackedAlloc @ release the exception
9702 /* restore the exception if the handler wants it */
9703 FETCH_INST() @ load rINST from rPC
9704 GET_INST_OPCODE(ip) @ extract opcode from rINST
9705 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
9706 streq r9, [r10, #offThread_exception] @ yes, restore the exception
9707 GOTO_OPCODE(ip) @ jump to next instruction
9709 .LnotCaughtLocally: @ r9=exception, r10=self
9710 /* fix stack overflow if necessary */
9711 ldrb r1, [r10, #offThread_stackOverflowed]
9712 cmp r1, #0 @ did we overflow earlier?
9713 movne r0, r10 @ if yes: r0<- self
9714 blne dvmCleanupStackOverflow @ if yes: call(self)
9716 @ may want to show "not caught locally" debug messages here
9717 #if DVM_SHOW_EXCEPTION >= 2
9718 /* call __android_log_print(prio, tag, format, ...) */
9719 /* "Exception %s from %s:%d not caught locally" */
9720 @ dvmLineNumFromPC(method, pc - method->insns)
9721 ldr r0, [rGLUE, #offGlue_method]
9722 ldr r1, [r0, #offMethod_insns]
9727 @ dvmGetMethodSourceFile(method)
9728 ldr r0, [rGLUE, #offGlue_method]
9729 bl dvmGetMethodSourceFile
9731 @ exception->clazz->descriptor
9732 ldr r3, [r9, #offObject_clazz]
9733 ldr r3, [r3, #offClassObject_descriptor]
9735 ldr r2, strExceptionNotCaughtLocally
9737 mov r0, #3 @ LOG_DEBUG
9738 bl __android_log_print
9740 str r9, [r10, #offThread_exception] @ restore exception
9741 mov r0, r9 @ r0<- exception
9742 mov r1, r10 @ r1<- self
9743 bl dvmReleaseTrackedAlloc @ release the exception
9744 mov r1, #0 @ "want switch" = false
9745 b common_gotoBail @ bail out
9749 * Exception handling, calls through "glue code".
9753 SAVE_PC_FP_TO_GLUE() @ export state
9754 mov r0, rGLUE @ arg to function
9755 bl dvmMterp_exceptionThrown
9756 b common_resumeAfterGlueCall
9761 * After returning from a "glued" function, pull out the updated
9762 * values and start executing at the next instruction.
9764 common_resumeAfterGlueCall:
9765 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
9766 FETCH_INST() @ load rINST from rPC
9767 GET_INST_OPCODE(ip) @ extract opcode from rINST
9768 GOTO_OPCODE(ip) @ jump to next instruction
9771 * Invalid array index.
9773 common_errArrayIndex:
9775 ldr r0, strArrayIndexException
9777 bl dvmThrowException
9778 b common_exceptionThrown
9781 * Invalid array value.
9783 common_errArrayStore:
9785 ldr r0, strArrayStoreException
9787 bl dvmThrowException
9788 b common_exceptionThrown
9791 * Integer divide or mod by zero.
9793 common_errDivideByZero:
9795 ldr r0, strArithmeticException
9796 ldr r1, strDivideByZero
9797 bl dvmThrowException
9798 b common_exceptionThrown
9801 * Attempt to allocate an array with a negative size.
9803 common_errNegativeArraySize:
9805 ldr r0, strNegativeArraySizeException
9807 bl dvmThrowException
9808 b common_exceptionThrown
9811 * Invocation of a non-existent method.
9813 common_errNoSuchMethod:
9815 ldr r0, strNoSuchMethodError
9817 bl dvmThrowException
9818 b common_exceptionThrown
9821 * We encountered a null object when we weren't expecting one. We
9822 * export the PC, throw a NullPointerException, and goto the exception
9825 common_errNullObject:
9827 ldr r0, strNullPointerException
9829 bl dvmThrowException
9830 b common_exceptionThrown
9833 * For debugging, cause an immediate fault. The source address will
9834 * be in lr (use a bl instruction to jump here).
9842 * Spit out a "we were here", preserving all registers. (The attempt
9843 * to save ip won't work, but we need to save an even number of
9844 * registers for EABI 64-bit stack alignment.)
9848 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9852 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9864 * Spit out the number in r0, preserving registers.
9867 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9871 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9875 * Print a newline, preserving registers.
9877 common_printNewline:
9878 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9881 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9885 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9888 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9892 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9896 * Print the 64-bit quantity in r0-r1, preserving registers.
9899 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9902 ldr r0, strPrintLong
9904 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9908 * Print full method info. Pass the Method* in r0. Preserves regs.
9911 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9912 bl dvmMterpPrintMethod
9913 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9917 * Call a C helper function that dumps regs and possibly some
9918 * additional info. Requires the C function to be compiled in.
9922 stmfd sp!, {r0, r1, r2, r3, ip, lr}
9923 bl dvmMterpDumpArmRegs
9924 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
9930 * String references, must be close to the code that uses them.
9933 strArithmeticException:
9934 .word .LstrArithmeticException
9935 strArrayIndexException:
9936 .word .LstrArrayIndexException
9937 strArrayStoreException:
9938 .word .LstrArrayStoreException
9940 .word .LstrDivideByZero
9941 strNegativeArraySizeException:
9942 .word .LstrNegativeArraySizeException
9943 strNoSuchMethodError:
9944 .word .LstrNoSuchMethodError
9945 strNullPointerException:
9946 .word .LstrNullPointerException
9950 strExceptionNotCaughtLocally:
9951 .word .LstrExceptionNotCaughtLocally
9960 .word .LstrPrintLong
9963 * Zero-terminated ASCII string data.
9965 * On ARM we have two choices: do like gcc does, and LDR from a .word
9966 * with the address, or use an ADR pseudo-op to get the address
9967 * directly. ADR saves 4 bytes and an indirection, but it's using a
9968 * PC-relative addressing mode and hence has a limited range, which
9969 * makes it not work well with mergeable string sections.
9971 .section .rodata.str1.4,"aMS",%progbits,1
9974 .asciz "Bad entry point %d\n"
9975 .LstrArithmeticException:
9976 .asciz "Ljava/lang/ArithmeticException;"
9977 .LstrArrayIndexException:
9978 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
9979 .LstrArrayStoreException:
9980 .asciz "Ljava/lang/ArrayStoreException;"
9981 .LstrClassCastException:
9982 .asciz "Ljava/lang/ClassCastException;"
9984 .asciz "divide by zero"
9985 .LstrFilledNewArrayNotImpl:
9986 .asciz "filled-new-array only implemented for objects and 'int'"
9988 .asciz "Ljava/lang/InternalError;"
9989 .LstrInstantiationError:
9990 .asciz "Ljava/lang/InstantiationError;"
9991 .LstrNegativeArraySizeException:
9992 .asciz "Ljava/lang/NegativeArraySizeException;"
9993 .LstrNoSuchMethodError:
9994 .asciz "Ljava/lang/NoSuchMethodError;"
9995 .LstrNullPointerException:
9996 .asciz "Ljava/lang/NullPointerException;"
10000 .LstrExceptionNotCaughtLocally:
10001 .asciz "Exception %s from %s:%d not caught locally\n"