2 * This file was generated automatically by gen-mterp.py for 'x86'.
7 /* File: x86/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 * 32-bit x86 definitions and declarations.
28 386 ABI general notes:
31 eax, edx, ecx, st(0)-st(7)
36 64-bit in edx:eax (low-order 32 in eax)
37 fp on top of fp stack st(0)
39 Parameters passed on stack, pushed right-to-left. On entry to target, first
40 parm is at 4(%esp). Traditional entry code is:
43 push %ebp # save old frame pointer
44 mov %ebp,%esp # establish new frame pointer
45 sub FrameSize,%esp # Allocate storage for spill, locals & outs
47 Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
49 Alignment of stack not strictly required, but should be for performance. We'll
50 align frame sizes to 16-byte multiples.
52 If we're not doing variable stack allocation (alloca), the frame pointer can be
53 eliminated and all arg references adjusted to be esp relative.
57 Some key interpreter variables will be assigned to registers. Note that each
58 will also have an associated spill location (mostly used useful for those assigned
59 to callee save registers).
62 rPC edi interpreted program counter, used for fetching instructions
63 rFP esi interpreted frame pointer, used for accessing locals and args
64 rINSTw bx first 16-bit code of current instruction
65 rINSTbl bl opcode portion of instruction word
66 rINSTbh bh high byte of inst word, usually contains src/tgt reg names
69 o High order 16 bits of ebx must be zero on entry to handler
70 o rPC, rFP, rINSTw/rINSTbl valid on handler entry and exit
71 o eax, edx and ecx are scratch, rINSTw/ebx sometimes scratch
72 o rPC is in the caller save set, and will be killed across external calls. Don't
73 forget to SPILL/UNSPILL it around call points
86 /* Frame diagram while executing dvmMterpStdRun, high to low addresses */
88 #define CALLER_RP ( 8)
90 #define rGLUE_SPILL ( 0) /* <- dvmMterpStdRun ebp */
91 /* Spill offsets relative to %ebp */
92 #define EDI_SPILL ( -4)
93 #define ESI_SPILL ( -8)
94 #define EBX_SPILL (-12) /* <- esp following dmMterpStdRun header */
95 #define rPC_SPILL (-16)
96 #define rFP_SPILL (-20)
97 #define rINST_SPILL (-24)
98 #define TMP_SPILL1 (-28)
99 #define TMP_SPILL2 (-32)
100 #define TMP_SPILL3 (-36)
101 #define LOCAL0_OFFSET (-40)
102 #define LOCAL1_OFFSET (-44)
103 #define LOCAL2_OFFSET (-48)
104 #define LOCAL3_OFFSET (-52)
105 /* Out Arg offsets, relative to %sp */
106 #define OUT_ARG4 ( 16)
107 #define OUT_ARG3 ( 12)
108 #define OUT_ARG2 ( 8)
109 #define OUT_ARG1 ( 4)
110 #define OUT_ARG0 ( 0) /* <- dvmMterpStdRun esp */
111 #define FRAME_SIZE 80
113 #define SPILL(reg) movl reg##,reg##_SPILL(%ebp)
114 #define UNSPILL(reg) movl reg##_SPILL(%ebp),reg
115 #define SPILL_TMP1(reg) movl reg,TMP_SPILL1(%ebp)
116 #define UNSPILL_TMP1(reg) movl TMP_SPILL1(%ebp),reg
117 #define SPILL_TMP2(reg) movl reg,TMP_SPILL2(%ebp)
118 #define UNSPILL_TMP2(reg) movl TMP_SPILL2(%ebp),reg
119 #define SPILL_TMP3(reg) movl reg,TMP_SPILL3(%ebp)
120 #define UNSPILL_TMP3(reg) movl TMP_SPILL3(%ebp),reg
122 /* save/restore the PC and/or FP from the glue struct */
123 .macro SAVE_PC_FP_TO_GLUE _reg
125 movl rPC,offGlue_pc(\_reg)
126 movl rFP,offGlue_fp(\_reg)
129 .macro LOAD_PC_FP_FROM_GLUE
131 movl offGlue_pc(rFP),rPC
132 movl offGlue_fp(rFP),rFP
135 /* The interpreter assumes a properly aligned stack on entry, and
136 * will preserve 16-byte alignment.
140 * "export" the PC to the interpreted stack frame, f/b/o future exception
141 * objects. Must * be done *before* something calls dvmThrowException.
143 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
144 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
146 * It's okay to do this more than once.
149 movl rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)
153 * Given a frame pointer, find the stack save area.
155 * In C this is "((StackSaveArea*)(_fp) -1)".
157 .macro SAVEAREA_FROM_FP _reg
158 leal -sizeofStackSaveArea(rFP), \_reg
162 * Fetch the next instruction from rPC into rINSTw. Does not advance rPC.
169 * Fetch the opcode byte and zero-extend it into _reg. Must be used
170 * in conjunction with GOTO_NEXT_R
172 .macro FETCH_INST_R _reg
177 * Fetch the opcode byte at _count words offset from rPC and zero-extend
178 * it into _reg. Must be used in conjunction with GOTO_NEXT_R
180 .macro FETCH_INST_OPCODE _count _reg
181 movzbl \_count*2(rPC),\_reg
185 * Fetch the nth instruction word from rPC into rINSTw. Does not advance
186 * rPC, and _count is in words
188 .macro FETCH_INST_WORD _count
189 movzwl \_count*2(rPC),rINST
193 * Fetch instruction word indexed (used for branching).
194 * Index is in instruction word units.
196 .macro FETCH_INST_INDEXED _reg
197 movzwl (rPC,\_reg,2),rINST
201 * Advance rPC by instruction count
203 .macro ADVANCE_PC _count
204 leal 2*\_count(rPC),rPC
208 * Advance rPC by branch offset in register
210 .macro ADVANCE_PC_INDEXED _reg
211 leal (rPC,\_reg,2),rPC
217 jmp *dvmAsmInstructionJmpTable(,%eax,4)
221 * Version of GOTO_NEXT that assumes _reg preloaded with opcode.
222 * Should be paired with FETCH_INST_R
224 .macro GOTO_NEXT_R _reg
226 jmp *dvmAsmInstructionJmpTable(,\_reg,4)
230 * Get/set the 32-bit value from a Dalvik register.
232 .macro GET_VREG_R _reg _vreg
233 movl (rFP,\_vreg,4),\_reg
236 .macro SET_VREG _reg _vreg
237 movl \_reg,(rFP,\_vreg,4)
240 .macro GET_VREG_WORD _reg _vreg _offset
241 movl 4*(\_offset)(rFP,\_vreg,4),\_reg
244 .macro SET_VREG_WORD _reg _vreg _offset
245 movl \_reg,4*(\_offset)(rFP,\_vreg,4)
252 /* Macros for x86-atom handlers */
254 * Get the 32-bit value from a dalvik register.
257 .macro GET_VREG _vreg
258 movl (rFP,\_vreg, 4), \_vreg
262 * Fetch the next instruction from the specified offset. Advances rPC
263 * to point to the next instruction. "_count" is in 16-bit code units.
265 * This must come AFTER anything that can throw an exception, or the
266 * exception catch may miss. (This also implies that it must come after
270 .macro FETCH_ADVANCE_INST _count
271 add $(\_count*2), rPC
276 * Fetch the next instruction from an offset specified by _reg. Updates
277 * rPC to point to the next instruction. "_reg" must specify the distance
278 * in bytes, *not* 16-bit code units, and may be a signed value.
281 .macro FETCH_ADVANCE_INST_RB _reg
287 * Fetch a half-word code unit from an offset past the current PC. The
288 * "_count" value is in 16-bit code units. Does not advance rPC.
289 * For example, given instruction of format: AA|op BBBB, it
293 .macro FETCH _count _reg
294 movzwl (\_count*2)(rPC), \_reg
298 * Fetch a half-word code unit from an offset past the current PC. The
299 * "_count" value is in 16-bit code units. Does not advance rPC.
300 * This variant treats the value as signed.
303 .macro FETCHs _count _reg
304 movswl (\_count*2)(rPC), \_reg
308 * Fetch the first byte from an offset past the current PC. The
309 * "_count" value is in 16-bit code units. Does not advance rPC.
310 * For example, given instruction of format: AA|op CC|BB, it
314 .macro FETCH_BB _count _reg
315 movzbl (\_count*2)(rPC), \_reg
319 * Fetch the second byte from an offset past the current PC. The
320 * "_count" value is in 16-bit code units. Does not advance rPC.
321 * For example, given instruction of format: AA|op CC|BB, it
325 .macro FETCH_CC _count _reg
326 movzbl (\_count*2 + 1)(rPC), \_reg
330 * Fetch the second byte from an offset past the current PC. The
331 * "_count" value is in 16-bit code units. Does not advance rPC.
332 * This variant treats the value as signed.
335 .macro FETCH_CCs _count _reg
336 movsbl (\_count*2 + 1)(rPC), \_reg
341 * Fetch one byte from an offset past the current PC. Pass in the same
342 * "_count" as you would for FETCH, and an additional 0/1 indicating which
343 * byte of the halfword you want (lo/hi).
346 .macro FETCH_B _reg _count _byte
347 movzbl (\_count*2+\_byte)(rPC), \_reg
351 * Put the instruction's opcode field into the specified register.
354 .macro GET_INST_OPCODE _reg
355 movzbl rINSTbl, \_reg
359 * Begin executing the opcode in _reg.
362 .macro GOTO_OPCODE _reg
364 addl $dvmAsmInstructionStart,\_reg
371 * Macros pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE
372 * by using a jump table. _rFinish should must be the same register for
376 .macro FFETCH _rFinish
377 movzbl (rPC), \_rFinish
380 .macro FGETOP_JMPa _rFinish
382 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
386 * Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE
387 * by using a jump table. _rFinish and _count should must be the same register for
391 .macro FFETCH_ADV _count _rFinish
392 movzbl (\_count*2)(rPC), \_rFinish
395 .macro FGETOP_JMP _count _rFinish
396 movzbl (\_count*2 + 1)(rPC), rINST
397 addl $(\_count*2), rPC
398 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
401 .macro FGETOP_JMP2 _rFinish
403 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
406 .macro OLD_JMP_1 _count _rFinish
407 movzbl (\_count*2)(rPC), \_rFinish
411 .macro OLD_JMP_2 _rFinish
412 addl $dvmAsmInstructionStart,\_rFinish
415 .macro OLD_JMP_3 _count
416 addl $(\_count*2), rPC
419 .macro OLD_JMP_4 _rFinish
424 .macro OLD_JMP_A_1 _reg _rFinish
425 movzbl (rPC, \_reg), \_rFinish
429 .macro OLD_JMP_A_2 _rFinish
430 addl $dvmAsmInstructionStart,\_rFinish
433 .macro OLD_JMP_A_3 _reg _rFinish
435 movzbl 1(rPC, \_reg), rINST
440 * Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE
441 * by using a jump table. _rFinish and _reg should must be the same register for
445 .macro FFETCH_ADV_RB _reg _rFinish
446 movzbl (\_reg, rPC), \_rFinish
449 .macro FGETOP_RB_JMP _reg _rFinish
450 movzbl 1(\_reg, rPC), rINST
452 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
456 * Attempts to speed up FETCH_INST, GET_INST_OPCODE using
457 * a jump table. This macro should be called before FINISH_JMP where
458 * rFinish should be the same register containing the opcode value.
459 * This is an attempt to split up FINISH in order to reduce or remove
460 * potential stalls due to the wait for rFINISH.
463 .macro FINISH_FETCH _rFinish
464 movzbl (rPC), \_rFinish
470 * Attempts to speed up FETCH_ADVANCE_INST, GET_INST_OPCODE using
471 * a jump table. This macro should be called before FINISH_JMP where
472 * rFinish should be the same register containing the opcode value.
473 * This is an attempt to split up FINISH in order to reduce or remove
474 * potential stalls due to the wait for rFINISH.
477 .macro FINISH_FETCH_ADVANCE _count _rFinish
478 movzbl (\_count*2)(rPC), \_rFinish
479 movzbl (\_count*2 + 1)(rPC), rINST
480 addl $(\_count*2), rPC
484 * Attempts to speed up FETCH_ADVANCE_INST_RB, GET_INST_OPCODE using
485 * a jump table. This macro should be called before FINISH_JMP where
486 * rFinish should be the same register containing the opcode value.
487 * This is an attempt to split up FINISH in order to reduce or remove
488 * potential stalls due to the wait for rFINISH.
491 .macro FINISH_FETCH_ADVANCE_RB _reg _rFinish
492 movzbl (\_reg, rPC), \_rFinish
493 movzbl 1(\_reg, rPC), rINST
498 * Attempts to speed up GOTO_OPCODE using a jump table. This macro should
499 * be called after a FINISH_FETCH* instruction where rFinish should be the
500 * same register containing the opcode value. This is an attempt to split up
501 * FINISH in order to reduce or remove potential stalls due to the wait for rFINISH.
504 .macro FINISH_JMP _rFinish
505 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
509 * Attempts to speed up FETCH_INST, GET_INST_OPCODE, GOTO_OPCODE by using
510 * a jump table. Uses a single macro - but it should be faster if we
511 * split up the fetch for rFinish and the jump using rFinish.
515 movzbl (rPC), rFinish
517 jmp *dvmAsmInstructionJmpTable(,rFinish, 4)
521 * Attempts to speed up FETCH_ADVANCE_INST, GET_INST_OPCODE,
522 * GOTO_OPCODE by using a jump table. Uses a single macro -
523 * but it should be faster if we split up the fetch for rFinish
524 * and the jump using rFinish.
528 movzbl (\_count*2)(rPC), rFinish
529 movzbl (\_count*2 + 1)(rPC), rINST
530 addl $(\_count*2), rPC
531 jmp *dvmAsmInstructionJmpTable(,rFinish, 4)
535 * Attempts to speed up FETCH_ADVANCE_INST_RB, GET_INST_OPCODE,
536 * GOTO_OPCODE by using a jump table. Uses a single macro -
537 * but it should be faster if we split up the fetch for rFinish
538 * and the jump using rFinish.
541 .macro FINISH_RB _reg _rFinish
542 movzbl (\_reg, rPC), \_rFinish
543 movzbl 1(\_reg, rPC), rINST
545 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
548 #define sReg0 LOCAL0_OFFSET(%ebp)
549 #define sReg1 LOCAL1_OFFSET(%ebp)
550 #define sReg2 LOCAL2_OFFSET(%ebp)
551 #define sReg3 LOCAL3_OFFSET(%ebp)
554 * Hard coded helper values.
560 .quad 0x8000000000000000
563 .quad 0xFFFFFFFFFFFFFFFF
566 .quad 0x0000000000000000
568 .quad 0x000000000000003F
571 .quad 0x0000000000000040
574 .quad 0x7FFFFFFFFFFFFFFF
577 .quad 0x8000000000000000
580 .quad 0x0000000000000000
591 * This is a #include, not a %include, because we want the C pre-processor
592 * to expand the macros into assembler assignment statements.
594 #include "../common/asm-constants.h"
597 .global dvmAsmInstructionStart
598 .type dvmAsmInstructionStart, %function
599 dvmAsmInstructionStart = .L_OP_NOP
602 /* ------------------------------ */
604 .L_OP_NOP: /* 0x00 */
605 /* File: x86/OP_NOP.S */
606 FETCH_INST_OPCODE 1 %edx
610 /* ------------------------------ */
612 .L_OP_MOVE: /* 0x01 */
613 /* File: x86/OP_MOVE.S */
614 /* for move, move-object, long-to-int */
616 movzbl rINSTbl,%eax # eax<- BA
617 andb $0xf,%al # eax<- A
618 shrl $4,rINST # rINST<- B
619 GET_VREG_R %ecx rINST
620 FETCH_INST_OPCODE 1 %edx
622 SET_VREG %ecx %eax # fp[A]<-fp[B]
625 /* ------------------------------ */
627 .L_OP_MOVE_FROM16: /* 0x02 */
628 /* File: x86/OP_MOVE_FROM16.S */
629 /* for: move/from16, move-object/from16 */
631 movzx rINSTbl,%eax # eax <= AA
632 movw 2(rPC),rINSTw # rINSTw <= BBBB
633 GET_VREG_R %ecx rINST # ecx<- fp[BBBB]
634 FETCH_INST_OPCODE 2 %edx
636 SET_VREG %ecx %eax # fp[AA]<- ecx]
639 /* ------------------------------ */
641 .L_OP_MOVE_16: /* 0x03 */
642 /* File: x86/OP_MOVE_16.S */
643 /* for: move/16, move-object/16 */
644 /* op vAAAA, vBBBB */
645 movzwl 4(rPC),%ecx # ecx<- BBBB
646 movzwl 2(rPC),%eax # eax<- AAAA
648 FETCH_INST_OPCODE 3 %edx
653 /* ------------------------------ */
655 .L_OP_MOVE_WIDE: /* 0x04 */
656 /* File: x86/OP_MOVE_WIDE.S */
657 /* move-wide vA, vB */
658 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
659 movzbl rINSTbl,%ecx # ecx <- BA
660 sarl $4,rINST # rINST<- B
661 GET_VREG_WORD %eax rINST 0 # eax<- v[B+0]
662 GET_VREG_WORD rINST rINST 1 # rINST<- v[B+1]
663 andb $0xf,%cl # ecx <- A
664 FETCH_INST_OPCODE 1 %edx
665 SET_VREG_WORD rINST %ecx 1 # v[A+1]<- rINST
667 SET_VREG_WORD %eax %ecx 0 # v[A+0]<- eax
670 /* ------------------------------ */
672 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
673 /* File: x86/OP_MOVE_WIDE_FROM16.S */
674 /* move-wide/from16 vAA, vBBBB */
675 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
676 movzwl 2(rPC),%ecx # ecx<- BBBB
677 movzbl rINSTbl,%eax # eax<- AAAA
678 GET_VREG_WORD rINST %ecx 0 # rINST<- v[BBBB+0]
679 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1]
680 FETCH_INST_OPCODE 2 %edx
682 SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST
683 SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- eax
686 /* ------------------------------ */
688 .L_OP_MOVE_WIDE_16: /* 0x06 */
689 /* File: x86/OP_MOVE_WIDE_16.S */
690 /* move-wide/16 vAAAA, vBBBB */
691 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
692 movzwl 4(rPC),%ecx # ecx<- BBBB
693 movzwl 2(rPC),%eax # eax<- AAAA
694 GET_VREG_WORD rINST %ecx 0 # rINSTw_WORD<- v[BBBB+0]
695 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1]
696 FETCH_INST_OPCODE 3 %edx
697 SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST
699 SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- ecx
702 /* ------------------------------ */
704 .L_OP_MOVE_OBJECT: /* 0x07 */
705 /* File: x86/OP_MOVE_OBJECT.S */
706 /* File: x86/OP_MOVE.S */
707 /* for move, move-object, long-to-int */
709 movzbl rINSTbl,%eax # eax<- BA
710 andb $0xf,%al # eax<- A
711 shrl $4,rINST # rINST<- B
712 GET_VREG_R %ecx rINST
713 FETCH_INST_OPCODE 1 %edx
715 SET_VREG %ecx %eax # fp[A]<-fp[B]
719 /* ------------------------------ */
721 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
722 /* File: x86/OP_MOVE_OBJECT_FROM16.S */
723 /* File: x86/OP_MOVE_FROM16.S */
724 /* for: move/from16, move-object/from16 */
726 movzx rINSTbl,%eax # eax <= AA
727 movw 2(rPC),rINSTw # rINSTw <= BBBB
728 GET_VREG_R %ecx rINST # ecx<- fp[BBBB]
729 FETCH_INST_OPCODE 2 %edx
731 SET_VREG %ecx %eax # fp[AA]<- ecx]
735 /* ------------------------------ */
737 .L_OP_MOVE_OBJECT_16: /* 0x09 */
738 /* File: x86/OP_MOVE_OBJECT_16.S */
739 /* File: x86/OP_MOVE_16.S */
740 /* for: move/16, move-object/16 */
741 /* op vAAAA, vBBBB */
742 movzwl 4(rPC),%ecx # ecx<- BBBB
743 movzwl 2(rPC),%eax # eax<- AAAA
745 FETCH_INST_OPCODE 3 %edx
751 /* ------------------------------ */
753 .L_OP_MOVE_RESULT: /* 0x0a */
754 /* File: x86/OP_MOVE_RESULT.S */
755 /* for: move-result, move-result-object */
757 movl rGLUE,%eax # eax<- rGLUE
758 movzx rINSTbl,%ecx # ecx<- AA
759 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l
760 FETCH_INST_OPCODE 1 %edx
762 SET_VREG %eax %ecx # fp[AA]<- retval.l
765 /* ------------------------------ */
767 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
768 /* File: x86/OP_MOVE_RESULT_WIDE.S */
769 /* move-result-wide vAA */
771 movl offGlue_retval(%ecx),%eax
772 movl 4+offGlue_retval(%ecx),%ecx
773 FETCH_INST_OPCODE 1 %edx
774 SET_VREG_WORD %eax rINST 0 # v[AA+0] <- eax
775 SET_VREG_WORD %ecx rINST 1 # v[AA+1] <- ecx
779 /* ------------------------------ */
781 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
782 /* File: x86/OP_MOVE_RESULT_OBJECT.S */
783 /* File: x86/OP_MOVE_RESULT.S */
784 /* for: move-result, move-result-object */
786 movl rGLUE,%eax # eax<- rGLUE
787 movzx rINSTbl,%ecx # ecx<- AA
788 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l
789 FETCH_INST_OPCODE 1 %edx
791 SET_VREG %eax %ecx # fp[AA]<- retval.l
795 /* ------------------------------ */
797 .L_OP_MOVE_EXCEPTION: /* 0x0d */
798 /* File: x86/OP_MOVE_EXCEPTION.S */
799 /* move-exception vAA */
801 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
802 movl offThread_exception(%ecx),%eax # eax<- dvmGetException bypass
803 SET_VREG %eax rINST # fp[AA]<- exception object
804 FETCH_INST_OPCODE 1 %edx
806 movl $0,offThread_exception(%ecx) # dvmClearException bypass
809 /* ------------------------------ */
811 .L_OP_RETURN_VOID: /* 0x0e */
812 /* File: x86/OP_RETURN_VOID.S */
813 jmp common_returnFromMethod
815 /* ------------------------------ */
817 .L_OP_RETURN: /* 0x0f */
818 /* File: x86/OP_RETURN.S */
820 * Return a 32-bit value. Copies the return value into the "glue"
821 * structure, then jumps to the return handler.
823 * for: return, return-object
827 GET_VREG_R %eax rINST # eax<- vAA
828 movl %eax,offGlue_retval(%ecx) # retval.i <- AA
829 jmp common_returnFromMethod
831 /* ------------------------------ */
833 .L_OP_RETURN_WIDE: /* 0x10 */
834 /* File: x86/OP_RETURN_WIDE.S */
836 * Return a 64-bit value. Copies the return value into the "glue"
837 * structure, then jumps to the return handler.
839 /* return-wide vAA */
841 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0]
842 GET_VREG_WORD rINST rINST 1 # rINST<- v[AA+1]
843 movl %eax,offGlue_retval(%ecx)
844 movl rINST,4+offGlue_retval(%ecx)
845 jmp common_returnFromMethod
847 /* ------------------------------ */
849 .L_OP_RETURN_OBJECT: /* 0x11 */
850 /* File: x86/OP_RETURN_OBJECT.S */
851 /* File: x86/OP_RETURN.S */
853 * Return a 32-bit value. Copies the return value into the "glue"
854 * structure, then jumps to the return handler.
856 * for: return, return-object
860 GET_VREG_R %eax rINST # eax<- vAA
861 movl %eax,offGlue_retval(%ecx) # retval.i <- AA
862 jmp common_returnFromMethod
865 /* ------------------------------ */
867 .L_OP_CONST_4: /* 0x12 */
868 /* File: x86/OP_CONST_4.S */
869 /* const/4 vA, #+B */
870 movsx rINSTbl,%eax # eax<-ssssssBx
872 andl %eax,%ecx # ecx<- A
873 FETCH_INST_OPCODE 1 %edx
879 /* ------------------------------ */
881 .L_OP_CONST_16: /* 0x13 */
882 /* File: x86/OP_CONST_16.S */
883 /* const/16 vAA, #+BBBB */
884 movswl 2(rPC),%ecx # ecx<- ssssBBBB
885 movl rINST,%eax # eax<- AA
886 FETCH_INST_OPCODE 2 %edx
888 SET_VREG %ecx %eax # vAA<- ssssBBBB
891 /* ------------------------------ */
893 .L_OP_CONST: /* 0x14 */
894 /* File: x86/OP_CONST.S */
895 /* const vAA, #+BBBBbbbb */
896 movl 2(rPC),%eax # grab all 32 bits at once
897 movl rINST,%ecx # ecx<- AA
898 FETCH_INST_OPCODE 3 %edx
900 SET_VREG %eax %ecx # vAA<- eax
903 /* ------------------------------ */
905 .L_OP_CONST_HIGH16: /* 0x15 */
906 /* File: x86/OP_CONST_HIGH16.S */
907 /* const/high16 vAA, #+BBBB0000 */
908 movzwl 2(rPC),%eax # eax<- 0000BBBB
909 movl rINST,%ecx # ecx<- AA
910 FETCH_INST_OPCODE 2 %edx
912 sall $16,%eax # eax<- BBBB0000
913 SET_VREG %eax %ecx # vAA<- eax
916 /* ------------------------------ */
918 .L_OP_CONST_WIDE_16: /* 0x16 */
919 /* File: x86/OP_CONST_WIDE_16.S */
920 /* const-wide/16 vAA, #+BBBB */
921 movswl 2(rPC),%eax # eax<- ssssBBBB
922 cltd # rPC:eax<- ssssssssssssBBBB
923 SET_VREG_WORD %edx rINST 1 # store msw
924 FETCH_INST_OPCODE 2 %edx
925 SET_VREG_WORD %eax rINST 0 # store lsw
929 /* ------------------------------ */
931 .L_OP_CONST_WIDE_32: /* 0x17 */
932 /* File: x86/OP_CONST_WIDE_32.S */
933 /* const-wide/32 vAA, #+BBBBbbbb */
934 movl 2(rPC),%eax # eax<- BBBBbbbb
935 cltd # rPC:eax<- ssssssssssssBBBB
936 SET_VREG_WORD %edx rINST,1 # store msw
937 FETCH_INST_OPCODE 3 %edx
938 SET_VREG_WORD %eax rINST 0 # store lsw
942 /* ------------------------------ */
944 .L_OP_CONST_WIDE: /* 0x18 */
945 /* File: x86/OP_CONST_WIDE.S */
946 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
947 movl 2(rPC),%eax # eax<- lsw
948 movzbl rINSTbl,%ecx # ecx<- AA
949 movl 6(rPC),rINST # rINST<- msw
950 leal (rFP,%ecx,4),%ecx # dst addr
952 FETCH_INST_OPCODE 5 %edx
957 /* ------------------------------ */
959 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
960 /* File: x86/OP_CONST_WIDE_HIGH16.S */
961 /* const-wide/high16 vAA, #+BBBB000000000000 */
962 movzwl 2(rPC),%eax # eax<- 0000BBBB
963 FETCH_INST_OPCODE 2 %edx
965 sall $16,%eax # eax<- BBBB0000
966 SET_VREG_WORD %eax rINST 1 # v[AA+1]<- eax
968 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
971 /* ------------------------------ */
973 .L_OP_CONST_STRING: /* 0x1a */
974 /* File: x86/OP_CONST_STRING.S */
976 /* const/string vAA, String@BBBB */
978 movzwl 2(rPC),%eax # eax<- BBBB
979 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
980 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
981 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
983 FETCH_INST_OPCODE 2 %edx
984 testl %eax,%eax # resolved yet?
985 je .LOP_CONST_STRING_resolve
986 SET_VREG %eax %ecx # vAA<- rResString[BBBB]
990 /* ------------------------------ */
992 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
993 /* File: x86/OP_CONST_STRING_JUMBO.S */
995 /* const/string vAA, String@BBBBBBBB */
997 movl 2(rPC),%eax # eax<- BBBBBBBB
998 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
999 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
1000 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
1002 FETCH_INST_OPCODE 3 %edx
1003 testl %eax,%eax # resolved yet?
1004 je .LOP_CONST_STRING_JUMBO_resolve
1005 SET_VREG %eax %ecx # vAA<- rResString[BBBB]
1009 /* ------------------------------ */
1011 .L_OP_CONST_CLASS: /* 0x1c */
1012 /* File: x86/OP_CONST_CLASS.S */
1014 /* const/class vAA, Class@BBBB */
1016 movzwl 2(rPC),%eax # eax<- BBBB
1017 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
1018 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
1019 movl (%ecx,%eax,4),%eax # eax<- rResClasses[BBBB]
1021 FETCH_INST_OPCODE 2 %edx
1022 testl %eax,%eax # resolved yet?
1023 je .LOP_CONST_CLASS_resolve
1024 SET_VREG %eax %ecx # vAA<- rResClasses[BBBB]
1028 /* ------------------------------ */
1030 .L_OP_MONITOR_ENTER: /* 0x1d */
1031 /* File: x86/OP_MONITOR_ENTER.S */
1033 * Synchronize on an object.
1035 /* monitor-enter vAA */
1037 GET_VREG_R %eax rINST # eax<- vAA
1038 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
1040 testl %eax,%eax # null object?
1041 EXPORT_PC # need for precise GC, MONITOR_TRACKING
1042 jne .LOP_MONITOR_ENTER_continue
1043 jmp common_errNullObject
1045 /* ------------------------------ */
1047 .L_OP_MONITOR_EXIT: /* 0x1e */
1048 /* File: x86/OP_MONITOR_EXIT.S */
1052 * Exceptions that occur when unlocking a monitor need to appear as
1053 * if they happened at the following instruction. See the Dalvik
1056 /* monitor-exit vAA */
1057 GET_VREG_R %eax rINST
1060 testl %eax,%eax # null object?
1061 je .LOP_MONITOR_EXIT_errNullObject # go if so
1062 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
1063 movl %eax,OUT_ARG1(%esp)
1064 movl %ecx,OUT_ARG0(%esp)
1065 jmp .LOP_MONITOR_EXIT_continue
1067 /* ------------------------------ */
1069 .L_OP_CHECK_CAST: /* 0x1f */
1070 /* File: x86/OP_CHECK_CAST.S */
1072 * Check to see if a cast from one class to another is allowed.
1074 /* check-cast vAA, class@BBBB */
1076 GET_VREG_R rINST,rINST # rINST<- vAA (object)
1077 movzwl 2(rPC),%eax # eax<- BBBB
1078 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
1079 testl rINST,rINST # is oject null?
1080 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
1081 je .LOP_CHECK_CAST_okay # null obj, cast always succeeds
1082 movl (%ecx,%eax,4),%eax # eax<- resolved class
1083 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
1084 testl %eax,%eax # have we resolved this before?
1085 je .LOP_CHECK_CAST_resolve # no, go do it now
1086 .LOP_CHECK_CAST_resolved:
1087 cmpl %eax,%ecx # same class (trivial success)?
1088 jne .LOP_CHECK_CAST_fullcheck # no, do full check
1089 .LOP_CHECK_CAST_okay:
1090 FETCH_INST_OPCODE 2 %edx
1094 /* ------------------------------ */
1096 .L_OP_INSTANCE_OF: /* 0x20 */
1097 /* File: x86/OP_INSTANCE_OF.S */
1099 * Check to see if an object reference is an instance of a class.
1101 * Most common situation is a non-null object, being compared against
1102 * an already-resolved class.
1104 /* instance-of vA, vB, class@CCCC */
1105 movl rINST,%eax # eax<- BA
1106 sarl $4,%eax # eax<- B
1107 GET_VREG_R %eax %eax # eax<- vB (obj)
1109 testl %eax,%eax # object null?
1110 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
1111 je .LOP_INSTANCE_OF_store # null obj, not instance, store it
1112 movzwl 2(rPC),%edx # edx<- CCCC
1113 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
1114 movl (%ecx,%edx,4),%ecx # ecx<- resolved class
1115 movl offObject_clazz(%eax),%eax # eax<- obj->clazz
1116 testl %ecx,%ecx # have we resolved this before?
1117 je .LOP_INSTANCE_OF_resolve # not resolved, do it now
1118 .LOP_INSTANCE_OF_resolved: # eax<- obj->clazz, ecx<- resolved class
1119 cmpl %eax,%ecx # same class (trivial success)?
1120 je .LOP_INSTANCE_OF_trivial # yes, trivial finish
1121 jmp .LOP_INSTANCE_OF_fullcheck # no, do full check
1123 /* ------------------------------ */
1125 .L_OP_ARRAY_LENGTH: /* 0x21 */
1126 /* File: x86/OP_ARRAY_LENGTH.S */
1128 * Return the length of an array.
1130 mov rINST,%eax # eax<- BA
1131 sarl $4,rINST # rINST<- B
1132 GET_VREG_R %ecx rINST # ecx<- vB (object ref)
1133 andb $0xf,%al # eax<- A
1134 testl %ecx,%ecx # is null?
1135 je common_errNullObject
1136 FETCH_INST_OPCODE 1 %edx
1137 movl offArrayObject_length(%ecx),%ecx
1142 /* ------------------------------ */
1144 .L_OP_NEW_INSTANCE: /* 0x22 */
1145 /* File: x86/OP_NEW_INSTANCE.S */
1147 * Create a new instance of a class.
1149 /* new-instance vAA, class@BBBB */
1151 movzwl 2(rPC),%eax # eax<- BBBB
1152 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
1153 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
1155 movl (%ecx,%eax,4),%ecx # ecx<- resolved class
1156 testl %ecx,%ecx # resolved?
1157 je .LOP_NEW_INSTANCE_resolve # no, go do it
1158 .LOP_NEW_INSTANCE_resolved: # on entry, ecx<- class
1159 cmpb $CLASS_INITIALIZED,offClassObject_status(%ecx)
1160 je .LOP_NEW_INSTANCE_initialized
1161 jmp .LOP_NEW_INSTANCE_needinit
1163 /* ------------------------------ */
1165 .L_OP_NEW_ARRAY: /* 0x23 */
1166 /* File: x86/OP_NEW_ARRAY.S */
1168 * Allocate an array of objects, specified with the array class
1171 * The verifier guarantees that this is an array class, so we don't
1172 * check for it here.
1174 /* new-array vA, vB, class@CCCC */
1177 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
1178 movzwl 2(rPC),%eax # eax<- CCCC
1179 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
1180 movl (%ecx,%eax,4),%ecx # ecx<- resolved class
1182 sarl $4,%eax # eax<- B
1183 GET_VREG_R %eax %eax # eax<- vB (array length)
1184 andb $0xf,rINSTbl # rINST<- A
1186 js common_errNegativeArraySize # bail
1187 testl %ecx,%ecx # already resolved?
1188 jne .LOP_NEW_ARRAY_finish # yes, fast path
1189 jmp .LOP_NEW_ARRAY_resolve # resolve now
1191 /* ------------------------------ */
1193 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1194 /* File: x86/OP_FILLED_NEW_ARRAY.S */
1196 * Create a new array with elements filled from registers.
1198 * for: filled-new-array, filled-new-array/range
1200 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1201 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1203 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
1204 movzwl 2(rPC),%ecx # ecx<- BBBB
1205 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
1206 movl (%eax,%ecx,4),%eax # eax<- resolved class
1208 testl %eax,%eax # already resolved?
1209 jne .LOP_FILLED_NEW_ARRAY_continue # yes, continue
1210 # less frequent path, so we'll redo some work
1212 movl $0,OUT_ARG2(%esp) # arg2<- false
1213 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
1214 movl offGlue_method(%eax),%eax # eax<- glue->method
1215 jmp .LOP_FILLED_NEW_ARRAY_more
1217 /* ------------------------------ */
1219 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1220 /* File: x86/OP_FILLED_NEW_ARRAY_RANGE.S */
1221 /* File: x86/OP_FILLED_NEW_ARRAY.S */
1223 * Create a new array with elements filled from registers.
1225 * for: filled-new-array, filled-new-array/range
1227 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1228 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1230 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
1231 movzwl 2(rPC),%ecx # ecx<- BBBB
1232 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
1233 movl (%eax,%ecx,4),%eax # eax<- resolved class
1235 testl %eax,%eax # already resolved?
1236 jne .LOP_FILLED_NEW_ARRAY_RANGE_continue # yes, continue
1237 # less frequent path, so we'll redo some work
1239 movl $0,OUT_ARG2(%esp) # arg2<- false
1240 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
1241 movl offGlue_method(%eax),%eax # eax<- glue->method
1242 jmp .LOP_FILLED_NEW_ARRAY_RANGE_more
1245 /* ------------------------------ */
1247 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1248 /* File: x86/OP_FILL_ARRAY_DATA.S */
1249 /* fill-array-data vAA, +BBBBBBBB */
1250 movl 2(rPC),%ecx # ecx<- BBBBbbbb
1251 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
1252 GET_VREG_R %eax rINST
1254 movl %eax,OUT_ARG0(%esp)
1255 movl %ecx,OUT_ARG1(%esp)
1256 call dvmInterpHandleFillArrayData
1257 FETCH_INST_OPCODE 3 %edx
1258 testl %eax,%eax # exception thrown?
1259 je common_exceptionThrown
1263 /* ------------------------------ */
1265 .L_OP_THROW: /* 0x27 */
1266 /* File: x86/OP_THROW.S */
1268 * Throw an exception object in the current thread.
1273 GET_VREG_R %eax rINST # eax<- exception object
1274 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
1275 testl %eax,%eax # null object?
1276 je common_errNullObject
1277 movl %eax,offThread_exception(%ecx) # thread->exception<- obj
1278 jmp common_exceptionThrown
1280 /* ------------------------------ */
1282 .L_OP_GOTO: /* 0x28 */
1283 /* File: x86/OP_GOTO.S */
1285 * Unconditional branch, 8-bit offset.
1287 * The branch distance is a signed code-unit offset, which we need to
1288 * double to get a byte offset.
1291 movsbl rINSTbl,rINST # ebx<- ssssssAA
1292 testl rINST,rINST # test for <0
1293 js common_backwardBranch
1295 FETCH_INST_INDEXED %eax
1296 ADVANCE_PC_INDEXED %eax
1299 /* ------------------------------ */
1301 .L_OP_GOTO_16: /* 0x29 */
1302 /* File: x86/OP_GOTO_16.S */
1304 * Unconditional branch, 16-bit offset.
1306 * The branch distance is a signed code-unit offset
1309 movswl 2(rPC),rINST # rINST<- ssssAAAA
1310 testl rINST,rINST # test for <0
1311 js common_backwardBranch
1313 FETCH_INST_INDEXED %eax
1314 ADVANCE_PC_INDEXED %eax
1317 /* ------------------------------ */
1319 .L_OP_GOTO_32: /* 0x2a */
1320 /* File: x86/OP_GOTO_32.S */
1322 * Unconditional branch, 32-bit offset.
1324 * The branch distance is a signed code-unit offset.
1326 * Unlike most opcodes, this one is allowed to branch to itself, so
1327 * our "backward branch" test must be "<=0" instead of "<0".
1329 /* goto/32 AAAAAAAA */
1330 movl 2(rPC),rINST # rINST<- AAAAAAAA
1331 cmpl $0,rINST # test for <= 0
1332 jle common_backwardBranch
1334 FETCH_INST_INDEXED %eax
1335 ADVANCE_PC_INDEXED %eax
1338 /* ------------------------------ */
1340 .L_OP_PACKED_SWITCH: /* 0x2b */
1341 /* File: x86/OP_PACKED_SWITCH.S */
1343 * Handle a packed-switch or sparse-switch instruction. In both cases
1344 * we decode it and hand it off to a helper function.
1346 * We don't really expect backward branches in a switch statement, but
1347 * they're perfectly legal, so we check for them here.
1349 * for: packed-switch, sparse-switch
1352 movl 2(rPC),%ecx # ecx<- BBBBbbbb
1353 GET_VREG_R %eax rINST # eax<- vAA
1354 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
1355 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
1356 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
1357 call dvmInterpHandlePackedSwitch
1359 movl %eax,rINST # set up word offset
1360 jle common_backwardBranch # check on special actions
1361 ADVANCE_PC_INDEXED rINST
1365 /* ------------------------------ */
1367 .L_OP_SPARSE_SWITCH: /* 0x2c */
1368 /* File: x86/OP_SPARSE_SWITCH.S */
1369 /* File: x86/OP_PACKED_SWITCH.S */
1371 * Handle a packed-switch or sparse-switch instruction. In both cases
1372 * we decode it and hand it off to a helper function.
1374 * We don't really expect backward branches in a switch statement, but
1375 * they're perfectly legal, so we check for them here.
1377 * for: packed-switch, sparse-switch
1380 movl 2(rPC),%ecx # ecx<- BBBBbbbb
1381 GET_VREG_R %eax rINST # eax<- vAA
1382 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
1383 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
1384 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
1385 call dvmInterpHandleSparseSwitch
1387 movl %eax,rINST # set up word offset
1388 jle common_backwardBranch # check on special actions
1389 ADVANCE_PC_INDEXED rINST
1394 /* ------------------------------ */
1396 .L_OP_CMPL_FLOAT: /* 0x2d */
1397 /* File: x86/OP_CMPL_FLOAT.S */
1398 /* File: x86/OP_CMPG_DOUBLE.S */
1399 /* float/double_cmp[gl] vAA, vBB, vCC */
1400 movzbl 3(rPC),%eax # eax<- CC
1401 movzbl 2(rPC),%ecx # ecx<- BB
1410 fucompp # z if equal, p set if NaN, c set if st0 < st1
1414 FETCH_INST_OPCODE 2 %edx
1415 jp .LOP_CMPL_FLOAT_isNaN
1416 je .LOP_CMPL_FLOAT_finish
1418 jb .LOP_CMPL_FLOAT_finish
1420 .LOP_CMPL_FLOAT_finish:
1426 /* ------------------------------ */
1428 .L_OP_CMPG_FLOAT: /* 0x2e */
1429 /* File: x86/OP_CMPG_FLOAT.S */
1430 /* File: x86/OP_CMPG_DOUBLE.S */
1431 /* float/double_cmp[gl] vAA, vBB, vCC */
1432 movzbl 3(rPC),%eax # eax<- CC
1433 movzbl 2(rPC),%ecx # ecx<- BB
1442 fucompp # z if equal, p set if NaN, c set if st0 < st1
1446 FETCH_INST_OPCODE 2 %edx
1447 jp .LOP_CMPG_FLOAT_isNaN
1448 je .LOP_CMPG_FLOAT_finish
1450 jb .LOP_CMPG_FLOAT_finish
1452 .LOP_CMPG_FLOAT_finish:
1458 /* ------------------------------ */
1460 .L_OP_CMPL_DOUBLE: /* 0x2f */
1461 /* File: x86/OP_CMPL_DOUBLE.S */
1462 /* File: x86/OP_CMPG_DOUBLE.S */
1463 /* float/double_cmp[gl] vAA, vBB, vCC */
1464 movzbl 3(rPC),%eax # eax<- CC
1465 movzbl 2(rPC),%ecx # ecx<- BB
1474 fucompp # z if equal, p set if NaN, c set if st0 < st1
1478 FETCH_INST_OPCODE 2 %edx
1479 jp .LOP_CMPL_DOUBLE_isNaN
1480 je .LOP_CMPL_DOUBLE_finish
1482 jb .LOP_CMPL_DOUBLE_finish
1484 .LOP_CMPL_DOUBLE_finish:
1490 /* ------------------------------ */
1492 .L_OP_CMPG_DOUBLE: /* 0x30 */
1493 /* File: x86/OP_CMPG_DOUBLE.S */
1494 /* float/double_cmp[gl] vAA, vBB, vCC */
1495 movzbl 3(rPC),%eax # eax<- CC
1496 movzbl 2(rPC),%ecx # ecx<- BB
1505 fucompp # z if equal, p set if NaN, c set if st0 < st1
1509 FETCH_INST_OPCODE 2 %edx
1510 jp .LOP_CMPG_DOUBLE_isNaN
1511 je .LOP_CMPG_DOUBLE_finish
1513 jb .LOP_CMPG_DOUBLE_finish
1515 .LOP_CMPG_DOUBLE_finish:
1520 /* ------------------------------ */
1522 .L_OP_CMP_LONG: /* 0x31 */
1523 /* File: x86/OP_CMP_LONG.S */
1525 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1526 * register based on the results of the comparison.
1528 /* cmp-long vAA, vBB, vCC */
1529 movzbl 2(rPC),%ecx # ecx<- BB
1530 movzbl 3(rPC),%edx # edx<- CC
1531 GET_VREG_WORD %eax %ecx,1 # eax<- v[BB+1]
1532 GET_VREG_WORD %ecx %ecx 0 # ecx<- v[BB+0]
1533 cmpl 4(rFP,%edx,4),%eax
1534 jl .LOP_CMP_LONG_smaller
1535 jg .LOP_CMP_LONG_bigger
1536 sub (rFP,%edx,4),%ecx
1537 ja .LOP_CMP_LONG_bigger
1538 jb .LOP_CMP_LONG_smaller
1539 jmp .LOP_CMP_LONG_finish
1541 /* ------------------------------ */
1543 .L_OP_IF_EQ: /* 0x32 */
1544 /* File: x86/OP_IF_EQ.S */
1545 /* File: x86/bincmp.S */
1547 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1548 * fragment that specifies the *reverse* comparison to perform, e.g.
1549 * for "if-le" you would use "gt".
1551 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1553 /* if-cmp vA, vB, +CCCC */
1554 movzx rINSTbl,%ecx # ecx <- A+
1555 andb $0xf,%cl # ecx <- A
1556 GET_VREG_R %eax %ecx # eax <- vA
1557 sarl $4,rINST # rINST<- B
1558 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1559 movswl 2(rPC),rINST # Get signed branch offset
1560 movl $2,%eax # assume not taken
1563 js common_backwardBranch
1566 FETCH_INST_INDEXED %eax
1567 ADVANCE_PC_INDEXED %eax
1571 /* ------------------------------ */
1573 .L_OP_IF_NE: /* 0x33 */
1574 /* File: x86/OP_IF_NE.S */
1575 /* File: x86/bincmp.S */
1577 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1578 * fragment that specifies the *reverse* comparison to perform, e.g.
1579 * for "if-le" you would use "gt".
1581 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1583 /* if-cmp vA, vB, +CCCC */
1584 movzx rINSTbl,%ecx # ecx <- A+
1585 andb $0xf,%cl # ecx <- A
1586 GET_VREG_R %eax %ecx # eax <- vA
1587 sarl $4,rINST # rINST<- B
1588 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1589 movswl 2(rPC),rINST # Get signed branch offset
1590 movl $2,%eax # assume not taken
1593 js common_backwardBranch
1596 FETCH_INST_INDEXED %eax
1597 ADVANCE_PC_INDEXED %eax
1601 /* ------------------------------ */
1603 .L_OP_IF_LT: /* 0x34 */
1604 /* File: x86/OP_IF_LT.S */
1605 /* File: x86/bincmp.S */
1607 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1608 * fragment that specifies the *reverse* comparison to perform, e.g.
1609 * for "if-le" you would use "gt".
1611 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1613 /* if-cmp vA, vB, +CCCC */
1614 movzx rINSTbl,%ecx # ecx <- A+
1615 andb $0xf,%cl # ecx <- A
1616 GET_VREG_R %eax %ecx # eax <- vA
1617 sarl $4,rINST # rINST<- B
1618 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1619 movswl 2(rPC),rINST # Get signed branch offset
1620 movl $2,%eax # assume not taken
1623 js common_backwardBranch
1626 FETCH_INST_INDEXED %eax
1627 ADVANCE_PC_INDEXED %eax
1631 /* ------------------------------ */
1633 .L_OP_IF_GE: /* 0x35 */
1634 /* File: x86/OP_IF_GE.S */
1635 /* File: x86/bincmp.S */
1637 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1638 * fragment that specifies the *reverse* comparison to perform, e.g.
1639 * for "if-le" you would use "gt".
1641 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1643 /* if-cmp vA, vB, +CCCC */
1644 movzx rINSTbl,%ecx # ecx <- A+
1645 andb $0xf,%cl # ecx <- A
1646 GET_VREG_R %eax %ecx # eax <- vA
1647 sarl $4,rINST # rINST<- B
1648 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1649 movswl 2(rPC),rINST # Get signed branch offset
1650 movl $2,%eax # assume not taken
1653 js common_backwardBranch
1656 FETCH_INST_INDEXED %eax
1657 ADVANCE_PC_INDEXED %eax
1661 /* ------------------------------ */
1663 .L_OP_IF_GT: /* 0x36 */
1664 /* File: x86/OP_IF_GT.S */
1665 /* File: x86/bincmp.S */
1667 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1668 * fragment that specifies the *reverse* comparison to perform, e.g.
1669 * for "if-le" you would use "gt".
1671 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1673 /* if-cmp vA, vB, +CCCC */
1674 movzx rINSTbl,%ecx # ecx <- A+
1675 andb $0xf,%cl # ecx <- A
1676 GET_VREG_R %eax %ecx # eax <- vA
1677 sarl $4,rINST # rINST<- B
1678 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1679 movswl 2(rPC),rINST # Get signed branch offset
1680 movl $2,%eax # assume not taken
1683 js common_backwardBranch
1686 FETCH_INST_INDEXED %eax
1687 ADVANCE_PC_INDEXED %eax
1691 /* ------------------------------ */
1693 .L_OP_IF_LE: /* 0x37 */
1694 /* File: x86/OP_IF_LE.S */
1695 /* File: x86/bincmp.S */
1697 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1698 * fragment that specifies the *reverse* comparison to perform, e.g.
1699 * for "if-le" you would use "gt".
1701 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1703 /* if-cmp vA, vB, +CCCC */
1704 movzx rINSTbl,%ecx # ecx <- A+
1705 andb $0xf,%cl # ecx <- A
1706 GET_VREG_R %eax %ecx # eax <- vA
1707 sarl $4,rINST # rINST<- B
1708 cmpl (rFP,rINST,4),%eax # compare (vA, vB)
1709 movswl 2(rPC),rINST # Get signed branch offset
1710 movl $2,%eax # assume not taken
1713 js common_backwardBranch
1716 FETCH_INST_INDEXED %eax
1717 ADVANCE_PC_INDEXED %eax
1721 /* ------------------------------ */
1723 .L_OP_IF_EQZ: /* 0x38 */
1724 /* File: x86/OP_IF_EQZ.S */
1725 /* File: x86/zcmp.S */
1727 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1728 * fragment that specifies the *reverse* comparison to perform, e.g.
1729 * for "if-le" you would use "gt".
1731 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1733 /* if-cmp vAA, +BBBB */
1734 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1735 movswl 2(rPC),rINST # fetch signed displacement
1736 movl $2,%eax # assume branch not taken
1739 js common_backwardBranch
1742 FETCH_INST_INDEXED %eax
1743 ADVANCE_PC_INDEXED %eax
1747 /* ------------------------------ */
1749 .L_OP_IF_NEZ: /* 0x39 */
1750 /* File: x86/OP_IF_NEZ.S */
1751 /* File: x86/zcmp.S */
1753 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1754 * fragment that specifies the *reverse* comparison to perform, e.g.
1755 * for "if-le" you would use "gt".
1757 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1759 /* if-cmp vAA, +BBBB */
1760 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1761 movswl 2(rPC),rINST # fetch signed displacement
1762 movl $2,%eax # assume branch not taken
1765 js common_backwardBranch
1768 FETCH_INST_INDEXED %eax
1769 ADVANCE_PC_INDEXED %eax
1773 /* ------------------------------ */
1775 .L_OP_IF_LTZ: /* 0x3a */
1776 /* File: x86/OP_IF_LTZ.S */
1777 /* File: x86/zcmp.S */
1779 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1780 * fragment that specifies the *reverse* comparison to perform, e.g.
1781 * for "if-le" you would use "gt".
1783 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1785 /* if-cmp vAA, +BBBB */
1786 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1787 movswl 2(rPC),rINST # fetch signed displacement
1788 movl $2,%eax # assume branch not taken
1791 js common_backwardBranch
1794 FETCH_INST_INDEXED %eax
1795 ADVANCE_PC_INDEXED %eax
1799 /* ------------------------------ */
1801 .L_OP_IF_GEZ: /* 0x3b */
1802 /* File: x86/OP_IF_GEZ.S */
1803 /* File: x86/zcmp.S */
1805 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1806 * fragment that specifies the *reverse* comparison to perform, e.g.
1807 * for "if-le" you would use "gt".
1809 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1811 /* if-cmp vAA, +BBBB */
1812 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1813 movswl 2(rPC),rINST # fetch signed displacement
1814 movl $2,%eax # assume branch not taken
1817 js common_backwardBranch
1820 FETCH_INST_INDEXED %eax
1821 ADVANCE_PC_INDEXED %eax
1825 /* ------------------------------ */
1827 .L_OP_IF_GTZ: /* 0x3c */
1828 /* File: x86/OP_IF_GTZ.S */
1829 /* File: x86/zcmp.S */
1831 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1832 * fragment that specifies the *reverse* comparison to perform, e.g.
1833 * for "if-le" you would use "gt".
1835 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1837 /* if-cmp vAA, +BBBB */
1838 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1839 movswl 2(rPC),rINST # fetch signed displacement
1840 movl $2,%eax # assume branch not taken
1843 js common_backwardBranch
1846 FETCH_INST_INDEXED %eax
1847 ADVANCE_PC_INDEXED %eax
1851 /* ------------------------------ */
1853 .L_OP_IF_LEZ: /* 0x3d */
1854 /* File: x86/OP_IF_LEZ.S */
1855 /* File: x86/zcmp.S */
1857 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1858 * fragment that specifies the *reverse* comparison to perform, e.g.
1859 * for "if-le" you would use "gt".
1861 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1863 /* if-cmp vAA, +BBBB */
1864 cmpl $0,(rFP,rINST,4) # compare (vA, 0)
1865 movswl 2(rPC),rINST # fetch signed displacement
1866 movl $2,%eax # assume branch not taken
1869 js common_backwardBranch
1872 FETCH_INST_INDEXED %eax
1873 ADVANCE_PC_INDEXED %eax
1877 /* ------------------------------ */
1879 .L_OP_UNUSED_3E: /* 0x3e */
1880 /* File: x86/OP_UNUSED_3E.S */
1881 /* File: x86/unused.S */
1885 /* ------------------------------ */
1887 .L_OP_UNUSED_3F: /* 0x3f */
1888 /* File: x86/OP_UNUSED_3F.S */
1889 /* File: x86/unused.S */
1893 /* ------------------------------ */
1895 .L_OP_UNUSED_40: /* 0x40 */
1896 /* File: x86/OP_UNUSED_40.S */
1897 /* File: x86/unused.S */
1901 /* ------------------------------ */
1903 .L_OP_UNUSED_41: /* 0x41 */
1904 /* File: x86/OP_UNUSED_41.S */
1905 /* File: x86/unused.S */
1909 /* ------------------------------ */
1911 .L_OP_UNUSED_42: /* 0x42 */
1912 /* File: x86/OP_UNUSED_42.S */
1913 /* File: x86/unused.S */
1917 /* ------------------------------ */
1919 .L_OP_UNUSED_43: /* 0x43 */
1920 /* File: x86/OP_UNUSED_43.S */
1921 /* File: x86/unused.S */
1925 /* ------------------------------ */
1927 .L_OP_AGET: /* 0x44 */
1928 /* File: x86/OP_AGET.S */
1930 * Array get, 32 bits or less. vAA <- vBB[vCC].
1932 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1934 /* op vAA, vBB, vCC */
1935 movzbl 2(rPC),%eax # eax<- BB
1936 movzbl 3(rPC),%ecx # ecx<- CC
1937 GET_VREG_R %eax %eax # eax<- vBB (array object)
1938 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
1939 testl %eax,%eax # null array object?
1940 je common_errNullObject # bail if so
1941 cmpl offArrayObject_length(%eax),%ecx
1942 jae common_errArrayIndex # index >= length, bail
1943 movl offArrayObject_contents(%eax,%ecx,4),%eax
1945 FETCH_INST_OPCODE 2 %edx
1950 /* ------------------------------ */
1952 .L_OP_AGET_WIDE: /* 0x45 */
1953 /* File: x86/OP_AGET_WIDE.S */
1955 * Array get, 64 bits. vAA <- vBB[vCC].
1958 /* op vAA, vBB, vCC */
1959 movzbl 2(rPC),%eax # eax<- BB
1960 movzbl 3(rPC),%ecx # ecx<- CC
1961 GET_VREG_R %eax %eax # eax<- vBB (array object)
1962 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
1963 testl %eax,%eax # null array object?
1964 je common_errNullObject # bail if so
1965 cmpl offArrayObject_length(%eax),%ecx
1966 jb .LOP_AGET_WIDE_finish # index < length, OK
1967 jmp common_errArrayIndex # index >= length, bail
1969 /* ------------------------------ */
1971 .L_OP_AGET_OBJECT: /* 0x46 */
1972 /* File: x86/OP_AGET_OBJECT.S */
1973 /* File: x86/OP_AGET.S */
1975 * Array get, 32 bits or less. vAA <- vBB[vCC].
1977 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1979 /* op vAA, vBB, vCC */
1980 movzbl 2(rPC),%eax # eax<- BB
1981 movzbl 3(rPC),%ecx # ecx<- CC
1982 GET_VREG_R %eax %eax # eax<- vBB (array object)
1983 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
1984 testl %eax,%eax # null array object?
1985 je common_errNullObject # bail if so
1986 cmpl offArrayObject_length(%eax),%ecx
1987 jae common_errArrayIndex # index >= length, bail
1988 movl offArrayObject_contents(%eax,%ecx,4),%eax
1989 .LOP_AGET_OBJECT_finish:
1990 FETCH_INST_OPCODE 2 %edx
1996 /* ------------------------------ */
1998 .L_OP_AGET_BOOLEAN: /* 0x47 */
1999 /* File: x86/OP_AGET_BOOLEAN.S */
2000 /* File: x86/OP_AGET.S */
2002 * Array get, 32 bits or less. vAA <- vBB[vCC].
2004 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2006 /* op vAA, vBB, vCC */
2007 movzbl 2(rPC),%eax # eax<- BB
2008 movzbl 3(rPC),%ecx # ecx<- CC
2009 GET_VREG_R %eax %eax # eax<- vBB (array object)
2010 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2011 testl %eax,%eax # null array object?
2012 je common_errNullObject # bail if so
2013 cmpl offArrayObject_length(%eax),%ecx
2014 jae common_errArrayIndex # index >= length, bail
2015 movzbl offArrayObject_contents(%eax,%ecx,1),%eax
2016 .LOP_AGET_BOOLEAN_finish:
2017 FETCH_INST_OPCODE 2 %edx
2023 /* ------------------------------ */
2025 .L_OP_AGET_BYTE: /* 0x48 */
2026 /* File: x86/OP_AGET_BYTE.S */
2027 /* File: x86/OP_AGET.S */
2029 * Array get, 32 bits or less. vAA <- vBB[vCC].
2031 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2033 /* op vAA, vBB, vCC */
2034 movzbl 2(rPC),%eax # eax<- BB
2035 movzbl 3(rPC),%ecx # ecx<- CC
2036 GET_VREG_R %eax %eax # eax<- vBB (array object)
2037 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2038 testl %eax,%eax # null array object?
2039 je common_errNullObject # bail if so
2040 cmpl offArrayObject_length(%eax),%ecx
2041 jae common_errArrayIndex # index >= length, bail
2042 movsbl offArrayObject_contents(%eax,%ecx,1),%eax
2043 .LOP_AGET_BYTE_finish:
2044 FETCH_INST_OPCODE 2 %edx
2050 /* ------------------------------ */
2052 .L_OP_AGET_CHAR: /* 0x49 */
2053 /* File: x86/OP_AGET_CHAR.S */
2054 /* File: x86/OP_AGET.S */
2056 * Array get, 32 bits or less. vAA <- vBB[vCC].
2058 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2060 /* op vAA, vBB, vCC */
2061 movzbl 2(rPC),%eax # eax<- BB
2062 movzbl 3(rPC),%ecx # ecx<- CC
2063 GET_VREG_R %eax %eax # eax<- vBB (array object)
2064 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2065 testl %eax,%eax # null array object?
2066 je common_errNullObject # bail if so
2067 cmpl offArrayObject_length(%eax),%ecx
2068 jae common_errArrayIndex # index >= length, bail
2069 movzwl offArrayObject_contents(%eax,%ecx,2),%eax
2070 .LOP_AGET_CHAR_finish:
2071 FETCH_INST_OPCODE 2 %edx
2077 /* ------------------------------ */
2079 .L_OP_AGET_SHORT: /* 0x4a */
2080 /* File: x86/OP_AGET_SHORT.S */
2081 /* File: x86/OP_AGET.S */
2083 * Array get, 32 bits or less. vAA <- vBB[vCC].
2085 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2087 /* op vAA, vBB, vCC */
2088 movzbl 2(rPC),%eax # eax<- BB
2089 movzbl 3(rPC),%ecx # ecx<- CC
2090 GET_VREG_R %eax %eax # eax<- vBB (array object)
2091 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2092 testl %eax,%eax # null array object?
2093 je common_errNullObject # bail if so
2094 cmpl offArrayObject_length(%eax),%ecx
2095 jae common_errArrayIndex # index >= length, bail
2096 movswl offArrayObject_contents(%eax,%ecx,2),%eax
2097 .LOP_AGET_SHORT_finish:
2098 FETCH_INST_OPCODE 2 %edx
2104 /* ------------------------------ */
2106 .L_OP_APUT: /* 0x4b */
2107 /* File: x86/OP_APUT.S */
2109 * Array put, 32 bits or less. vBB[vCC] <- vAA
2111 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2113 /* op vAA, vBB, vCC */
2114 movzbl 2(rPC),%eax # eax<- BB
2115 movzbl 3(rPC),%ecx # ecx<- CC
2116 GET_VREG_R %eax %eax # eax<- vBB (array object)
2117 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2118 testl %eax,%eax # null array object?
2119 je common_errNullObject # bail if so
2120 cmpl offArrayObject_length(%eax),%ecx
2121 jae common_errArrayIndex # index >= length, bail
2122 leal offArrayObject_contents(%eax,%ecx,4),%eax
2124 GET_VREG_R %ecx rINST
2125 FETCH_INST_OPCODE 2 %edx
2130 /* ------------------------------ */
2132 .L_OP_APUT_WIDE: /* 0x4c */
2133 /* File: x86/OP_APUT_WIDE.S */
2135 * Array put, 64 bits. vBB[vCC]<-vAA.
2138 /* op vAA, vBB, vCC */
2139 movzbl 2(rPC),%eax # eax<- BB
2140 movzbl 3(rPC),%ecx # ecx<- CC
2141 GET_VREG_R %eax %eax # eax<- vBB (array object)
2142 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2143 testl %eax,%eax # null array object?
2144 je common_errNullObject # bail if so
2145 cmpl offArrayObject_length(%eax),%ecx
2146 jb .LOP_APUT_WIDE_finish # index < length, OK
2147 jmp common_errArrayIndex # index >= length, bail
2149 /* ------------------------------ */
2151 .L_OP_APUT_OBJECT: /* 0x4d */
2152 /* File: x86/OP_APUT_OBJECT.S */
2154 * Array put, 32 bits or less. vBB[vCC] <- vAA
2156 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2158 /* op vAA, vBB, vCC */
2159 movzbl 2(rPC),%eax # eax<- BB
2160 movzbl 3(rPC),%ecx # ecx<- CC
2161 GET_VREG_R %eax %eax # eax<- vBB (array object)
2162 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2163 GET_VREG_R rINST rINST # rINST<- vAA
2164 testl %eax,%eax # null array object?
2165 je common_errNullObject # bail if so
2166 cmpl offArrayObject_length(%eax),%ecx
2167 jb .LOP_APUT_OBJECT_continue
2168 jmp common_errArrayIndex # index >= length, bail
2170 /* ------------------------------ */
2172 .L_OP_APUT_BOOLEAN: /* 0x4e */
2173 /* File: x86/OP_APUT_BOOLEAN.S */
2174 /* File: x86/OP_APUT.S */
2176 * Array put, 32 bits or less. vBB[vCC] <- vAA
2178 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2180 /* op vAA, vBB, vCC */
2181 movzbl 2(rPC),%eax # eax<- BB
2182 movzbl 3(rPC),%ecx # ecx<- CC
2183 GET_VREG_R %eax %eax # eax<- vBB (array object)
2184 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2185 testl %eax,%eax # null array object?
2186 je common_errNullObject # bail if so
2187 cmpl offArrayObject_length(%eax),%ecx
2188 jae common_errArrayIndex # index >= length, bail
2189 leal offArrayObject_contents(%eax,%ecx,1),%eax
2190 .LOP_APUT_BOOLEAN_finish:
2191 GET_VREG_R %ecx rINST
2192 FETCH_INST_OPCODE 2 %edx
2198 /* ------------------------------ */
2200 .L_OP_APUT_BYTE: /* 0x4f */
2201 /* File: x86/OP_APUT_BYTE.S */
2202 /* File: x86/OP_APUT.S */
2204 * Array put, 32 bits or less. vBB[vCC] <- vAA
2206 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2208 /* op vAA, vBB, vCC */
2209 movzbl 2(rPC),%eax # eax<- BB
2210 movzbl 3(rPC),%ecx # ecx<- CC
2211 GET_VREG_R %eax %eax # eax<- vBB (array object)
2212 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2213 testl %eax,%eax # null array object?
2214 je common_errNullObject # bail if so
2215 cmpl offArrayObject_length(%eax),%ecx
2216 jae common_errArrayIndex # index >= length, bail
2217 leal offArrayObject_contents(%eax,%ecx,1),%eax
2218 .LOP_APUT_BYTE_finish:
2219 GET_VREG_R %ecx rINST
2220 FETCH_INST_OPCODE 2 %edx
2226 /* ------------------------------ */
2228 .L_OP_APUT_CHAR: /* 0x50 */
2229 /* File: x86/OP_APUT_CHAR.S */
2230 /* File: x86/OP_APUT.S */
2232 * Array put, 32 bits or less. vBB[vCC] <- vAA
2234 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2236 /* op vAA, vBB, vCC */
2237 movzbl 2(rPC),%eax # eax<- BB
2238 movzbl 3(rPC),%ecx # ecx<- CC
2239 GET_VREG_R %eax %eax # eax<- vBB (array object)
2240 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2241 testl %eax,%eax # null array object?
2242 je common_errNullObject # bail if so
2243 cmpl offArrayObject_length(%eax),%ecx
2244 jae common_errArrayIndex # index >= length, bail
2245 leal offArrayObject_contents(%eax,%ecx,2),%eax
2246 .LOP_APUT_CHAR_finish:
2247 GET_VREG_R %ecx rINST
2248 FETCH_INST_OPCODE 2 %edx
2254 /* ------------------------------ */
2256 .L_OP_APUT_SHORT: /* 0x51 */
2257 /* File: x86/OP_APUT_SHORT.S */
2258 /* File: x86/OP_APUT.S */
2260 * Array put, 32 bits or less. vBB[vCC] <- vAA
2262 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2264 /* op vAA, vBB, vCC */
2265 movzbl 2(rPC),%eax # eax<- BB
2266 movzbl 3(rPC),%ecx # ecx<- CC
2267 GET_VREG_R %eax %eax # eax<- vBB (array object)
2268 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
2269 testl %eax,%eax # null array object?
2270 je common_errNullObject # bail if so
2271 cmpl offArrayObject_length(%eax),%ecx
2272 jae common_errArrayIndex # index >= length, bail
2273 leal offArrayObject_contents(%eax,%ecx,2),%eax
2274 .LOP_APUT_SHORT_finish:
2275 GET_VREG_R %ecx rINST
2276 FETCH_INST_OPCODE 2 %edx
2282 /* ------------------------------ */
2284 .L_OP_IGET: /* 0x52 */
2285 /* File: x86/OP_IGET.S */
2287 * General 32-bit instance field get.
2289 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2291 /* op vA, vB, field@CCCC */
2293 movzwl 2(rPC),%edx # edx<- 0000CCCC
2294 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2295 movzbl rINSTbl,%ecx # ecx<- BA
2296 sarl $4,%ecx # ecx<- B
2297 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2298 andb $0xf,rINSTbl # rINST<- A
2299 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2300 movl (%eax,%edx,4),%eax # resolved entry
2301 testl %eax,%eax # is resolved entry null?
2302 jne .LOP_IGET_finish # no, already resolved
2303 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2305 jmp .LOP_IGET_resolve
2307 /* ------------------------------ */
2309 .L_OP_IGET_WIDE: /* 0x53 */
2310 /* File: x86/OP_IGET_WIDE.S */
2312 * 64-bit instance field get.
2315 /* op vA, vB, field@CCCC */
2317 movzwl 2(rPC),%edx # edx<- 0000CCCC
2318 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2319 movzbl rINSTbl,%ecx # ecx<- BA
2320 sarl $4,%ecx # ecx<- B
2321 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2322 andb $0xf,rINSTbl # rINST<- A
2323 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2324 movl (%eax,%edx,4),%eax # resolved entry
2325 testl %eax,%eax # is resolved entry null?
2326 jne .LOP_IGET_WIDE_finish # no, already resolved
2327 movl %edx,OUT_ARG1(%esp) # for dvmResolveInstField
2329 jmp .LOP_IGET_WIDE_resolve
2331 /* ------------------------------ */
2333 .L_OP_IGET_OBJECT: /* 0x54 */
2334 /* File: x86/OP_IGET_OBJECT.S */
2335 /* File: x86/OP_IGET.S */
2337 * General 32-bit instance field get.
2339 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2341 /* op vA, vB, field@CCCC */
2343 movzwl 2(rPC),%edx # edx<- 0000CCCC
2344 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2345 movzbl rINSTbl,%ecx # ecx<- BA
2346 sarl $4,%ecx # ecx<- B
2347 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2348 andb $0xf,rINSTbl # rINST<- A
2349 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2350 movl (%eax,%edx,4),%eax # resolved entry
2351 testl %eax,%eax # is resolved entry null?
2352 jne .LOP_IGET_OBJECT_finish # no, already resolved
2353 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2355 jmp .LOP_IGET_OBJECT_resolve
2358 /* ------------------------------ */
2360 .L_OP_IGET_BOOLEAN: /* 0x55 */
2361 /* File: x86/OP_IGET_BOOLEAN.S */
2362 /* File: x86/OP_IGET.S */
2364 * General 32-bit instance field get.
2366 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2368 /* op vA, vB, field@CCCC */
2370 movzwl 2(rPC),%edx # edx<- 0000CCCC
2371 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2372 movzbl rINSTbl,%ecx # ecx<- BA
2373 sarl $4,%ecx # ecx<- B
2374 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2375 andb $0xf,rINSTbl # rINST<- A
2376 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2377 movl (%eax,%edx,4),%eax # resolved entry
2378 testl %eax,%eax # is resolved entry null?
2379 jne .LOP_IGET_BOOLEAN_finish # no, already resolved
2380 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2382 jmp .LOP_IGET_BOOLEAN_resolve
2385 /* ------------------------------ */
2387 .L_OP_IGET_BYTE: /* 0x56 */
2388 /* File: x86/OP_IGET_BYTE.S */
2389 /* File: x86/OP_IGET.S */
2391 * General 32-bit instance field get.
2393 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2395 /* op vA, vB, field@CCCC */
2397 movzwl 2(rPC),%edx # edx<- 0000CCCC
2398 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2399 movzbl rINSTbl,%ecx # ecx<- BA
2400 sarl $4,%ecx # ecx<- B
2401 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2402 andb $0xf,rINSTbl # rINST<- A
2403 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2404 movl (%eax,%edx,4),%eax # resolved entry
2405 testl %eax,%eax # is resolved entry null?
2406 jne .LOP_IGET_BYTE_finish # no, already resolved
2407 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2409 jmp .LOP_IGET_BYTE_resolve
2412 /* ------------------------------ */
2414 .L_OP_IGET_CHAR: /* 0x57 */
2415 /* File: x86/OP_IGET_CHAR.S */
2416 /* File: x86/OP_IGET.S */
2418 * General 32-bit instance field get.
2420 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2422 /* op vA, vB, field@CCCC */
2424 movzwl 2(rPC),%edx # edx<- 0000CCCC
2425 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2426 movzbl rINSTbl,%ecx # ecx<- BA
2427 sarl $4,%ecx # ecx<- B
2428 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2429 andb $0xf,rINSTbl # rINST<- A
2430 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2431 movl (%eax,%edx,4),%eax # resolved entry
2432 testl %eax,%eax # is resolved entry null?
2433 jne .LOP_IGET_CHAR_finish # no, already resolved
2434 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2436 jmp .LOP_IGET_CHAR_resolve
2439 /* ------------------------------ */
2441 .L_OP_IGET_SHORT: /* 0x58 */
2442 /* File: x86/OP_IGET_SHORT.S */
2443 /* File: x86/OP_IGET.S */
2445 * General 32-bit instance field get.
2447 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2449 /* op vA, vB, field@CCCC */
2451 movzwl 2(rPC),%edx # edx<- 0000CCCC
2452 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2453 movzbl rINSTbl,%ecx # ecx<- BA
2454 sarl $4,%ecx # ecx<- B
2455 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2456 andb $0xf,rINSTbl # rINST<- A
2457 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2458 movl (%eax,%edx,4),%eax # resolved entry
2459 testl %eax,%eax # is resolved entry null?
2460 jne .LOP_IGET_SHORT_finish # no, already resolved
2461 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
2463 jmp .LOP_IGET_SHORT_resolve
2466 /* ------------------------------ */
2468 .L_OP_IPUT: /* 0x59 */
2469 /* File: x86/OP_IPUT.S */
2472 * General 32-bit instance field put.
2474 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2476 /* op vA, vB, field@CCCC */
2478 movzwl 2(rPC),%edx # %edx<- 0000CCCC
2479 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2480 movzbl rINSTbl,%ecx # ecx<- BA
2481 sarl $4,%ecx # ecx<- B
2482 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2483 andb $0xf,rINSTbl # rINST<- A
2484 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2485 movl (%eax,%edx,4),%eax # resolved entry
2486 testl %eax,%eax # is resolved entry null?
2487 jne .LOP_IPUT_finish # no, already resolved
2488 movl %edx,OUT_ARG1(%esp)
2490 jmp .LOP_IPUT_resolve
2492 /* ------------------------------ */
2494 .L_OP_IPUT_WIDE: /* 0x5a */
2495 /* File: x86/OP_IPUT_WIDE.S */
2497 * 64-bit instance field put.
2500 /* op vA, vB, field@CCCC */
2502 movzwl 2(rPC),%edx # edx<- 0000CCCC
2503 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2504 movzbl rINSTbl,%ecx # ecx<- BA
2505 sarl $4,%ecx # ecx<- B
2506 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2507 andb $0xf,rINSTbl # rINST<- A
2508 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2509 movl (%eax,%edx,4),%eax # resolved entry
2510 testl %eax,%eax # is resolved entry null?
2511 jne .LOP_IPUT_WIDE_finish # no, already resolved
2512 movl %edx,OUT_ARG1(%esp)
2514 jmp .LOP_IPUT_WIDE_resolve
2516 /* ------------------------------ */
2518 .L_OP_IPUT_OBJECT: /* 0x5b */
2519 /* File: x86/OP_IPUT_OBJECT.S */
2525 /* op vA, vB, field@CCCC */
2527 movzwl 2(rPC),%edx # edx<- 0000CCCC
2528 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2529 movzbl rINSTbl,%ecx # ecx<- BA
2530 sarl $4,%ecx # ecx<- B
2531 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2532 andb $0xf,rINSTbl # rINST<- A
2533 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2534 movl (%eax,%edx,4),%eax # resolved entry
2535 testl %eax,%eax # is resolved entry null?
2536 jne .LOP_IPUT_OBJECT_finish # no, already resolved
2537 movl %edx,OUT_ARG1(%esp)
2539 jmp .LOP_IPUT_OBJECT_resolve
2541 /* ------------------------------ */
2543 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2544 /* File: x86/OP_IPUT_BOOLEAN.S */
2545 /* File: x86/OP_IPUT.S */
2548 * General 32-bit instance field put.
2550 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2552 /* op vA, vB, field@CCCC */
2554 movzwl 2(rPC),%edx # %edx<- 0000CCCC
2555 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2556 movzbl rINSTbl,%ecx # ecx<- BA
2557 sarl $4,%ecx # ecx<- B
2558 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2559 andb $0xf,rINSTbl # rINST<- A
2560 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2561 movl (%eax,%edx,4),%eax # resolved entry
2562 testl %eax,%eax # is resolved entry null?
2563 jne .LOP_IPUT_BOOLEAN_finish # no, already resolved
2564 movl %edx,OUT_ARG1(%esp)
2566 jmp .LOP_IPUT_BOOLEAN_resolve
2569 /* ------------------------------ */
2571 .L_OP_IPUT_BYTE: /* 0x5d */
2572 /* File: x86/OP_IPUT_BYTE.S */
2573 /* File: x86/OP_IPUT.S */
2576 * General 32-bit instance field put.
2578 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2580 /* op vA, vB, field@CCCC */
2582 movzwl 2(rPC),%edx # %edx<- 0000CCCC
2583 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2584 movzbl rINSTbl,%ecx # ecx<- BA
2585 sarl $4,%ecx # ecx<- B
2586 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2587 andb $0xf,rINSTbl # rINST<- A
2588 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2589 movl (%eax,%edx,4),%eax # resolved entry
2590 testl %eax,%eax # is resolved entry null?
2591 jne .LOP_IPUT_BYTE_finish # no, already resolved
2592 movl %edx,OUT_ARG1(%esp)
2594 jmp .LOP_IPUT_BYTE_resolve
2597 /* ------------------------------ */
2599 .L_OP_IPUT_CHAR: /* 0x5e */
2600 /* File: x86/OP_IPUT_CHAR.S */
2601 /* File: x86/OP_IPUT.S */
2604 * General 32-bit instance field put.
2606 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2608 /* op vA, vB, field@CCCC */
2610 movzwl 2(rPC),%edx # %edx<- 0000CCCC
2611 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2612 movzbl rINSTbl,%ecx # ecx<- BA
2613 sarl $4,%ecx # ecx<- B
2614 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2615 andb $0xf,rINSTbl # rINST<- A
2616 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2617 movl (%eax,%edx,4),%eax # resolved entry
2618 testl %eax,%eax # is resolved entry null?
2619 jne .LOP_IPUT_CHAR_finish # no, already resolved
2620 movl %edx,OUT_ARG1(%esp)
2622 jmp .LOP_IPUT_CHAR_resolve
2625 /* ------------------------------ */
2627 .L_OP_IPUT_SHORT: /* 0x5f */
2628 /* File: x86/OP_IPUT_SHORT.S */
2629 /* File: x86/OP_IPUT.S */
2632 * General 32-bit instance field put.
2634 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2636 /* op vA, vB, field@CCCC */
2638 movzwl 2(rPC),%edx # %edx<- 0000CCCC
2639 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2640 movzbl rINSTbl,%ecx # ecx<- BA
2641 sarl $4,%ecx # ecx<- B
2642 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2643 andb $0xf,rINSTbl # rINST<- A
2644 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
2645 movl (%eax,%edx,4),%eax # resolved entry
2646 testl %eax,%eax # is resolved entry null?
2647 jne .LOP_IPUT_SHORT_finish # no, already resolved
2648 movl %edx,OUT_ARG1(%esp)
2650 jmp .LOP_IPUT_SHORT_resolve
2653 /* ------------------------------ */
2655 .L_OP_SGET: /* 0x60 */
2656 /* File: x86/OP_SGET.S */
2658 * General 32-bit SGET handler.
2660 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2662 /* op vAA, field@BBBB */
2664 movzwl 2(rPC),%eax # eax<- field ref BBBB
2665 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2666 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2667 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2668 testl %eax,%eax # resolved entry null?
2669 je .LOP_SGET_resolve # if not, make it so
2670 .LOP_SGET_finish: # field ptr in eax
2671 movl offStaticField_value(%eax),%eax
2672 FETCH_INST_OPCODE 2 %edx
2677 /* ------------------------------ */
2679 .L_OP_SGET_WIDE: /* 0x61 */
2680 /* File: x86/OP_SGET_WIDE.S */
2682 * 64-bit SGET handler.
2685 /* sget-wide vAA, field@BBBB */
2687 movzwl 2(rPC),%eax # eax<- field ref BBBB
2688 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2689 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2690 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2691 testl %eax,%eax # resolved entry null?
2692 je .LOP_SGET_WIDE_resolve # if not, make it so
2693 .LOP_SGET_WIDE_finish: # field ptr in eax
2694 movl offStaticField_value(%eax),%ecx # ecx<- lsw
2695 movl 4+offStaticField_value(%eax),%eax # eax<- msw
2696 FETCH_INST_OPCODE 2 %edx
2698 SET_VREG_WORD %ecx rINST 0
2699 SET_VREG_WORD %eax rINST 1
2702 /* ------------------------------ */
2704 .L_OP_SGET_OBJECT: /* 0x62 */
2705 /* File: x86/OP_SGET_OBJECT.S */
2706 /* File: x86/OP_SGET.S */
2708 * General 32-bit SGET handler.
2710 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2712 /* op vAA, field@BBBB */
2714 movzwl 2(rPC),%eax # eax<- field ref BBBB
2715 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2716 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2717 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2718 testl %eax,%eax # resolved entry null?
2719 je .LOP_SGET_OBJECT_resolve # if not, make it so
2720 .LOP_SGET_OBJECT_finish: # field ptr in eax
2721 movl offStaticField_value(%eax),%eax
2722 FETCH_INST_OPCODE 2 %edx
2728 /* ------------------------------ */
2730 .L_OP_SGET_BOOLEAN: /* 0x63 */
2731 /* File: x86/OP_SGET_BOOLEAN.S */
2732 /* File: x86/OP_SGET.S */
2734 * General 32-bit SGET handler.
2736 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2738 /* op vAA, field@BBBB */
2740 movzwl 2(rPC),%eax # eax<- field ref BBBB
2741 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2742 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2743 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2744 testl %eax,%eax # resolved entry null?
2745 je .LOP_SGET_BOOLEAN_resolve # if not, make it so
2746 .LOP_SGET_BOOLEAN_finish: # field ptr in eax
2747 movl offStaticField_value(%eax),%eax
2748 FETCH_INST_OPCODE 2 %edx
2754 /* ------------------------------ */
2756 .L_OP_SGET_BYTE: /* 0x64 */
2757 /* File: x86/OP_SGET_BYTE.S */
2758 /* File: x86/OP_SGET.S */
2760 * General 32-bit SGET handler.
2762 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2764 /* op vAA, field@BBBB */
2766 movzwl 2(rPC),%eax # eax<- field ref BBBB
2767 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2768 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2769 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2770 testl %eax,%eax # resolved entry null?
2771 je .LOP_SGET_BYTE_resolve # if not, make it so
2772 .LOP_SGET_BYTE_finish: # field ptr in eax
2773 movl offStaticField_value(%eax),%eax
2774 FETCH_INST_OPCODE 2 %edx
2780 /* ------------------------------ */
2782 .L_OP_SGET_CHAR: /* 0x65 */
2783 /* File: x86/OP_SGET_CHAR.S */
2784 /* File: x86/OP_SGET.S */
2786 * General 32-bit SGET handler.
2788 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2790 /* op vAA, field@BBBB */
2792 movzwl 2(rPC),%eax # eax<- field ref BBBB
2793 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2794 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2795 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2796 testl %eax,%eax # resolved entry null?
2797 je .LOP_SGET_CHAR_resolve # if not, make it so
2798 .LOP_SGET_CHAR_finish: # field ptr in eax
2799 movl offStaticField_value(%eax),%eax
2800 FETCH_INST_OPCODE 2 %edx
2806 /* ------------------------------ */
2808 .L_OP_SGET_SHORT: /* 0x66 */
2809 /* File: x86/OP_SGET_SHORT.S */
2810 /* File: x86/OP_SGET.S */
2812 * General 32-bit SGET handler.
2814 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2816 /* op vAA, field@BBBB */
2818 movzwl 2(rPC),%eax # eax<- field ref BBBB
2819 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2820 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2821 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2822 testl %eax,%eax # resolved entry null?
2823 je .LOP_SGET_SHORT_resolve # if not, make it so
2824 .LOP_SGET_SHORT_finish: # field ptr in eax
2825 movl offStaticField_value(%eax),%eax
2826 FETCH_INST_OPCODE 2 %edx
2832 /* ------------------------------ */
2834 .L_OP_SPUT: /* 0x67 */
2835 /* File: x86/OP_SPUT.S */
2837 * General 32-bit SPUT handler.
2839 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2841 /* op vAA, field@BBBB */
2843 movzwl 2(rPC),%eax # eax<- field ref BBBB
2844 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2845 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2846 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2847 testl %eax,%eax # resolved entry null?
2848 je .LOP_SPUT_resolve # if not, make it so
2849 .LOP_SPUT_finish: # field ptr in eax
2850 GET_VREG_R %ecx rINST
2851 FETCH_INST_OPCODE 2 %edx
2853 movl %ecx,offStaticField_value(%eax)
2856 /* ------------------------------ */
2858 .L_OP_SPUT_WIDE: /* 0x68 */
2859 /* File: x86/OP_SPUT_WIDE.S */
2861 * General 32-bit SPUT handler.
2863 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2865 /* op vAA, field@BBBB */
2867 movzwl 2(rPC),%eax # eax<- field ref BBBB
2868 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2869 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2870 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2871 testl %eax,%eax # resolved entry null?
2872 je .LOP_SPUT_WIDE_resolve # if not, make it so
2873 .LOP_SPUT_WIDE_finish: # field ptr in eax
2874 GET_VREG_WORD %ecx rINST 0 # rINST<- lsw
2875 GET_VREG_WORD rINST rINST 1 # ecx<- msw
2876 FETCH_INST_OPCODE 2 %edx
2878 movl %ecx,offStaticField_value(%eax)
2879 movl rINST,4+offStaticField_value(%eax)
2882 /* ------------------------------ */
2884 .L_OP_SPUT_OBJECT: /* 0x69 */
2885 /* File: x86/OP_SPUT_OBJECT.S */
2887 * SPUT object handler.
2889 /* op vAA, field@BBBB */
2891 movzwl 2(rPC),%eax # eax<- field ref BBBB
2892 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2893 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2894 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField
2895 testl %eax,%eax # resolved entry null?
2896 je .LOP_SPUT_OBJECT_resolve # if not, make it so
2897 .LOP_SPUT_OBJECT_finish: # field ptr in eax
2898 movzbl rINSTbl,%ecx # ecx<- AA
2899 GET_VREG_R %ecx %ecx
2900 jmp .LOP_SPUT_OBJECT_continue
2902 /* ------------------------------ */
2904 .L_OP_SPUT_BOOLEAN: /* 0x6a */
2905 /* File: x86/OP_SPUT_BOOLEAN.S */
2906 /* File: x86/OP_SPUT.S */
2908 * General 32-bit SPUT handler.
2910 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2912 /* op vAA, field@BBBB */
2914 movzwl 2(rPC),%eax # eax<- field ref BBBB
2915 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2916 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2917 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2918 testl %eax,%eax # resolved entry null?
2919 je .LOP_SPUT_BOOLEAN_resolve # if not, make it so
2920 .LOP_SPUT_BOOLEAN_finish: # field ptr in eax
2921 GET_VREG_R %ecx rINST
2922 FETCH_INST_OPCODE 2 %edx
2924 movl %ecx,offStaticField_value(%eax)
2928 /* ------------------------------ */
2930 .L_OP_SPUT_BYTE: /* 0x6b */
2931 /* File: x86/OP_SPUT_BYTE.S */
2932 /* File: x86/OP_SPUT.S */
2934 * General 32-bit SPUT handler.
2936 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2938 /* op vAA, field@BBBB */
2940 movzwl 2(rPC),%eax # eax<- field ref BBBB
2941 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2942 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2943 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2944 testl %eax,%eax # resolved entry null?
2945 je .LOP_SPUT_BYTE_resolve # if not, make it so
2946 .LOP_SPUT_BYTE_finish: # field ptr in eax
2947 GET_VREG_R %ecx rINST
2948 FETCH_INST_OPCODE 2 %edx
2950 movl %ecx,offStaticField_value(%eax)
2954 /* ------------------------------ */
2956 .L_OP_SPUT_CHAR: /* 0x6c */
2957 /* File: x86/OP_SPUT_CHAR.S */
2958 /* File: x86/OP_SPUT.S */
2960 * General 32-bit SPUT handler.
2962 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2964 /* op vAA, field@BBBB */
2966 movzwl 2(rPC),%eax # eax<- field ref BBBB
2967 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2968 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2969 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2970 testl %eax,%eax # resolved entry null?
2971 je .LOP_SPUT_CHAR_resolve # if not, make it so
2972 .LOP_SPUT_CHAR_finish: # field ptr in eax
2973 GET_VREG_R %ecx rINST
2974 FETCH_INST_OPCODE 2 %edx
2976 movl %ecx,offStaticField_value(%eax)
2980 /* ------------------------------ */
2982 .L_OP_SPUT_SHORT: /* 0x6d */
2983 /* File: x86/OP_SPUT_SHORT.S */
2984 /* File: x86/OP_SPUT.S */
2986 * General 32-bit SPUT handler.
2988 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2990 /* op vAA, field@BBBB */
2992 movzwl 2(rPC),%eax # eax<- field ref BBBB
2993 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2994 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2995 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2996 testl %eax,%eax # resolved entry null?
2997 je .LOP_SPUT_SHORT_resolve # if not, make it so
2998 .LOP_SPUT_SHORT_finish: # field ptr in eax
2999 GET_VREG_R %ecx rINST
3000 FETCH_INST_OPCODE 2 %edx
3002 movl %ecx,offStaticField_value(%eax)
3006 /* ------------------------------ */
3008 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3009 /* File: x86/OP_INVOKE_VIRTUAL.S */
3012 * Handle a virtual method call.
3014 * for: invoke-virtual, invoke-virtual/range
3016 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3017 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3019 movzwl 2(rPC),%ecx # ecx<- BBBB
3020 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
3022 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods
3023 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod
3024 testl %eax,%eax # already resolved?
3025 jne .LOP_INVOKE_VIRTUAL_continue # yes, continue
3027 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
3028 movl offGlue_method(%eax),%eax # eax<- glue->method
3029 jmp .LOP_INVOKE_VIRTUAL_more
3031 /* ------------------------------ */
3033 .L_OP_INVOKE_SUPER: /* 0x6f */
3034 /* File: x86/OP_INVOKE_SUPER.S */
3036 * Handle a "super" method call.
3038 * for: invoke-super, invoke-super/range
3040 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3041 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3043 movzwl 2(rPC),%eax # eax<- BBBB
3044 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex
3046 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3047 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod
3048 movl offGlue_method(rINST),%eax # eax<- method
3049 movzwl 4(rPC),rINST # rINST<- GFED or CCCC
3051 andl $0xf,rINST # rINST<- D (or stays CCCC)
3053 GET_VREG_R rINST rINST # rINST<- "this" ptr
3054 testl rINST,rINST # null "this"?
3055 je common_errNullObject # yes, throw
3056 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
3057 testl %ecx,%ecx # already resolved?
3058 jne .LOP_INVOKE_SUPER_continue # yes - go on
3059 jmp .LOP_INVOKE_SUPER_resolve
3061 /* ------------------------------ */
3063 .L_OP_INVOKE_DIRECT: /* 0x70 */
3064 /* File: x86/OP_INVOKE_DIRECT.S */
3066 * Handle a direct method call.
3068 * (We could defer the "is 'this' pointer null" test to the common
3069 * method invocation code, and use a flag to indicate that static
3070 * calls don't count. If we do this as part of copying the arguments
3071 * out we could avoiding loading the first arg twice.)
3073 * for: invoke-direct, invoke-direct/range
3075 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3076 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3078 movzwl 2(rPC),%eax # eax<- BBBB
3079 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3081 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3082 movzwl 4(rPC),%edx # edx<- GFED or CCCC
3083 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
3085 andl $0xf,%edx # edx<- D (or stays CCCC)
3087 testl %eax,%eax # already resolved?
3088 GET_VREG_R %ecx %edx # ecx<- "this" ptr
3089 je .LOP_INVOKE_DIRECT_resolve # not resolved, do it now
3090 .LOP_INVOKE_DIRECT_finish:
3091 testl %ecx,%ecx # null "this"?
3092 jne common_invokeMethodNoRange # no, continue on
3093 jmp common_errNullObject
3095 /* ------------------------------ */
3097 .L_OP_INVOKE_STATIC: /* 0x71 */
3098 /* File: x86/OP_INVOKE_STATIC.S */
3100 * Handle a static method call.
3102 * for: invoke-static, invoke-static/range
3104 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3105 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3107 movzwl 2(rPC),%eax # eax<- BBBB
3108 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3110 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3111 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
3113 jne common_invokeMethodNoRange
3115 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
3117 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3118 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3119 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz
3120 jmp .LOP_INVOKE_STATIC_continue
3122 /* ------------------------------ */
3124 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3125 /* File: x86/OP_INVOKE_INTERFACE.S */
3127 * Handle an interface method call.
3129 * for: invoke-interface, invoke-interface/range
3131 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3132 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3133 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
3136 andl $0xf,%eax # eax<- C (or stays CCCC)
3138 GET_VREG_R %eax %eax # eax<- "this"
3140 testl %eax,%eax # null this?
3141 je common_errNullObject # yes, fail
3142 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3143 movl %eax,OUT_ARG0(%esp) # arg0<- class
3144 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex
3145 movl offGlue_method(%ecx),%ecx # ecx<- method
3146 movl %eax,OUT_ARG3(%esp) # arg3<- dex
3147 movzwl 2(rPC),%eax # eax<- BBBB
3148 movl %ecx,OUT_ARG2(%esp) # arg2<- method
3149 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3150 jmp .LOP_INVOKE_INTERFACE_continue
3152 /* ------------------------------ */
3154 .L_OP_UNUSED_73: /* 0x73 */
3155 /* File: x86/OP_UNUSED_73.S */
3156 /* File: x86/unused.S */
3160 /* ------------------------------ */
3162 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3163 /* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */
3164 /* File: x86/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 */
3174 movzwl 2(rPC),%ecx # ecx<- BBBB
3175 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
3177 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods
3178 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod
3179 testl %eax,%eax # already resolved?
3180 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # yes, continue
3182 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
3183 movl offGlue_method(%eax),%eax # eax<- glue->method
3184 jmp .LOP_INVOKE_VIRTUAL_RANGE_more
3187 /* ------------------------------ */
3189 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3190 /* File: x86/OP_INVOKE_SUPER_RANGE.S */
3191 /* File: x86/OP_INVOKE_SUPER.S */
3193 * Handle a "super" method call.
3195 * for: invoke-super, invoke-super/range
3197 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3198 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3200 movzwl 2(rPC),%eax # eax<- BBBB
3201 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex
3203 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3204 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod
3205 movl offGlue_method(rINST),%eax # eax<- method
3206 movzwl 4(rPC),rINST # rINST<- GFED or CCCC
3208 andl $0xf,rINST # rINST<- D (or stays CCCC)
3210 GET_VREG_R rINST rINST # rINST<- "this" ptr
3211 testl rINST,rINST # null "this"?
3212 je common_errNullObject # yes, throw
3213 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
3214 testl %ecx,%ecx # already resolved?
3215 jne .LOP_INVOKE_SUPER_RANGE_continue # yes - go on
3216 jmp .LOP_INVOKE_SUPER_RANGE_resolve
3219 /* ------------------------------ */
3221 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3222 /* File: x86/OP_INVOKE_DIRECT_RANGE.S */
3223 /* File: x86/OP_INVOKE_DIRECT.S */
3225 * Handle a direct method call.
3227 * (We could defer the "is 'this' pointer null" test to the common
3228 * method invocation code, and use a flag to indicate that static
3229 * calls don't count. If we do this as part of copying the arguments
3230 * out we could avoiding loading the first arg twice.)
3232 * for: invoke-direct, invoke-direct/range
3234 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3235 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3237 movzwl 2(rPC),%eax # eax<- BBBB
3238 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3240 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3241 movzwl 4(rPC),%edx # edx<- GFED or CCCC
3242 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
3244 andl $0xf,%edx # edx<- D (or stays CCCC)
3246 testl %eax,%eax # already resolved?
3247 GET_VREG_R %ecx %edx # ecx<- "this" ptr
3248 je .LOP_INVOKE_DIRECT_RANGE_resolve # not resolved, do it now
3249 .LOP_INVOKE_DIRECT_RANGE_finish:
3250 testl %ecx,%ecx # null "this"?
3251 jne common_invokeMethodRange # no, continue on
3252 jmp common_errNullObject
3255 /* ------------------------------ */
3257 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3258 /* File: x86/OP_INVOKE_STATIC_RANGE.S */
3259 /* File: x86/OP_INVOKE_STATIC.S */
3261 * Handle a static method call.
3263 * for: invoke-static, invoke-static/range
3265 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3266 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3268 movzwl 2(rPC),%eax # eax<- BBBB
3269 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3271 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3272 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
3274 jne common_invokeMethodRange
3276 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
3278 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3279 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3280 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz
3281 jmp .LOP_INVOKE_STATIC_RANGE_continue
3284 /* ------------------------------ */
3286 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3287 /* File: x86/OP_INVOKE_INTERFACE_RANGE.S */
3288 /* File: x86/OP_INVOKE_INTERFACE.S */
3290 * Handle an interface method call.
3292 * for: invoke-interface, invoke-interface/range
3294 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3295 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3296 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
3299 andl $0xf,%eax # eax<- C (or stays CCCC)
3301 GET_VREG_R %eax %eax # eax<- "this"
3303 testl %eax,%eax # null this?
3304 je common_errNullObject # yes, fail
3305 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3306 movl %eax,OUT_ARG0(%esp) # arg0<- class
3307 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex
3308 movl offGlue_method(%ecx),%ecx # ecx<- method
3309 movl %eax,OUT_ARG3(%esp) # arg3<- dex
3310 movzwl 2(rPC),%eax # eax<- BBBB
3311 movl %ecx,OUT_ARG2(%esp) # arg2<- method
3312 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3313 jmp .LOP_INVOKE_INTERFACE_RANGE_continue
3316 /* ------------------------------ */
3318 .L_OP_UNUSED_79: /* 0x79 */
3319 /* File: x86/OP_UNUSED_79.S */
3320 /* File: x86/unused.S */
3324 /* ------------------------------ */
3326 .L_OP_UNUSED_7A: /* 0x7a */
3327 /* File: x86/OP_UNUSED_7A.S */
3328 /* File: x86/unused.S */
3332 /* ------------------------------ */
3334 .L_OP_NEG_INT: /* 0x7b */
3335 /* File: x86/OP_NEG_INT.S */
3336 /* File: x86/unop.S */
3338 * Generic 32-bit unary operation. Provide an "instr" line that
3339 * specifies an instruction that performs "result = op eax".
3342 movzbl rINSTbl,%ecx # ecx<- A+
3343 sarl $4,rINST # rINST<- B
3344 GET_VREG_R %eax rINST # eax<- vB
3345 andb $0xf,%cl # ecx<- A
3346 FETCH_INST_OPCODE 1 %edx
3355 /* ------------------------------ */
3357 .L_OP_NOT_INT: /* 0x7c */
3358 /* File: x86/OP_NOT_INT.S */
3359 /* File: x86/unop.S */
3361 * Generic 32-bit unary operation. Provide an "instr" line that
3362 * specifies an instruction that performs "result = op eax".
3365 movzbl rINSTbl,%ecx # ecx<- A+
3366 sarl $4,rINST # rINST<- B
3367 GET_VREG_R %eax rINST # eax<- vB
3368 andb $0xf,%cl # ecx<- A
3369 FETCH_INST_OPCODE 1 %edx
3378 /* ------------------------------ */
3380 .L_OP_NEG_LONG: /* 0x7d */
3381 /* File: x86/OP_NEG_LONG.S */
3383 movzbl rINSTbl,%ecx # ecx<- BA
3384 sarl $4,%ecx # ecx<- B
3385 andb $0xf,rINSTbl # rINST<- A
3386 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
3387 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1]
3391 FETCH_INST_OPCODE 1 %edx
3392 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax
3393 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx
3397 /* ------------------------------ */
3399 .L_OP_NOT_LONG: /* 0x7e */
3400 /* File: x86/OP_NOT_LONG.S */
3402 movzbl rINSTbl,%ecx # ecx<- BA
3403 sarl $4,%ecx # ecx<- B
3404 andb $0xf,rINSTbl # rINST<- A
3405 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
3406 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1]
3407 FETCH_INST_OPCODE 1 %edx
3410 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax
3411 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx
3415 /* ------------------------------ */
3417 .L_OP_NEG_FLOAT: /* 0x7f */
3418 /* File: x86/OP_NEG_FLOAT.S */
3419 /* File: x86/fpcvt.S */
3421 * Generic 32-bit FP conversion operation.
3424 movzbl rINSTbl,%ecx # ecx<- A+
3425 sarl $4,rINST # rINST<- B
3426 flds (rFP,rINST,4) # %st0<- vB
3427 andb $0xf,%cl # ecx<- A
3428 FETCH_INST_OPCODE 1 %edx
3431 fstps (rFP,%ecx,4) # vA<- %st0
3435 /* ------------------------------ */
3437 .L_OP_NEG_DOUBLE: /* 0x80 */
3438 /* File: x86/OP_NEG_DOUBLE.S */
3439 /* File: x86/fpcvt.S */
3441 * Generic 32-bit FP conversion operation.
3444 movzbl rINSTbl,%ecx # ecx<- A+
3445 sarl $4,rINST # rINST<- B
3446 fldl (rFP,rINST,4) # %st0<- vB
3447 andb $0xf,%cl # ecx<- A
3448 FETCH_INST_OPCODE 1 %edx
3451 fstpl (rFP,%ecx,4) # vA<- %st0
3455 /* ------------------------------ */
3457 .L_OP_INT_TO_LONG: /* 0x81 */
3458 /* File: x86/OP_INT_TO_LONG.S */
3459 /* int to long vA, vB */
3460 movzbl rINSTbl,%eax # eax<- +A
3461 sarl $4,%eax # eax<- B
3462 GET_VREG_R %eax %eax # eax<- vB
3463 andb $0xf,rINSTbl # rINST<- A
3464 cltd # edx:eax<- sssssssBBBBBBBB
3465 SET_VREG_WORD %edx rINST 1 # v[A+1]<- edx/rPC
3466 FETCH_INST_OPCODE 1 %edx
3467 SET_VREG_WORD %eax rINST 0 # v[A+0]<- %eax
3471 /* ------------------------------ */
3473 .L_OP_INT_TO_FLOAT: /* 0x82 */
3474 /* File: x86/OP_INT_TO_FLOAT.S */
3475 /* File: x86/fpcvt.S */
3477 * Generic 32-bit FP conversion operation.
3480 movzbl rINSTbl,%ecx # ecx<- A+
3481 sarl $4,rINST # rINST<- B
3482 fildl (rFP,rINST,4) # %st0<- vB
3483 andb $0xf,%cl # ecx<- A
3484 FETCH_INST_OPCODE 1 %edx
3487 fstps (rFP,%ecx,4) # vA<- %st0
3491 /* ------------------------------ */
3493 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3494 /* File: x86/OP_INT_TO_DOUBLE.S */
3495 /* File: x86/fpcvt.S */
3497 * Generic 32-bit FP conversion operation.
3500 movzbl rINSTbl,%ecx # ecx<- A+
3501 sarl $4,rINST # rINST<- B
3502 fildl (rFP,rINST,4) # %st0<- vB
3503 andb $0xf,%cl # ecx<- A
3504 FETCH_INST_OPCODE 1 %edx
3507 fstpl (rFP,%ecx,4) # vA<- %st0
3511 /* ------------------------------ */
3513 .L_OP_LONG_TO_INT: /* 0x84 */
3514 /* File: x86/OP_LONG_TO_INT.S */
3515 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3516 /* File: x86/OP_MOVE.S */
3517 /* for move, move-object, long-to-int */
3519 movzbl rINSTbl,%eax # eax<- BA
3520 andb $0xf,%al # eax<- A
3521 shrl $4,rINST # rINST<- B
3522 GET_VREG_R %ecx rINST
3523 FETCH_INST_OPCODE 1 %edx
3525 SET_VREG %ecx %eax # fp[A]<-fp[B]
3529 /* ------------------------------ */
3531 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3532 /* File: x86/OP_LONG_TO_FLOAT.S */
3533 /* File: x86/fpcvt.S */
3535 * Generic 32-bit FP conversion operation.
3538 movzbl rINSTbl,%ecx # ecx<- A+
3539 sarl $4,rINST # rINST<- B
3540 fildll (rFP,rINST,4) # %st0<- vB
3541 andb $0xf,%cl # ecx<- A
3542 FETCH_INST_OPCODE 1 %edx
3545 fstps (rFP,%ecx,4) # vA<- %st0
3549 /* ------------------------------ */
3551 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3552 /* File: x86/OP_LONG_TO_DOUBLE.S */
3553 /* File: x86/fpcvt.S */
3555 * Generic 32-bit FP conversion operation.
3558 movzbl rINSTbl,%ecx # ecx<- A+
3559 sarl $4,rINST # rINST<- B
3560 fildll (rFP,rINST,4) # %st0<- vB
3561 andb $0xf,%cl # ecx<- A
3562 FETCH_INST_OPCODE 1 %edx
3565 fstpl (rFP,%ecx,4) # vA<- %st0
3569 /* ------------------------------ */
3571 .L_OP_FLOAT_TO_INT: /* 0x87 */
3572 /* File: x86/OP_FLOAT_TO_INT.S */
3573 /* File: x86/cvtfp_int.S */
3574 /* On fp to int conversions, Java requires that
3575 * if the result > maxint, it should be clamped to maxint. If it is less
3576 * than minint, it should be clamped to minint. If it is a nan, the result
3577 * should be zero. Further, the rounding mode is to truncate. This model
3578 * differs from what is delivered normally via the x86 fpu, so we have
3579 * to play some games.
3581 /* float/double to int/long vA, vB */
3582 movzbl rINSTbl,%ecx # ecx<- A+
3583 sarl $4,rINST # rINST<- B
3585 fldl (rFP,rINST,4) # %st0<- vB
3587 flds (rFP,rINST,4) # %st0<- vB
3590 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3591 movzwl LOCAL0_OFFSET(%ebp),%eax
3593 movw %ax,LOCAL0_OFFSET+2(%ebp)
3594 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3595 FETCH_INST_OPCODE 1 %edx
3596 andb $0xf,%cl # ecx<- A
3598 fistpll (rFP,%ecx,4) # convert and store
3600 fistpl (rFP,%ecx,4) # convert and store
3602 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3603 jmp .LOP_FLOAT_TO_INT_continue
3606 /* ------------------------------ */
3608 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3609 /* File: x86/OP_FLOAT_TO_LONG.S */
3610 /* File: x86/cvtfp_int.S */
3611 /* On fp to int conversions, Java requires that
3612 * if the result > maxint, it should be clamped to maxint. If it is less
3613 * than minint, it should be clamped to minint. If it is a nan, the result
3614 * should be zero. Further, the rounding mode is to truncate. This model
3615 * differs from what is delivered normally via the x86 fpu, so we have
3616 * to play some games.
3618 /* float/double to int/long vA, vB */
3619 movzbl rINSTbl,%ecx # ecx<- A+
3620 sarl $4,rINST # rINST<- B
3622 fldl (rFP,rINST,4) # %st0<- vB
3624 flds (rFP,rINST,4) # %st0<- vB
3627 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3628 movzwl LOCAL0_OFFSET(%ebp),%eax
3630 movw %ax,LOCAL0_OFFSET+2(%ebp)
3631 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3632 FETCH_INST_OPCODE 1 %edx
3633 andb $0xf,%cl # ecx<- A
3635 fistpll (rFP,%ecx,4) # convert and store
3637 fistpl (rFP,%ecx,4) # convert and store
3639 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3640 jmp .LOP_FLOAT_TO_LONG_continue
3643 /* ------------------------------ */
3645 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3646 /* File: x86/OP_FLOAT_TO_DOUBLE.S */
3647 /* File: x86/fpcvt.S */
3649 * Generic 32-bit FP conversion operation.
3652 movzbl rINSTbl,%ecx # ecx<- A+
3653 sarl $4,rINST # rINST<- B
3654 flds (rFP,rINST,4) # %st0<- vB
3655 andb $0xf,%cl # ecx<- A
3656 FETCH_INST_OPCODE 1 %edx
3659 fstpl (rFP,%ecx,4) # vA<- %st0
3663 /* ------------------------------ */
3665 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3666 /* File: x86/OP_DOUBLE_TO_INT.S */
3667 /* File: x86/cvtfp_int.S */
3668 /* On fp to int conversions, Java requires that
3669 * if the result > maxint, it should be clamped to maxint. If it is less
3670 * than minint, it should be clamped to minint. If it is a nan, the result
3671 * should be zero. Further, the rounding mode is to truncate. This model
3672 * differs from what is delivered normally via the x86 fpu, so we have
3673 * to play some games.
3675 /* float/double to int/long vA, vB */
3676 movzbl rINSTbl,%ecx # ecx<- A+
3677 sarl $4,rINST # rINST<- B
3679 fldl (rFP,rINST,4) # %st0<- vB
3681 flds (rFP,rINST,4) # %st0<- vB
3684 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3685 movzwl LOCAL0_OFFSET(%ebp),%eax
3687 movw %ax,LOCAL0_OFFSET+2(%ebp)
3688 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3689 FETCH_INST_OPCODE 1 %edx
3690 andb $0xf,%cl # ecx<- A
3692 fistpll (rFP,%ecx,4) # convert and store
3694 fistpl (rFP,%ecx,4) # convert and store
3696 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3697 jmp .LOP_DOUBLE_TO_INT_continue
3700 /* ------------------------------ */
3702 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3703 /* File: x86/OP_DOUBLE_TO_LONG.S */
3704 /* File: x86/cvtfp_int.S */
3705 /* On fp to int conversions, Java requires that
3706 * if the result > maxint, it should be clamped to maxint. If it is less
3707 * than minint, it should be clamped to minint. If it is a nan, the result
3708 * should be zero. Further, the rounding mode is to truncate. This model
3709 * differs from what is delivered normally via the x86 fpu, so we have
3710 * to play some games.
3712 /* float/double to int/long vA, vB */
3713 movzbl rINSTbl,%ecx # ecx<- A+
3714 sarl $4,rINST # rINST<- B
3716 fldl (rFP,rINST,4) # %st0<- vB
3718 flds (rFP,rINST,4) # %st0<- vB
3721 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3722 movzwl LOCAL0_OFFSET(%ebp),%eax
3724 movw %ax,LOCAL0_OFFSET+2(%ebp)
3725 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3726 FETCH_INST_OPCODE 1 %edx
3727 andb $0xf,%cl # ecx<- A
3729 fistpll (rFP,%ecx,4) # convert and store
3731 fistpl (rFP,%ecx,4) # convert and store
3733 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3734 jmp .LOP_DOUBLE_TO_LONG_continue
3737 /* ------------------------------ */
3739 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3740 /* File: x86/OP_DOUBLE_TO_FLOAT.S */
3741 /* File: x86/fpcvt.S */
3743 * Generic 32-bit FP conversion operation.
3746 movzbl rINSTbl,%ecx # ecx<- A+
3747 sarl $4,rINST # rINST<- B
3748 fldl (rFP,rINST,4) # %st0<- vB
3749 andb $0xf,%cl # ecx<- A
3750 FETCH_INST_OPCODE 1 %edx
3753 fstps (rFP,%ecx,4) # vA<- %st0
3757 /* ------------------------------ */
3759 .L_OP_INT_TO_BYTE: /* 0x8d */
3760 /* File: x86/OP_INT_TO_BYTE.S */
3761 /* File: x86/unop.S */
3763 * Generic 32-bit unary operation. Provide an "instr" line that
3764 * specifies an instruction that performs "result = op eax".
3767 movzbl rINSTbl,%ecx # ecx<- A+
3768 sarl $4,rINST # rINST<- B
3769 GET_VREG_R %eax rINST # eax<- vB
3770 andb $0xf,%cl # ecx<- A
3771 FETCH_INST_OPCODE 1 %edx
3780 /* ------------------------------ */
3782 .L_OP_INT_TO_CHAR: /* 0x8e */
3783 /* File: x86/OP_INT_TO_CHAR.S */
3784 /* File: x86/unop.S */
3786 * Generic 32-bit unary operation. Provide an "instr" line that
3787 * specifies an instruction that performs "result = op eax".
3790 movzbl rINSTbl,%ecx # ecx<- A+
3791 sarl $4,rINST # rINST<- B
3792 GET_VREG_R %eax rINST # eax<- vB
3793 andb $0xf,%cl # ecx<- A
3794 FETCH_INST_OPCODE 1 %edx
3803 /* ------------------------------ */
3805 .L_OP_INT_TO_SHORT: /* 0x8f */
3806 /* File: x86/OP_INT_TO_SHORT.S */
3807 /* File: x86/unop.S */
3809 * Generic 32-bit unary operation. Provide an "instr" line that
3810 * specifies an instruction that performs "result = op eax".
3813 movzbl rINSTbl,%ecx # ecx<- A+
3814 sarl $4,rINST # rINST<- B
3815 GET_VREG_R %eax rINST # eax<- vB
3816 andb $0xf,%cl # ecx<- A
3817 FETCH_INST_OPCODE 1 %edx
3826 /* ------------------------------ */
3828 .L_OP_ADD_INT: /* 0x90 */
3829 /* File: x86/OP_ADD_INT.S */
3830 /* File: x86/binop.S */
3832 * Generic 32-bit binary operation. Provide an "instr" line that
3833 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3834 * This could be an x86 instruction or a function call. (If the result
3835 * comes back in a register other than eax, you can override "result".)
3837 * For: add-int, sub-int, and-int, or-int,
3838 * xor-int, shl-int, shr-int, ushr-int
3840 /* binop vAA, vBB, vCC */
3841 movzbl 2(rPC),%eax # eax<- BB
3842 movzbl 3(rPC),%ecx # ecx<- CC
3843 GET_VREG_R %eax %eax # eax<- vBB
3844 addl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3845 FETCH_INST_OPCODE 2 %edx
3851 /* ------------------------------ */
3853 .L_OP_SUB_INT: /* 0x91 */
3854 /* File: x86/OP_SUB_INT.S */
3855 /* File: x86/binop.S */
3857 * Generic 32-bit binary operation. Provide an "instr" line that
3858 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3859 * This could be an x86 instruction or a function call. (If the result
3860 * comes back in a register other than eax, you can override "result".)
3862 * For: add-int, sub-int, and-int, or-int,
3863 * xor-int, shl-int, shr-int, ushr-int
3865 /* binop vAA, vBB, vCC */
3866 movzbl 2(rPC),%eax # eax<- BB
3867 movzbl 3(rPC),%ecx # ecx<- CC
3868 GET_VREG_R %eax %eax # eax<- vBB
3869 subl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3870 FETCH_INST_OPCODE 2 %edx
3876 /* ------------------------------ */
3878 .L_OP_MUL_INT: /* 0x92 */
3879 /* File: x86/OP_MUL_INT.S */
3881 * 32-bit binary multiplication.
3883 /* mul vAA, vBB, vCC */
3884 movzbl 2(rPC),%eax # eax<- BB
3885 movzbl 3(rPC),%ecx # ecx<- CC
3886 GET_VREG_R %eax %eax # eax<- vBB
3887 imull (rFP,%ecx,4),%eax # trashes edx
3888 FETCH_INST_OPCODE 2 %edx
3893 /* ------------------------------ */
3895 .L_OP_DIV_INT: /* 0x93 */
3896 /* File: x86/OP_DIV_INT.S */
3897 /* File: x86/bindiv.S */
3900 * 32-bit binary div/rem operation. Handles special case of op0=minint and
3903 /* binop vAA, vBB, vCC */
3904 movzbl 2(rPC),%eax # eax<- BB
3905 movzbl 3(rPC),%ecx # ecx<- CC
3906 GET_VREG_R %eax %eax # eax<- vBB
3907 GET_VREG_R %ecx %ecx # eax<- vBB
3909 je common_errDivideByZero
3911 jne .LOP_DIV_INT_continue_div
3912 cmpl $0x80000000,%eax
3913 jne .LOP_DIV_INT_continue_div
3914 movl $0x80000000,%eax
3915 jmp .LOP_DIV_INT_finish_div
3919 /* ------------------------------ */
3921 .L_OP_REM_INT: /* 0x94 */
3922 /* File: x86/OP_REM_INT.S */
3923 /* File: x86/bindiv.S */
3926 * 32-bit binary div/rem operation. Handles special case of op0=minint and
3929 /* binop vAA, vBB, vCC */
3930 movzbl 2(rPC),%eax # eax<- BB
3931 movzbl 3(rPC),%ecx # ecx<- CC
3932 GET_VREG_R %eax %eax # eax<- vBB
3933 GET_VREG_R %ecx %ecx # eax<- vBB
3935 je common_errDivideByZero
3937 jne .LOP_REM_INT_continue_div
3938 cmpl $0x80000000,%eax
3939 jne .LOP_REM_INT_continue_div
3941 jmp .LOP_REM_INT_finish_div
3945 /* ------------------------------ */
3947 .L_OP_AND_INT: /* 0x95 */
3948 /* File: x86/OP_AND_INT.S */
3949 /* File: x86/binop.S */
3951 * Generic 32-bit binary operation. Provide an "instr" line that
3952 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3953 * This could be an x86 instruction or a function call. (If the result
3954 * comes back in a register other than eax, you can override "result".)
3956 * For: add-int, sub-int, and-int, or-int,
3957 * xor-int, shl-int, shr-int, ushr-int
3959 /* binop vAA, vBB, vCC */
3960 movzbl 2(rPC),%eax # eax<- BB
3961 movzbl 3(rPC),%ecx # ecx<- CC
3962 GET_VREG_R %eax %eax # eax<- vBB
3963 andl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3964 FETCH_INST_OPCODE 2 %edx
3970 /* ------------------------------ */
3972 .L_OP_OR_INT: /* 0x96 */
3973 /* File: x86/OP_OR_INT.S */
3974 /* File: x86/binop.S */
3976 * Generic 32-bit binary operation. Provide an "instr" line that
3977 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3978 * This could be an x86 instruction or a function call. (If the result
3979 * comes back in a register other than eax, you can override "result".)
3981 * For: add-int, sub-int, and-int, or-int,
3982 * xor-int, shl-int, shr-int, ushr-int
3984 /* binop vAA, vBB, vCC */
3985 movzbl 2(rPC),%eax # eax<- BB
3986 movzbl 3(rPC),%ecx # ecx<- CC
3987 GET_VREG_R %eax %eax # eax<- vBB
3988 orl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3989 FETCH_INST_OPCODE 2 %edx
3995 /* ------------------------------ */
3997 .L_OP_XOR_INT: /* 0x97 */
3998 /* File: x86/OP_XOR_INT.S */
3999 /* File: x86/binop.S */
4001 * Generic 32-bit binary operation. Provide an "instr" line that
4002 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
4003 * This could be an x86 instruction or a function call. (If the result
4004 * comes back in a register other than eax, you can override "result".)
4006 * For: add-int, sub-int, and-int, or-int,
4007 * xor-int, shl-int, shr-int, ushr-int
4009 /* binop vAA, vBB, vCC */
4010 movzbl 2(rPC),%eax # eax<- BB
4011 movzbl 3(rPC),%ecx # ecx<- CC
4012 GET_VREG_R %eax %eax # eax<- vBB
4013 xorl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
4014 FETCH_INST_OPCODE 2 %edx
4020 /* ------------------------------ */
4022 .L_OP_SHL_INT: /* 0x98 */
4023 /* File: x86/OP_SHL_INT.S */
4024 /* File: x86/binop1.S */
4026 * Generic 32-bit binary operation in which both operands loaded to
4027 * registers (op0 in eax, op1 in ecx).
4029 /* binop vAA, vBB, vCC */
4030 movzbl 2(rPC),%eax # eax<- BB
4031 movzbl 3(rPC),%ecx # ecx<- CC
4032 GET_VREG_R %eax %eax # eax<- vBB
4033 GET_VREG_R %ecx %ecx # eax<- vBB
4034 sall %cl,%eax # ex: addl %ecx,%eax
4035 FETCH_INST_OPCODE 2 %edx
4041 /* ------------------------------ */
4043 .L_OP_SHR_INT: /* 0x99 */
4044 /* File: x86/OP_SHR_INT.S */
4045 /* File: x86/binop1.S */
4047 * Generic 32-bit binary operation in which both operands loaded to
4048 * registers (op0 in eax, op1 in ecx).
4050 /* binop vAA, vBB, vCC */
4051 movzbl 2(rPC),%eax # eax<- BB
4052 movzbl 3(rPC),%ecx # ecx<- CC
4053 GET_VREG_R %eax %eax # eax<- vBB
4054 GET_VREG_R %ecx %ecx # eax<- vBB
4055 sarl %cl,%eax # ex: addl %ecx,%eax
4056 FETCH_INST_OPCODE 2 %edx
4062 /* ------------------------------ */
4064 .L_OP_USHR_INT: /* 0x9a */
4065 /* File: x86/OP_USHR_INT.S */
4066 /* File: x86/binop1.S */
4068 * Generic 32-bit binary operation in which both operands loaded to
4069 * registers (op0 in eax, op1 in ecx).
4071 /* binop vAA, vBB, vCC */
4072 movzbl 2(rPC),%eax # eax<- BB
4073 movzbl 3(rPC),%ecx # ecx<- CC
4074 GET_VREG_R %eax %eax # eax<- vBB
4075 GET_VREG_R %ecx %ecx # eax<- vBB
4076 shrl %cl,%eax # ex: addl %ecx,%eax
4077 FETCH_INST_OPCODE 2 %edx
4083 /* ------------------------------ */
4085 .L_OP_ADD_LONG: /* 0x9b */
4086 /* File: x86/OP_ADD_LONG.S */
4087 /* File: x86/binopWide.S */
4089 * Generic 64-bit binary operation.
4091 /* binop vAA, vBB, vCC */
4093 movzbl 2(rPC),%eax # eax<- BB
4094 movzbl 3(rPC),%ecx # ecx<- CC
4095 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0]
4096 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1]
4097 addl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx
4098 adcl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4099 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx
4100 FETCH_INST_OPCODE 2 %edx
4101 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax
4106 /* ------------------------------ */
4108 .L_OP_SUB_LONG: /* 0x9c */
4109 /* File: x86/OP_SUB_LONG.S */
4110 /* File: x86/binopWide.S */
4112 * Generic 64-bit binary operation.
4114 /* binop vAA, vBB, vCC */
4116 movzbl 2(rPC),%eax # eax<- BB
4117 movzbl 3(rPC),%ecx # ecx<- CC
4118 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0]
4119 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1]
4120 subl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx
4121 sbbl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4122 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx
4123 FETCH_INST_OPCODE 2 %edx
4124 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax
4129 /* ------------------------------ */
4131 .L_OP_MUL_LONG: /* 0x9d */
4132 /* File: x86/OP_MUL_LONG.S */
4134 * Signed 64-bit integer multiply.
4136 * We could definately use more free registers for
4137 * this code. We spill rINSTw (ebx),
4138 * giving us eax, ebc, ecx and edx as computational
4139 * temps. On top of that, we'll spill edi (rFP)
4140 * for use as the vB pointer and esi for use
4141 * as the vC pointer. Yuck.
4143 /* mul-long vAA, vBB, vCC */
4144 movzbl 2(rPC),%eax # eax<- B
4145 movzbl 3(rPC),%ecx # ecx<- C
4149 leal (rFP,%eax,4),%esi # esi<- &v[B]
4150 leal (rFP,%ecx,4),rFP # rFP<- &v[C]
4151 movl 4(%esi),%ecx # ecx<- Bmsw
4152 imull (rFP),%ecx # ecx<- (Bmsw*Clsw)
4153 movl 4(rFP),%eax # eax<- Cmsw
4154 imull (%esi),%eax # eax<- (Cmsw*Blsw)
4155 addl %eax,%ecx # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw)
4156 movl (rFP),%eax # eax<- Clsw
4157 mull (%esi) # eax<- (Clsw*Alsw)
4160 jmp .LOP_MUL_LONG_continue
4162 /* ------------------------------ */
4164 .L_OP_DIV_LONG: /* 0x9e */
4165 /* File: x86/OP_DIV_LONG.S */
4166 /* div vAA, vBB, vCC */
4167 movzbl 3(rPC),%eax # eax<- CC
4168 movzbl 2(rPC),%ecx # ecx<- BB
4169 GET_VREG_WORD %edx %eax 0
4170 GET_VREG_WORD %eax %eax 1
4171 movl %edx,OUT_ARG2(%esp)
4173 je .LOP_DIV_LONG_check_zero
4175 je .LOP_DIV_LONG_check_neg1
4176 .LOP_DIV_LONG_notSpecial:
4177 GET_VREG_WORD %edx %ecx 0
4178 GET_VREG_WORD %ecx %ecx 1
4179 .LOP_DIV_LONG_notSpecial1:
4180 movl %eax,OUT_ARG3(%esp)
4181 movl %edx,OUT_ARG0(%esp)
4182 movl %ecx,OUT_ARG1(%esp)
4183 jmp .LOP_DIV_LONG_continue
4185 /* ------------------------------ */
4187 .L_OP_REM_LONG: /* 0x9f */
4188 /* File: x86/OP_REM_LONG.S */
4189 /* File: x86/OP_DIV_LONG.S */
4190 /* div vAA, vBB, vCC */
4191 movzbl 3(rPC),%eax # eax<- CC
4192 movzbl 2(rPC),%ecx # ecx<- BB
4193 GET_VREG_WORD %edx %eax 0
4194 GET_VREG_WORD %eax %eax 1
4195 movl %edx,OUT_ARG2(%esp)
4197 je .LOP_REM_LONG_check_zero
4199 je .LOP_REM_LONG_check_neg1
4200 .LOP_REM_LONG_notSpecial:
4201 GET_VREG_WORD %edx %ecx 0
4202 GET_VREG_WORD %ecx %ecx 1
4203 .LOP_REM_LONG_notSpecial1:
4204 movl %eax,OUT_ARG3(%esp)
4205 movl %edx,OUT_ARG0(%esp)
4206 movl %ecx,OUT_ARG1(%esp)
4207 jmp .LOP_REM_LONG_continue
4210 /* ------------------------------ */
4212 .L_OP_AND_LONG: /* 0xa0 */
4213 /* File: x86/OP_AND_LONG.S */
4214 /* File: x86/binopWide.S */
4216 * Generic 64-bit binary operation.
4218 /* binop vAA, vBB, vCC */
4220 movzbl 2(rPC),%eax # eax<- BB
4221 movzbl 3(rPC),%ecx # ecx<- CC
4222 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0]
4223 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1]
4224 andl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx
4225 andl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4226 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx
4227 FETCH_INST_OPCODE 2 %edx
4228 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax
4233 /* ------------------------------ */
4235 .L_OP_OR_LONG: /* 0xa1 */
4236 /* File: x86/OP_OR_LONG.S */
4237 /* File: x86/binopWide.S */
4239 * Generic 64-bit binary operation.
4241 /* binop vAA, vBB, vCC */
4243 movzbl 2(rPC),%eax # eax<- BB
4244 movzbl 3(rPC),%ecx # ecx<- CC
4245 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0]
4246 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1]
4247 orl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx
4248 orl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4249 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx
4250 FETCH_INST_OPCODE 2 %edx
4251 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax
4256 /* ------------------------------ */
4258 .L_OP_XOR_LONG: /* 0xa2 */
4259 /* File: x86/OP_XOR_LONG.S */
4260 /* File: x86/binopWide.S */
4262 * Generic 64-bit binary operation.
4264 /* binop vAA, vBB, vCC */
4266 movzbl 2(rPC),%eax # eax<- BB
4267 movzbl 3(rPC),%ecx # ecx<- CC
4268 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0]
4269 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1]
4270 xorl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx
4271 xorl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4272 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx
4273 FETCH_INST_OPCODE 2 %edx
4274 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax
4279 /* ------------------------------ */
4281 .L_OP_SHL_LONG: /* 0xa3 */
4282 /* File: x86/OP_SHL_LONG.S */
4284 * Long integer shift. This is different from the generic 32/64-bit
4285 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4286 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4287 * 6 bits of the shift distance. x86 shifts automatically mask off
4288 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4291 /* shl-long vAA, vBB, vCC */
4292 /* ecx gets shift count */
4293 /* Need to spill edx */
4294 /* rINSTw gets AA */
4295 movzbl 2(rPC),%eax # eax<- BB
4296 movzbl 3(rPC),%ecx # ecx<- CC
4297 GET_VREG_WORD %edx %eax 1 # ecx<- v[BB+1]
4298 GET_VREG_R %ecx %ecx # ecx<- vCC
4299 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0]
4307 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- %edx
4308 FETCH_INST_OPCODE 2 %edx
4309 jmp .LOP_SHL_LONG_finish
4311 /* ------------------------------ */
4313 .L_OP_SHR_LONG: /* 0xa4 */
4314 /* File: x86/OP_SHR_LONG.S */
4316 * Long integer shift. This is different from the generic 32/64-bit
4317 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4318 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4319 * 6 bits of the shift distance. x86 shifts automatically mask off
4320 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4323 /* shr-long vAA, vBB, vCC */
4324 /* ecx gets shift count */
4325 /* Need to spill edx */
4326 /* rINSTw gets AA */
4327 movzbl 2(rPC),%eax # eax<- BB
4328 movzbl 3(rPC),%ecx # ecx<- CC
4329 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1]
4330 GET_VREG_R %ecx %ecx # ecx<- vCC
4331 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0]
4339 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx
4340 FETCH_INST_OPCODE 2 %edx
4341 jmp .LOP_SHR_LONG_finish
4343 /* ------------------------------ */
4345 .L_OP_USHR_LONG: /* 0xa5 */
4346 /* File: x86/OP_USHR_LONG.S */
4348 * Long integer shift. This is different from the generic 32/64-bit
4349 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4350 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4351 * 6 bits of the shift distance. x86 shifts automatically mask off
4352 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4355 /* shr-long vAA, vBB, vCC */
4356 /* ecx gets shift count */
4357 /* Need to spill edx */
4358 /* rINSTw gets AA */
4359 movzbl 2(rPC),%eax # eax<- BB
4360 movzbl 3(rPC),%ecx # ecx<- CC
4361 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1]
4362 GET_VREG_R %ecx %ecx # ecx<- vCC
4363 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0]
4371 FETCH_INST_OPCODE 2 %edx
4372 SET_VREG_WORD %edx rINST 1 # v[BB+1]<- edx
4373 jmp .LOP_USHR_LONG_finish
4375 /* ------------------------------ */
4377 .L_OP_ADD_FLOAT: /* 0xa6 */
4378 /* File: x86/OP_ADD_FLOAT.S */
4379 /* File: x86/binflop.S */
4381 * Generic 32-bit binary float operation.
4383 * For: add-fp, sub-fp, mul-fp, div-fp
4385 /* binop vAA, vBB, vCC */
4386 movzbl 2(rPC),%eax # eax<- CC
4387 movzbl 3(rPC),%ecx # ecx<- BB
4388 flds (rFP,%eax,4) # vCC to fp stack
4389 fadds (rFP,%ecx,4) # ex: faddp
4390 FETCH_INST_OPCODE 2 %edx
4392 fstps (rFP,rINST,4) # %st to vAA
4396 /* ------------------------------ */
4398 .L_OP_SUB_FLOAT: /* 0xa7 */
4399 /* File: x86/OP_SUB_FLOAT.S */
4400 /* File: x86/binflop.S */
4402 * Generic 32-bit binary float operation.
4404 * For: add-fp, sub-fp, mul-fp, div-fp
4406 /* binop vAA, vBB, vCC */
4407 movzbl 2(rPC),%eax # eax<- CC
4408 movzbl 3(rPC),%ecx # ecx<- BB
4409 flds (rFP,%eax,4) # vCC to fp stack
4410 fsubs (rFP,%ecx,4) # ex: faddp
4411 FETCH_INST_OPCODE 2 %edx
4413 fstps (rFP,rINST,4) # %st to vAA
4417 /* ------------------------------ */
4419 .L_OP_MUL_FLOAT: /* 0xa8 */
4420 /* File: x86/OP_MUL_FLOAT.S */
4421 /* File: x86/binflop.S */
4423 * Generic 32-bit binary float operation.
4425 * For: add-fp, sub-fp, mul-fp, div-fp
4427 /* binop vAA, vBB, vCC */
4428 movzbl 2(rPC),%eax # eax<- CC
4429 movzbl 3(rPC),%ecx # ecx<- BB
4430 flds (rFP,%eax,4) # vCC to fp stack
4431 fmuls (rFP,%ecx,4) # ex: faddp
4432 FETCH_INST_OPCODE 2 %edx
4434 fstps (rFP,rINST,4) # %st to vAA
4438 /* ------------------------------ */
4440 .L_OP_DIV_FLOAT: /* 0xa9 */
4441 /* File: x86/OP_DIV_FLOAT.S */
4442 /* File: x86/binflop.S */
4444 * Generic 32-bit binary float operation.
4446 * For: add-fp, sub-fp, mul-fp, div-fp
4448 /* binop vAA, vBB, vCC */
4449 movzbl 2(rPC),%eax # eax<- CC
4450 movzbl 3(rPC),%ecx # ecx<- BB
4451 flds (rFP,%eax,4) # vCC to fp stack
4452 fdivs (rFP,%ecx,4) # ex: faddp
4453 FETCH_INST_OPCODE 2 %edx
4455 fstps (rFP,rINST,4) # %st to vAA
4459 /* ------------------------------ */
4461 .L_OP_REM_FLOAT: /* 0xaa */
4462 /* File: x86/OP_REM_FLOAT.S */
4463 /* rem_float vAA, vBB, vCC */
4464 movzbl 3(rPC),%ecx # ecx<- BB
4465 movzbl 2(rPC),%eax # eax<- CC
4466 flds (rFP,%ecx,4) # vCC to fp stack
4467 flds (rFP,%eax,4) # vCC to fp stack
4468 movzbl rINSTbl,%ecx # ecx<- AA
4469 FETCH_INST_OPCODE 2 %edx
4477 fstps (rFP,%ecx,4) # %st to vAA
4480 /* ------------------------------ */
4482 .L_OP_ADD_DOUBLE: /* 0xab */
4483 /* File: x86/OP_ADD_DOUBLE.S */
4484 /* File: x86/binflop.S */
4486 * Generic 32-bit binary float operation.
4488 * For: add-fp, sub-fp, mul-fp, div-fp
4490 /* binop vAA, vBB, vCC */
4491 movzbl 2(rPC),%eax # eax<- CC
4492 movzbl 3(rPC),%ecx # ecx<- BB
4493 fldl (rFP,%eax,4) # vCC to fp stack
4494 faddl (rFP,%ecx,4) # ex: faddp
4495 FETCH_INST_OPCODE 2 %edx
4497 fstpl (rFP,rINST,4) # %st to vAA
4501 /* ------------------------------ */
4503 .L_OP_SUB_DOUBLE: /* 0xac */
4504 /* File: x86/OP_SUB_DOUBLE.S */
4505 /* File: x86/binflop.S */
4507 * Generic 32-bit binary float operation.
4509 * For: add-fp, sub-fp, mul-fp, div-fp
4511 /* binop vAA, vBB, vCC */
4512 movzbl 2(rPC),%eax # eax<- CC
4513 movzbl 3(rPC),%ecx # ecx<- BB
4514 fldl (rFP,%eax,4) # vCC to fp stack
4515 fsubl (rFP,%ecx,4) # ex: faddp
4516 FETCH_INST_OPCODE 2 %edx
4518 fstpl (rFP,rINST,4) # %st to vAA
4522 /* ------------------------------ */
4524 .L_OP_MUL_DOUBLE: /* 0xad */
4525 /* File: x86/OP_MUL_DOUBLE.S */
4526 /* File: x86/binflop.S */
4528 * Generic 32-bit binary float operation.
4530 * For: add-fp, sub-fp, mul-fp, div-fp
4532 /* binop vAA, vBB, vCC */
4533 movzbl 2(rPC),%eax # eax<- CC
4534 movzbl 3(rPC),%ecx # ecx<- BB
4535 fldl (rFP,%eax,4) # vCC to fp stack
4536 fmull (rFP,%ecx,4) # ex: faddp
4537 FETCH_INST_OPCODE 2 %edx
4539 fstpl (rFP,rINST,4) # %st to vAA
4543 /* ------------------------------ */
4545 .L_OP_DIV_DOUBLE: /* 0xae */
4546 /* File: x86/OP_DIV_DOUBLE.S */
4547 /* File: x86/binflop.S */
4549 * Generic 32-bit binary float operation.
4551 * For: add-fp, sub-fp, mul-fp, div-fp
4553 /* binop vAA, vBB, vCC */
4554 movzbl 2(rPC),%eax # eax<- CC
4555 movzbl 3(rPC),%ecx # ecx<- BB
4556 fldl (rFP,%eax,4) # vCC to fp stack
4557 fdivl (rFP,%ecx,4) # ex: faddp
4558 FETCH_INST_OPCODE 2 %edx
4560 fstpl (rFP,rINST,4) # %st to vAA
4564 /* ------------------------------ */
4566 .L_OP_REM_DOUBLE: /* 0xaf */
4567 /* File: x86/OP_REM_DOUBLE.S */
4568 /* rem_float vAA, vBB, vCC */
4569 movzbl 3(rPC),%ecx # ecx<- BB
4570 movzbl 2(rPC),%eax # eax<- CC
4571 fldl (rFP,%ecx,4) # vCC to fp stack
4572 fldl (rFP,%eax,4) # vCC to fp stack
4573 movzbl rINSTbl,%ecx # ecx<- AA
4574 FETCH_INST_OPCODE 2 %edx
4582 fstpl (rFP,%ecx,4) # %st to vAA
4585 /* ------------------------------ */
4587 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
4588 /* File: x86/OP_ADD_INT_2ADDR.S */
4589 /* File: x86/binop2addr.S */
4591 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4592 * that specifies an instruction that performs "result = r0 op r1".
4593 * This could be an ARM instruction or a function call. (If the result
4594 * comes back in a register other than r0, you can override "result".)
4596 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4597 * vCC (r1). Useful for integer division and modulus.
4599 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4600 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4601 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4602 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4604 /* binop/2addr vA, vB */
4605 movzx rINSTbl,%ecx # ecx<- A+
4606 sarl $4,rINST # rINST<- B
4607 GET_VREG_R %eax rINST # eax<- vB
4608 FETCH_INST_OPCODE 1 %edx
4609 andb $0xf,%cl # ecx<- A
4610 addl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4615 /* ------------------------------ */
4617 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
4618 /* File: x86/OP_SUB_INT_2ADDR.S */
4619 /* File: x86/binop2addr.S */
4621 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4622 * that specifies an instruction that performs "result = r0 op r1".
4623 * This could be an ARM instruction or a function call. (If the result
4624 * comes back in a register other than r0, you can override "result".)
4626 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4627 * vCC (r1). Useful for integer division and modulus.
4629 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4630 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4631 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4632 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4634 /* binop/2addr vA, vB */
4635 movzx rINSTbl,%ecx # ecx<- A+
4636 sarl $4,rINST # rINST<- B
4637 GET_VREG_R %eax rINST # eax<- vB
4638 FETCH_INST_OPCODE 1 %edx
4639 andb $0xf,%cl # ecx<- A
4640 subl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4645 /* ------------------------------ */
4647 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
4648 /* File: x86/OP_MUL_INT_2ADDR.S */
4650 movzx rINSTbl,%ecx # ecx<- A+
4651 sarl $4,rINST # rINST<- B
4652 GET_VREG_R %eax rINST # eax<- vB
4653 andb $0xf,%cl # ecx<- A
4654 imull (rFP,%ecx,4),%eax
4655 FETCH_INST_OPCODE 1 %edx
4660 /* ------------------------------ */
4662 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
4663 /* File: x86/OP_DIV_INT_2ADDR.S */
4664 /* File: x86/bindiv2addr.S */
4666 * 32-bit binary div/rem operation. Handles special case of op0=minint and
4669 /* div/rem/2addr vA, vB */
4670 movzx rINSTbl,%ecx # eax<- BA
4671 sarl $4,%ecx # ecx<- B
4672 GET_VREG_R %ecx %ecx # eax<- vBB
4673 andb $0xf,rINSTbl # rINST<- A
4674 GET_VREG_R %eax rINST # eax<- vBB
4676 je common_errDivideByZero
4678 jne .LOP_DIV_INT_2ADDR_continue_div2addr
4679 cmpl $0x80000000,%eax
4680 jne .LOP_DIV_INT_2ADDR_continue_div2addr
4681 movl $0x80000000,%eax
4682 jmp .LOP_DIV_INT_2ADDR_finish_div2addr
4686 /* ------------------------------ */
4688 .L_OP_REM_INT_2ADDR: /* 0xb4 */
4689 /* File: x86/OP_REM_INT_2ADDR.S */
4690 /* File: x86/bindiv2addr.S */
4692 * 32-bit binary div/rem operation. Handles special case of op0=minint and
4695 /* div/rem/2addr vA, vB */
4696 movzx rINSTbl,%ecx # eax<- BA
4697 sarl $4,%ecx # ecx<- B
4698 GET_VREG_R %ecx %ecx # eax<- vBB
4699 andb $0xf,rINSTbl # rINST<- A
4700 GET_VREG_R %eax rINST # eax<- vBB
4702 je common_errDivideByZero
4704 jne .LOP_REM_INT_2ADDR_continue_div2addr
4705 cmpl $0x80000000,%eax
4706 jne .LOP_REM_INT_2ADDR_continue_div2addr
4708 jmp .LOP_REM_INT_2ADDR_finish_div2addr
4712 /* ------------------------------ */
4714 .L_OP_AND_INT_2ADDR: /* 0xb5 */
4715 /* File: x86/OP_AND_INT_2ADDR.S */
4716 /* File: x86/binop2addr.S */
4718 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4719 * that specifies an instruction that performs "result = r0 op r1".
4720 * This could be an ARM instruction or a function call. (If the result
4721 * comes back in a register other than r0, you can override "result".)
4723 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4724 * vCC (r1). Useful for integer division and modulus.
4726 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4727 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4728 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4729 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4731 /* binop/2addr vA, vB */
4732 movzx rINSTbl,%ecx # ecx<- A+
4733 sarl $4,rINST # rINST<- B
4734 GET_VREG_R %eax rINST # eax<- vB
4735 FETCH_INST_OPCODE 1 %edx
4736 andb $0xf,%cl # ecx<- A
4737 andl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4742 /* ------------------------------ */
4744 .L_OP_OR_INT_2ADDR: /* 0xb6 */
4745 /* File: x86/OP_OR_INT_2ADDR.S */
4746 /* File: x86/binop2addr.S */
4748 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4749 * that specifies an instruction that performs "result = r0 op r1".
4750 * This could be an ARM instruction or a function call. (If the result
4751 * comes back in a register other than r0, you can override "result".)
4753 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4754 * vCC (r1). Useful for integer division and modulus.
4756 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4757 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4758 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4759 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4761 /* binop/2addr vA, vB */
4762 movzx rINSTbl,%ecx # ecx<- A+
4763 sarl $4,rINST # rINST<- B
4764 GET_VREG_R %eax rINST # eax<- vB
4765 FETCH_INST_OPCODE 1 %edx
4766 andb $0xf,%cl # ecx<- A
4767 orl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4772 /* ------------------------------ */
4774 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
4775 /* File: x86/OP_XOR_INT_2ADDR.S */
4776 /* File: x86/binop2addr.S */
4778 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4779 * that specifies an instruction that performs "result = r0 op r1".
4780 * This could be an ARM instruction or a function call. (If the result
4781 * comes back in a register other than r0, you can override "result".)
4783 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4784 * vCC (r1). Useful for integer division and modulus.
4786 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4787 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4788 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4789 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4791 /* binop/2addr vA, vB */
4792 movzx rINSTbl,%ecx # ecx<- A+
4793 sarl $4,rINST # rINST<- B
4794 GET_VREG_R %eax rINST # eax<- vB
4795 FETCH_INST_OPCODE 1 %edx
4796 andb $0xf,%cl # ecx<- A
4797 xorl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4802 /* ------------------------------ */
4804 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
4805 /* File: x86/OP_SHL_INT_2ADDR.S */
4806 /* File: x86/shop2addr.S */
4808 * Generic 32-bit "shift/2addr" operation.
4810 /* shift/2addr vA, vB */
4811 movzx rINSTbl,%ecx # eax<- BA
4812 sarl $4,%ecx # ecx<- B
4813 GET_VREG_R %ecx %ecx # eax<- vBB
4814 andb $0xf,rINSTbl # rINST<- A
4815 GET_VREG_R %eax rINST # eax<- vAA
4816 sall %cl,%eax # ex: sarl %cl,%eax
4817 FETCH_INST_OPCODE 1 %edx
4823 /* ------------------------------ */
4825 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
4826 /* File: x86/OP_SHR_INT_2ADDR.S */
4827 /* File: x86/shop2addr.S */
4829 * Generic 32-bit "shift/2addr" operation.
4831 /* shift/2addr vA, vB */
4832 movzx rINSTbl,%ecx # eax<- BA
4833 sarl $4,%ecx # ecx<- B
4834 GET_VREG_R %ecx %ecx # eax<- vBB
4835 andb $0xf,rINSTbl # rINST<- A
4836 GET_VREG_R %eax rINST # eax<- vAA
4837 sarl %cl,%eax # ex: sarl %cl,%eax
4838 FETCH_INST_OPCODE 1 %edx
4844 /* ------------------------------ */
4846 .L_OP_USHR_INT_2ADDR: /* 0xba */
4847 /* File: x86/OP_USHR_INT_2ADDR.S */
4848 /* File: x86/shop2addr.S */
4850 * Generic 32-bit "shift/2addr" operation.
4852 /* shift/2addr vA, vB */
4853 movzx rINSTbl,%ecx # eax<- BA
4854 sarl $4,%ecx # ecx<- B
4855 GET_VREG_R %ecx %ecx # eax<- vBB
4856 andb $0xf,rINSTbl # rINST<- A
4857 GET_VREG_R %eax rINST # eax<- vAA
4858 shrl %cl,%eax # ex: sarl %cl,%eax
4859 FETCH_INST_OPCODE 1 %edx
4865 /* ------------------------------ */
4867 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
4868 /* File: x86/OP_ADD_LONG_2ADDR.S */
4869 /* File: x86/binopWide2addr.S */
4871 * Generic 64-bit binary operation.
4873 /* binop/2addr vA, vB */
4874 movzbl rINSTbl,%ecx # ecx<- BA
4875 sarl $4,%ecx # ecx<- B
4876 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
4877 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1]
4878 andb $0xF,rINSTbl # rINST<- A
4879 addl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4)
4880 adcl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4)
4881 FETCH_INST_OPCODE 1 %edx
4886 /* ------------------------------ */
4888 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
4889 /* File: x86/OP_SUB_LONG_2ADDR.S */
4890 /* File: x86/binopWide2addr.S */
4892 * Generic 64-bit binary operation.
4894 /* binop/2addr vA, vB */
4895 movzbl rINSTbl,%ecx # ecx<- BA
4896 sarl $4,%ecx # ecx<- B
4897 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
4898 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1]
4899 andb $0xF,rINSTbl # rINST<- A
4900 subl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4)
4901 sbbl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4)
4902 FETCH_INST_OPCODE 1 %edx
4907 /* ------------------------------ */
4909 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
4910 /* File: x86/OP_MUL_LONG_2ADDR.S */
4912 * Signed 64-bit integer multiply, 2-addr version
4914 * We could definately use more free registers for
4915 * this code. We must spill %edx (edx) because it
4916 * is used by imul. We'll also spill rINST (ebx),
4917 * giving us eax, ebc, ecx and edx as computational
4918 * temps. On top of that, we'll spill %esi (edi)
4919 * for use as the vA pointer and rFP (esi) for use
4920 * as the vB pointer. Yuck.
4922 /* mul-long/2addr vA, vB */
4923 movzbl rINSTbl,%eax # eax<- BA
4924 andb $0xf,%al # eax<- A
4925 sarl $4,rINST # rINST<- B
4928 leal (rFP,%eax,4),%esi # %esi<- &v[A]
4929 leal (rFP,rINST,4),rFP # rFP<- &v[B]
4930 movl 4(%esi),%ecx # ecx<- Amsw
4931 imull (rFP),%ecx # ecx<- (Amsw*Blsw)
4932 movl 4(rFP),%eax # eax<- Bmsw
4933 imull (%esi),%eax # eax<- (Bmsw*Alsw)
4934 addl %eax,%ecx # ecx<- (Amsw*Blsw)+(Bmsw*Alsw)
4935 movl (rFP),%eax # eax<- Blsw
4936 mull (%esi) # eax<- (Blsw*Alsw)
4937 jmp .LOP_MUL_LONG_2ADDR_continue
4939 /* ------------------------------ */
4941 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
4942 /* File: x86/OP_DIV_LONG_2ADDR.S */
4943 /* div/2addr vA, vB */
4945 shrl $4,%eax # eax<- B
4946 andb $0xf,rINSTbl # rINST<- A
4947 GET_VREG_WORD %edx %eax 0
4948 GET_VREG_WORD %eax %eax 1
4949 movl %edx,OUT_ARG2(%esp)
4951 je .LOP_DIV_LONG_2ADDR_check_zero
4953 je .LOP_DIV_LONG_2ADDR_check_neg1
4954 .LOP_DIV_LONG_2ADDR_notSpecial:
4955 GET_VREG_WORD %edx rINST 0
4956 GET_VREG_WORD %ecx rINST 1
4957 .LOP_DIV_LONG_2ADDR_notSpecial1:
4958 jmp .LOP_DIV_LONG_2ADDR_continue
4960 /* ------------------------------ */
4962 .L_OP_REM_LONG_2ADDR: /* 0xbf */
4963 /* File: x86/OP_REM_LONG_2ADDR.S */
4964 /* File: x86/OP_DIV_LONG_2ADDR.S */
4965 /* div/2addr vA, vB */
4967 shrl $4,%eax # eax<- B
4968 andb $0xf,rINSTbl # rINST<- A
4969 GET_VREG_WORD %edx %eax 0
4970 GET_VREG_WORD %eax %eax 1
4971 movl %edx,OUT_ARG2(%esp)
4973 je .LOP_REM_LONG_2ADDR_check_zero
4975 je .LOP_REM_LONG_2ADDR_check_neg1
4976 .LOP_REM_LONG_2ADDR_notSpecial:
4977 GET_VREG_WORD %edx rINST 0
4978 GET_VREG_WORD %ecx rINST 1
4979 .LOP_REM_LONG_2ADDR_notSpecial1:
4980 jmp .LOP_REM_LONG_2ADDR_continue
4983 /* ------------------------------ */
4985 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
4986 /* File: x86/OP_AND_LONG_2ADDR.S */
4987 /* File: x86/binopWide2addr.S */
4989 * Generic 64-bit binary operation.
4991 /* binop/2addr vA, vB */
4992 movzbl rINSTbl,%ecx # ecx<- BA
4993 sarl $4,%ecx # ecx<- B
4994 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
4995 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1]
4996 andb $0xF,rINSTbl # rINST<- A
4997 andl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4)
4998 andl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4)
4999 FETCH_INST_OPCODE 1 %edx
5004 /* ------------------------------ */
5006 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
5007 /* File: x86/OP_OR_LONG_2ADDR.S */
5008 /* File: x86/binopWide2addr.S */
5010 * Generic 64-bit binary operation.
5012 /* binop/2addr vA, vB */
5013 movzbl rINSTbl,%ecx # ecx<- BA
5014 sarl $4,%ecx # ecx<- B
5015 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
5016 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1]
5017 andb $0xF,rINSTbl # rINST<- A
5018 orl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4)
5019 orl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4)
5020 FETCH_INST_OPCODE 1 %edx
5025 /* ------------------------------ */
5027 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5028 /* File: x86/OP_XOR_LONG_2ADDR.S */
5029 /* File: x86/binopWide2addr.S */
5031 * Generic 64-bit binary operation.
5033 /* binop/2addr vA, vB */
5034 movzbl rINSTbl,%ecx # ecx<- BA
5035 sarl $4,%ecx # ecx<- B
5036 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0]
5037 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1]
5038 andb $0xF,rINSTbl # rINST<- A
5039 xorl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4)
5040 xorl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4)
5041 FETCH_INST_OPCODE 1 %edx
5046 /* ------------------------------ */
5048 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5049 /* File: x86/OP_SHL_LONG_2ADDR.S */
5051 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
5052 * 32-bit shift distance.
5054 /* shl-long/2addr vA, vB */
5055 /* ecx gets shift count */
5056 /* Need to spill edx */
5057 /* rINSTw gets AA */
5058 movzbl rINSTbl,%ecx # ecx<- BA
5059 andb $0xf,rINSTbl # rINST<- A
5060 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0]
5061 sarl $4,%ecx # ecx<- B
5062 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1]
5063 GET_VREG_R %ecx %ecx # ecx<- vBB
5071 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx
5072 jmp .LOP_SHL_LONG_2ADDR_finish
5074 /* ------------------------------ */
5076 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5077 /* File: x86/OP_SHR_LONG_2ADDR.S */
5079 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
5080 * 32-bit shift distance.
5082 /* shl-long/2addr vA, vB */
5083 /* ecx gets shift count */
5084 /* Need to spill edx */
5085 /* rINSTw gets AA */
5086 movzbl rINSTbl,%ecx # ecx<- BA
5087 andb $0xf,rINSTbl # rINST<- A
5088 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0]
5089 sarl $4,%ecx # ecx<- B
5090 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1]
5091 GET_VREG_R %ecx %ecx # ecx<- vBB
5099 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx
5100 jmp .LOP_SHR_LONG_2ADDR_finish
5102 /* ------------------------------ */
5104 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
5105 /* File: x86/OP_USHR_LONG_2ADDR.S */
5107 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
5108 * 32-bit shift distance.
5110 /* shl-long/2addr vA, vB */
5111 /* ecx gets shift count */
5112 /* Need to spill edx */
5113 /* rINSTw gets AA */
5114 movzbl rINSTbl,%ecx # ecx<- BA
5115 andb $0xf,rINSTbl # rINST<- A
5116 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0]
5117 sarl $4,%ecx # ecx<- B
5118 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1]
5119 GET_VREG_R %ecx %ecx # ecx<- vBB
5127 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx
5128 jmp .LOP_USHR_LONG_2ADDR_finish
5130 /* ------------------------------ */
5132 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
5133 /* File: x86/OP_ADD_FLOAT_2ADDR.S */
5134 /* File: x86/binflop2addr.S */
5136 * Generic 32-bit binary float operation.
5138 * For: add-fp, sub-fp, mul-fp, div-fp
5141 /* binop/2addr vA, vB */
5142 movzx rINSTbl,%ecx # ecx<- A+
5143 andb $0xf,%cl # ecx<- A
5144 flds (rFP,%ecx,4) # vAA to fp stack
5145 sarl $4,rINST # rINST<- B
5146 fadds (rFP,rINST,4) # ex: faddp
5147 FETCH_INST_OPCODE 1 %edx
5149 fstps (rFP,%ecx,4) # %st to vA
5153 /* ------------------------------ */
5155 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
5156 /* File: x86/OP_SUB_FLOAT_2ADDR.S */
5157 /* File: x86/binflop2addr.S */
5159 * Generic 32-bit binary float operation.
5161 * For: add-fp, sub-fp, mul-fp, div-fp
5164 /* binop/2addr vA, vB */
5165 movzx rINSTbl,%ecx # ecx<- A+
5166 andb $0xf,%cl # ecx<- A
5167 flds (rFP,%ecx,4) # vAA to fp stack
5168 sarl $4,rINST # rINST<- B
5169 fsubs (rFP,rINST,4) # ex: faddp
5170 FETCH_INST_OPCODE 1 %edx
5172 fstps (rFP,%ecx,4) # %st to vA
5176 /* ------------------------------ */
5178 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
5179 /* File: x86/OP_MUL_FLOAT_2ADDR.S */
5180 /* File: x86/binflop2addr.S */
5182 * Generic 32-bit binary float operation.
5184 * For: add-fp, sub-fp, mul-fp, div-fp
5187 /* binop/2addr vA, vB */
5188 movzx rINSTbl,%ecx # ecx<- A+
5189 andb $0xf,%cl # ecx<- A
5190 flds (rFP,%ecx,4) # vAA to fp stack
5191 sarl $4,rINST # rINST<- B
5192 fmuls (rFP,rINST,4) # ex: faddp
5193 FETCH_INST_OPCODE 1 %edx
5195 fstps (rFP,%ecx,4) # %st to vA
5199 /* ------------------------------ */
5201 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
5202 /* File: x86/OP_DIV_FLOAT_2ADDR.S */
5203 /* File: x86/binflop2addr.S */
5205 * Generic 32-bit binary float operation.
5207 * For: add-fp, sub-fp, mul-fp, div-fp
5210 /* binop/2addr vA, vB */
5211 movzx rINSTbl,%ecx # ecx<- A+
5212 andb $0xf,%cl # ecx<- A
5213 flds (rFP,%ecx,4) # vAA to fp stack
5214 sarl $4,rINST # rINST<- B
5215 fdivs (rFP,rINST,4) # ex: faddp
5216 FETCH_INST_OPCODE 1 %edx
5218 fstps (rFP,%ecx,4) # %st to vA
5222 /* ------------------------------ */
5224 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
5225 /* File: x86/OP_REM_FLOAT_2ADDR.S */
5226 /* rem_float/2addr vA, vB */
5227 movzx rINSTbl,%ecx # ecx<- A+
5228 sarl $4,rINST # rINST<- B
5229 flds (rFP,rINST,4) # vBB to fp stack
5230 andb $0xf,%cl # ecx<- A
5231 flds (rFP,%ecx,4) # vAA to fp stack
5232 FETCH_INST_OPCODE 1 %edx
5240 fstps (rFP,%ecx,4) # %st to vA
5243 /* ------------------------------ */
5245 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
5246 /* File: x86/OP_ADD_DOUBLE_2ADDR.S */
5247 /* File: x86/binflop2addr.S */
5249 * Generic 32-bit binary float operation.
5251 * For: add-fp, sub-fp, mul-fp, div-fp
5254 /* binop/2addr vA, vB */
5255 movzx rINSTbl,%ecx # ecx<- A+
5256 andb $0xf,%cl # ecx<- A
5257 fldl (rFP,%ecx,4) # vAA to fp stack
5258 sarl $4,rINST # rINST<- B
5259 faddl (rFP,rINST,4) # ex: faddp
5260 FETCH_INST_OPCODE 1 %edx
5262 fstpl (rFP,%ecx,4) # %st to vA
5266 /* ------------------------------ */
5268 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
5269 /* File: x86/OP_SUB_DOUBLE_2ADDR.S */
5270 /* File: x86/binflop2addr.S */
5272 * Generic 32-bit binary float operation.
5274 * For: add-fp, sub-fp, mul-fp, div-fp
5277 /* binop/2addr vA, vB */
5278 movzx rINSTbl,%ecx # ecx<- A+
5279 andb $0xf,%cl # ecx<- A
5280 fldl (rFP,%ecx,4) # vAA to fp stack
5281 sarl $4,rINST # rINST<- B
5282 fsubl (rFP,rINST,4) # ex: faddp
5283 FETCH_INST_OPCODE 1 %edx
5285 fstpl (rFP,%ecx,4) # %st to vA
5289 /* ------------------------------ */
5291 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
5292 /* File: x86/OP_MUL_DOUBLE_2ADDR.S */
5293 /* File: x86/binflop2addr.S */
5295 * Generic 32-bit binary float operation.
5297 * For: add-fp, sub-fp, mul-fp, div-fp
5300 /* binop/2addr vA, vB */
5301 movzx rINSTbl,%ecx # ecx<- A+
5302 andb $0xf,%cl # ecx<- A
5303 fldl (rFP,%ecx,4) # vAA to fp stack
5304 sarl $4,rINST # rINST<- B
5305 fmull (rFP,rINST,4) # ex: faddp
5306 FETCH_INST_OPCODE 1 %edx
5308 fstpl (rFP,%ecx,4) # %st to vA
5312 /* ------------------------------ */
5314 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
5315 /* File: x86/OP_DIV_DOUBLE_2ADDR.S */
5316 /* File: x86/binflop2addr.S */
5318 * Generic 32-bit binary float operation.
5320 * For: add-fp, sub-fp, mul-fp, div-fp
5323 /* binop/2addr vA, vB */
5324 movzx rINSTbl,%ecx # ecx<- A+
5325 andb $0xf,%cl # ecx<- A
5326 fldl (rFP,%ecx,4) # vAA to fp stack
5327 sarl $4,rINST # rINST<- B
5328 fdivl (rFP,rINST,4) # ex: faddp
5329 FETCH_INST_OPCODE 1 %edx
5331 fstpl (rFP,%ecx,4) # %st to vA
5335 /* ------------------------------ */
5337 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
5338 /* File: x86/OP_REM_DOUBLE_2ADDR.S */
5339 /* rem_float/2addr vA, vB */
5340 movzx rINSTbl,%ecx # ecx<- A+
5341 sarl $4,rINST # rINST<- B
5342 fldl (rFP,rINST,4) # vBB to fp stack
5343 andb $0xf,%cl # ecx<- A
5344 fldl (rFP,%ecx,4) # vAA to fp stack
5345 FETCH_INST_OPCODE 1 %edx
5353 fstpl (rFP,%ecx,4) # %st to vA
5356 /* ------------------------------ */
5358 .L_OP_ADD_INT_LIT16: /* 0xd0 */
5359 /* File: x86/OP_ADD_INT_LIT16.S */
5360 /* File: x86/binopLit16.S */
5362 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5363 * that specifies an instruction that performs "result = eax op ecx".
5364 * This could be an x86 instruction or a function call. (If the result
5365 * comes back in a register other than eax, you can override "result".)
5367 * For: add-int/lit16, rsub-int,
5368 * and-int/lit16, or-int/lit16, xor-int/lit16
5370 /* binop/lit16 vA, vB, #+CCCC */
5371 movzbl rINSTbl,%eax # eax<- 000000BA
5372 sarl $4,%eax # eax<- B
5373 GET_VREG_R %eax %eax # eax<- vB
5374 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5375 andb $0xf,rINSTbl # rINST<- A
5376 addl %ecx,%eax # for example: addl %ecx, %eax
5378 FETCH_INST_OPCODE 2 %edx
5383 /* ------------------------------ */
5385 .L_OP_RSUB_INT: /* 0xd1 */
5386 /* File: x86/OP_RSUB_INT.S */
5387 /* File: x86/binopLit16.S */
5389 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5390 * that specifies an instruction that performs "result = eax op ecx".
5391 * This could be an x86 instruction or a function call. (If the result
5392 * comes back in a register other than eax, you can override "result".)
5394 * For: add-int/lit16, rsub-int,
5395 * and-int/lit16, or-int/lit16, xor-int/lit16
5397 /* binop/lit16 vA, vB, #+CCCC */
5398 movzbl rINSTbl,%eax # eax<- 000000BA
5399 sarl $4,%eax # eax<- B
5400 GET_VREG_R %eax %eax # eax<- vB
5401 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5402 andb $0xf,rINSTbl # rINST<- A
5403 subl %eax,%ecx # for example: addl %ecx, %eax
5405 FETCH_INST_OPCODE 2 %edx
5410 /* ------------------------------ */
5412 .L_OP_MUL_INT_LIT16: /* 0xd2 */
5413 /* File: x86/OP_MUL_INT_LIT16.S */
5414 /* mul/lit16 vA, vB, #+CCCC */
5415 /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5416 movzbl rINSTbl,%eax # eax<- 000000BA
5417 sarl $4,%eax # eax<- B
5418 GET_VREG_R %eax %eax # eax<- vB
5419 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5420 andb $0xf,rINSTbl # rINST<- A
5421 imull %ecx,%eax # trashes edx
5422 FETCH_INST_OPCODE 2 %edx
5427 /* ------------------------------ */
5429 .L_OP_DIV_INT_LIT16: /* 0xd3 */
5430 /* File: x86/OP_DIV_INT_LIT16.S */
5431 /* File: x86/bindivLit16.S */
5433 * 32-bit binary div/rem operation. Handles special case of op0=minint and
5436 /* div/rem/lit16 vA, vB, #+CCCC */
5437 /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5438 movzbl rINSTbl,%eax # eax<- 000000BA
5439 sarl $4,%eax # eax<- B
5440 GET_VREG_R %eax %eax # eax<- vB
5441 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5442 andb $0xf,rINSTbl # rINST<- A
5444 je common_errDivideByZero
5446 jne .LOP_DIV_INT_LIT16_continue_div
5447 cmpl $0x80000000,%eax
5448 jne .LOP_DIV_INT_LIT16_continue_div
5449 movl $0x80000000,%eax
5450 jmp .LOP_DIV_INT_LIT16_finish_div
5454 /* ------------------------------ */
5456 .L_OP_REM_INT_LIT16: /* 0xd4 */
5457 /* File: x86/OP_REM_INT_LIT16.S */
5458 /* File: x86/bindivLit16.S */
5460 * 32-bit binary div/rem operation. Handles special case of op0=minint and
5463 /* div/rem/lit16 vA, vB, #+CCCC */
5464 /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5465 movzbl rINSTbl,%eax # eax<- 000000BA
5466 sarl $4,%eax # eax<- B
5467 GET_VREG_R %eax %eax # eax<- vB
5468 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5469 andb $0xf,rINSTbl # rINST<- A
5471 je common_errDivideByZero
5473 jne .LOP_REM_INT_LIT16_continue_div
5474 cmpl $0x80000000,%eax
5475 jne .LOP_REM_INT_LIT16_continue_div
5477 jmp .LOP_REM_INT_LIT16_finish_div
5481 /* ------------------------------ */
5483 .L_OP_AND_INT_LIT16: /* 0xd5 */
5484 /* File: x86/OP_AND_INT_LIT16.S */
5485 /* File: x86/binopLit16.S */
5487 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5488 * that specifies an instruction that performs "result = eax op ecx".
5489 * This could be an x86 instruction or a function call. (If the result
5490 * comes back in a register other than eax, you can override "result".)
5492 * For: add-int/lit16, rsub-int,
5493 * and-int/lit16, or-int/lit16, xor-int/lit16
5495 /* binop/lit16 vA, vB, #+CCCC */
5496 movzbl rINSTbl,%eax # eax<- 000000BA
5497 sarl $4,%eax # eax<- B
5498 GET_VREG_R %eax %eax # eax<- vB
5499 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5500 andb $0xf,rINSTbl # rINST<- A
5501 andl %ecx,%eax # for example: addl %ecx, %eax
5503 FETCH_INST_OPCODE 2 %edx
5508 /* ------------------------------ */
5510 .L_OP_OR_INT_LIT16: /* 0xd6 */
5511 /* File: x86/OP_OR_INT_LIT16.S */
5512 /* File: x86/binopLit16.S */
5514 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5515 * that specifies an instruction that performs "result = eax op ecx".
5516 * This could be an x86 instruction or a function call. (If the result
5517 * comes back in a register other than eax, you can override "result".)
5519 * For: add-int/lit16, rsub-int,
5520 * and-int/lit16, or-int/lit16, xor-int/lit16
5522 /* binop/lit16 vA, vB, #+CCCC */
5523 movzbl rINSTbl,%eax # eax<- 000000BA
5524 sarl $4,%eax # eax<- B
5525 GET_VREG_R %eax %eax # eax<- vB
5526 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5527 andb $0xf,rINSTbl # rINST<- A
5528 orl %ecx,%eax # for example: addl %ecx, %eax
5530 FETCH_INST_OPCODE 2 %edx
5535 /* ------------------------------ */
5537 .L_OP_XOR_INT_LIT16: /* 0xd7 */
5538 /* File: x86/OP_XOR_INT_LIT16.S */
5539 /* File: x86/binopLit16.S */
5541 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5542 * that specifies an instruction that performs "result = eax op ecx".
5543 * This could be an x86 instruction or a function call. (If the result
5544 * comes back in a register other than eax, you can override "result".)
5546 * For: add-int/lit16, rsub-int,
5547 * and-int/lit16, or-int/lit16, xor-int/lit16
5549 /* binop/lit16 vA, vB, #+CCCC */
5550 movzbl rINSTbl,%eax # eax<- 000000BA
5551 sarl $4,%eax # eax<- B
5552 GET_VREG_R %eax %eax # eax<- vB
5553 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5554 andb $0xf,rINSTbl # rINST<- A
5555 xor %ecx,%eax # for example: addl %ecx, %eax
5557 FETCH_INST_OPCODE 2 %edx
5562 /* ------------------------------ */
5564 .L_OP_ADD_INT_LIT8: /* 0xd8 */
5565 /* File: x86/OP_ADD_INT_LIT8.S */
5566 /* File: x86/binopLit8.S */
5568 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5569 * that specifies an instruction that performs "result = eax op ecx".
5570 * This could be an x86 instruction or a function call. (If the result
5571 * comes back in a register other than r0, you can override "result".)
5573 * For: add-int/lit8, rsub-int/lit8
5574 * and-int/lit8, or-int/lit8, xor-int/lit8,
5575 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5577 /* binop/lit8 vAA, vBB, #+CC */
5578 movzbl 2(rPC),%eax # eax<- BB
5579 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5580 GET_VREG_R %eax %eax # eax<- rBB
5581 addl %ecx,%eax # ex: addl %ecx,%eax
5582 FETCH_INST_OPCODE 2 %edx
5588 /* ------------------------------ */
5590 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
5591 /* File: x86/OP_RSUB_INT_LIT8.S */
5592 /* File: x86/binopLit8.S */
5594 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5595 * that specifies an instruction that performs "result = eax op ecx".
5596 * This could be an x86 instruction or a function call. (If the result
5597 * comes back in a register other than r0, you can override "result".)
5599 * For: add-int/lit8, rsub-int/lit8
5600 * and-int/lit8, or-int/lit8, xor-int/lit8,
5601 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5603 /* binop/lit8 vAA, vBB, #+CC */
5604 movzbl 2(rPC),%eax # eax<- BB
5605 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5606 GET_VREG_R %eax %eax # eax<- rBB
5607 subl %eax,%ecx # ex: addl %ecx,%eax
5608 FETCH_INST_OPCODE 2 %edx
5614 /* ------------------------------ */
5616 .L_OP_MUL_INT_LIT8: /* 0xda */
5617 /* File: x86/OP_MUL_INT_LIT8.S */
5618 /* mul/lit8 vAA, vBB, #+CC */
5619 movzbl 2(rPC),%eax # eax<- BB
5620 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5621 GET_VREG_R %eax %eax # eax<- rBB
5622 imull %ecx,%eax # trashes edx
5623 FETCH_INST_OPCODE 2 %edx
5628 /* ------------------------------ */
5630 .L_OP_DIV_INT_LIT8: /* 0xdb */
5631 /* File: x86/OP_DIV_INT_LIT8.S */
5632 /* File: x86/bindivLit8.S */
5634 * 32-bit div/rem "lit8" binary operation. Handles special case of
5635 * op0=minint & op1=-1
5637 /* div/rem/lit8 vAA, vBB, #+CC */
5638 movzbl 2(rPC),%eax # eax<- BB
5639 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5640 GET_VREG_R %eax %eax # eax<- rBB
5642 je common_errDivideByZero
5643 cmpl $0x80000000,%eax
5644 jne .LOP_DIV_INT_LIT8_continue_div
5646 jne .LOP_DIV_INT_LIT8_continue_div
5647 movl $0x80000000,%eax
5648 jmp .LOP_DIV_INT_LIT8_finish_div
5652 /* ------------------------------ */
5654 .L_OP_REM_INT_LIT8: /* 0xdc */
5655 /* File: x86/OP_REM_INT_LIT8.S */
5656 /* File: x86/bindivLit8.S */
5658 * 32-bit div/rem "lit8" binary operation. Handles special case of
5659 * op0=minint & op1=-1
5661 /* div/rem/lit8 vAA, vBB, #+CC */
5662 movzbl 2(rPC),%eax # eax<- BB
5663 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5664 GET_VREG_R %eax %eax # eax<- rBB
5666 je common_errDivideByZero
5667 cmpl $0x80000000,%eax
5668 jne .LOP_REM_INT_LIT8_continue_div
5670 jne .LOP_REM_INT_LIT8_continue_div
5672 jmp .LOP_REM_INT_LIT8_finish_div
5676 /* ------------------------------ */
5678 .L_OP_AND_INT_LIT8: /* 0xdd */
5679 /* File: x86/OP_AND_INT_LIT8.S */
5680 /* File: x86/binopLit8.S */
5682 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5683 * that specifies an instruction that performs "result = eax op ecx".
5684 * This could be an x86 instruction or a function call. (If the result
5685 * comes back in a register other than r0, you can override "result".)
5687 * For: add-int/lit8, rsub-int/lit8
5688 * and-int/lit8, or-int/lit8, xor-int/lit8,
5689 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5691 /* binop/lit8 vAA, vBB, #+CC */
5692 movzbl 2(rPC),%eax # eax<- BB
5693 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5694 GET_VREG_R %eax %eax # eax<- rBB
5695 andl %ecx,%eax # ex: addl %ecx,%eax
5696 FETCH_INST_OPCODE 2 %edx
5702 /* ------------------------------ */
5704 .L_OP_OR_INT_LIT8: /* 0xde */
5705 /* File: x86/OP_OR_INT_LIT8.S */
5706 /* File: x86/binopLit8.S */
5708 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5709 * that specifies an instruction that performs "result = eax op ecx".
5710 * This could be an x86 instruction or a function call. (If the result
5711 * comes back in a register other than r0, you can override "result".)
5713 * For: add-int/lit8, rsub-int/lit8
5714 * and-int/lit8, or-int/lit8, xor-int/lit8,
5715 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5717 /* binop/lit8 vAA, vBB, #+CC */
5718 movzbl 2(rPC),%eax # eax<- BB
5719 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5720 GET_VREG_R %eax %eax # eax<- rBB
5721 orl %ecx,%eax # ex: addl %ecx,%eax
5722 FETCH_INST_OPCODE 2 %edx
5728 /* ------------------------------ */
5730 .L_OP_XOR_INT_LIT8: /* 0xdf */
5731 /* File: x86/OP_XOR_INT_LIT8.S */
5732 /* File: x86/binopLit8.S */
5734 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5735 * that specifies an instruction that performs "result = eax op ecx".
5736 * This could be an x86 instruction or a function call. (If the result
5737 * comes back in a register other than r0, you can override "result".)
5739 * For: add-int/lit8, rsub-int/lit8
5740 * and-int/lit8, or-int/lit8, xor-int/lit8,
5741 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5743 /* binop/lit8 vAA, vBB, #+CC */
5744 movzbl 2(rPC),%eax # eax<- BB
5745 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5746 GET_VREG_R %eax %eax # eax<- rBB
5747 xor %ecx,%eax # ex: addl %ecx,%eax
5748 FETCH_INST_OPCODE 2 %edx
5754 /* ------------------------------ */
5756 .L_OP_SHL_INT_LIT8: /* 0xe0 */
5757 /* File: x86/OP_SHL_INT_LIT8.S */
5758 /* File: x86/binopLit8.S */
5760 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5761 * that specifies an instruction that performs "result = eax op ecx".
5762 * This could be an x86 instruction or a function call. (If the result
5763 * comes back in a register other than r0, you can override "result".)
5765 * For: add-int/lit8, rsub-int/lit8
5766 * and-int/lit8, or-int/lit8, xor-int/lit8,
5767 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5769 /* binop/lit8 vAA, vBB, #+CC */
5770 movzbl 2(rPC),%eax # eax<- BB
5771 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5772 GET_VREG_R %eax %eax # eax<- rBB
5773 sall %cl,%eax # ex: addl %ecx,%eax
5774 FETCH_INST_OPCODE 2 %edx
5780 /* ------------------------------ */
5782 .L_OP_SHR_INT_LIT8: /* 0xe1 */
5783 /* File: x86/OP_SHR_INT_LIT8.S */
5784 /* File: x86/binopLit8.S */
5786 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5787 * that specifies an instruction that performs "result = eax op ecx".
5788 * This could be an x86 instruction or a function call. (If the result
5789 * comes back in a register other than r0, you can override "result".)
5791 * For: add-int/lit8, rsub-int/lit8
5792 * and-int/lit8, or-int/lit8, xor-int/lit8,
5793 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5795 /* binop/lit8 vAA, vBB, #+CC */
5796 movzbl 2(rPC),%eax # eax<- BB
5797 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5798 GET_VREG_R %eax %eax # eax<- rBB
5799 sarl %cl,%eax # ex: addl %ecx,%eax
5800 FETCH_INST_OPCODE 2 %edx
5806 /* ------------------------------ */
5808 .L_OP_USHR_INT_LIT8: /* 0xe2 */
5809 /* File: x86/OP_USHR_INT_LIT8.S */
5810 /* File: x86/binopLit8.S */
5812 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5813 * that specifies an instruction that performs "result = eax op ecx".
5814 * This could be an x86 instruction or a function call. (If the result
5815 * comes back in a register other than r0, you can override "result".)
5817 * For: add-int/lit8, rsub-int/lit8
5818 * and-int/lit8, or-int/lit8, xor-int/lit8,
5819 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5821 /* binop/lit8 vAA, vBB, #+CC */
5822 movzbl 2(rPC),%eax # eax<- BB
5823 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5824 GET_VREG_R %eax %eax # eax<- rBB
5825 shrl %cl,%eax # ex: addl %ecx,%eax
5826 FETCH_INST_OPCODE 2 %edx
5832 /* ------------------------------ */
5834 .L_OP_IGET_VOLATILE: /* 0xe3 */
5835 /* File: x86/OP_IGET_VOLATILE.S */
5836 /* File: x86/OP_IGET.S */
5838 * General 32-bit instance field get.
5840 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
5842 /* op vA, vB, field@CCCC */
5844 movzwl 2(rPC),%edx # edx<- 0000CCCC
5845 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
5846 movzbl rINSTbl,%ecx # ecx<- BA
5847 sarl $4,%ecx # ecx<- B
5848 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
5849 andb $0xf,rINSTbl # rINST<- A
5850 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
5851 movl (%eax,%edx,4),%eax # resolved entry
5852 testl %eax,%eax # is resolved entry null?
5853 jne .LOP_IGET_VOLATILE_finish # no, already resolved
5854 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
5856 jmp .LOP_IGET_VOLATILE_resolve
5859 /* ------------------------------ */
5861 .L_OP_IPUT_VOLATILE: /* 0xe4 */
5862 /* File: x86/OP_IPUT_VOLATILE.S */
5863 /* File: x86/OP_IPUT.S */
5866 * General 32-bit instance field put.
5868 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
5870 /* op vA, vB, field@CCCC */
5872 movzwl 2(rPC),%edx # %edx<- 0000CCCC
5873 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
5874 movzbl rINSTbl,%ecx # ecx<- BA
5875 sarl $4,%ecx # ecx<- B
5876 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
5877 andb $0xf,rINSTbl # rINST<- A
5878 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
5879 movl (%eax,%edx,4),%eax # resolved entry
5880 testl %eax,%eax # is resolved entry null?
5881 jne .LOP_IPUT_VOLATILE_finish # no, already resolved
5882 movl %edx,OUT_ARG1(%esp)
5884 jmp .LOP_IPUT_VOLATILE_resolve
5887 /* ------------------------------ */
5889 .L_OP_SGET_VOLATILE: /* 0xe5 */
5890 /* File: x86/OP_SGET_VOLATILE.S */
5891 /* File: x86/OP_SGET.S */
5893 * General 32-bit SGET handler.
5895 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
5897 /* op vAA, field@BBBB */
5899 movzwl 2(rPC),%eax # eax<- field ref BBBB
5900 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
5901 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
5902 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
5903 testl %eax,%eax # resolved entry null?
5904 je .LOP_SGET_VOLATILE_resolve # if not, make it so
5905 .LOP_SGET_VOLATILE_finish: # field ptr in eax
5906 movl offStaticField_value(%eax),%eax
5907 FETCH_INST_OPCODE 2 %edx
5913 /* ------------------------------ */
5915 .L_OP_SPUT_VOLATILE: /* 0xe6 */
5916 /* File: x86/OP_SPUT_VOLATILE.S */
5917 /* File: x86/OP_SPUT.S */
5919 * General 32-bit SPUT handler.
5921 * for: sput, sput-boolean, sput-byte, sput-char, sput-short
5923 /* op vAA, field@BBBB */
5925 movzwl 2(rPC),%eax # eax<- field ref BBBB
5926 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
5927 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
5928 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
5929 testl %eax,%eax # resolved entry null?
5930 je .LOP_SPUT_VOLATILE_resolve # if not, make it so
5931 .LOP_SPUT_VOLATILE_finish: # field ptr in eax
5932 GET_VREG_R %ecx rINST
5933 FETCH_INST_OPCODE 2 %edx
5935 movl %ecx,offStaticField_value(%eax)
5939 /* ------------------------------ */
5941 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
5942 /* File: x86/OP_IGET_OBJECT_VOLATILE.S */
5943 /* File: x86/OP_IGET.S */
5945 * General 32-bit instance field get.
5947 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
5949 /* op vA, vB, field@CCCC */
5951 movzwl 2(rPC),%edx # edx<- 0000CCCC
5952 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
5953 movzbl rINSTbl,%ecx # ecx<- BA
5954 sarl $4,%ecx # ecx<- B
5955 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
5956 andb $0xf,rINSTbl # rINST<- A
5957 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
5958 movl (%eax,%edx,4),%eax # resolved entry
5959 testl %eax,%eax # is resolved entry null?
5960 jne .LOP_IGET_OBJECT_VOLATILE_finish # no, already resolved
5961 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField
5963 jmp .LOP_IGET_OBJECT_VOLATILE_resolve
5966 /* ------------------------------ */
5968 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
5970 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
5971 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
5972 call dvmMterp_OP_IGET_WIDE_VOLATILE # do the real work
5974 LOAD_PC_FP_FROM_GLUE # retrieve updated values
5977 /* ------------------------------ */
5979 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
5981 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
5982 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
5983 call dvmMterp_OP_IPUT_WIDE_VOLATILE # do the real work
5985 LOAD_PC_FP_FROM_GLUE # retrieve updated values
5988 /* ------------------------------ */
5990 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
5992 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
5993 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
5994 call dvmMterp_OP_SGET_WIDE_VOLATILE # do the real work
5996 LOAD_PC_FP_FROM_GLUE # retrieve updated values
5999 /* ------------------------------ */
6001 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
6003 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
6004 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
6005 call dvmMterp_OP_SPUT_WIDE_VOLATILE # do the real work
6007 LOAD_PC_FP_FROM_GLUE # retrieve updated values
6010 /* ------------------------------ */
6012 .L_OP_BREAKPOINT: /* 0xec */
6013 /* File: x86/OP_BREAKPOINT.S */
6014 /* File: x86/unused.S */
6018 /* ------------------------------ */
6020 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
6021 /* File: x86/OP_THROW_VERIFICATION_ERROR.S */
6023 * Handle a throw-verification-error instruction. This throws an
6024 * exception for an error discovered during verification. The
6025 * exception is indicated by AA, with some detail provided by BBBB.
6027 /* op AA, ref@BBBB */
6029 movzwl 2(rPC),%eax # eax<- BBBB
6030 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6032 movl %eax,OUT_ARG2(%esp) # arg2<- BBBB
6033 movl rINST,OUT_ARG1(%esp) # arg1<- AA
6034 movl %ecx,OUT_ARG0(%esp) # arg0<- method
6035 call dvmThrowVerificationError # call(method, kind, ref)
6036 jmp common_exceptionThrown # handle exception
6038 /* ------------------------------ */
6040 .L_OP_EXECUTE_INLINE: /* 0xee */
6041 /* File: x86/OP_EXECUTE_INLINE.S */
6043 * Execute a "native inline" instruction.
6045 * We will be calling through a function table:
6047 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
6049 * Ignores argument count - always loads 4.
6052 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
6055 movzwl 2(rPC),%eax # eax<- BBBB
6056 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
6057 movl %ecx,OUT_ARG4(%esp)
6058 call .LOP_EXECUTE_INLINE_continue # make call; will return after
6059 testl %eax,%eax # successful?
6060 FETCH_INST_OPCODE 3 %edx
6061 je common_exceptionThrown # no, handle exception
6065 /* ------------------------------ */
6067 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
6069 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
6070 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
6071 call dvmMterp_OP_EXECUTE_INLINE_RANGE # do the real work
6073 LOAD_PC_FP_FROM_GLUE # retrieve updated values
6076 /* ------------------------------ */
6078 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
6079 /* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
6081 * invoke-direct-empty is a no-op in a "standard" interpreter.
6087 /* ------------------------------ */
6089 .L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
6091 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx
6092 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
6093 call dvmMterp_OP_RETURN_VOID_BARRIER # do the real work
6095 LOAD_PC_FP_FROM_GLUE # retrieve updated values
6098 /* ------------------------------ */
6100 .L_OP_IGET_QUICK: /* 0xf2 */
6101 /* File: x86/OP_IGET_QUICK.S */
6102 /* For: iget-quick, iget-object-quick */
6103 /* op vA, vB, offset@CCCC */
6104 movzbl rINSTbl,%ecx # ecx<- BA
6105 sarl $4,%ecx # ecx<- B
6106 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6107 movzwl 2(rPC),%eax # eax<- field byte offset
6108 cmpl $0,%ecx # is object null?
6109 je common_errNullObject
6110 movl (%ecx,%eax,1),%eax
6111 FETCH_INST_OPCODE 2 %edx
6113 andb $0xf,rINSTbl # rINST<- A
6114 SET_VREG %eax rINST # fp[A]<- result
6117 /* ------------------------------ */
6119 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
6120 /* File: x86/OP_IGET_WIDE_QUICK.S */
6121 /* For: iget-wide-quick */
6122 /* op vA, vB, offset@CCCC */
6123 movzbl rINSTbl,%ecx # ecx<- BA
6124 sarl $4,%ecx # ecx<- B
6125 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6126 movzwl 2(rPC),%eax # eax<- field byte offset
6127 cmpl $0,%ecx # is object null?
6128 je common_errNullObject
6129 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source
6130 movl (%eax),%ecx # ecx<- lsw
6131 movl 4(%eax),%eax # eax<- msw
6132 andb $0xf,rINSTbl # rINST<- A
6133 FETCH_INST_OPCODE 2 %edx
6134 SET_VREG_WORD %ecx rINST 0 # v[A+0]<- lsw
6135 SET_VREG_WORD %eax rINST 1 # v[A+1]<- msw
6139 /* ------------------------------ */
6141 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
6142 /* File: x86/OP_IGET_OBJECT_QUICK.S */
6143 /* File: x86/OP_IGET_QUICK.S */
6144 /* For: iget-quick, iget-object-quick */
6145 /* op vA, vB, offset@CCCC */
6146 movzbl rINSTbl,%ecx # ecx<- BA
6147 sarl $4,%ecx # ecx<- B
6148 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6149 movzwl 2(rPC),%eax # eax<- field byte offset
6150 cmpl $0,%ecx # is object null?
6151 je common_errNullObject
6152 movl (%ecx,%eax,1),%eax
6153 FETCH_INST_OPCODE 2 %edx
6155 andb $0xf,rINSTbl # rINST<- A
6156 SET_VREG %eax rINST # fp[A]<- result
6160 /* ------------------------------ */
6162 .L_OP_IPUT_QUICK: /* 0xf5 */
6163 /* File: x86/OP_IPUT_QUICK.S */
6164 /* For: iput-quick */
6165 /* op vA, vB, offset@CCCC */
6166 movzbl rINSTbl,%ecx # ecx<- BA
6167 sarl $4,%ecx # ecx<- B
6168 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6169 andb $0xf,rINSTbl # rINST<- A
6170 GET_VREG_R rINST,rINST # rINST<- v[A]
6171 movzwl 2(rPC),%eax # eax<- field byte offset
6172 testl %ecx,%ecx # is object null?
6173 FETCH_INST_OPCODE 2 %edx
6174 je common_errNullObject
6175 movl rINST,(%ecx,%eax,1)
6179 /* ------------------------------ */
6181 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
6182 /* File: x86/OP_IPUT_WIDE_QUICK.S */
6183 /* For: iput-wide-quick */
6184 /* op vA, vB, offset@CCCC */
6185 movzbl rINSTbl,%ecx # ecx<- BA
6186 sarl $4,%ecx # ecx<- B
6187 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6188 movzwl 2(rPC),%eax # eax<- field byte offset
6189 testl %ecx,%ecx # is object null?
6190 je common_errNullObject
6191 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target
6192 andb $0xf,rINSTbl # rINST<- A
6193 GET_VREG_WORD %eax rINST 0 # eax<- lsw
6194 GET_VREG_WORD rINST rINST 1 # rINST<- msw
6195 FETCH_INST_OPCODE 2 %edx
6201 /* ------------------------------ */
6203 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
6204 /* File: x86/OP_IPUT_OBJECT_QUICK.S */
6205 /* For: iput-object-quick */
6206 /* op vA, vB, offset@CCCC */
6207 movzbl rINSTbl,%ecx # ecx<- BA
6208 sarl $4,%ecx # ecx<- B
6209 GET_VREG_R %ecx %ecx # vB (object we're operating on)
6210 andb $0xf,rINSTbl # rINST<- A
6211 GET_VREG_R rINST rINST # rINST<- v[A]
6212 movzwl 2(rPC),%eax # eax<- field byte offset
6213 testl %ecx,%ecx # is object null?
6214 je common_errNullObject
6215 movl rINST,(%ecx,%eax,1)
6217 jmp .LOP_IPUT_OBJECT_QUICK_finish
6219 /* ------------------------------ */
6221 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6222 /* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6224 * Handle an optimized virtual method call.
6226 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6228 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6229 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6230 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6231 movzwl 2(rPC),%ecx # ecx<- BBBB
6233 andl $0xf,%eax # eax<- C (or stays CCCC)
6235 GET_VREG_R %eax %eax # eax<- vC ("this" ptr)
6236 testl %eax,%eax # null?
6237 je common_errNullObject # yep, throw exception
6238 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6239 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6240 EXPORT_PC # might throw later - get ready
6241 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
6242 jmp common_invokeMethodNoRange
6244 /* ------------------------------ */
6246 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6247 /* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6248 /* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6250 * Handle an optimized virtual method call.
6252 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6254 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6255 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6256 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6257 movzwl 2(rPC),%ecx # ecx<- BBBB
6259 andl $0xf,%eax # eax<- C (or stays CCCC)
6261 GET_VREG_R %eax %eax # eax<- vC ("this" ptr)
6262 testl %eax,%eax # null?
6263 je common_errNullObject # yep, throw exception
6264 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6265 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6266 EXPORT_PC # might throw later - get ready
6267 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
6268 jmp common_invokeMethodRange
6271 /* ------------------------------ */
6273 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6274 /* File: x86/OP_INVOKE_SUPER_QUICK.S */
6276 * Handle an optimized "super" method call.
6278 * for: [opt] invoke-super-quick, invoke-super-quick/range
6280 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6281 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6283 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6284 movl offGlue_method(%ecx),%ecx # ecx<- current method
6286 andl $0xf,%eax # eax<- D (or stays CCCC)
6288 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6289 GET_VREG_R %eax %eax # eax<- "this"
6290 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6291 testl %eax,%eax # null "this"?
6292 je common_errNullObject # "this" is null, throw exception
6293 movzwl 2(rPC),%eax # eax<- BBBB
6294 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6296 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
6297 jmp common_invokeMethodNoRange
6299 /* ------------------------------ */
6301 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6302 /* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6303 /* File: x86/OP_INVOKE_SUPER_QUICK.S */
6305 * Handle an optimized "super" method call.
6307 * for: [opt] invoke-super-quick, invoke-super-quick/range
6309 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6310 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6312 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6313 movl offGlue_method(%ecx),%ecx # ecx<- current method
6315 andl $0xf,%eax # eax<- D (or stays CCCC)
6317 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6318 GET_VREG_R %eax %eax # eax<- "this"
6319 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6320 testl %eax,%eax # null "this"?
6321 je common_errNullObject # "this" is null, throw exception
6322 movzwl 2(rPC),%eax # eax<- BBBB
6323 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6325 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
6326 jmp common_invokeMethodRange
6329 /* ------------------------------ */
6331 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
6332 /* File: x86/OP_IPUT_OBJECT_VOLATILE.S */
6333 /* File: x86/OP_IPUT_OBJECT.S */
6339 /* op vA, vB, field@CCCC */
6341 movzwl 2(rPC),%edx # edx<- 0000CCCC
6342 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
6343 movzbl rINSTbl,%ecx # ecx<- BA
6344 sarl $4,%ecx # ecx<- B
6345 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
6346 andb $0xf,rINSTbl # rINST<- A
6347 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
6348 movl (%eax,%edx,4),%eax # resolved entry
6349 testl %eax,%eax # is resolved entry null?
6350 jne .LOP_IPUT_OBJECT_VOLATILE_finish # no, already resolved
6351 movl %edx,OUT_ARG1(%esp)
6353 jmp .LOP_IPUT_OBJECT_VOLATILE_resolve
6356 /* ------------------------------ */
6358 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
6359 /* File: x86/OP_SGET_OBJECT_VOLATILE.S */
6360 /* File: x86/OP_SGET.S */
6362 * General 32-bit SGET handler.
6364 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
6366 /* op vAA, field@BBBB */
6368 movzwl 2(rPC),%eax # eax<- field ref BBBB
6369 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
6370 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
6371 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
6372 testl %eax,%eax # resolved entry null?
6373 je .LOP_SGET_OBJECT_VOLATILE_resolve # if not, make it so
6374 .LOP_SGET_OBJECT_VOLATILE_finish: # field ptr in eax
6375 movl offStaticField_value(%eax),%eax
6376 FETCH_INST_OPCODE 2 %edx
6382 /* ------------------------------ */
6384 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
6385 /* File: x86/OP_SPUT_OBJECT_VOLATILE.S */
6386 /* File: x86/OP_SPUT_OBJECT.S */
6388 * SPUT object handler.
6390 /* op vAA, field@BBBB */
6392 movzwl 2(rPC),%eax # eax<- field ref BBBB
6393 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
6394 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
6395 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField
6396 testl %eax,%eax # resolved entry null?
6397 je .LOP_SPUT_OBJECT_VOLATILE_resolve # if not, make it so
6398 .LOP_SPUT_OBJECT_VOLATILE_finish: # field ptr in eax
6399 movzbl rINSTbl,%ecx # ecx<- AA
6400 GET_VREG_R %ecx %ecx
6401 jmp .LOP_SPUT_OBJECT_VOLATILE_continue
6404 /* ------------------------------ */
6406 .L_OP_UNUSED_FF: /* 0xff */
6407 /* File: x86/OP_UNUSED_FF.S */
6408 /* File: x86/unused.S */
6414 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
6415 .global dvmAsmInstructionEnd
6416 dvmAsmInstructionEnd:
6419 * ===========================================================================
6420 * Sister implementations
6421 * ===========================================================================
6423 .global dvmAsmSisterStart
6424 .type dvmAsmSisterStart, %function
6429 /* continuation for OP_CONST_STRING */
6431 /* This is the less common path, so we'll redo some work
6432 here rather than force spills on the common path */
6433 .LOP_CONST_STRING_resolve:
6435 movl %ecx,rINST # rINST<- AA
6437 movl offGlue_method(%eax),%eax # eax<- glue->method
6438 movzwl 2(rPC),%ecx # ecx<- BBBB
6439 movl offMethod_clazz(%eax),%eax
6440 movl %ecx,OUT_ARG1(%esp)
6441 movl %eax,OUT_ARG0(%esp)
6442 call dvmResolveString # go resolve
6443 testl %eax,%eax # failed?
6444 je common_exceptionThrown
6446 FETCH_INST_OPCODE 2 %edx
6450 /* continuation for OP_CONST_STRING_JUMBO */
6452 /* This is the less common path, so we'll redo some work
6453 here rather than force spills on the common path */
6454 .LOP_CONST_STRING_JUMBO_resolve:
6456 movl %ecx,rINST # rINST<- AA
6458 movl offGlue_method(%eax),%eax # eax<- glue->method
6459 movl 2(rPC),%ecx # ecx<- BBBBBBBB
6460 movl offMethod_clazz(%eax),%eax
6461 movl %ecx,OUT_ARG1(%esp)
6462 movl %eax,OUT_ARG0(%esp)
6463 call dvmResolveString # go resolve
6464 testl %eax,%eax # failed?
6465 je common_exceptionThrown
6467 FETCH_INST_OPCODE 3 %edx
6471 /* continuation for OP_CONST_CLASS */
6473 /* This is the less common path, so we'll redo some work
6474 here rather than force spills on the common path */
6475 .LOP_CONST_CLASS_resolve:
6477 movl %ecx,rINST # rINST<- AA
6479 movl offGlue_method(%eax),%eax # eax<- glue->method
6480 movl $1,OUT_ARG2(%esp) # true
6481 movzwl 2(rPC),%ecx # ecx<- BBBB
6482 movl offMethod_clazz(%eax),%eax
6483 movl %ecx,OUT_ARG1(%esp)
6484 movl %eax,OUT_ARG0(%esp)
6485 call dvmResolveClass # go resolve
6486 testl %eax,%eax # failed?
6487 je common_exceptionThrown
6489 FETCH_INST_OPCODE 2 %edx
6493 /* continuation for OP_MONITOR_ENTER */
6495 .LOP_MONITOR_ENTER_continue:
6496 movl %ecx,OUT_ARG0(%esp)
6497 movl %eax,OUT_ARG1(%esp)
6498 call dvmLockObject # dvmLockObject(self,object)
6499 #ifdef WITH_DEADLOCK_PREDICTION
6501 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self
6502 movl offThread_exception(%ecx),%eax
6504 jne common_exceptionThrown
6509 /* continuation for OP_MONITOR_EXIT */
6511 .LOP_MONITOR_EXIT_continue:
6512 call dvmUnlockObject # unlock(self,obj)
6513 FETCH_INST_OPCODE 1 %edx
6514 testl %eax,%eax # success?
6516 je common_exceptionThrown # no, exception pending
6518 .LOP_MONITOR_EXIT_errNullObject:
6519 ADVANCE_PC 1 # advance before throw
6520 jmp common_errNullObject
6522 /* continuation for OP_CHECK_CAST */
6525 * Trivial test failed, need to perform full check. This is common.
6526 * ecx holds obj->clazz
6527 * eax holds class resolved from BBBB
6528 * rINST holds object
6530 .LOP_CHECK_CAST_fullcheck:
6531 movl %eax,OUT_ARG1(%esp)
6532 movl %ecx,OUT_ARG0(%esp)
6533 call dvmInstanceofNonTrivial # eax<- boolean result
6534 testl %eax,%eax # failed?
6535 jne .LOP_CHECK_CAST_okay # no, success
6537 # A cast has failed. We need to throw a ClassCastException with the
6538 # class of the object that failed to be cast.
6540 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
6541 movl $.LstrClassCastException,%eax
6542 movl offClassObject_descriptor(%ecx),%ecx
6543 movl %eax,OUT_ARG0(%esp) # arg0<- message
6544 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor
6545 call dvmThrowExceptionWithClassMessage
6546 jmp common_exceptionThrown
6549 * Resolution required. This is the least-likely path, and we're
6550 * going to have to recreate some data.
6552 * rINST holds object
6554 .LOP_CHECK_CAST_resolve:
6557 movzwl 2(rPC),%eax # eax<- BBBB
6558 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6559 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
6560 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6561 movl $0,OUT_ARG2(%esp) # arg2<- false
6562 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6563 call dvmResolveClass # eax<- resolved ClassObject ptr
6564 testl %eax,%eax # got null?
6565 je common_exceptionThrown # yes, handle exception
6566 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
6567 jmp .LOP_CHECK_CAST_resolved # pick up where we left off
6569 /* continuation for OP_INSTANCE_OF */
6572 * Trivial test failed, need to perform full check. This is common.
6573 * eax holds obj->clazz
6574 * ecx holds class resolved from BBBB
6577 .LOP_INSTANCE_OF_fullcheck:
6578 movl %eax,OUT_ARG0(%esp)
6579 movl %ecx,OUT_ARG1(%esp)
6580 call dvmInstanceofNonTrivial # eax<- boolean result
6581 # fall through to OP_INSTANCE_OF_store
6584 * eax holds boolean result
6587 .LOP_INSTANCE_OF_store:
6588 FETCH_INST_OPCODE 2 %edx
6589 andb $0xf,rINSTbl # <- A
6591 SET_VREG %eax rINST # vA<- eax
6595 * Trivial test succeeded, save and bail.
6598 .LOP_INSTANCE_OF_trivial:
6599 FETCH_INST_OPCODE 2 %edx
6600 andb $0xf,rINSTbl # <- A
6603 SET_VREG %eax rINST # vA<- true
6607 * Resolution required. This is the least-likely path.
6612 .LOP_INSTANCE_OF_resolve:
6613 movl %edx,OUT_ARG1(%esp) # arg1<- BBBB
6615 movl offGlue_method(%ecx),%ecx
6616 movl $1,OUT_ARG2(%esp) # arg2<- true
6617 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6619 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6620 call dvmResolveClass # eax<- resolved ClassObject ptr
6621 testl %eax,%eax # success?
6622 je common_exceptionThrown # no, handle exception
6623 /* Now, we need to sync up with fast path. We need eax to
6624 * hold the obj->clazz, and ecx to hold the resolved class
6626 movl %eax,%ecx # ecx<- resolved class
6627 movl rINST,%eax # eax<- BA
6628 sarl $4,%eax # eax<- B
6629 GET_VREG_R %eax %eax # eax<- vB (obj)
6630 movl offObject_clazz(%eax),%eax # eax<- obj->clazz
6631 jmp .LOP_INSTANCE_OF_resolved
6633 /* continuation for OP_NEW_INSTANCE */
6635 .LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class
6636 /* TODO: remove test for interface/abstract, now done in verifier */
6637 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6638 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6639 jne .LOP_NEW_INSTANCE_abstract
6640 .LOP_NEW_INSTANCE_finish: # ecx=class
6641 movl %ecx,OUT_ARG0(%esp)
6642 call dvmAllocObject # eax<- new object
6643 FETCH_INST_OPCODE 2 %edx
6644 testl %eax,%eax # success?
6645 je common_exceptionThrown # no, bail out
6651 * Class initialization required.
6653 * ecx holds class object
6655 .LOP_NEW_INSTANCE_needinit:
6656 SPILL_TMP1(%ecx) # save object
6657 movl %ecx,OUT_ARG0(%esp)
6658 call dvmInitClass # initialize class
6659 UNSPILL_TMP1(%ecx) # restore object
6660 testl %eax,%eax # success?
6661 jne .LOP_NEW_INSTANCE_initialized # success, continue
6662 jmp common_exceptionThrown # go deal with init exception
6665 * Resolution required. This is the least-likely path.
6668 .LOP_NEW_INSTANCE_resolve:
6671 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6672 movl %eax,OUT_ARG1(%esp)
6673 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6674 movl $0,OUT_ARG2(%esp)
6675 movl %ecx,OUT_ARG0(%esp)
6676 call dvmResolveClass # call(clazz,off,flags)
6677 movl %eax,%ecx # ecx<- resolved ClassObject ptr
6678 testl %ecx,%ecx # success?
6679 jne .LOP_NEW_INSTANCE_resolved # good to go
6680 jmp common_exceptionThrown # no, handle exception
6684 * We can't instantiate an abstract class or interface, so throw an
6685 * InstantiationError with the class descriptor as the message.
6687 * ecx holds class object
6689 .LOP_NEW_INSTANCE_abstract:
6690 movl offClassObject_descriptor(%ecx),%eax
6691 movl $.LstrInstantiationError,OUT_ARG0(%esp)
6692 movl %eax,OUT_ARG1(%esp)
6693 call dvmThrowExceptionWithClassMessage
6694 jmp common_exceptionThrown
6696 /* continuation for OP_NEW_ARRAY */
6699 * Resolve class. (This is an uncommon case.)
6700 * ecx holds class (null here)
6701 * eax holds array length (vB)
6703 .LOP_NEW_ARRAY_resolve:
6705 SPILL_TMP1(%eax) # save array length
6706 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6707 movzwl 2(rPC),%eax # eax<- CCCC
6708 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6709 movl %eax,OUT_ARG1(%esp)
6710 movl $0,OUT_ARG2(%esp)
6711 movl %ecx,OUT_ARG0(%esp)
6712 call dvmResolveClass # eax<- call(clazz,ref,flag)
6715 testl %ecx,%ecx # successful resolution?
6716 je common_exceptionThrown # no, bail.
6717 # fall through to OP_NEW_ARRAY_finish
6723 * eax holds array length (vB)
6725 .LOP_NEW_ARRAY_finish:
6726 movl %ecx,OUT_ARG0(%esp)
6727 movl %eax,OUT_ARG1(%esp)
6728 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6729 call dvmAllocArrayByClass # eax<- call(clazz,length,flags)
6730 FETCH_INST_OPCODE 2 %edx
6731 testl %eax,%eax # failed?
6732 je common_exceptionThrown # yup - go handle
6737 /* continuation for OP_FILLED_NEW_ARRAY */
6739 .LOP_FILLED_NEW_ARRAY_more:
6740 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6741 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6742 call dvmResolveClass # eax<- call(clazz,ref,flag)
6743 testl %eax,%eax # null?
6744 je common_exceptionThrown # yes, handle it
6746 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6750 * eax holds array class [r0]
6751 * rINST holds AA or BB [r10]
6754 .LOP_FILLED_NEW_ARRAY_continue:
6755 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6756 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6757 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6758 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6760 cmpb $'I',%cl # supported?
6765 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet
6767 movl %ecx,offGlue_retval+4(%eax) # save type
6769 SPILL_TMP1(rINST) # save copy, need "B" later
6772 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length)
6773 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6775 testl %eax,%eax # alloc successful?
6776 je common_exceptionThrown # no, handle exception
6777 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6778 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6779 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6782 * eax is pointer to tgt
6784 * ecx is FEDC or CCCC
6786 * We now need to copy values from registers into the array
6790 # set up src pointer
6793 movl %eax,%edi # set up dst ptr
6794 leal (rFP,%ecx,4),%esi # set up src ptr
6795 movl rINST,%ecx # load count register
6801 movl offGlue_retval+4(%ecx),%eax # eax<- type
6802 FETCH_INST_OPCODE 3 %edx
6806 andl $0x0f,%edx # edx<- 0000000A
6807 sall $16,%edx # edx<- 000A0000
6808 orl %ecx,%edx # edx<- 000AFEDC
6811 andl %edx,%ecx # ecx<- next reg to load
6812 GET_VREG_R %ecx %ecx
6820 movl offGlue_retval+4(%ecx),%eax # eax<- type
6821 FETCH_INST_OPCODE 3 %edx
6824 cmpb $'I',%al # Int array?
6825 je 5f # skip card mark if so
6826 movl offGlue_retval(%ecx),%eax # eax<- object head
6827 movl offGlue_cardTable(%ecx),%ecx # card table base
6828 shrl $GC_CARD_SHIFT,%eax # convert to card num
6829 movb %cl,(%ecx,%eax) # mark card
6836 * Throw an exception indicating that we have not implemented this
6837 * mode of filled-new-array.
6839 .LOP_FILLED_NEW_ARRAY_notimpl:
6840 movl $.LstrInternalErrorA,%eax
6841 movl %eax,OUT_ARG0(%esp)
6842 movl $.LstrFilledNewArrayNotImplA,%eax
6843 movl %eax,OUT_ARG1(%esp)
6844 call dvmThrowException
6845 jmp common_exceptionThrown
6847 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6849 .LOP_FILLED_NEW_ARRAY_RANGE_more:
6850 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6851 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6852 call dvmResolveClass # eax<- call(clazz,ref,flag)
6853 testl %eax,%eax # null?
6854 je common_exceptionThrown # yes, handle it
6856 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6860 * eax holds array class [r0]
6861 * rINST holds AA or BB [r10]
6864 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
6865 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6866 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6867 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6868 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6870 cmpb $'I',%cl # supported?
6875 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet
6877 movl %ecx,offGlue_retval+4(%eax) # save type
6879 SPILL_TMP1(rINST) # save copy, need "B" later
6882 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length)
6883 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6885 testl %eax,%eax # alloc successful?
6886 je common_exceptionThrown # no, handle exception
6887 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6888 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6889 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6892 * eax is pointer to tgt
6894 * ecx is FEDC or CCCC
6896 * We now need to copy values from registers into the array
6900 # set up src pointer
6903 movl %eax,%edi # set up dst ptr
6904 leal (rFP,%ecx,4),%esi # set up src ptr
6905 movl rINST,%ecx # load count register
6911 movl offGlue_retval+4(%ecx),%eax # eax<- type
6912 FETCH_INST_OPCODE 3 %edx
6916 andl $0x0f,%edx # edx<- 0000000A
6917 sall $16,%edx # edx<- 000A0000
6918 orl %ecx,%edx # edx<- 000AFEDC
6921 andl %edx,%ecx # ecx<- next reg to load
6922 GET_VREG_R %ecx %ecx
6930 movl offGlue_retval+4(%ecx),%eax # eax<- type
6931 FETCH_INST_OPCODE 3 %edx
6934 cmpb $'I',%al # Int array?
6935 je 5f # skip card mark if so
6936 movl offGlue_retval(%ecx),%eax # eax<- object head
6937 movl offGlue_cardTable(%ecx),%ecx # card table base
6938 shrl $GC_CARD_SHIFT,%eax # convert to card num
6939 movb %cl,(%ecx,%eax) # mark card
6946 * Throw an exception indicating that we have not implemented this
6947 * mode of filled-new-array.
6949 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6950 movl $.LstrInternalErrorA,%eax
6951 movl %eax,OUT_ARG0(%esp)
6952 movl $.LstrFilledNewArrayNotImplA,%eax
6953 movl %eax,OUT_ARG1(%esp)
6954 call dvmThrowException
6955 jmp common_exceptionThrown
6957 /* continuation for OP_CMPL_FLOAT */
6959 .LOP_CMPL_FLOAT_isNaN:
6961 jmp .LOP_CMPL_FLOAT_finish
6963 /* continuation for OP_CMPG_FLOAT */
6965 .LOP_CMPG_FLOAT_isNaN:
6967 jmp .LOP_CMPG_FLOAT_finish
6969 /* continuation for OP_CMPL_DOUBLE */
6971 .LOP_CMPL_DOUBLE_isNaN:
6973 jmp .LOP_CMPL_DOUBLE_finish
6975 /* continuation for OP_CMPG_DOUBLE */
6977 .LOP_CMPG_DOUBLE_isNaN:
6979 jmp .LOP_CMPG_DOUBLE_finish
6981 /* continuation for OP_CMP_LONG */
6983 .LOP_CMP_LONG_bigger:
6985 jmp .LOP_CMP_LONG_finish
6986 .LOP_CMP_LONG_smaller:
6988 .LOP_CMP_LONG_finish:
6990 FETCH_INST_OPCODE 2 %edx
6994 /* continuation for OP_AGET_WIDE */
6996 .LOP_AGET_WIDE_finish:
6997 leal offArrayObject_contents(%eax,%ecx,8),%eax
7000 SET_VREG_WORD %ecx rINST 0
7001 SET_VREG_WORD %eax rINST 1
7002 FETCH_INST_OPCODE 2 %edx
7006 /* continuation for OP_APUT_WIDE */
7008 .LOP_APUT_WIDE_finish:
7009 leal offArrayObject_contents(%eax,%ecx,8),%eax
7010 GET_VREG_WORD %ecx rINST 0
7011 GET_VREG_WORD rINST rINST 1
7013 FETCH_INST_OPCODE 2 %edx
7018 /* continuation for OP_APUT_OBJECT */
7021 * eax<- array object
7025 .LOP_APUT_OBJECT_continue:
7026 leal offArrayObject_contents(%eax,%ecx,4),%ecx
7027 testl rINST,rINST # storing null reference?
7028 je .LOP_APUT_OBJECT_skip_check
7030 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
7031 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
7032 movl %eax,OUT_ARG1(%esp)
7033 movl %ecx,OUT_ARG0(%esp)
7034 call dvmCanPutArrayElement # test object type vs. array type
7038 je common_errArrayStore
7039 movl offGlue_cardTable(%eax),%eax # get card table base
7041 FETCH_INST_OPCODE 2 %edx
7042 shrl $GC_CARD_SHIFT,%ecx # convert addr to card number
7043 movb %al,(%eax,%ecx) # mark card
7047 .LOP_APUT_OBJECT_skip_check:
7049 FETCH_INST_OPCODE 2 %edx
7053 /* continuation for OP_IGET */
7058 movl offGlue_method(%edx),%edx # edx<- current method
7059 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7060 SPILL_TMP1(%ecx) # save obj pointer across call
7061 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7062 call dvmResolveInstField # ... to dvmResolveInstField
7064 testl %eax,%eax # returns InstrField ptr
7065 jne .LOP_IGET_finish
7066 jmp common_exceptionThrown
7071 * eax holds resolved field
7075 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7076 testl %ecx,%ecx # object null?
7077 je common_errNullObject # object was null
7078 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7079 movl rINST,%eax # eax<- A
7080 FETCH_INST_OPCODE 2 %edx
7085 /* continuation for OP_IGET_WIDE */
7088 .LOP_IGET_WIDE_resolve:
7090 movl offGlue_method(%edx),%edx # edx<- current method
7091 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7092 SPILL_TMP1(%ecx) # save objpointer across call
7093 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7094 call dvmResolveInstField # ... to dvmResolveInstField
7096 testl %eax,%eax # returns InstrField ptr
7097 jne .LOP_IGET_WIDE_finish
7098 jmp common_exceptionThrown
7100 .LOP_IGET_WIDE_finish:
7103 * eax holds resolved field
7107 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7108 testl %ecx,%ecx # object null?
7109 je common_errNullObject # object was null
7110 leal (%ecx,%eax,1),%eax # eax<- address of field
7111 movl (%eax),%ecx # ecx<- lsw
7112 movl 4(%eax),%eax # eax<- msw
7113 FETCH_INST_OPCODE 2 %edx
7114 SET_VREG_WORD %ecx rINST 0
7115 SET_VREG_WORD %eax rINST 1
7119 /* continuation for OP_IGET_OBJECT */
7122 .LOP_IGET_OBJECT_resolve:
7124 movl offGlue_method(%edx),%edx # edx<- current method
7125 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7126 SPILL_TMP1(%ecx) # save obj pointer across call
7127 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7128 call dvmResolveInstField # ... to dvmResolveInstField
7130 testl %eax,%eax # returns InstrField ptr
7131 jne .LOP_IGET_OBJECT_finish
7132 jmp common_exceptionThrown
7134 .LOP_IGET_OBJECT_finish:
7137 * eax holds resolved field
7141 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7142 testl %ecx,%ecx # object null?
7143 je common_errNullObject # object was null
7144 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7145 movl rINST,%eax # eax<- A
7146 FETCH_INST_OPCODE 2 %edx
7151 /* continuation for OP_IGET_BOOLEAN */
7154 .LOP_IGET_BOOLEAN_resolve:
7156 movl offGlue_method(%edx),%edx # edx<- current method
7157 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7158 SPILL_TMP1(%ecx) # save obj pointer across call
7159 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7160 call dvmResolveInstField # ... to dvmResolveInstField
7162 testl %eax,%eax # returns InstrField ptr
7163 jne .LOP_IGET_BOOLEAN_finish
7164 jmp common_exceptionThrown
7166 .LOP_IGET_BOOLEAN_finish:
7169 * eax holds resolved field
7173 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7174 testl %ecx,%ecx # object null?
7175 je common_errNullObject # object was null
7176 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7177 movl rINST,%eax # eax<- A
7178 FETCH_INST_OPCODE 2 %edx
7183 /* continuation for OP_IGET_BYTE */
7186 .LOP_IGET_BYTE_resolve:
7188 movl offGlue_method(%edx),%edx # edx<- current method
7189 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7190 SPILL_TMP1(%ecx) # save obj pointer across call
7191 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7192 call dvmResolveInstField # ... to dvmResolveInstField
7194 testl %eax,%eax # returns InstrField ptr
7195 jne .LOP_IGET_BYTE_finish
7196 jmp common_exceptionThrown
7198 .LOP_IGET_BYTE_finish:
7201 * eax holds resolved field
7205 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7206 testl %ecx,%ecx # object null?
7207 je common_errNullObject # object was null
7208 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7209 movl rINST,%eax # eax<- A
7210 FETCH_INST_OPCODE 2 %edx
7215 /* continuation for OP_IGET_CHAR */
7218 .LOP_IGET_CHAR_resolve:
7220 movl offGlue_method(%edx),%edx # edx<- current method
7221 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7222 SPILL_TMP1(%ecx) # save obj pointer across call
7223 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7224 call dvmResolveInstField # ... to dvmResolveInstField
7226 testl %eax,%eax # returns InstrField ptr
7227 jne .LOP_IGET_CHAR_finish
7228 jmp common_exceptionThrown
7230 .LOP_IGET_CHAR_finish:
7233 * eax holds resolved field
7237 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7238 testl %ecx,%ecx # object null?
7239 je common_errNullObject # object was null
7240 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7241 movl rINST,%eax # eax<- A
7242 FETCH_INST_OPCODE 2 %edx
7247 /* continuation for OP_IGET_SHORT */
7250 .LOP_IGET_SHORT_resolve:
7252 movl offGlue_method(%edx),%edx # edx<- current method
7253 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7254 SPILL_TMP1(%ecx) # save obj pointer across call
7255 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7256 call dvmResolveInstField # ... to dvmResolveInstField
7258 testl %eax,%eax # returns InstrField ptr
7259 jne .LOP_IGET_SHORT_finish
7260 jmp common_exceptionThrown
7262 .LOP_IGET_SHORT_finish:
7265 * eax holds resolved field
7269 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7270 testl %ecx,%ecx # object null?
7271 je common_errNullObject # object was null
7272 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7273 movl rINST,%eax # eax<- A
7274 FETCH_INST_OPCODE 2 %edx
7279 /* continuation for OP_IPUT */
7284 movl offGlue_method(%edx),%edx # edx<- current method
7285 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7286 SPILL_TMP1(%ecx) # save obj pointer across call
7287 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7288 call dvmResolveInstField # ... to dvmResolveInstField
7290 testl %eax,%eax # returns InstrField ptr
7291 jne .LOP_IPUT_finish
7292 jmp common_exceptionThrown
7297 * eax holds resolved field
7301 GET_VREG_R rINST rINST # rINST<- v[A]
7302 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7303 testl %ecx,%ecx # object null?
7304 je common_errNullObject # object was null
7305 FETCH_INST_OPCODE 2 %edx
7306 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7310 /* continuation for OP_IPUT_WIDE */
7313 .LOP_IPUT_WIDE_resolve:
7315 movl offGlue_method(%edx),%edx # edx<- current method
7316 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7317 SPILL_TMP1(%ecx) # save obj pointer across call
7318 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7319 call dvmResolveInstField # ... to dvmResolveInstField
7321 testl %eax,%eax # ... which returns InstrField ptr
7322 jne .LOP_IPUT_WIDE_finish
7323 jmp common_exceptionThrown
7325 .LOP_IPUT_WIDE_finish:
7328 * eax holds resolved field
7330 * %edx is scratch, but needs to be unspilled
7333 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7334 testl %ecx,%ecx # object null?
7335 je common_errNullObject # object was null
7336 leal (%ecx,%eax,1),%eax # eax<- address of field
7337 GET_VREG_WORD %ecx rINST 0 # ecx<- lsw
7338 GET_VREG_WORD rINST rINST 1 # rINST<- msw
7339 FETCH_INST_OPCODE 2 %edx
7345 /* continuation for OP_IPUT_OBJECT */
7348 .LOP_IPUT_OBJECT_resolve:
7350 movl offGlue_method(%edx),%edx # edx<- current method
7351 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7352 SPILL_TMP1(%ecx) # save obj pointer across call
7353 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7354 call dvmResolveInstField # ... to dvmResolveInstField
7356 testl %eax,%eax # returns InstrField ptr
7357 jne .LOP_IPUT_OBJECT_finish
7358 jmp common_exceptionThrown
7360 .LOP_IPUT_OBJECT_finish:
7363 * eax holds resolved field
7365 * %edx is scratch, but needs to be unspilled
7368 GET_VREG_R rINST rINST # rINST<- v[A]
7369 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7370 testl %ecx,%ecx # object null?
7371 je common_errNullObject # object was null
7372 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits)
7374 testl rINST,rINST # stored a NULL?
7375 movl offGlue_cardTable(%eax),%eax # get card table base
7376 FETCH_INST_OPCODE 2 %edx
7377 je 1f # skip card mark if null store
7378 shrl $GC_CARD_SHIFT,%ecx # object head to card number
7379 movb %al,(%eax,%ecx) # mark card
7384 /* continuation for OP_IPUT_BOOLEAN */
7387 .LOP_IPUT_BOOLEAN_resolve:
7389 movl offGlue_method(%edx),%edx # edx<- current method
7390 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7391 SPILL_TMP1(%ecx) # save obj pointer across call
7392 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7393 call dvmResolveInstField # ... to dvmResolveInstField
7395 testl %eax,%eax # returns InstrField ptr
7396 jne .LOP_IPUT_BOOLEAN_finish
7397 jmp common_exceptionThrown
7399 .LOP_IPUT_BOOLEAN_finish:
7402 * eax holds resolved field
7406 GET_VREG_R rINST rINST # rINST<- v[A]
7407 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7408 testl %ecx,%ecx # object null?
7409 je common_errNullObject # object was null
7410 FETCH_INST_OPCODE 2 %edx
7411 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7415 /* continuation for OP_IPUT_BYTE */
7418 .LOP_IPUT_BYTE_resolve:
7420 movl offGlue_method(%edx),%edx # edx<- current method
7421 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7422 SPILL_TMP1(%ecx) # save obj pointer across call
7423 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7424 call dvmResolveInstField # ... to dvmResolveInstField
7426 testl %eax,%eax # returns InstrField ptr
7427 jne .LOP_IPUT_BYTE_finish
7428 jmp common_exceptionThrown
7430 .LOP_IPUT_BYTE_finish:
7433 * eax holds resolved field
7437 GET_VREG_R rINST rINST # rINST<- v[A]
7438 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7439 testl %ecx,%ecx # object null?
7440 je common_errNullObject # object was null
7441 FETCH_INST_OPCODE 2 %edx
7442 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7446 /* continuation for OP_IPUT_CHAR */
7449 .LOP_IPUT_CHAR_resolve:
7451 movl offGlue_method(%edx),%edx # edx<- current method
7452 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7453 SPILL_TMP1(%ecx) # save obj pointer across call
7454 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7455 call dvmResolveInstField # ... to dvmResolveInstField
7457 testl %eax,%eax # returns InstrField ptr
7458 jne .LOP_IPUT_CHAR_finish
7459 jmp common_exceptionThrown
7461 .LOP_IPUT_CHAR_finish:
7464 * eax holds resolved field
7468 GET_VREG_R rINST rINST # rINST<- v[A]
7469 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7470 testl %ecx,%ecx # object null?
7471 je common_errNullObject # object was null
7472 FETCH_INST_OPCODE 2 %edx
7473 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7477 /* continuation for OP_IPUT_SHORT */
7480 .LOP_IPUT_SHORT_resolve:
7482 movl offGlue_method(%edx),%edx # edx<- current method
7483 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
7484 SPILL_TMP1(%ecx) # save obj pointer across call
7485 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
7486 call dvmResolveInstField # ... to dvmResolveInstField
7488 testl %eax,%eax # returns InstrField ptr
7489 jne .LOP_IPUT_SHORT_finish
7490 jmp common_exceptionThrown
7492 .LOP_IPUT_SHORT_finish:
7495 * eax holds resolved field
7499 GET_VREG_R rINST rINST # rINST<- v[A]
7500 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7501 testl %ecx,%ecx # object null?
7502 je common_errNullObject # object was null
7503 FETCH_INST_OPCODE 2 %edx
7504 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7508 /* continuation for OP_SGET */
7511 * Go resolve the field
7515 movzwl 2(rPC),%eax # eax<- field ref BBBB
7516 movl offGlue_method(%ecx),%ecx # ecx<- current method
7517 EXPORT_PC # could throw, need to export
7518 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7519 movl %eax,OUT_ARG1(%esp)
7520 movl %ecx,OUT_ARG0(%esp)
7521 call dvmResolveStaticField # eax<- resolved StaticField ptr
7523 jne .LOP_SGET_finish # success, continue
7524 jmp common_exceptionThrown # no, handle exception
7526 /* continuation for OP_SGET_WIDE */
7529 * Go resolve the field
7531 .LOP_SGET_WIDE_resolve:
7533 movzwl 2(rPC),%eax # eax<- field ref BBBB
7534 movl offGlue_method(%ecx),%ecx # ecx<- current method
7535 EXPORT_PC # could throw, need to export
7536 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7537 movl %eax,OUT_ARG1(%esp)
7538 movl %ecx,OUT_ARG0(%esp)
7539 call dvmResolveStaticField # eax<- resolved StaticField ptr
7541 jne .LOP_SGET_WIDE_finish # success, continue
7542 jmp common_exceptionThrown # no, handle exception
7544 /* continuation for OP_SGET_OBJECT */
7547 * Go resolve the field
7549 .LOP_SGET_OBJECT_resolve:
7551 movzwl 2(rPC),%eax # eax<- field ref BBBB
7552 movl offGlue_method(%ecx),%ecx # ecx<- current method
7553 EXPORT_PC # could throw, need to export
7554 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7555 movl %eax,OUT_ARG1(%esp)
7556 movl %ecx,OUT_ARG0(%esp)
7557 call dvmResolveStaticField # eax<- resolved StaticField ptr
7559 jne .LOP_SGET_OBJECT_finish # success, continue
7560 jmp common_exceptionThrown # no, handle exception
7562 /* continuation for OP_SGET_BOOLEAN */
7565 * Go resolve the field
7567 .LOP_SGET_BOOLEAN_resolve:
7569 movzwl 2(rPC),%eax # eax<- field ref BBBB
7570 movl offGlue_method(%ecx),%ecx # ecx<- current method
7571 EXPORT_PC # could throw, need to export
7572 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7573 movl %eax,OUT_ARG1(%esp)
7574 movl %ecx,OUT_ARG0(%esp)
7575 call dvmResolveStaticField # eax<- resolved StaticField ptr
7577 jne .LOP_SGET_BOOLEAN_finish # success, continue
7578 jmp common_exceptionThrown # no, handle exception
7580 /* continuation for OP_SGET_BYTE */
7583 * Go resolve the field
7585 .LOP_SGET_BYTE_resolve:
7587 movzwl 2(rPC),%eax # eax<- field ref BBBB
7588 movl offGlue_method(%ecx),%ecx # ecx<- current method
7589 EXPORT_PC # could throw, need to export
7590 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7591 movl %eax,OUT_ARG1(%esp)
7592 movl %ecx,OUT_ARG0(%esp)
7593 call dvmResolveStaticField # eax<- resolved StaticField ptr
7595 jne .LOP_SGET_BYTE_finish # success, continue
7596 jmp common_exceptionThrown # no, handle exception
7598 /* continuation for OP_SGET_CHAR */
7601 * Go resolve the field
7603 .LOP_SGET_CHAR_resolve:
7605 movzwl 2(rPC),%eax # eax<- field ref BBBB
7606 movl offGlue_method(%ecx),%ecx # ecx<- current method
7607 EXPORT_PC # could throw, need to export
7608 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7609 movl %eax,OUT_ARG1(%esp)
7610 movl %ecx,OUT_ARG0(%esp)
7611 call dvmResolveStaticField # eax<- resolved StaticField ptr
7613 jne .LOP_SGET_CHAR_finish # success, continue
7614 jmp common_exceptionThrown # no, handle exception
7616 /* continuation for OP_SGET_SHORT */
7619 * Go resolve the field
7621 .LOP_SGET_SHORT_resolve:
7623 movzwl 2(rPC),%eax # eax<- field ref BBBB
7624 movl offGlue_method(%ecx),%ecx # ecx<- current method
7625 EXPORT_PC # could throw, need to export
7626 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7627 movl %eax,OUT_ARG1(%esp)
7628 movl %ecx,OUT_ARG0(%esp)
7629 call dvmResolveStaticField # eax<- resolved StaticField ptr
7631 jne .LOP_SGET_SHORT_finish # success, continue
7632 jmp common_exceptionThrown # no, handle exception
7634 /* continuation for OP_SPUT */
7637 * Go resolve the field
7641 movzwl 2(rPC),%eax # eax<- field ref BBBB
7642 movl offGlue_method(%ecx),%ecx # ecx<- current method
7643 EXPORT_PC # could throw, need to export
7644 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7645 movl %eax,OUT_ARG1(%esp)
7646 movl %ecx,OUT_ARG0(%esp)
7647 call dvmResolveStaticField # eax<- resolved StaticField ptr
7649 jne .LOP_SPUT_finish # success, continue
7650 jmp common_exceptionThrown # no, handle exception
7652 /* continuation for OP_SPUT_WIDE */
7655 * Go resolve the field
7657 .LOP_SPUT_WIDE_resolve:
7659 movzwl 2(rPC),%eax # eax<- field ref BBBB
7660 movl offGlue_method(%ecx),%ecx # ecx<- current method
7661 EXPORT_PC # could throw, need to export
7662 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7663 movl %eax,OUT_ARG1(%esp)
7664 movl %ecx,OUT_ARG0(%esp)
7665 call dvmResolveStaticField # eax<- resolved StaticField ptr
7667 jne .LOP_SPUT_WIDE_finish # success, continue
7668 jmp common_exceptionThrown # no, handle exception
7670 /* continuation for OP_SPUT_OBJECT */
7673 .LOP_SPUT_OBJECT_continue:
7674 movl %ecx,offStaticField_value(%eax)
7677 FETCH_INST_OPCODE 2 %edx
7679 movl offGlue_cardTable(%ecx),%ecx # get card table base
7680 shrl $GC_CARD_SHIFT,%eax # head to card number
7681 movb %cl,(%ecx,%eax) # mark card
7686 .LOP_SPUT_OBJECT_resolve:
7688 movzwl 2(rPC),%eax # eax<- field ref BBBB
7689 movl offGlue_method(%ecx),%ecx # ecx<- current method
7690 EXPORT_PC # could throw, need to export
7691 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7692 movl %eax,OUT_ARG1(%esp)
7693 movl %ecx,OUT_ARG0(%esp)
7694 call dvmResolveStaticField # eax<- resolved StaticField ptr
7696 jne .LOP_SPUT_OBJECT_finish # success, continue
7697 jmp common_exceptionThrown # no, handle exception
7699 /* continuation for OP_SPUT_BOOLEAN */
7702 * Go resolve the field
7704 .LOP_SPUT_BOOLEAN_resolve:
7706 movzwl 2(rPC),%eax # eax<- field ref BBBB
7707 movl offGlue_method(%ecx),%ecx # ecx<- current method
7708 EXPORT_PC # could throw, need to export
7709 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7710 movl %eax,OUT_ARG1(%esp)
7711 movl %ecx,OUT_ARG0(%esp)
7712 call dvmResolveStaticField # eax<- resolved StaticField ptr
7714 jne .LOP_SPUT_BOOLEAN_finish # success, continue
7715 jmp common_exceptionThrown # no, handle exception
7717 /* continuation for OP_SPUT_BYTE */
7720 * Go resolve the field
7722 .LOP_SPUT_BYTE_resolve:
7724 movzwl 2(rPC),%eax # eax<- field ref BBBB
7725 movl offGlue_method(%ecx),%ecx # ecx<- current method
7726 EXPORT_PC # could throw, need to export
7727 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7728 movl %eax,OUT_ARG1(%esp)
7729 movl %ecx,OUT_ARG0(%esp)
7730 call dvmResolveStaticField # eax<- resolved StaticField ptr
7732 jne .LOP_SPUT_BYTE_finish # success, continue
7733 jmp common_exceptionThrown # no, handle exception
7735 /* continuation for OP_SPUT_CHAR */
7738 * Go resolve the field
7740 .LOP_SPUT_CHAR_resolve:
7742 movzwl 2(rPC),%eax # eax<- field ref BBBB
7743 movl offGlue_method(%ecx),%ecx # ecx<- current method
7744 EXPORT_PC # could throw, need to export
7745 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7746 movl %eax,OUT_ARG1(%esp)
7747 movl %ecx,OUT_ARG0(%esp)
7748 call dvmResolveStaticField # eax<- resolved StaticField ptr
7750 jne .LOP_SPUT_CHAR_finish # success, continue
7751 jmp common_exceptionThrown # no, handle exception
7753 /* continuation for OP_SPUT_SHORT */
7756 * Go resolve the field
7758 .LOP_SPUT_SHORT_resolve:
7760 movzwl 2(rPC),%eax # eax<- field ref BBBB
7761 movl offGlue_method(%ecx),%ecx # ecx<- current method
7762 EXPORT_PC # could throw, need to export
7763 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7764 movl %eax,OUT_ARG1(%esp)
7765 movl %ecx,OUT_ARG0(%esp)
7766 call dvmResolveStaticField # eax<- resolved StaticField ptr
7768 jne .LOP_SPUT_SHORT_finish # success, continue
7769 jmp common_exceptionThrown # no, handle exception
7771 /* continuation for OP_INVOKE_VIRTUAL */
7774 .LOP_INVOKE_VIRTUAL_more:
7775 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7776 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7777 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7778 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7779 testl %eax,%eax # got null?
7780 jne .LOP_INVOKE_VIRTUAL_continue # no, continue
7781 jmp common_exceptionThrown # yes, handle exception
7784 * eax = resolved base method
7787 .LOP_INVOKE_VIRTUAL_continue:
7788 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7790 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7792 GET_VREG_R %ecx %ecx # ecx<- "this"
7793 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7794 testl %ecx,%ecx # null this?
7795 je common_errNullObject # go if so
7796 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7797 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7798 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
7799 jmp common_invokeMethodNoRange
7801 /* continuation for OP_INVOKE_SUPER */
7805 * ecx = resolved base method [r0]
7806 * eax = method->clazz [r9]
7808 .LOP_INVOKE_SUPER_continue:
7809 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7810 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7811 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7812 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass
7813 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7814 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
7815 jmp common_invokeMethodNoRange
7819 * ecx = null (needs to be resolved base method)
7820 * eax = method->clazz
7822 .LOP_INVOKE_SUPER_resolve:
7823 SPILL_TMP1(%eax) # method->clazz
7824 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7825 movzwl 2(rPC),%ecx # ecx<- BBBB
7826 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7827 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7828 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7829 testl %eax,%eax # got null?
7830 movl %eax,%ecx # ecx<- resolved base method
7831 UNSPILL_TMP1(%eax) # restore method->clazz
7832 jne .LOP_INVOKE_SUPER_continue # good to go - continue
7833 jmp common_exceptionThrown # handle exception
7836 * Throw a NoSuchMethodError with the method name as the message.
7837 * ecx = resolved base method
7839 .LOP_INVOKE_SUPER_nsm:
7840 movl offMethod_name(%ecx),%eax
7841 mov %eax,OUT_ARG1(%esp)
7842 jmp common_errNoSuchMethod
7844 /* continuation for OP_INVOKE_DIRECT */
7848 * TMP_SPILL <- "this" register
7849 * Things a bit ugly on this path, but it's the less
7850 * frequent one. We'll have to do some reloading.
7852 .LOP_INVOKE_DIRECT_resolve:
7855 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7856 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7857 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7858 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7859 movl %eax,OUT_ARG1(%esp)
7860 movl %ecx,OUT_ARG0(%esp)
7861 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7864 jne .LOP_INVOKE_DIRECT_finish
7865 jmp common_exceptionThrown
7867 /* continuation for OP_INVOKE_STATIC */
7869 .LOP_INVOKE_STATIC_continue:
7870 movl $METHOD_STATIC,%eax
7871 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7872 call dvmResolveMethod # call(clazz,ref,flags)
7873 testl %eax,%eax # got null?
7874 jne common_invokeMethodNoRange
7875 jmp common_exceptionThrown
7877 /* continuation for OP_INVOKE_INTERFACE */
7879 .LOP_INVOKE_INTERFACE_continue:
7880 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7882 je common_exceptionThrown
7883 jmp common_invokeMethodNoRange
7885 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
7888 .LOP_INVOKE_VIRTUAL_RANGE_more:
7889 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7890 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7891 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7892 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7893 testl %eax,%eax # got null?
7894 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue
7895 jmp common_exceptionThrown # yes, handle exception
7898 * eax = resolved base method
7901 .LOP_INVOKE_VIRTUAL_RANGE_continue:
7902 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7904 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7906 GET_VREG_R %ecx %ecx # ecx<- "this"
7907 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7908 testl %ecx,%ecx # null this?
7909 je common_errNullObject # go if so
7910 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7911 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7912 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
7913 jmp common_invokeMethodRange
7915 /* continuation for OP_INVOKE_SUPER_RANGE */
7919 * ecx = resolved base method [r0]
7920 * eax = method->clazz [r9]
7922 .LOP_INVOKE_SUPER_RANGE_continue:
7923 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7924 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7925 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7926 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass
7927 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7928 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
7929 jmp common_invokeMethodRange
7933 * ecx = null (needs to be resolved base method)
7934 * eax = method->clazz
7936 .LOP_INVOKE_SUPER_RANGE_resolve:
7937 SPILL_TMP1(%eax) # method->clazz
7938 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7939 movzwl 2(rPC),%ecx # ecx<- BBBB
7940 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7941 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7942 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7943 testl %eax,%eax # got null?
7944 movl %eax,%ecx # ecx<- resolved base method
7945 UNSPILL_TMP1(%eax) # restore method->clazz
7946 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue
7947 jmp common_exceptionThrown # handle exception
7950 * Throw a NoSuchMethodError with the method name as the message.
7951 * ecx = resolved base method
7953 .LOP_INVOKE_SUPER_RANGE_nsm:
7954 movl offMethod_name(%ecx),%eax
7955 mov %eax,OUT_ARG1(%esp)
7956 jmp common_errNoSuchMethod
7958 /* continuation for OP_INVOKE_DIRECT_RANGE */
7962 * TMP_SPILL <- "this" register
7963 * Things a bit ugly on this path, but it's the less
7964 * frequent one. We'll have to do some reloading.
7966 .LOP_INVOKE_DIRECT_RANGE_resolve:
7969 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7970 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7971 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7972 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7973 movl %eax,OUT_ARG1(%esp)
7974 movl %ecx,OUT_ARG0(%esp)
7975 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7978 jne .LOP_INVOKE_DIRECT_RANGE_finish
7979 jmp common_exceptionThrown
7981 /* continuation for OP_INVOKE_STATIC_RANGE */
7983 .LOP_INVOKE_STATIC_RANGE_continue:
7984 movl $METHOD_STATIC,%eax
7985 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7986 call dvmResolveMethod # call(clazz,ref,flags)
7987 testl %eax,%eax # got null?
7988 jne common_invokeMethodRange
7989 jmp common_exceptionThrown
7991 /* continuation for OP_INVOKE_INTERFACE_RANGE */
7993 .LOP_INVOKE_INTERFACE_RANGE_continue:
7994 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7996 je common_exceptionThrown
7997 jmp common_invokeMethodRange
7999 /* continuation for OP_FLOAT_TO_INT */
8002 .LOP_FLOAT_TO_INT_continue:
8004 movl $0x80000000,%eax
8005 xorl 4(rFP,%ecx,4),%eax
8006 orl (rFP,%ecx,4),%eax
8008 cmpl $0x80000000,(rFP,%ecx,4)
8010 je .LOP_FLOAT_TO_INT_special_case # fix up result
8012 .LOP_FLOAT_TO_INT_finish:
8016 .LOP_FLOAT_TO_INT_special_case:
8019 jp .LOP_FLOAT_TO_INT_isNaN
8020 adcl $-1,(rFP,%ecx,4)
8022 adcl $-1,4(rFP,%ecx,4)
8024 jmp .LOP_FLOAT_TO_INT_finish
8025 .LOP_FLOAT_TO_INT_isNaN:
8026 movl $0,(rFP,%ecx,4)
8028 movl $0,4(rFP,%ecx,4)
8030 jmp .LOP_FLOAT_TO_INT_finish
8032 /* continuation for OP_FLOAT_TO_LONG */
8035 .LOP_FLOAT_TO_LONG_continue:
8037 movl $0x80000000,%eax
8038 xorl 4(rFP,%ecx,4),%eax
8039 orl (rFP,%ecx,4),%eax
8041 cmpl $0x80000000,(rFP,%ecx,4)
8043 je .LOP_FLOAT_TO_LONG_special_case # fix up result
8045 .LOP_FLOAT_TO_LONG_finish:
8049 .LOP_FLOAT_TO_LONG_special_case:
8052 jp .LOP_FLOAT_TO_LONG_isNaN
8053 adcl $-1,(rFP,%ecx,4)
8055 adcl $-1,4(rFP,%ecx,4)
8057 jmp .LOP_FLOAT_TO_LONG_finish
8058 .LOP_FLOAT_TO_LONG_isNaN:
8059 movl $0,(rFP,%ecx,4)
8061 movl $0,4(rFP,%ecx,4)
8063 jmp .LOP_FLOAT_TO_LONG_finish
8065 /* continuation for OP_DOUBLE_TO_INT */
8068 .LOP_DOUBLE_TO_INT_continue:
8070 movl $0x80000000,%eax
8071 xorl 4(rFP,%ecx,4),%eax
8072 orl (rFP,%ecx,4),%eax
8074 cmpl $0x80000000,(rFP,%ecx,4)
8076 je .LOP_DOUBLE_TO_INT_special_case # fix up result
8078 .LOP_DOUBLE_TO_INT_finish:
8082 .LOP_DOUBLE_TO_INT_special_case:
8085 jp .LOP_DOUBLE_TO_INT_isNaN
8086 adcl $-1,(rFP,%ecx,4)
8088 adcl $-1,4(rFP,%ecx,4)
8090 jmp .LOP_DOUBLE_TO_INT_finish
8091 .LOP_DOUBLE_TO_INT_isNaN:
8092 movl $0,(rFP,%ecx,4)
8094 movl $0,4(rFP,%ecx,4)
8096 jmp .LOP_DOUBLE_TO_INT_finish
8098 /* continuation for OP_DOUBLE_TO_LONG */
8101 .LOP_DOUBLE_TO_LONG_continue:
8103 movl $0x80000000,%eax
8104 xorl 4(rFP,%ecx,4),%eax
8105 orl (rFP,%ecx,4),%eax
8107 cmpl $0x80000000,(rFP,%ecx,4)
8109 je .LOP_DOUBLE_TO_LONG_special_case # fix up result
8111 .LOP_DOUBLE_TO_LONG_finish:
8115 .LOP_DOUBLE_TO_LONG_special_case:
8118 jp .LOP_DOUBLE_TO_LONG_isNaN
8119 adcl $-1,(rFP,%ecx,4)
8121 adcl $-1,4(rFP,%ecx,4)
8123 jmp .LOP_DOUBLE_TO_LONG_finish
8124 .LOP_DOUBLE_TO_LONG_isNaN:
8125 movl $0,(rFP,%ecx,4)
8127 movl $0,4(rFP,%ecx,4)
8129 jmp .LOP_DOUBLE_TO_LONG_finish
8131 /* continuation for OP_DIV_INT */
8132 .LOP_DIV_INT_continue_div:
8135 .LOP_DIV_INT_finish_div:
8137 FETCH_INST_OPCODE 2 %edx
8141 /* continuation for OP_REM_INT */
8142 .LOP_REM_INT_continue_div:
8145 .LOP_REM_INT_finish_div:
8147 FETCH_INST_OPCODE 2 %edx
8151 /* continuation for OP_MUL_LONG */
8153 .LOP_MUL_LONG_continue:
8154 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8155 FETCH_INST_OPCODE 2 %ecx
8157 movl %edx,4(rFP,rINST,4) # v[B+1]<- %edx
8158 movl %eax,(rFP,rINST,4) # v[B]<- %eax
8162 /* continuation for OP_DIV_LONG */
8164 .LOP_DIV_LONG_continue:
8166 .LOP_DIV_LONG_finish:
8167 SET_VREG_WORD %edx rINST 1
8168 SET_VREG_WORD %eax rINST 0
8169 FETCH_INST_OPCODE 2 %edx
8173 .LOP_DIV_LONG_check_zero:
8175 jne .LOP_DIV_LONG_notSpecial
8176 jmp common_errDivideByZero
8177 .LOP_DIV_LONG_check_neg1:
8179 jne .LOP_DIV_LONG_notSpecial
8180 GET_VREG_WORD %edx %ecx 0
8181 GET_VREG_WORD %ecx %ecx 1
8183 jne .LOP_DIV_LONG_notSpecial1
8184 cmpl $0x80000000,%ecx
8185 jne .LOP_DIV_LONG_notSpecial1
8186 /* minint / -1, return minint on div, 0 on rem */
8188 movl $0x80000000,%edx
8189 jmp .LOP_DIV_LONG_finish
8191 /* continuation for OP_REM_LONG */
8193 .LOP_REM_LONG_continue:
8195 .LOP_REM_LONG_finish:
8196 SET_VREG_WORD %edx rINST 1
8197 SET_VREG_WORD %eax rINST 0
8198 FETCH_INST_OPCODE 2 %edx
8202 .LOP_REM_LONG_check_zero:
8204 jne .LOP_REM_LONG_notSpecial
8205 jmp common_errDivideByZero
8206 .LOP_REM_LONG_check_neg1:
8208 jne .LOP_REM_LONG_notSpecial
8209 GET_VREG_WORD %edx %ecx 0
8210 GET_VREG_WORD %ecx %ecx 1
8212 jne .LOP_REM_LONG_notSpecial1
8213 cmpl $0x80000000,%ecx
8214 jne .LOP_REM_LONG_notSpecial1
8215 /* minint / -1, return minint on div, 0 on rem */
8218 jmp .LOP_REM_LONG_finish
8220 /* continuation for OP_SHL_LONG */
8222 .LOP_SHL_LONG_finish:
8223 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- %eax
8227 /* continuation for OP_SHR_LONG */
8230 .LOP_SHR_LONG_finish:
8231 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
8235 /* continuation for OP_USHR_LONG */
8238 .LOP_USHR_LONG_finish:
8239 SET_VREG_WORD %eax rINST 0 # v[BB+0]<- eax
8243 /* continuation for OP_DIV_INT_2ADDR */
8244 .LOP_DIV_INT_2ADDR_continue_div2addr:
8247 .LOP_DIV_INT_2ADDR_finish_div2addr:
8249 FETCH_INST_OPCODE 1 %edx
8253 /* continuation for OP_REM_INT_2ADDR */
8254 .LOP_REM_INT_2ADDR_continue_div2addr:
8257 .LOP_REM_INT_2ADDR_finish_div2addr:
8259 FETCH_INST_OPCODE 1 %edx
8263 /* continuation for OP_MUL_LONG_2ADDR */
8265 .LOP_MUL_LONG_2ADDR_continue:
8266 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8267 movl %edx,4(%esi) # v[A+1]<- %edx
8268 movl %eax,(%esi) # v[A]<- %eax
8270 FETCH_INST_OPCODE 1 %ecx
8275 /* continuation for OP_DIV_LONG_2ADDR */
8277 .LOP_DIV_LONG_2ADDR_continue:
8278 movl %eax,OUT_ARG3(%esp)
8279 movl %edx,OUT_ARG0(%esp)
8280 movl %ecx,OUT_ARG1(%esp)
8282 .LOP_DIV_LONG_2ADDR_finish:
8283 SET_VREG_WORD %edx rINST 1
8284 SET_VREG_WORD %eax rINST 0
8285 FETCH_INST_OPCODE 1 %edx
8289 .LOP_DIV_LONG_2ADDR_check_zero:
8291 jne .LOP_DIV_LONG_2ADDR_notSpecial
8292 jmp common_errDivideByZero
8293 .LOP_DIV_LONG_2ADDR_check_neg1:
8295 jne .LOP_DIV_LONG_2ADDR_notSpecial
8296 GET_VREG_WORD %edx rINST 0
8297 GET_VREG_WORD %ecx rINST 1
8299 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8300 cmpl $0x80000000,%ecx
8301 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8302 /* minint / -1, return minint on div, 0 on rem */
8304 movl $0x80000000,%edx
8305 jmp .LOP_DIV_LONG_2ADDR_finish
8307 /* continuation for OP_REM_LONG_2ADDR */
8309 .LOP_REM_LONG_2ADDR_continue:
8310 movl %eax,OUT_ARG3(%esp)
8311 movl %edx,OUT_ARG0(%esp)
8312 movl %ecx,OUT_ARG1(%esp)
8314 .LOP_REM_LONG_2ADDR_finish:
8315 SET_VREG_WORD %edx rINST 1
8316 SET_VREG_WORD %eax rINST 0
8317 FETCH_INST_OPCODE 1 %edx
8321 .LOP_REM_LONG_2ADDR_check_zero:
8323 jne .LOP_REM_LONG_2ADDR_notSpecial
8324 jmp common_errDivideByZero
8325 .LOP_REM_LONG_2ADDR_check_neg1:
8327 jne .LOP_REM_LONG_2ADDR_notSpecial
8328 GET_VREG_WORD %edx rINST 0
8329 GET_VREG_WORD %ecx rINST 1
8331 jne .LOP_REM_LONG_2ADDR_notSpecial1
8332 cmpl $0x80000000,%ecx
8333 jne .LOP_REM_LONG_2ADDR_notSpecial1
8334 /* minint / -1, return minint on div, 0 on rem */
8337 jmp .LOP_REM_LONG_2ADDR_finish
8339 /* continuation for OP_SHL_LONG_2ADDR */
8342 .LOP_SHL_LONG_2ADDR_finish:
8343 FETCH_INST_OPCODE 1 %edx
8344 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
8348 /* continuation for OP_SHR_LONG_2ADDR */
8351 .LOP_SHR_LONG_2ADDR_finish:
8352 FETCH_INST_OPCODE 1 %edx
8353 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
8357 /* continuation for OP_USHR_LONG_2ADDR */
8360 .LOP_USHR_LONG_2ADDR_finish:
8361 FETCH_INST_OPCODE 1 %edx
8362 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
8366 /* continuation for OP_DIV_INT_LIT16 */
8367 .LOP_DIV_INT_LIT16_continue_div:
8370 .LOP_DIV_INT_LIT16_finish_div:
8372 FETCH_INST_OPCODE 2 %edx
8376 /* continuation for OP_REM_INT_LIT16 */
8377 .LOP_REM_INT_LIT16_continue_div:
8380 .LOP_REM_INT_LIT16_finish_div:
8382 FETCH_INST_OPCODE 2 %edx
8386 /* continuation for OP_DIV_INT_LIT8 */
8387 .LOP_DIV_INT_LIT8_continue_div:
8390 .LOP_DIV_INT_LIT8_finish_div:
8392 FETCH_INST_OPCODE 2 %edx
8396 /* continuation for OP_REM_INT_LIT8 */
8397 .LOP_REM_INT_LIT8_continue_div:
8400 .LOP_REM_INT_LIT8_finish_div:
8402 FETCH_INST_OPCODE 2 %edx
8406 /* continuation for OP_IGET_VOLATILE */
8409 .LOP_IGET_VOLATILE_resolve:
8411 movl offGlue_method(%edx),%edx # edx<- current method
8412 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
8413 SPILL_TMP1(%ecx) # save obj pointer across call
8414 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
8415 call dvmResolveInstField # ... to dvmResolveInstField
8417 testl %eax,%eax # returns InstrField ptr
8418 jne .LOP_IGET_VOLATILE_finish
8419 jmp common_exceptionThrown
8421 .LOP_IGET_VOLATILE_finish:
8424 * eax holds resolved field
8428 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
8429 testl %ecx,%ecx # object null?
8430 je common_errNullObject # object was null
8431 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
8432 movl rINST,%eax # eax<- A
8433 FETCH_INST_OPCODE 2 %edx
8438 /* continuation for OP_IPUT_VOLATILE */
8441 .LOP_IPUT_VOLATILE_resolve:
8443 movl offGlue_method(%edx),%edx # edx<- current method
8444 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
8445 SPILL_TMP1(%ecx) # save obj pointer across call
8446 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
8447 call dvmResolveInstField # ... to dvmResolveInstField
8449 testl %eax,%eax # returns InstrField ptr
8450 jne .LOP_IPUT_VOLATILE_finish
8451 jmp common_exceptionThrown
8453 .LOP_IPUT_VOLATILE_finish:
8456 * eax holds resolved field
8460 GET_VREG_R rINST rINST # rINST<- v[A]
8461 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
8462 testl %ecx,%ecx # object null?
8463 je common_errNullObject # object was null
8464 FETCH_INST_OPCODE 2 %edx
8465 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
8469 /* continuation for OP_SGET_VOLATILE */
8472 * Go resolve the field
8474 .LOP_SGET_VOLATILE_resolve:
8476 movzwl 2(rPC),%eax # eax<- field ref BBBB
8477 movl offGlue_method(%ecx),%ecx # ecx<- current method
8478 EXPORT_PC # could throw, need to export
8479 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8480 movl %eax,OUT_ARG1(%esp)
8481 movl %ecx,OUT_ARG0(%esp)
8482 call dvmResolveStaticField # eax<- resolved StaticField ptr
8484 jne .LOP_SGET_VOLATILE_finish # success, continue
8485 jmp common_exceptionThrown # no, handle exception
8487 /* continuation for OP_SPUT_VOLATILE */
8490 * Go resolve the field
8492 .LOP_SPUT_VOLATILE_resolve:
8494 movzwl 2(rPC),%eax # eax<- field ref BBBB
8495 movl offGlue_method(%ecx),%ecx # ecx<- current method
8496 EXPORT_PC # could throw, need to export
8497 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8498 movl %eax,OUT_ARG1(%esp)
8499 movl %ecx,OUT_ARG0(%esp)
8500 call dvmResolveStaticField # eax<- resolved StaticField ptr
8502 jne .LOP_SPUT_VOLATILE_finish # success, continue
8503 jmp common_exceptionThrown # no, handle exception
8505 /* continuation for OP_IGET_OBJECT_VOLATILE */
8508 .LOP_IGET_OBJECT_VOLATILE_resolve:
8510 movl offGlue_method(%edx),%edx # edx<- current method
8511 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
8512 SPILL_TMP1(%ecx) # save obj pointer across call
8513 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
8514 call dvmResolveInstField # ... to dvmResolveInstField
8516 testl %eax,%eax # returns InstrField ptr
8517 jne .LOP_IGET_OBJECT_VOLATILE_finish
8518 jmp common_exceptionThrown
8520 .LOP_IGET_OBJECT_VOLATILE_finish:
8523 * eax holds resolved field
8527 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
8528 testl %ecx,%ecx # object null?
8529 je common_errNullObject # object was null
8530 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
8531 movl rINST,%eax # eax<- A
8532 FETCH_INST_OPCODE 2 %edx
8537 /* continuation for OP_EXECUTE_INLINE */
8539 .LOP_EXECUTE_INLINE_continue:
8541 * Extract args, call function.
8542 * ecx = #of args (0-4)
8544 * @esp = return addr
8545 * esp is -4 from normal
8547 * Go ahead and load all 4 args, even if not used.
8553 GET_VREG_R %ecx %ecx
8555 movl %ecx,4+OUT_ARG0(%esp)
8559 GET_VREG_R %ecx %ecx
8561 movl %ecx,4+OUT_ARG1(%esp)
8565 GET_VREG_R %ecx %ecx
8567 movl %ecx,4+OUT_ARG2(%esp)
8571 GET_VREG_R %ecx %ecx
8573 movl %ecx,4+OUT_ARG3(%esp)
8575 sall $4,%eax # index *= sizeof(table entry)
8576 jmp *gDvmInlineOpsTable(%eax)
8577 # will return to caller of .LOP_EXECUTE_INLINE_continue
8579 /* continuation for OP_IPUT_OBJECT_QUICK */
8581 .LOP_IPUT_OBJECT_QUICK_finish:
8582 testl rINST,rINST # did we store null?
8583 FETCH_INST_OPCODE 2 %edx
8584 movl offGlue_cardTable(%eax),%eax # get card table base
8585 je 1f # skip card mark if null store
8586 shrl $GC_CARD_SHIFT,%ecx # object head to card number
8587 movb %al,(%eax,%ecx) # mark card
8592 /* continuation for OP_IPUT_OBJECT_VOLATILE */
8595 .LOP_IPUT_OBJECT_VOLATILE_resolve:
8597 movl offGlue_method(%edx),%edx # edx<- current method
8598 movl offMethod_clazz(%edx),%edx # edx<- method->clazz
8599 SPILL_TMP1(%ecx) # save obj pointer across call
8600 movl %edx,OUT_ARG0(%esp) # pass in method->clazz
8601 call dvmResolveInstField # ... to dvmResolveInstField
8603 testl %eax,%eax # returns InstrField ptr
8604 jne .LOP_IPUT_OBJECT_VOLATILE_finish
8605 jmp common_exceptionThrown
8607 .LOP_IPUT_OBJECT_VOLATILE_finish:
8610 * eax holds resolved field
8612 * %edx is scratch, but needs to be unspilled
8615 GET_VREG_R rINST rINST # rINST<- v[A]
8616 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
8617 testl %ecx,%ecx # object null?
8618 je common_errNullObject # object was null
8619 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits)
8621 testl rINST,rINST # stored a NULL?
8622 movl offGlue_cardTable(%eax),%eax # get card table base
8623 FETCH_INST_OPCODE 2 %edx
8624 je 1f # skip card mark if null store
8625 shrl $GC_CARD_SHIFT,%ecx # object head to card number
8626 movb %al,(%eax,%ecx) # mark card
8631 /* continuation for OP_SGET_OBJECT_VOLATILE */
8634 * Go resolve the field
8636 .LOP_SGET_OBJECT_VOLATILE_resolve:
8638 movzwl 2(rPC),%eax # eax<- field ref BBBB
8639 movl offGlue_method(%ecx),%ecx # ecx<- current method
8640 EXPORT_PC # could throw, need to export
8641 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8642 movl %eax,OUT_ARG1(%esp)
8643 movl %ecx,OUT_ARG0(%esp)
8644 call dvmResolveStaticField # eax<- resolved StaticField ptr
8646 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue
8647 jmp common_exceptionThrown # no, handle exception
8649 /* continuation for OP_SPUT_OBJECT_VOLATILE */
8652 .LOP_SPUT_OBJECT_VOLATILE_continue:
8653 movl %ecx,offStaticField_value(%eax)
8656 FETCH_INST_OPCODE 2 %edx
8658 movl offGlue_cardTable(%ecx),%ecx # get card table base
8659 shrl $GC_CARD_SHIFT,%eax # head to card number
8660 movb %cl,(%ecx,%eax) # mark card
8665 .LOP_SPUT_OBJECT_VOLATILE_resolve:
8667 movzwl 2(rPC),%eax # eax<- field ref BBBB
8668 movl offGlue_method(%ecx),%ecx # ecx<- current method
8669 EXPORT_PC # could throw, need to export
8670 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8671 movl %eax,OUT_ARG1(%esp)
8672 movl %ecx,OUT_ARG0(%esp)
8673 call dvmResolveStaticField # eax<- resolved StaticField ptr
8675 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue
8676 jmp common_exceptionThrown # no, handle exception
8678 .size dvmAsmSisterStart, .-dvmAsmSisterStart
8679 .global dvmAsmSisterEnd
8682 /* File: x86/entry.S */
8684 * Copyright (C) 2008 The Android Open Source Project
8686 * Licensed under the Apache License, Version 2.0 (the "License");
8687 * you may not use this file except in compliance with the License.
8688 * You may obtain a copy of the License at
8690 * http://www.apache.org/licenses/LICENSE-2.0
8692 * Unless required by applicable law or agreed to in writing, software
8693 * distributed under the License is distributed on an "AS IS" BASIS,
8694 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8695 * See the License for the specific language governing permissions and
8696 * limitations under the License.
8701 .global dvmMterpStdRun
8702 .type dvmMterpStdRun, %function
8704 * bool dvmMterpStdRun(MterpGlue* glue)
8706 * Interpreter entry point. Returns changeInterp.
8710 movl 4(%esp), %ecx # get incoming rGLUE
8711 push %ebp # save caller base pointer
8712 push %ecx # save rGLUE at (%ebp)
8713 movl %esp, %ebp # set our %ebp
8715 * At this point we've allocated two slots on the stack
8716 * via push and stack is 8-byte aligned. Allocate space
8717 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for
8718 * padding to bring us to 16-byte alignment
8720 subl $(FRAME_SIZE-8), %esp
8722 /* Spill callee save regs */
8723 movl %edi,EDI_SPILL(%ebp)
8724 movl %esi,ESI_SPILL(%ebp)
8725 movl %ebx,EBX_SPILL(%ebp)
8727 /* Set up "named" registers */
8728 movl offGlue_pc(%ecx),rPC
8729 movl offGlue_fp(%ecx),rFP
8731 /* Remember %esp for future "longjmp" */
8732 movl %esp,offGlue_bailPtr(%ecx)
8735 movb offGlue_entryPoint(%ecx),%al
8738 cmpb $kInterpEntryInstr,%al
8741 /* Normal case: start executing the instruction at rPC */
8746 /* Reset to normal case */
8747 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8748 cmpb $kInterpEntryReturn,%al
8749 je common_returnFromMethod
8750 cmpb $kInterpEntryThrow,%al
8751 je common_exceptionThrown
8753 movl %eax,OUT_ARG1(%esp)
8754 movl $.LstrBadEntryPoint,OUT_ARG0(%esp)
8760 .global dvmMterpStdBail
8761 .type dvmMterpStdBail, %function
8763 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8765 * Restore the stack pointer and PC from the save point established on entry.
8766 * This is essentially the same as a longjmp, but should be cheaper. The
8767 * last instruction causes us to return to whoever called dvmMterpStdRun.
8769 * We're not going to build a standard frame here, so the arg accesses will
8770 * look a little strange.
8773 * esp+4 (arg0) MterpGlue* glue
8774 * esp+8 (arg1) bool changeInterp
8777 movl 4(%esp),%ecx # grab glue
8778 movl 8(%esp),%eax # changeInterp to return reg
8779 movl offGlue_bailPtr(%ecx),%esp # Restore "setjmp" esp
8780 movl (FRAME_SIZE-8)(%esp), %ebp # Restore %ebp at point of setjmp
8781 movl EDI_SPILL(%ebp),%edi
8782 movl ESI_SPILL(%ebp),%esi
8783 movl EBX_SPILL(%ebp),%ebx
8784 movl PREV_FP(%ebp),%ebp # restore caller's ebp
8785 addl $FRAME_SIZE,%esp # strip frame
8786 ret # return to dvmMterpStdRun's caller
8794 .asciz "Bad entry point %d\n"
8798 * FIXME: Should have the config/rebuild mechanism generate this
8799 * for targets that need it.
8803 dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable
8804 .LdvmAsmInstructionJmpTable:
8807 .long .L_OP_MOVE_FROM16
8809 .long .L_OP_MOVE_WIDE
8810 .long .L_OP_MOVE_WIDE_FROM16
8811 .long .L_OP_MOVE_WIDE_16
8812 .long .L_OP_MOVE_OBJECT
8813 .long .L_OP_MOVE_OBJECT_FROM16
8814 .long .L_OP_MOVE_OBJECT_16
8815 .long .L_OP_MOVE_RESULT
8816 .long .L_OP_MOVE_RESULT_WIDE
8817 .long .L_OP_MOVE_RESULT_OBJECT
8818 .long .L_OP_MOVE_EXCEPTION
8819 .long .L_OP_RETURN_VOID
8821 .long .L_OP_RETURN_WIDE
8822 .long .L_OP_RETURN_OBJECT
8824 .long .L_OP_CONST_16
8826 .long .L_OP_CONST_HIGH16
8827 .long .L_OP_CONST_WIDE_16
8828 .long .L_OP_CONST_WIDE_32
8829 .long .L_OP_CONST_WIDE
8830 .long .L_OP_CONST_WIDE_HIGH16
8831 .long .L_OP_CONST_STRING
8832 .long .L_OP_CONST_STRING_JUMBO
8833 .long .L_OP_CONST_CLASS
8834 .long .L_OP_MONITOR_ENTER
8835 .long .L_OP_MONITOR_EXIT
8836 .long .L_OP_CHECK_CAST
8837 .long .L_OP_INSTANCE_OF
8838 .long .L_OP_ARRAY_LENGTH
8839 .long .L_OP_NEW_INSTANCE
8840 .long .L_OP_NEW_ARRAY
8841 .long .L_OP_FILLED_NEW_ARRAY
8842 .long .L_OP_FILLED_NEW_ARRAY_RANGE
8843 .long .L_OP_FILL_ARRAY_DATA
8848 .long .L_OP_PACKED_SWITCH
8849 .long .L_OP_SPARSE_SWITCH
8850 .long .L_OP_CMPL_FLOAT
8851 .long .L_OP_CMPG_FLOAT
8852 .long .L_OP_CMPL_DOUBLE
8853 .long .L_OP_CMPG_DOUBLE
8854 .long .L_OP_CMP_LONG
8867 .long .L_OP_UNUSED_3E
8868 .long .L_OP_UNUSED_3F
8869 .long .L_OP_UNUSED_40
8870 .long .L_OP_UNUSED_41
8871 .long .L_OP_UNUSED_42
8872 .long .L_OP_UNUSED_43
8874 .long .L_OP_AGET_WIDE
8875 .long .L_OP_AGET_OBJECT
8876 .long .L_OP_AGET_BOOLEAN
8877 .long .L_OP_AGET_BYTE
8878 .long .L_OP_AGET_CHAR
8879 .long .L_OP_AGET_SHORT
8881 .long .L_OP_APUT_WIDE
8882 .long .L_OP_APUT_OBJECT
8883 .long .L_OP_APUT_BOOLEAN
8884 .long .L_OP_APUT_BYTE
8885 .long .L_OP_APUT_CHAR
8886 .long .L_OP_APUT_SHORT
8888 .long .L_OP_IGET_WIDE
8889 .long .L_OP_IGET_OBJECT
8890 .long .L_OP_IGET_BOOLEAN
8891 .long .L_OP_IGET_BYTE
8892 .long .L_OP_IGET_CHAR
8893 .long .L_OP_IGET_SHORT
8895 .long .L_OP_IPUT_WIDE
8896 .long .L_OP_IPUT_OBJECT
8897 .long .L_OP_IPUT_BOOLEAN
8898 .long .L_OP_IPUT_BYTE
8899 .long .L_OP_IPUT_CHAR
8900 .long .L_OP_IPUT_SHORT
8902 .long .L_OP_SGET_WIDE
8903 .long .L_OP_SGET_OBJECT
8904 .long .L_OP_SGET_BOOLEAN
8905 .long .L_OP_SGET_BYTE
8906 .long .L_OP_SGET_CHAR
8907 .long .L_OP_SGET_SHORT
8909 .long .L_OP_SPUT_WIDE
8910 .long .L_OP_SPUT_OBJECT
8911 .long .L_OP_SPUT_BOOLEAN
8912 .long .L_OP_SPUT_BYTE
8913 .long .L_OP_SPUT_CHAR
8914 .long .L_OP_SPUT_SHORT
8915 .long .L_OP_INVOKE_VIRTUAL
8916 .long .L_OP_INVOKE_SUPER
8917 .long .L_OP_INVOKE_DIRECT
8918 .long .L_OP_INVOKE_STATIC
8919 .long .L_OP_INVOKE_INTERFACE
8920 .long .L_OP_UNUSED_73
8921 .long .L_OP_INVOKE_VIRTUAL_RANGE
8922 .long .L_OP_INVOKE_SUPER_RANGE
8923 .long .L_OP_INVOKE_DIRECT_RANGE
8924 .long .L_OP_INVOKE_STATIC_RANGE
8925 .long .L_OP_INVOKE_INTERFACE_RANGE
8926 .long .L_OP_UNUSED_79
8927 .long .L_OP_UNUSED_7A
8930 .long .L_OP_NEG_LONG
8931 .long .L_OP_NOT_LONG
8932 .long .L_OP_NEG_FLOAT
8933 .long .L_OP_NEG_DOUBLE
8934 .long .L_OP_INT_TO_LONG
8935 .long .L_OP_INT_TO_FLOAT
8936 .long .L_OP_INT_TO_DOUBLE
8937 .long .L_OP_LONG_TO_INT
8938 .long .L_OP_LONG_TO_FLOAT
8939 .long .L_OP_LONG_TO_DOUBLE
8940 .long .L_OP_FLOAT_TO_INT
8941 .long .L_OP_FLOAT_TO_LONG
8942 .long .L_OP_FLOAT_TO_DOUBLE
8943 .long .L_OP_DOUBLE_TO_INT
8944 .long .L_OP_DOUBLE_TO_LONG
8945 .long .L_OP_DOUBLE_TO_FLOAT
8946 .long .L_OP_INT_TO_BYTE
8947 .long .L_OP_INT_TO_CHAR
8948 .long .L_OP_INT_TO_SHORT
8959 .long .L_OP_USHR_INT
8960 .long .L_OP_ADD_LONG
8961 .long .L_OP_SUB_LONG
8962 .long .L_OP_MUL_LONG
8963 .long .L_OP_DIV_LONG
8964 .long .L_OP_REM_LONG
8965 .long .L_OP_AND_LONG
8967 .long .L_OP_XOR_LONG
8968 .long .L_OP_SHL_LONG
8969 .long .L_OP_SHR_LONG
8970 .long .L_OP_USHR_LONG
8971 .long .L_OP_ADD_FLOAT
8972 .long .L_OP_SUB_FLOAT
8973 .long .L_OP_MUL_FLOAT
8974 .long .L_OP_DIV_FLOAT
8975 .long .L_OP_REM_FLOAT
8976 .long .L_OP_ADD_DOUBLE
8977 .long .L_OP_SUB_DOUBLE
8978 .long .L_OP_MUL_DOUBLE
8979 .long .L_OP_DIV_DOUBLE
8980 .long .L_OP_REM_DOUBLE
8981 .long .L_OP_ADD_INT_2ADDR
8982 .long .L_OP_SUB_INT_2ADDR
8983 .long .L_OP_MUL_INT_2ADDR
8984 .long .L_OP_DIV_INT_2ADDR
8985 .long .L_OP_REM_INT_2ADDR
8986 .long .L_OP_AND_INT_2ADDR
8987 .long .L_OP_OR_INT_2ADDR
8988 .long .L_OP_XOR_INT_2ADDR
8989 .long .L_OP_SHL_INT_2ADDR
8990 .long .L_OP_SHR_INT_2ADDR
8991 .long .L_OP_USHR_INT_2ADDR
8992 .long .L_OP_ADD_LONG_2ADDR
8993 .long .L_OP_SUB_LONG_2ADDR
8994 .long .L_OP_MUL_LONG_2ADDR
8995 .long .L_OP_DIV_LONG_2ADDR
8996 .long .L_OP_REM_LONG_2ADDR
8997 .long .L_OP_AND_LONG_2ADDR
8998 .long .L_OP_OR_LONG_2ADDR
8999 .long .L_OP_XOR_LONG_2ADDR
9000 .long .L_OP_SHL_LONG_2ADDR
9001 .long .L_OP_SHR_LONG_2ADDR
9002 .long .L_OP_USHR_LONG_2ADDR
9003 .long .L_OP_ADD_FLOAT_2ADDR
9004 .long .L_OP_SUB_FLOAT_2ADDR
9005 .long .L_OP_MUL_FLOAT_2ADDR
9006 .long .L_OP_DIV_FLOAT_2ADDR
9007 .long .L_OP_REM_FLOAT_2ADDR
9008 .long .L_OP_ADD_DOUBLE_2ADDR
9009 .long .L_OP_SUB_DOUBLE_2ADDR
9010 .long .L_OP_MUL_DOUBLE_2ADDR
9011 .long .L_OP_DIV_DOUBLE_2ADDR
9012 .long .L_OP_REM_DOUBLE_2ADDR
9013 .long .L_OP_ADD_INT_LIT16
9014 .long .L_OP_RSUB_INT
9015 .long .L_OP_MUL_INT_LIT16
9016 .long .L_OP_DIV_INT_LIT16
9017 .long .L_OP_REM_INT_LIT16
9018 .long .L_OP_AND_INT_LIT16
9019 .long .L_OP_OR_INT_LIT16
9020 .long .L_OP_XOR_INT_LIT16
9021 .long .L_OP_ADD_INT_LIT8
9022 .long .L_OP_RSUB_INT_LIT8
9023 .long .L_OP_MUL_INT_LIT8
9024 .long .L_OP_DIV_INT_LIT8
9025 .long .L_OP_REM_INT_LIT8
9026 .long .L_OP_AND_INT_LIT8
9027 .long .L_OP_OR_INT_LIT8
9028 .long .L_OP_XOR_INT_LIT8
9029 .long .L_OP_SHL_INT_LIT8
9030 .long .L_OP_SHR_INT_LIT8
9031 .long .L_OP_USHR_INT_LIT8
9032 .long .L_OP_IGET_VOLATILE
9033 .long .L_OP_IPUT_VOLATILE
9034 .long .L_OP_SGET_VOLATILE
9035 .long .L_OP_SPUT_VOLATILE
9036 .long .L_OP_IGET_OBJECT_VOLATILE
9037 .long .L_OP_IGET_WIDE_VOLATILE
9038 .long .L_OP_IPUT_WIDE_VOLATILE
9039 .long .L_OP_SGET_WIDE_VOLATILE
9040 .long .L_OP_SPUT_WIDE_VOLATILE
9041 .long .L_OP_BREAKPOINT
9042 .long .L_OP_THROW_VERIFICATION_ERROR
9043 .long .L_OP_EXECUTE_INLINE
9044 .long .L_OP_EXECUTE_INLINE_RANGE
9045 .long .L_OP_INVOKE_DIRECT_EMPTY
9046 .long .L_OP_RETURN_VOID_BARRIER
9047 .long .L_OP_IGET_QUICK
9048 .long .L_OP_IGET_WIDE_QUICK
9049 .long .L_OP_IGET_OBJECT_QUICK
9050 .long .L_OP_IPUT_QUICK
9051 .long .L_OP_IPUT_WIDE_QUICK
9052 .long .L_OP_IPUT_OBJECT_QUICK
9053 .long .L_OP_INVOKE_VIRTUAL_QUICK
9054 .long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE
9055 .long .L_OP_INVOKE_SUPER_QUICK
9056 .long .L_OP_INVOKE_SUPER_QUICK_RANGE
9057 .long .L_OP_IPUT_OBJECT_VOLATILE
9058 .long .L_OP_SGET_OBJECT_VOLATILE
9059 .long .L_OP_SPUT_OBJECT_VOLATILE
9060 .long .L_OP_UNUSED_FF
9063 /* File: x86/footer.S */
9065 * Copyright (C) 2008 The Android Open Source Project
9067 * Licensed under the Apache License, Version 2.0 (the "License");
9068 * you may not use this file except in compliance with the License.
9069 * You may obtain a copy of the License at
9071 * http://www.apache.org/licenses/LICENSE-2.0
9073 * Unless required by applicable law or agreed to in writing, software
9074 * distributed under the License is distributed on an "AS IS" BASIS,
9075 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9076 * See the License for the specific language governing permissions and
9077 * limitations under the License.
9080 * Common subroutines and data.
9083 #if defined(WITH_JIT)
9085 * Placeholder entries for x86 JIT
9087 .global dvmJitToInterpPunt
9089 .global dvmJitToInterpSingleStep
9090 dvmJitToInterpSingleStep:
9091 .global dvmJitToInterpNoChainNoProfile
9092 dvmJitToInterpNoChainNoProfile:
9093 .global dvmJitToInterpTraceSelectNoChain
9094 dvmJitToInterpTraceSelectNoChain:
9095 .global dvmJitToInterpTraceSelect
9096 dvmJitToInterpTraceSelect:
9097 .global dvmJitToInterpBackwardBranch
9098 dvmJitToInterpBackwardBranch:
9099 .global dvmJitToInterpNormal
9100 dvmJitToInterpNormal:
9101 .global dvmJitToInterpNoChain
9102 dvmJitToInterpNoChain:
9107 * Common code when a backwards branch is taken
9110 * ebx (a.k.a. rINST) -> PC adjustment in 16-bit words
9112 common_backwardBranch:
9114 call common_periodicChecks # Note: expects rPC to be preserved
9115 ADVANCE_PC_INDEXED rINST
9122 * Common code for method invocation with range.
9125 * eax = Method* methodToCall
9126 * rINSTw trashed, must reload
9129 common_invokeMethodRange:
9133 * prepare to copy args to "outs" area of current frame
9136 movzbl 1(rPC),rINST # rINST<- AA
9137 movzwl 4(rPC), %ecx # %ecx<- CCCC
9138 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea
9140 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
9141 jz .LinvokeArgsDone # no args; jump to args done
9145 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
9146 * (very few methods have > 10 args; could unroll for common cases)
9149 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx
9150 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC
9151 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
9152 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs
9153 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
9155 movl (%ecx), %ebx # %ebx<- vCCCC
9156 lea 4(%ecx), %ecx # %ecx<- &vCCCC++
9157 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET--
9158 movl %ebx, (%edx) # *outs<- vCCCC
9159 lea 4(%edx), %edx # outs++
9160 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero
9161 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx
9162 jmp .LinvokeArgsDone # continue
9165 * %eax is "Method* methodToCall", the method we're trying to call
9166 * prepare to copy args to "outs" area of current frame
9169 common_invokeMethodNoRange:
9171 movzbl 1(rPC),rINST # rINST<- BA
9172 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
9173 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B
9174 je .LinvokeArgsDone # no args; jump to args done
9175 movzwl 4(rPC), %ecx # %ecx<- GFED
9176 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea
9179 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
9183 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2
9184 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED
9185 jl 1f # handle 1 arg
9186 je 2f # handle 2 args
9187 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4
9188 jl 3f # handle 3 args
9189 je 4f # handle 4 args
9191 andl $15, rINST # rINSTw<- A
9192 lea -4(%edx), %edx # %edx<- update &outs; &outs--
9193 movl (rFP, rINST, 4), %ecx # %ecx<- vA
9194 movl %ecx, (%edx) # *outs<- vA
9195 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
9197 shr $12, %ecx # %ecx<- G
9198 lea -4(%edx), %edx # %edx<- update &outs; &outs--
9199 movl (rFP, %ecx, 4), %ecx # %ecx<- vG
9200 movl %ecx, (%edx) # *outs<- vG
9201 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
9203 and $0x0f00, %ecx # %ecx<- 0F00
9204 shr $8, %ecx # %ecx<- F
9205 lea -4(%edx), %edx # %edx<- update &outs; &outs--
9206 movl (rFP, %ecx, 4), %ecx # %ecx<- vF
9207 movl %ecx, (%edx) # *outs<- vF
9208 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
9210 and $0x00f0, %ecx # %ecx<- 00E0
9211 shr $4, %ecx # %ecx<- E
9212 lea -4(%edx), %edx # %edx<- update &outs; &outs--
9213 movl (rFP, %ecx, 4), %ecx # %ecx<- vE
9214 movl %ecx, (%edx) # *outs<- vE
9215 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
9217 and $0x000f, %ecx # %ecx<- 000D
9218 movl (rFP, %ecx, 4), %ecx # %ecx<- vD
9219 movl %ecx, -4(%edx) # *--outs<- vD
9223 * %eax is "Method* methodToCall", the method we're trying to call
9224 * find space for the new stack frame, check for overflow
9228 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
9229 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
9230 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall
9231 shl $2, %edx # %edx<- update offset
9232 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea
9233 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize)
9234 movl rGLUE,%edx # %edx<- pMterpGlue
9235 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs
9236 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
9237 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
9238 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd
9239 shl $2, %ecx # %ecx<- update offset for outsSize
9240 movl %eax, %edx # %edx<- newSaveArea
9241 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize)
9242 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom
9243 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall
9244 jl .LstackOverflow # handle frame overflow
9247 * set up newSaveArea
9251 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea
9252 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
9254 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
9255 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
9256 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
9257 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
9258 jne .LinvokeNative # handle native call
9261 * Update "glue" values for the new method
9262 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
9265 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz
9266 movl rGLUE,%ecx # %ecx<- pMterpGlue
9267 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
9268 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall
9269 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
9270 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
9271 movl offGlue_self(%ecx), %eax # %eax<- glue->self
9272 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
9273 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
9275 GOTO_NEXT # jump to methodToCall->insns
9278 * Prep for the native call
9279 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
9283 movl rGLUE,%ecx # %ecx<- pMterpGlue
9284 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
9285 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self
9286 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
9287 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
9288 movl %edx, OUT_ARG4(%esp) # save newSaveArea
9289 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
9290 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP
9291 movl %ecx, OUT_ARG3(%esp) # save glue->self
9292 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self
9293 movl rGLUE,%ecx # %ecx<- pMterpGlue
9294 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall
9295 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval
9296 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue
9297 push %edx # push parameter newFP
9299 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
9301 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea
9302 movl OUT_ARG3(%esp), %eax # %eax<- glue->self
9303 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
9304 cmp $0, offThread_exception(%eax) # check for exception
9305 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
9306 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
9307 jne common_exceptionThrown # handle exception
9308 FETCH_INST_OPCODE 3 %edx
9310 GOTO_NEXT_R %edx # jump to next instruction
9312 .LstackOverflow: # eax=methodToCall
9313 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
9314 movl rGLUE,%eax # %eax<- pMterpGlue
9315 movl offGlue_self(%eax), %eax # %eax<- glue->self
9316 movl %eax, OUT_ARG0(%esp) # push parameter self
9317 call dvmHandleStackOverflow # call: (Thread* self, Method* meth)
9318 jmp common_exceptionThrown # handle exception
9322 * Do we need the thread to be suspended or have debugger/profiling activity?
9325 * ebx -> PC adjustment in 16-bit words (must be preserved)
9326 * ecx -> GLUE pointer
9327 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint
9329 * Note: A call will normally kill %eax and %ecx. To
9330 * streamline the normal case, this routine will preserve
9331 * %ecx in addition to the normal caller save regs. The save/restore
9332 * is a bit ugly, but will happen in the relatively uncommon path.
9333 * TODO: Basic-block style Jit will need a hook here as well. Fold it into
9334 * the suspendCount check so we can get both in 1 shot.
9336 common_periodicChecks:
9337 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount
9342 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive
9343 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers
9344 testl %eax,%eax # debugger enabled?
9346 movzbl (%eax),%eax # get active count
9348 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers
9349 movl rGLUE,%ecx # restore rGLUE
9350 jne 3f # one or both active - switch interp
9355 /* Check for suspend */
9357 /* At this point, the return pointer to the caller of
9358 * common_periodicChecks is on the top of stack. We need to preserve
9360 * The outgoing profile is:
9361 * bool dvmCheckSuspendPending(Thread* self)
9362 * Because we reached here via a call, go ahead and build a new frame.
9364 EXPORT_PC # need for precise GC
9365 movl offGlue_self(%ecx),%eax # eax<- glue->self
9369 movl %eax,OUT_ARG0(%esp)
9370 call dvmCheckSuspendPending
9376 * Need to check to see if debugger or profiler flags got set
9377 * while we were suspended.
9381 /* Switch interpreters */
9382 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
9383 * "complete" the interpretation of backwards branches. In effect, we
9384 * are completing the interpretation of the branch instruction here,
9385 * and the new interpreter will resume interpretation at the branch
9386 * target. However, a switch request recognized during the handling
9387 * of a return from method instruction results in an immediate abort,
9388 * and the new interpreter will resume by re-interpreting the return
9392 leal (rPC,%ebx,2),rPC # adjust pc to show target
9393 movl rGLUE,%ecx # bail expect GLUE already loaded
9394 movl $1,rINST # set changeInterp to true
9399 * Common code for handling a return instruction
9401 common_returnFromMethod:
9403 /* Set entry mode in case we bail */
9404 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx)
9405 xorl rINST,rINST # zero offset in case we switch interps
9406 call common_periodicChecks # Note: expects %ecx to be preserved
9408 SAVEAREA_FROM_FP %eax # eax<- saveArea (old)
9409 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
9410 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST
9411 cmpl $0,rINST # break?
9412 je common_gotoBail # break frame, bail out completely
9414 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC
9415 movl offGlue_self(%ecx),%eax # eax<- self
9416 movl rINST,offGlue_method(%ecx) # glue->method = newSave->meethod
9417 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp
9418 movl offMethod_clazz(rINST),%eax # eax<- method->clazz
9419 FETCH_INST_OPCODE 3 %edx
9420 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
9422 movl %eax,offGlue_methodClassDex(%ecx)
9423 /* not bailing - restore entry mode to default */
9424 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
9428 * Prepare to strip the current frame and "longjump" back to caller of
9432 * rINST holds changeInterp
9433 * ecx holds glue pointer
9435 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
9438 movl rPC,offGlue_pc(%ecx) # export state to glue
9439 movl rFP,offGlue_fp(%ecx)
9440 movl %ecx,OUT_ARG0(%esp) # glue in arg0
9441 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1
9442 call dvmMterpStdBail # bail out....
9446 * After returning from a "glued" function, pull out the updated values
9447 * and start executing at the next instruction.
9449 common_resumeAfterGlueCall:
9450 LOAD_PC_FP_FROM_GLUE
9455 * Integer divide or mod by zero
9457 common_errDivideByZero:
9459 movl $.LstrArithmeticException,%eax
9460 movl %eax,OUT_ARG0(%esp)
9461 movl $.LstrDivideByZero,%eax
9462 movl %eax,OUT_ARG1(%esp)
9463 call dvmThrowException
9464 jmp common_exceptionThrown
9467 * Attempt to allocate an array with a negative size.
9469 common_errNegativeArraySize:
9471 movl $.LstrNegativeArraySizeException,%eax
9472 movl %eax,OUT_ARG0(%esp)
9474 movl %eax,OUT_ARG1(%esp)
9475 call dvmThrowException
9476 jmp common_exceptionThrown
9479 * Attempt to allocate an array with a negative size.
9481 common_errNoSuchMethod:
9484 movl $.LstrNoSuchMethodError,%eax
9485 movl %eax,OUT_ARG0(%esp)
9487 movl %eax,OUT_ARG1(%esp)
9488 call dvmThrowException
9489 jmp common_exceptionThrown
9492 * Hit a null object when we weren't expecting one. Export the PC, throw a
9493 * NullPointerException and goto the exception processing code.
9495 common_errNullObject:
9497 movl $.LstrNullPointerException,%eax
9498 movl %eax,OUT_ARG0(%esp)
9500 movl %eax,OUT_ARG1(%esp)
9501 call dvmThrowException
9502 jmp common_exceptionThrown
9505 * Array index exceeds max.
9507 common_errArrayIndex:
9509 movl $.LstrArrayIndexException,%eax
9510 movl %eax,OUT_ARG0(%esp)
9512 movl %eax,OUT_ARG1(%esp)
9513 call dvmThrowException
9514 jmp common_exceptionThrown
9516 * Invalid array value.
9518 common_errArrayStore:
9520 movl $.LstrArrayStoreException,%eax
9521 movl %eax,OUT_ARG0(%esp)
9523 movl %eax,OUT_ARG1(%esp)
9524 call dvmThrowException
9525 jmp common_exceptionThrown
9528 * Somebody has thrown an exception. Handle it.
9530 * If the exception processing code returns to us (instead of falling
9531 * out of the interpreter), continue with whatever the next instruction
9532 * now happens to be.
9534 * This does not return.
9536 common_exceptionThrown:
9538 movl rPC,offGlue_pc(%ecx)
9539 movl rFP,offGlue_fp(%ecx)
9540 movl %ecx,OUT_ARG0(%esp)
9541 call dvmMterp_exceptionThrown
9542 jmp common_resumeAfterGlueCall
9545 movl $0xdeadf00d,%eax
9554 .LstrNullPointerException:
9555 .asciz "Ljava/lang/NullPointerException;"
9556 .LstrArithmeticException:
9557 .asciz "Ljava/lang/ArithmeticException;"
9559 .asciz "divide by zero"
9560 .LstrArrayIndexException:
9561 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
9562 .LstrArrayStoreException:
9563 .asciz "Ljava/lang/ArrayStoreException;"
9564 .LstrNegativeArraySizeException:
9565 .asciz "Ljava/lang/NegativeArraySizeException;"
9566 .LstrInstantiationError:
9567 .asciz "Ljava/lang/InstantiationError;"
9568 .LstrClassCastException:
9569 .asciz "Ljava/lang/ClassCastException;"
9570 .LstrNoSuchMethodError:
9571 .asciz "Ljava/lang/NoSuchMethodError;"
9572 .LstrInternalErrorA:
9573 .asciz "Ljava/lang/InternalError;"
9574 .LstrFilledNewArrayNotImplA:
9575 .asciz "filled-new-array only implemented for 'int'"