InterpAsm-x86.S revision 3e1bbffab14075a340ad0165c6ada6a43875a01f
1/*
2 * This file was generated automatically by gen-mterp.py for 'x86'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: x86/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
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
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
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.
22 */
23/*
24 * 32-bit x86 definitions and declarations.
25 */
26
27/*
28386 ABI general notes:
29
30Caller save set:
31   eax, edx, ecx, st(0)-st(7)
32Callee save set:
33   ebx, esi, edi, ebp
34Return regs:
35   32-bit in eax
36   64-bit in edx:eax (low-order 32 in eax)
37   fp on top of fp stack st(0)
38
39Parameters passed on stack, pushed right-to-left.  On entry to target, first
40parm is at 4(%esp).  Traditional entry code is:
41
42functEntry:
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
46
47Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
48
49Alignment of stack not strictly required, but should be for performance.  We'll
50align frame sizes to 16-byte multiples.
51
52If we're not doing variable stack allocation (alloca), the frame pointer can be
53eliminated and all arg references adjusted to be esp relative.
54
55Mterp notes:
56
57Some key interpreter variables will be assigned to registers.  Note that each
58will also have an associated spill location (mostly used useful for those assigned
59to callee save registers).
60
61  nick     reg   purpose
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
67
68Notes:
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
74
75*/
76
77#define rGLUE    (%ebp)
78#define rPC      %esi
79#define rFP      %edi
80#define rINST    %ebx
81#define rINSTw   %bx
82#define rINSTbh  %bh
83#define rINSTbl  %bl
84
85
86/* Frame diagram while executing dvmMterpStdRun, high to low addresses */
87#define IN_ARG0        ( 12)
88#define CALLER_RP      (  8)
89#define PREV_FP        (  4)
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
112
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
121
122/* save/restore the PC and/or FP from the glue struct */
123.macro SAVE_PC_FP_TO_GLUE _reg
124    movl     rGLUE,\_reg
125    movl     rPC,offGlue_pc(\_reg)
126    movl     rFP,offGlue_fp(\_reg)
127.endm
128
129.macro LOAD_PC_FP_FROM_GLUE
130    movl    rGLUE,rFP
131    movl    offGlue_pc(rFP),rPC
132    movl    offGlue_fp(rFP),rFP
133.endm
134
135/* The interpreter assumes a properly aligned stack on entry, and
136 * will preserve 16-byte alignment.
137 */
138
139/*
140 * "export" the PC to the interpreted stack frame, f/b/o future exception
141 * objects.  Must * be done *before* something calls dvmThrowException.
142 *
143 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
144 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
145 *
146 * It's okay to do this more than once.
147 */
148.macro EXPORT_PC
149    movl     rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)
150.endm
151
152/*
153 * Given a frame pointer, find the stack save area.
154 *
155 * In C this is "((StackSaveArea*)(_fp) -1)".
156 */
157.macro SAVEAREA_FROM_FP _reg
158    leal    -sizeofStackSaveArea(rFP), \_reg
159.endm
160
161/*
162 * Fetch the next instruction from rPC into rINSTw.  Does not advance rPC.
163 */
164.macro FETCH_INST
165    movzwl    (rPC),rINST
166.endm
167
168/*
169 * Fetch the opcode byte and zero-extend it into _reg.  Must be used
170 * in conjunction with GOTO_NEXT_R
171 */
172.macro FETCH_INST_R _reg
173    movzbl    (rPC),\_reg
174.endm
175
176/*
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
179 */
180.macro FETCH_INST_OPCODE _count _reg
181    movzbl  \_count*2(rPC),\_reg
182.endm
183
184/*
185 * Fetch the nth instruction word from rPC into rINSTw.  Does not advance
186 * rPC, and _count is in words
187 */
188.macro FETCH_INST_WORD _count
189    movzwl  \_count*2(rPC),rINST
190.endm
191
192/*
193 * Fetch instruction word indexed (used for branching).
194 * Index is in instruction word units.
195 */
196.macro FETCH_INST_INDEXED _reg
197    movzwl  (rPC,\_reg,2),rINST
198.endm
199
200/*
201 * Advance rPC by instruction count
202 */
203.macro ADVANCE_PC _count
204    leal  2*\_count(rPC),rPC
205.endm
206
207/*
208 * Advance rPC by branch offset in register
209 */
210.macro ADVANCE_PC_INDEXED _reg
211    leal (rPC,\_reg,2),rPC
212.endm
213
214.macro GOTO_NEXT
215     movzx   rINSTbl,%eax
216     movzbl  rINSTbh,rINST
217     jmp     *dvmAsmInstructionJmpTable(,%eax,4)
218.endm
219
220   /*
221    * Version of GOTO_NEXT that assumes _reg preloaded with opcode.
222    * Should be paired with FETCH_INST_R
223    */
224.macro GOTO_NEXT_R _reg
225     movzbl  1(rPC),rINST
226     jmp     *dvmAsmInstructionJmpTable(,\_reg,4)
227.endm
228
229/*
230 * Get/set the 32-bit value from a Dalvik register.
231 */
232.macro GET_VREG_R _reg _vreg
233    movl     (rFP,\_vreg,4),\_reg
234.endm
235
236.macro SET_VREG _reg _vreg
237    movl     \_reg,(rFP,\_vreg,4)
238.endm
239
240.macro GET_VREG_WORD _reg _vreg _offset
241    movl     4*(\_offset)(rFP,\_vreg,4),\_reg
242.endm
243
244.macro SET_VREG_WORD _reg _vreg _offset
245    movl     \_reg,4*(\_offset)(rFP,\_vreg,4)
246.endm
247
248#if 1
249
250#define rFinish %edx
251
252/* Macros for x86-atom handlers */
253    /*
254    * Get the 32-bit value from a dalvik register.
255    */
256
257    .macro      GET_VREG _vreg
258    movl        (rFP,\_vreg, 4), \_vreg
259    .endm
260
261   /*
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.
264    *
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
267    * EXPORT_PC())
268    */
269
270    .macro      FETCH_ADVANCE_INST _count
271    add         $(\_count*2), rPC
272    movzwl      (rPC), rINST
273    .endm
274
275   /*
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.
279    */
280
281    .macro      FETCH_ADVANCE_INST_RB _reg
282    addl        \_reg, rPC
283    movzwl      (rPC), rINST
284    .endm
285
286   /*
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
290    * fetches BBBB.
291    */
292
293    .macro      FETCH _count _reg
294    movzwl      (\_count*2)(rPC), \_reg
295    .endm
296
297   /*
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.
301    */
302
303    .macro      FETCHs _count _reg
304    movswl      (\_count*2)(rPC), \_reg
305    .endm
306
307   /*
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
311    * fetches BB.
312    */
313
314    .macro      FETCH_BB _count _reg
315    movzbl      (\_count*2)(rPC), \_reg
316    .endm
317
318    /*
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
322    * fetches CC.
323    */
324
325    .macro      FETCH_CC _count _reg
326    movzbl      (\_count*2 + 1)(rPC), \_reg
327    .endm
328
329   /*
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.
333    */
334
335    .macro      FETCH_CCs _count _reg
336    movsbl      (\_count*2 + 1)(rPC), \_reg
337    .endm
338
339
340   /*
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).
344    */
345
346    .macro      FETCH_B _reg  _count  _byte
347    movzbl      (\_count*2+\_byte)(rPC), \_reg
348    .endm
349
350   /*
351    * Put the instruction's opcode field into the specified register.
352    */
353
354    .macro      GET_INST_OPCODE _reg
355    movzbl      rINSTbl, \_reg
356    .endm
357
358   /*
359    * Begin executing the opcode in _reg.
360    */
361
362    .macro      GOTO_OPCODE _reg
363    shl         $6, \_reg
364    addl        $dvmAsmInstructionStart,\_reg
365    jmp         *\_reg
366    .endm
367
368
369
370   /*
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
373    * both macros.
374    */
375
376    .macro      FFETCH _rFinish
377    movzbl      (rPC), \_rFinish
378    .endm
379
380    .macro      FGETOP_JMPa _rFinish
381    movzbl      1(rPC), rINST
382    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
383    .endm
384
385   /*
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
388    * both macros.
389    */
390
391    .macro      FFETCH_ADV _count _rFinish
392    movzbl      (\_count*2)(rPC), \_rFinish
393    .endm
394
395    .macro      FGETOP_JMP _count _rFinish
396    movzbl      (\_count*2 + 1)(rPC), rINST
397    addl        $(\_count*2), rPC
398    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
399    .endm
400
401    .macro      FGETOP_JMP2 _rFinish
402    movzbl      1(rPC), rINST
403    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
404    .endm
405
406    .macro      OLD_JMP_1 _count _rFinish
407    movzbl      (\_count*2)(rPC), \_rFinish
408    shl         $6, \_rFinish
409    .endm
410
411    .macro      OLD_JMP_2 _rFinish
412    addl        $dvmAsmInstructionStart,\_rFinish
413    .endm
414
415    .macro      OLD_JMP_3 _count
416    addl        $(\_count*2), rPC
417    .endm
418
419    .macro      OLD_JMP_4 _rFinish
420    movzbl      1(rPC), rINST
421    jmp         *\_rFinish
422    .endm
423
424    .macro      OLD_JMP_A_1 _reg _rFinish
425    movzbl      (rPC, \_reg), \_rFinish
426    shl         $6, \_rFinish
427    .endm
428
429    .macro      OLD_JMP_A_2 _rFinish
430    addl        $dvmAsmInstructionStart,\_rFinish
431    .endm
432
433    .macro      OLD_JMP_A_3 _reg _rFinish
434    addl        \_reg, rPC
435    movzbl      1(rPC, \_reg), rINST
436    jmp         *\_rFinish
437    .endm
438
439   /*
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
442    * both macros.
443    */
444
445    .macro      FFETCH_ADV_RB _reg _rFinish
446    movzbl      (\_reg, rPC), \_rFinish
447    .endm
448
449    .macro      FGETOP_RB_JMP _reg _rFinish
450    movzbl      1(\_reg, rPC), rINST
451    addl        \_reg, rPC
452    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
453    .endm
454
455   /*
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.
461    */
462
463    .macro      FINISH_FETCH _rFinish
464    movzbl      (rPC), \_rFinish
465    movzbl      1(rPC), rINST
466    .endm
467
468
469   /*
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.
475    */
476
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
481    .endm
482
483   /*
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.
489    */
490
491    .macro      FINISH_FETCH_ADVANCE_RB _reg _rFinish
492    movzbl      (\_reg, rPC), \_rFinish
493    movzbl      1(\_reg, rPC), rINST
494    addl        \_reg, rPC
495    .endm
496
497   /*
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.
502    */
503
504    .macro      FINISH_JMP _rFinish
505    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
506    .endm
507
508   /*
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.
512    */
513
514    .macro      FINISH_A
515    movzbl      (rPC), rFinish
516    movzbl      1(rPC), rINST
517    jmp         *dvmAsmInstructionJmpTable(,rFinish, 4)
518    .endm
519
520   /*
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.
525    */
526
527    .macro      FINISH _count
528    movzbl      (\_count*2)(rPC), rFinish
529    movzbl      (\_count*2 + 1)(rPC), rINST
530    addl        $(\_count*2), rPC
531    jmp         *dvmAsmInstructionJmpTable(,rFinish, 4)
532    .endm
533
534   /*
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.
539    */
540
541    .macro      FINISH_RB _reg _rFinish
542    movzbl      (\_reg, rPC), \_rFinish
543    movzbl      1(\_reg, rPC), rINST
544    addl        \_reg, rPC
545    jmp         *dvmAsmInstructionJmpTable(,\_rFinish, 4)
546    .endm
547
548#define sReg0 LOCAL0_OFFSET(%ebp)
549#define sReg1 LOCAL1_OFFSET(%ebp)
550#define sReg2 LOCAL2_OFFSET(%ebp)
551#define sReg3 LOCAL3_OFFSET(%ebp)
552
553   /*
554    * Hard coded helper values.
555    */
556
557.balign 16
558
559.LdoubNeg:
560    .quad       0x8000000000000000
561
562.L64bits:
563    .quad       0xFFFFFFFFFFFFFFFF
564
565.LshiftMask2:
566    .quad       0x0000000000000000
567.LshiftMask:
568    .quad       0x000000000000003F
569
570.Lvalue64:
571    .quad       0x0000000000000040
572
573.LvaluePosInfLong:
574    .quad       0x7FFFFFFFFFFFFFFF
575
576.LvalueNegInfLong:
577    .quad       0x8000000000000000
578
579.LvalueNanLong:
580    .quad       0x0000000000000000
581
582.LintMin:
583.long   0x80000000
584
585.LintMax:
586.long   0x7FFFFFFF
587#endif
588
589
590/*
591 * This is a #include, not a %include, because we want the C pre-processor
592 * to expand the macros into assembler assignment statements.
593 */
594#include "../common/asm-constants.h"
595
596
597    .global dvmAsmInstructionStart
598    .type   dvmAsmInstructionStart, %function
599dvmAsmInstructionStart = .L_OP_NOP
600    .text
601
602/* ------------------------------ */
603    .balign 64
604.L_OP_NOP: /* 0x00 */
605/* File: x86/OP_NOP.S */
606    FETCH_INST_OPCODE 1 %edx
607    ADVANCE_PC 1
608    GOTO_NEXT_R %edx
609
610/* ------------------------------ */
611    .balign 64
612.L_OP_MOVE: /* 0x01 */
613/* File: x86/OP_MOVE.S */
614    /* for move, move-object, long-to-int */
615    /* op vA, vB */
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
621    ADVANCE_PC 1
622    SET_VREG %ecx %eax           # fp[A]<-fp[B]
623    GOTO_NEXT_R %edx
624
625/* ------------------------------ */
626    .balign 64
627.L_OP_MOVE_FROM16: /* 0x02 */
628/* File: x86/OP_MOVE_FROM16.S */
629    /* for: move/from16, move-object/from16 */
630    /* op vAA, vBBBB */
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
635    ADVANCE_PC 2
636    SET_VREG %ecx %eax                # fp[AA]<- ecx]
637    GOTO_NEXT_R %edx
638
639/* ------------------------------ */
640    .balign 64
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
647    GET_VREG_R  %ecx %ecx
648    FETCH_INST_OPCODE 3 %edx
649    ADVANCE_PC 3
650    SET_VREG  %ecx %eax
651    GOTO_NEXT_R %edx
652
653/* ------------------------------ */
654    .balign 64
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
666    ADVANCE_PC 1
667    SET_VREG_WORD %eax %ecx 0             # v[A+0]<- eax
668    GOTO_NEXT_R %edx
669
670/* ------------------------------ */
671    .balign 64
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
681    ADVANCE_PC 2
682    SET_VREG_WORD rINST %eax 0         # v[AAAA+0]<- rINST
683    SET_VREG_WORD %ecx %eax 1          # v[AAAA+1]<- eax
684    GOTO_NEXT_R %edx
685
686/* ------------------------------ */
687    .balign 64
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
698    ADVANCE_PC 3
699    SET_VREG_WORD %ecx %eax 1        # v[AAAA+1]<- ecx
700    GOTO_NEXT_R %edx
701
702/* ------------------------------ */
703    .balign 64
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 */
708    /* op vA, vB */
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
714    ADVANCE_PC 1
715    SET_VREG %ecx %eax           # fp[A]<-fp[B]
716    GOTO_NEXT_R %edx
717
718
719/* ------------------------------ */
720    .balign 64
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 */
725    /* op vAA, vBBBB */
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
730    ADVANCE_PC 2
731    SET_VREG %ecx %eax                # fp[AA]<- ecx]
732    GOTO_NEXT_R %edx
733
734
735/* ------------------------------ */
736    .balign 64
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
744    GET_VREG_R  %ecx %ecx
745    FETCH_INST_OPCODE 3 %edx
746    ADVANCE_PC 3
747    SET_VREG  %ecx %eax
748    GOTO_NEXT_R %edx
749
750
751/* ------------------------------ */
752    .balign 64
753.L_OP_MOVE_RESULT: /* 0x0a */
754/* File: x86/OP_MOVE_RESULT.S */
755    /* for: move-result, move-result-object */
756    /* op vAA */
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
761    ADVANCE_PC 1
762    SET_VREG  %eax %ecx                    # fp[AA]<- retval.l
763    GOTO_NEXT_R %edx
764
765/* ------------------------------ */
766    .balign 64
767.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
768/* File: x86/OP_MOVE_RESULT_WIDE.S */
769    /* move-result-wide vAA */
770    movl    rGLUE,%ecx
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
776    ADVANCE_PC 1
777    GOTO_NEXT_R %edx
778
779/* ------------------------------ */
780    .balign 64
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 */
785    /* op vAA */
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
790    ADVANCE_PC 1
791    SET_VREG  %eax %ecx                    # fp[AA]<- retval.l
792    GOTO_NEXT_R %edx
793
794
795/* ------------------------------ */
796    .balign 64
797.L_OP_MOVE_EXCEPTION: /* 0x0d */
798/* File: x86/OP_MOVE_EXCEPTION.S */
799    /* move-exception vAA */
800    movl    rGLUE,%ecx
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
805    ADVANCE_PC 1
806    movl    $0,offThread_exception(%ecx) # dvmClearException bypass
807    GOTO_NEXT_R %edx
808
809/* ------------------------------ */
810    .balign 64
811.L_OP_RETURN_VOID: /* 0x0e */
812/* File: x86/OP_RETURN_VOID.S */
813    jmp       common_returnFromMethod
814
815/* ------------------------------ */
816    .balign 64
817.L_OP_RETURN: /* 0x0f */
818/* File: x86/OP_RETURN.S */
819    /*
820     * Return a 32-bit value.  Copies the return value into the "glue"
821     * structure, then jumps to the return handler.
822     *
823     * for: return, return-object
824     */
825    /* op vAA */
826    movl    rGLUE,%ecx
827    GET_VREG_R %eax rINST               # eax<- vAA
828    movl    %eax,offGlue_retval(%ecx)   # retval.i <- AA
829    jmp     common_returnFromMethod
830
831/* ------------------------------ */
832    .balign 64
833.L_OP_RETURN_WIDE: /* 0x10 */
834/* File: x86/OP_RETURN_WIDE.S */
835    /*
836     * Return a 64-bit value.  Copies the return value into the "glue"
837     * structure, then jumps to the return handler.
838     */
839    /* return-wide vAA */
840    movl    rGLUE,%ecx
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
846
847/* ------------------------------ */
848    .balign 64
849.L_OP_RETURN_OBJECT: /* 0x11 */
850/* File: x86/OP_RETURN_OBJECT.S */
851/* File: x86/OP_RETURN.S */
852    /*
853     * Return a 32-bit value.  Copies the return value into the "glue"
854     * structure, then jumps to the return handler.
855     *
856     * for: return, return-object
857     */
858    /* op vAA */
859    movl    rGLUE,%ecx
860    GET_VREG_R %eax rINST               # eax<- vAA
861    movl    %eax,offGlue_retval(%ecx)   # retval.i <- AA
862    jmp     common_returnFromMethod
863
864
865/* ------------------------------ */
866    .balign 64
867.L_OP_CONST_4: /* 0x12 */
868/* File: x86/OP_CONST_4.S */
869    /* const/4 vA, #+B */
870    movsx   rINSTbl,%eax              # eax<-ssssssBx
871    movl    $0xf,%ecx
872    andl    %eax,%ecx                 # ecx<- A
873    FETCH_INST_OPCODE 1 %edx
874    ADVANCE_PC 1
875    sarl    $4,%eax
876    SET_VREG %eax %ecx
877    GOTO_NEXT_R %edx
878
879/* ------------------------------ */
880    .balign 64
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
887    ADVANCE_PC 2
888    SET_VREG %ecx %eax                 # vAA<- ssssBBBB
889    GOTO_NEXT_R %edx
890
891/* ------------------------------ */
892    .balign 64
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
899    ADVANCE_PC 3
900    SET_VREG %eax %ecx                # vAA<- eax
901    GOTO_NEXT_R %edx
902
903/* ------------------------------ */
904    .balign 64
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
911    ADVANCE_PC 2
912    sall       $16,%eax                  # eax<- BBBB0000
913    SET_VREG %eax %ecx                    # vAA<- eax
914    GOTO_NEXT_R %edx
915
916/* ------------------------------ */
917    .balign 64
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
926    ADVANCE_PC 2
927    GOTO_NEXT_R %edx
928
929/* ------------------------------ */
930    .balign 64
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
939    ADVANCE_PC 3
940    GOTO_NEXT_R %edx
941
942/* ------------------------------ */
943    .balign 64
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
951    movl      rINST,4(%ecx)
952    FETCH_INST_OPCODE 5 %edx
953    movl      %eax,(%ecx)
954    ADVANCE_PC 5
955    GOTO_NEXT_R %edx
956
957/* ------------------------------ */
958    .balign 64
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
964    ADVANCE_PC 2
965    sall       $16,%eax                  # eax<- BBBB0000
966    SET_VREG_WORD %eax rINST 1            # v[AA+1]<- eax
967    xorl       %eax,%eax
968    SET_VREG_WORD %eax rINST 0            # v[AA+0]<- eax
969    GOTO_NEXT_R %edx
970
971/* ------------------------------ */
972    .balign 64
973.L_OP_CONST_STRING: /* 0x1a */
974/* File: x86/OP_CONST_STRING.S */
975
976    /* const/string vAA, String@BBBB */
977    movl      rGLUE,%ecx
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]
982    movl      rINST,%ecx
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]
987    ADVANCE_PC 2
988    GOTO_NEXT_R %edx
989
990/* ------------------------------ */
991    .balign 64
992.L_OP_CONST_STRING_JUMBO: /* 0x1b */
993/* File: x86/OP_CONST_STRING_JUMBO.S */
994
995    /* const/string vAA, String@BBBBBBBB */
996    movl      rGLUE,%ecx
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]
1001    movl      rINST,%ecx
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]
1006    ADVANCE_PC 3
1007    GOTO_NEXT_R %edx
1008
1009/* ------------------------------ */
1010    .balign 64
1011.L_OP_CONST_CLASS: /* 0x1c */
1012/* File: x86/OP_CONST_CLASS.S */
1013
1014    /* const/class vAA, Class@BBBB */
1015    movl      rGLUE,%ecx
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]
1020    movl      rINST,%ecx
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]
1025    ADVANCE_PC 2
1026    GOTO_NEXT_R %edx
1027
1028/* ------------------------------ */
1029    .balign 64
1030.L_OP_MONITOR_ENTER: /* 0x1d */
1031/* File: x86/OP_MONITOR_ENTER.S */
1032    /*
1033     * Synchronize on an object.
1034     */
1035    /* monitor-enter vAA */
1036    movl    rGLUE,%ecx
1037    GET_VREG_R %eax rINST               # eax<- vAA
1038    movl    offGlue_self(%ecx),%ecx     # ecx<- glue->self
1039    FETCH_INST_WORD 1
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
1044
1045/* ------------------------------ */
1046    .balign 64
1047.L_OP_MONITOR_EXIT: /* 0x1e */
1048/* File: x86/OP_MONITOR_EXIT.S */
1049    /*
1050     * Unlock an object.
1051     *
1052     * Exceptions that occur when unlocking a monitor need to appear as
1053     * if they happened at the following instruction.  See the Dalvik
1054     * instruction spec.
1055     */
1056    /* monitor-exit vAA */
1057    GET_VREG_R %eax rINST
1058    movl    rGLUE,%ecx
1059    EXPORT_PC
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
1066
1067/* ------------------------------ */
1068    .balign 64
1069.L_OP_CHECK_CAST: /* 0x1f */
1070/* File: x86/OP_CHECK_CAST.S */
1071    /*
1072     * Check to see if a cast from one class to another is allowed.
1073     */
1074    /* check-cast vAA, class@BBBB */
1075    movl      rGLUE,%ecx
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
1091    ADVANCE_PC 2
1092    GOTO_NEXT_R %edx
1093
1094/* ------------------------------ */
1095    .balign 64
1096.L_OP_INSTANCE_OF: /* 0x20 */
1097/* File: x86/OP_INSTANCE_OF.S */
1098    /*
1099     * Check to see if an object reference is an instance of a class.
1100     *
1101     * Most common situation is a non-null object, being compared against
1102     * an already-resolved class.
1103     */
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)
1108    movl    rGLUE,%ecx
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
1122
1123/* ------------------------------ */
1124    .balign 64
1125.L_OP_ARRAY_LENGTH: /* 0x21 */
1126/* File: x86/OP_ARRAY_LENGTH.S */
1127    /*
1128     * Return the length of an array.
1129     */
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
1138   ADVANCE_PC 1
1139   SET_VREG %ecx %eax
1140   GOTO_NEXT_R %edx
1141
1142/* ------------------------------ */
1143    .balign 64
1144.L_OP_NEW_INSTANCE: /* 0x22 */
1145/* File: x86/OP_NEW_INSTANCE.S */
1146    /*
1147     * Create a new instance of a class.
1148     */
1149    /* new-instance vAA, class@BBBB */
1150    movl      rGLUE,%ecx
1151    movzwl    2(rPC),%eax               # eax<- BBBB
1152    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- pDvmDex
1153    movl      offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
1154    EXPORT_PC
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
1162
1163/* ------------------------------ */
1164    .balign 64
1165.L_OP_NEW_ARRAY: /* 0x23 */
1166/* File: x86/OP_NEW_ARRAY.S */
1167    /*
1168     * Allocate an array of objects, specified with the array class
1169     * and a count.
1170     *
1171     * The verifier guarantees that this is an array class, so we don't
1172     * check for it here.
1173     */
1174    /* new-array vA, vB, class@CCCC */
1175    movl    rGLUE,%ecx
1176    EXPORT_PC
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
1181    movzbl  rINSTbl,%eax
1182    sarl    $4,%eax                          # eax<- B
1183    GET_VREG_R %eax %eax                      # eax<- vB (array length)
1184    andb    $0xf,rINSTbl                     # rINST<- A
1185    testl   %eax,%eax
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
1190
1191/* ------------------------------ */
1192    .balign 64
1193.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1194/* File: x86/OP_FILLED_NEW_ARRAY.S */
1195    /*
1196     * Create a new array with elements filled from registers.
1197     *
1198     * for: filled-new-array, filled-new-array/range
1199     */
1200    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1201    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1202    movl    rGLUE,%eax
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
1207    EXPORT_PC
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
1211    movl    rGLUE,%eax
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
1216
1217/* ------------------------------ */
1218    .balign 64
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 */
1222    /*
1223     * Create a new array with elements filled from registers.
1224     *
1225     * for: filled-new-array, filled-new-array/range
1226     */
1227    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1228    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1229    movl    rGLUE,%eax
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
1234    EXPORT_PC
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
1238    movl    rGLUE,%eax
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
1243
1244
1245/* ------------------------------ */
1246    .balign 64
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
1253    EXPORT_PC
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
1260    ADVANCE_PC 3
1261    GOTO_NEXT_R %edx
1262
1263/* ------------------------------ */
1264    .balign 64
1265.L_OP_THROW: /* 0x27 */
1266/* File: x86/OP_THROW.S */
1267    /*
1268     * Throw an exception object in the current thread.
1269     */
1270    /* throw vAA */
1271    movl     rGLUE,%ecx
1272    EXPORT_PC
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
1279
1280/* ------------------------------ */
1281    .balign 64
1282.L_OP_GOTO: /* 0x28 */
1283/* File: x86/OP_GOTO.S */
1284    /*
1285     * Unconditional branch, 8-bit offset.
1286     *
1287     * The branch distance is a signed code-unit offset, which we need to
1288     * double to get a byte offset.
1289     */
1290    /* goto +AA */
1291    movsbl  rINSTbl,rINST         # ebx<- ssssssAA
1292    testl   rINST,rINST           # test for <0
1293    js      common_backwardBranch
1294    movl    rINST,%eax
1295    FETCH_INST_INDEXED %eax
1296    ADVANCE_PC_INDEXED %eax
1297    GOTO_NEXT
1298
1299/* ------------------------------ */
1300    .balign 64
1301.L_OP_GOTO_16: /* 0x29 */
1302/* File: x86/OP_GOTO_16.S */
1303    /*
1304     * Unconditional branch, 16-bit offset.
1305     *
1306     * The branch distance is a signed code-unit offset
1307     */
1308    /* goto/16 +AAAA */
1309    movswl  2(rPC),rINST           # rINST<- ssssAAAA
1310    testl   rINST,rINST            # test for <0
1311    js      common_backwardBranch
1312    movl    rINST,%eax
1313    FETCH_INST_INDEXED %eax
1314    ADVANCE_PC_INDEXED %eax
1315    GOTO_NEXT
1316
1317/* ------------------------------ */
1318    .balign 64
1319.L_OP_GOTO_32: /* 0x2a */
1320/* File: x86/OP_GOTO_32.S */
1321    /*
1322     * Unconditional branch, 32-bit offset.
1323     *
1324     * The branch distance is a signed code-unit offset.
1325     *
1326     * Unlike most opcodes, this one is allowed to branch to itself, so
1327     * our "backward branch" test must be "<=0" instead of "<0".
1328     */
1329    /* goto/32 AAAAAAAA */
1330    movl    2(rPC),rINST           # rINST<- AAAAAAAA
1331    cmpl    $0,rINST              # test for <= 0
1332    jle     common_backwardBranch
1333    movl    rINST,%eax
1334    FETCH_INST_INDEXED %eax
1335    ADVANCE_PC_INDEXED %eax
1336    GOTO_NEXT
1337
1338/* ------------------------------ */
1339    .balign 64
1340.L_OP_PACKED_SWITCH: /* 0x2b */
1341/* File: x86/OP_PACKED_SWITCH.S */
1342    /*
1343     * Handle a packed-switch or sparse-switch instruction.  In both cases
1344     * we decode it and hand it off to a helper function.
1345     *
1346     * We don't really expect backward branches in a switch statement, but
1347     * they're perfectly legal, so we check for them here.
1348     *
1349     * for: packed-switch, sparse-switch
1350     */
1351    /* op vAA, +BBBB */
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
1358    testl   %eax,%eax
1359    movl    %eax,rINST            # set up word offset
1360    jle     common_backwardBranch # check on special actions
1361    ADVANCE_PC_INDEXED rINST
1362    FETCH_INST
1363    GOTO_NEXT
1364
1365/* ------------------------------ */
1366    .balign 64
1367.L_OP_SPARSE_SWITCH: /* 0x2c */
1368/* File: x86/OP_SPARSE_SWITCH.S */
1369/* File: x86/OP_PACKED_SWITCH.S */
1370    /*
1371     * Handle a packed-switch or sparse-switch instruction.  In both cases
1372     * we decode it and hand it off to a helper function.
1373     *
1374     * We don't really expect backward branches in a switch statement, but
1375     * they're perfectly legal, so we check for them here.
1376     *
1377     * for: packed-switch, sparse-switch
1378     */
1379    /* op vAA, +BBBB */
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
1386    testl   %eax,%eax
1387    movl    %eax,rINST            # set up word offset
1388    jle     common_backwardBranch # check on special actions
1389    ADVANCE_PC_INDEXED rINST
1390    FETCH_INST
1391    GOTO_NEXT
1392
1393
1394/* ------------------------------ */
1395    .balign 64
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
1402    .if 0
1403    fldl     (rFP,%eax,4)
1404    fldl     (rFP,%ecx,4)
1405    .else
1406    flds     (rFP,%eax,4)
1407    flds     (rFP,%ecx,4)
1408    .endif
1409    xorl     %ecx,%ecx
1410    fucompp     # z if equal, p set if NaN, c set if st0 < st1
1411    fnstsw   %ax
1412    sahf
1413    movl      rINST,%eax
1414    FETCH_INST_OPCODE 2 %edx
1415    jp       .LOP_CMPL_FLOAT_isNaN
1416    je       .LOP_CMPL_FLOAT_finish
1417    sbbl     %ecx,%ecx
1418    jb       .LOP_CMPL_FLOAT_finish
1419    incl     %ecx
1420.LOP_CMPL_FLOAT_finish:
1421    SET_VREG %ecx %eax
1422    ADVANCE_PC 2
1423    GOTO_NEXT_R %edx
1424
1425
1426/* ------------------------------ */
1427    .balign 64
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
1434    .if 0
1435    fldl     (rFP,%eax,4)
1436    fldl     (rFP,%ecx,4)
1437    .else
1438    flds     (rFP,%eax,4)
1439    flds     (rFP,%ecx,4)
1440    .endif
1441    xorl     %ecx,%ecx
1442    fucompp     # z if equal, p set if NaN, c set if st0 < st1
1443    fnstsw   %ax
1444    sahf
1445    movl      rINST,%eax
1446    FETCH_INST_OPCODE 2 %edx
1447    jp       .LOP_CMPG_FLOAT_isNaN
1448    je       .LOP_CMPG_FLOAT_finish
1449    sbbl     %ecx,%ecx
1450    jb       .LOP_CMPG_FLOAT_finish
1451    incl     %ecx
1452.LOP_CMPG_FLOAT_finish:
1453    SET_VREG %ecx %eax
1454    ADVANCE_PC 2
1455    GOTO_NEXT_R %edx
1456
1457
1458/* ------------------------------ */
1459    .balign 64
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
1466    .if 1
1467    fldl     (rFP,%eax,4)
1468    fldl     (rFP,%ecx,4)
1469    .else
1470    flds     (rFP,%eax,4)
1471    flds     (rFP,%ecx,4)
1472    .endif
1473    xorl     %ecx,%ecx
1474    fucompp     # z if equal, p set if NaN, c set if st0 < st1
1475    fnstsw   %ax
1476    sahf
1477    movl      rINST,%eax
1478    FETCH_INST_OPCODE 2 %edx
1479    jp       .LOP_CMPL_DOUBLE_isNaN
1480    je       .LOP_CMPL_DOUBLE_finish
1481    sbbl     %ecx,%ecx
1482    jb       .LOP_CMPL_DOUBLE_finish
1483    incl     %ecx
1484.LOP_CMPL_DOUBLE_finish:
1485    SET_VREG %ecx %eax
1486    ADVANCE_PC 2
1487    GOTO_NEXT_R %edx
1488
1489
1490/* ------------------------------ */
1491    .balign 64
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
1497    .if 1
1498    fldl     (rFP,%eax,4)
1499    fldl     (rFP,%ecx,4)
1500    .else
1501    flds     (rFP,%eax,4)
1502    flds     (rFP,%ecx,4)
1503    .endif
1504    xorl     %ecx,%ecx
1505    fucompp     # z if equal, p set if NaN, c set if st0 < st1
1506    fnstsw   %ax
1507    sahf
1508    movl      rINST,%eax
1509    FETCH_INST_OPCODE 2 %edx
1510    jp       .LOP_CMPG_DOUBLE_isNaN
1511    je       .LOP_CMPG_DOUBLE_finish
1512    sbbl     %ecx,%ecx
1513    jb       .LOP_CMPG_DOUBLE_finish
1514    incl     %ecx
1515.LOP_CMPG_DOUBLE_finish:
1516    SET_VREG %ecx %eax
1517    ADVANCE_PC 2
1518    GOTO_NEXT_R %edx
1519
1520/* ------------------------------ */
1521    .balign 64
1522.L_OP_CMP_LONG: /* 0x31 */
1523/* File: x86/OP_CMP_LONG.S */
1524    /*
1525     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1526     * register based on the results of the comparison.
1527     */
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
1540
1541/* ------------------------------ */
1542    .balign 64
1543.L_OP_IF_EQ: /* 0x32 */
1544/* File: x86/OP_IF_EQ.S */
1545/* File: x86/bincmp.S */
1546    /*
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".
1550     *
1551     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1552     */
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
1561    jne   1f
1562    testl    rINST,rINST
1563    js       common_backwardBranch
1564    movl     rINST,%eax
15651:
1566    FETCH_INST_INDEXED %eax
1567    ADVANCE_PC_INDEXED %eax
1568    GOTO_NEXT
1569
1570
1571/* ------------------------------ */
1572    .balign 64
1573.L_OP_IF_NE: /* 0x33 */
1574/* File: x86/OP_IF_NE.S */
1575/* File: x86/bincmp.S */
1576    /*
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".
1580     *
1581     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1582     */
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
1591    je   1f
1592    testl    rINST,rINST
1593    js       common_backwardBranch
1594    movl     rINST,%eax
15951:
1596    FETCH_INST_INDEXED %eax
1597    ADVANCE_PC_INDEXED %eax
1598    GOTO_NEXT
1599
1600
1601/* ------------------------------ */
1602    .balign 64
1603.L_OP_IF_LT: /* 0x34 */
1604/* File: x86/OP_IF_LT.S */
1605/* File: x86/bincmp.S */
1606    /*
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".
1610     *
1611     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1612     */
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
1621    jge   1f
1622    testl    rINST,rINST
1623    js       common_backwardBranch
1624    movl     rINST,%eax
16251:
1626    FETCH_INST_INDEXED %eax
1627    ADVANCE_PC_INDEXED %eax
1628    GOTO_NEXT
1629
1630
1631/* ------------------------------ */
1632    .balign 64
1633.L_OP_IF_GE: /* 0x35 */
1634/* File: x86/OP_IF_GE.S */
1635/* File: x86/bincmp.S */
1636    /*
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".
1640     *
1641     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1642     */
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
1651    jl   1f
1652    testl    rINST,rINST
1653    js       common_backwardBranch
1654    movl     rINST,%eax
16551:
1656    FETCH_INST_INDEXED %eax
1657    ADVANCE_PC_INDEXED %eax
1658    GOTO_NEXT
1659
1660
1661/* ------------------------------ */
1662    .balign 64
1663.L_OP_IF_GT: /* 0x36 */
1664/* File: x86/OP_IF_GT.S */
1665/* File: x86/bincmp.S */
1666    /*
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".
1670     *
1671     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1672     */
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
1681    jle   1f
1682    testl    rINST,rINST
1683    js       common_backwardBranch
1684    movl     rINST,%eax
16851:
1686    FETCH_INST_INDEXED %eax
1687    ADVANCE_PC_INDEXED %eax
1688    GOTO_NEXT
1689
1690
1691/* ------------------------------ */
1692    .balign 64
1693.L_OP_IF_LE: /* 0x37 */
1694/* File: x86/OP_IF_LE.S */
1695/* File: x86/bincmp.S */
1696    /*
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".
1700     *
1701     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1702     */
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
1711    jg   1f
1712    testl    rINST,rINST
1713    js       common_backwardBranch
1714    movl     rINST,%eax
17151:
1716    FETCH_INST_INDEXED %eax
1717    ADVANCE_PC_INDEXED %eax
1718    GOTO_NEXT
1719
1720
1721/* ------------------------------ */
1722    .balign 64
1723.L_OP_IF_EQZ: /* 0x38 */
1724/* File: x86/OP_IF_EQZ.S */
1725/* File: x86/zcmp.S */
1726    /*
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".
1730     *
1731     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1732     */
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
1737    jne   1f
1738    testl    rINST,rINST
1739    js       common_backwardBranch
1740    movl     rINST,%eax
17411:
1742    FETCH_INST_INDEXED %eax
1743    ADVANCE_PC_INDEXED %eax
1744    GOTO_NEXT
1745
1746
1747/* ------------------------------ */
1748    .balign 64
1749.L_OP_IF_NEZ: /* 0x39 */
1750/* File: x86/OP_IF_NEZ.S */
1751/* File: x86/zcmp.S */
1752    /*
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".
1756     *
1757     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1758     */
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
1763    je   1f
1764    testl    rINST,rINST
1765    js       common_backwardBranch
1766    movl     rINST,%eax
17671:
1768    FETCH_INST_INDEXED %eax
1769    ADVANCE_PC_INDEXED %eax
1770    GOTO_NEXT
1771
1772
1773/* ------------------------------ */
1774    .balign 64
1775.L_OP_IF_LTZ: /* 0x3a */
1776/* File: x86/OP_IF_LTZ.S */
1777/* File: x86/zcmp.S */
1778    /*
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".
1782     *
1783     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1784     */
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
1789    jge   1f
1790    testl    rINST,rINST
1791    js       common_backwardBranch
1792    movl     rINST,%eax
17931:
1794    FETCH_INST_INDEXED %eax
1795    ADVANCE_PC_INDEXED %eax
1796    GOTO_NEXT
1797
1798
1799/* ------------------------------ */
1800    .balign 64
1801.L_OP_IF_GEZ: /* 0x3b */
1802/* File: x86/OP_IF_GEZ.S */
1803/* File: x86/zcmp.S */
1804    /*
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".
1808     *
1809     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1810     */
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
1815    jl   1f
1816    testl    rINST,rINST
1817    js       common_backwardBranch
1818    movl     rINST,%eax
18191:
1820    FETCH_INST_INDEXED %eax
1821    ADVANCE_PC_INDEXED %eax
1822    GOTO_NEXT
1823
1824
1825/* ------------------------------ */
1826    .balign 64
1827.L_OP_IF_GTZ: /* 0x3c */
1828/* File: x86/OP_IF_GTZ.S */
1829/* File: x86/zcmp.S */
1830    /*
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".
1834     *
1835     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1836     */
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
1841    jle   1f
1842    testl    rINST,rINST
1843    js       common_backwardBranch
1844    movl     rINST,%eax
18451:
1846    FETCH_INST_INDEXED %eax
1847    ADVANCE_PC_INDEXED %eax
1848    GOTO_NEXT
1849
1850
1851/* ------------------------------ */
1852    .balign 64
1853.L_OP_IF_LEZ: /* 0x3d */
1854/* File: x86/OP_IF_LEZ.S */
1855/* File: x86/zcmp.S */
1856    /*
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".
1860     *
1861     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1862     */
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
1867    jg   1f
1868    testl    rINST,rINST
1869    js       common_backwardBranch
1870    movl     rINST,%eax
18711:
1872    FETCH_INST_INDEXED %eax
1873    ADVANCE_PC_INDEXED %eax
1874    GOTO_NEXT
1875
1876
1877/* ------------------------------ */
1878    .balign 64
1879.L_OP_UNUSED_3E: /* 0x3e */
1880/* File: x86/OP_UNUSED_3E.S */
1881/* File: x86/unused.S */
1882    jmp     common_abort
1883
1884
1885/* ------------------------------ */
1886    .balign 64
1887.L_OP_UNUSED_3F: /* 0x3f */
1888/* File: x86/OP_UNUSED_3F.S */
1889/* File: x86/unused.S */
1890    jmp     common_abort
1891
1892
1893/* ------------------------------ */
1894    .balign 64
1895.L_OP_UNUSED_40: /* 0x40 */
1896/* File: x86/OP_UNUSED_40.S */
1897/* File: x86/unused.S */
1898    jmp     common_abort
1899
1900
1901/* ------------------------------ */
1902    .balign 64
1903.L_OP_UNUSED_41: /* 0x41 */
1904/* File: x86/OP_UNUSED_41.S */
1905/* File: x86/unused.S */
1906    jmp     common_abort
1907
1908
1909/* ------------------------------ */
1910    .balign 64
1911.L_OP_UNUSED_42: /* 0x42 */
1912/* File: x86/OP_UNUSED_42.S */
1913/* File: x86/unused.S */
1914    jmp     common_abort
1915
1916
1917/* ------------------------------ */
1918    .balign 64
1919.L_OP_UNUSED_43: /* 0x43 */
1920/* File: x86/OP_UNUSED_43.S */
1921/* File: x86/unused.S */
1922    jmp     common_abort
1923
1924
1925/* ------------------------------ */
1926    .balign 64
1927.L_OP_AGET: /* 0x44 */
1928/* File: x86/OP_AGET.S */
1929    /*
1930     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1931     *
1932     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1933     */
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.  Expects
1943                                        #    arrayObj in eax
1944                                        #    index in ecx
1945    movl     offArrayObject_contents(%eax,%ecx,4),%eax
1946.LOP_AGET_finish:
1947    FETCH_INST_OPCODE 2 %edx
1948    SET_VREG  %eax rINST
1949    ADVANCE_PC 2
1950    GOTO_NEXT_R %edx
1951
1952/* ------------------------------ */
1953    .balign 64
1954.L_OP_AGET_WIDE: /* 0x45 */
1955/* File: x86/OP_AGET_WIDE.S */
1956    /*
1957     * Array get, 64 bits.  vAA <- vBB[vCC].
1958     *
1959     */
1960    /* op vAA, vBB, vCC */
1961    movzbl    2(rPC),%eax               # eax<- BB
1962    movzbl    3(rPC),%ecx               # ecx<- CC
1963    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
1964    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
1965    testl     %eax,%eax                 # null array object?
1966    je        common_errNullObject      # bail if so
1967    cmpl      offArrayObject_length(%eax),%ecx
1968    jb        .LOP_AGET_WIDE_finish        # index < length, OK
1969    jmp       common_errArrayIndex      # index >= length, bail.  Expects
1970                                        #    arrayObj in eax
1971                                        #    index in ecx
1972
1973/* ------------------------------ */
1974    .balign 64
1975.L_OP_AGET_OBJECT: /* 0x46 */
1976/* File: x86/OP_AGET_OBJECT.S */
1977/* File: x86/OP_AGET.S */
1978    /*
1979     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1980     *
1981     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1982     */
1983    /* op vAA, vBB, vCC */
1984    movzbl    2(rPC),%eax               # eax<- BB
1985    movzbl    3(rPC),%ecx               # ecx<- CC
1986    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
1987    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
1988    testl     %eax,%eax                 # null array object?
1989    je        common_errNullObject      # bail if so
1990    cmpl      offArrayObject_length(%eax),%ecx
1991    jae       common_errArrayIndex      # index >= length, bail.  Expects
1992                                        #    arrayObj in eax
1993                                        #    index in ecx
1994    movl     offArrayObject_contents(%eax,%ecx,4),%eax
1995.LOP_AGET_OBJECT_finish:
1996    FETCH_INST_OPCODE 2 %edx
1997    SET_VREG  %eax rINST
1998    ADVANCE_PC 2
1999    GOTO_NEXT_R %edx
2000
2001
2002/* ------------------------------ */
2003    .balign 64
2004.L_OP_AGET_BOOLEAN: /* 0x47 */
2005/* File: x86/OP_AGET_BOOLEAN.S */
2006/* File: x86/OP_AGET.S */
2007    /*
2008     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2009     *
2010     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2011     */
2012    /* op vAA, vBB, vCC */
2013    movzbl    2(rPC),%eax               # eax<- BB
2014    movzbl    3(rPC),%ecx               # ecx<- CC
2015    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2016    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2017    testl     %eax,%eax                 # null array object?
2018    je        common_errNullObject      # bail if so
2019    cmpl      offArrayObject_length(%eax),%ecx
2020    jae       common_errArrayIndex      # index >= length, bail.  Expects
2021                                        #    arrayObj in eax
2022                                        #    index in ecx
2023    movzbl     offArrayObject_contents(%eax,%ecx,1),%eax
2024.LOP_AGET_BOOLEAN_finish:
2025    FETCH_INST_OPCODE 2 %edx
2026    SET_VREG  %eax rINST
2027    ADVANCE_PC 2
2028    GOTO_NEXT_R %edx
2029
2030
2031/* ------------------------------ */
2032    .balign 64
2033.L_OP_AGET_BYTE: /* 0x48 */
2034/* File: x86/OP_AGET_BYTE.S */
2035/* File: x86/OP_AGET.S */
2036    /*
2037     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2038     *
2039     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2040     */
2041    /* op vAA, vBB, vCC */
2042    movzbl    2(rPC),%eax               # eax<- BB
2043    movzbl    3(rPC),%ecx               # ecx<- CC
2044    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2045    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2046    testl     %eax,%eax                 # null array object?
2047    je        common_errNullObject      # bail if so
2048    cmpl      offArrayObject_length(%eax),%ecx
2049    jae       common_errArrayIndex      # index >= length, bail.  Expects
2050                                        #    arrayObj in eax
2051                                        #    index in ecx
2052    movsbl     offArrayObject_contents(%eax,%ecx,1),%eax
2053.LOP_AGET_BYTE_finish:
2054    FETCH_INST_OPCODE 2 %edx
2055    SET_VREG  %eax rINST
2056    ADVANCE_PC 2
2057    GOTO_NEXT_R %edx
2058
2059
2060/* ------------------------------ */
2061    .balign 64
2062.L_OP_AGET_CHAR: /* 0x49 */
2063/* File: x86/OP_AGET_CHAR.S */
2064/* File: x86/OP_AGET.S */
2065    /*
2066     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2067     *
2068     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2069     */
2070    /* op vAA, vBB, vCC */
2071    movzbl    2(rPC),%eax               # eax<- BB
2072    movzbl    3(rPC),%ecx               # ecx<- CC
2073    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2074    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2075    testl     %eax,%eax                 # null array object?
2076    je        common_errNullObject      # bail if so
2077    cmpl      offArrayObject_length(%eax),%ecx
2078    jae       common_errArrayIndex      # index >= length, bail.  Expects
2079                                        #    arrayObj in eax
2080                                        #    index in ecx
2081    movzwl     offArrayObject_contents(%eax,%ecx,2),%eax
2082.LOP_AGET_CHAR_finish:
2083    FETCH_INST_OPCODE 2 %edx
2084    SET_VREG  %eax rINST
2085    ADVANCE_PC 2
2086    GOTO_NEXT_R %edx
2087
2088
2089/* ------------------------------ */
2090    .balign 64
2091.L_OP_AGET_SHORT: /* 0x4a */
2092/* File: x86/OP_AGET_SHORT.S */
2093/* File: x86/OP_AGET.S */
2094    /*
2095     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2096     *
2097     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2098     */
2099    /* op vAA, vBB, vCC */
2100    movzbl    2(rPC),%eax               # eax<- BB
2101    movzbl    3(rPC),%ecx               # ecx<- CC
2102    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2103    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2104    testl     %eax,%eax                 # null array object?
2105    je        common_errNullObject      # bail if so
2106    cmpl      offArrayObject_length(%eax),%ecx
2107    jae       common_errArrayIndex      # index >= length, bail.  Expects
2108                                        #    arrayObj in eax
2109                                        #    index in ecx
2110    movswl     offArrayObject_contents(%eax,%ecx,2),%eax
2111.LOP_AGET_SHORT_finish:
2112    FETCH_INST_OPCODE 2 %edx
2113    SET_VREG  %eax rINST
2114    ADVANCE_PC 2
2115    GOTO_NEXT_R %edx
2116
2117
2118/* ------------------------------ */
2119    .balign 64
2120.L_OP_APUT: /* 0x4b */
2121/* File: x86/OP_APUT.S */
2122    /*
2123     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2124     *
2125     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2126     */
2127    /* op vAA, vBB, vCC */
2128    movzbl    2(rPC),%eax               # eax<- BB
2129    movzbl    3(rPC),%ecx               # ecx<- CC
2130    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2131    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2132    testl     %eax,%eax                 # null array object?
2133    je        common_errNullObject      # bail if so
2134    cmpl      offArrayObject_length(%eax),%ecx
2135    jae       common_errArrayIndex      # index >= length, bail.  Expects:
2136                                        #   arrayObj in eax
2137                                        #   index in ecx
2138    leal      offArrayObject_contents(%eax,%ecx,4),%eax
2139.LOP_APUT_finish:
2140    GET_VREG_R  %ecx rINST
2141    FETCH_INST_OPCODE 2 %edx
2142    movl     %ecx,(%eax)
2143    ADVANCE_PC 2
2144    GOTO_NEXT_R %edx
2145
2146/* ------------------------------ */
2147    .balign 64
2148.L_OP_APUT_WIDE: /* 0x4c */
2149/* File: x86/OP_APUT_WIDE.S */
2150    /*
2151     * Array put, 64 bits.  vBB[vCC]<-vAA.
2152     *
2153     */
2154    /* op vAA, vBB, vCC */
2155    movzbl    2(rPC),%eax               # eax<- BB
2156    movzbl    3(rPC),%ecx               # ecx<- CC
2157    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2158    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2159    testl     %eax,%eax                 # null array object?
2160    je        common_errNullObject      # bail if so
2161    cmpl      offArrayObject_length(%eax),%ecx
2162    jb        .LOP_APUT_WIDE_finish        # index < length, OK
2163    jmp       common_errArrayIndex      # index >= length, bail.  Expects:
2164                                        #   arrayObj in eax
2165                                        #   index in ecx
2166
2167/* ------------------------------ */
2168    .balign 64
2169.L_OP_APUT_OBJECT: /* 0x4d */
2170/* File: x86/OP_APUT_OBJECT.S */
2171    /*
2172     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2173     *
2174     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2175     */
2176    /* op vAA, vBB, vCC */
2177    movzbl    2(rPC),%eax               # eax<- BB
2178    movzbl    3(rPC),%ecx               # ecx<- CC
2179    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2180    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2181    GET_VREG_R  rINST rINST             # rINST<- vAA
2182    testl     %eax,%eax                 # null array object?
2183    je        common_errNullObject      # bail if so
2184    cmpl      offArrayObject_length(%eax),%ecx
2185    jb        .LOP_APUT_OBJECT_continue
2186    jmp       common_errArrayIndex      # index >= length, bail.  Expects
2187                                        #    arrayObj in eax
2188                                        #    index in ecx
2189
2190/* ------------------------------ */
2191    .balign 64
2192.L_OP_APUT_BOOLEAN: /* 0x4e */
2193/* File: x86/OP_APUT_BOOLEAN.S */
2194/* File: x86/OP_APUT.S */
2195    /*
2196     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2197     *
2198     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2199     */
2200    /* op vAA, vBB, vCC */
2201    movzbl    2(rPC),%eax               # eax<- BB
2202    movzbl    3(rPC),%ecx               # ecx<- CC
2203    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2204    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2205    testl     %eax,%eax                 # null array object?
2206    je        common_errNullObject      # bail if so
2207    cmpl      offArrayObject_length(%eax),%ecx
2208    jae       common_errArrayIndex      # index >= length, bail.  Expects:
2209                                        #   arrayObj in eax
2210                                        #   index in ecx
2211    leal      offArrayObject_contents(%eax,%ecx,1),%eax
2212.LOP_APUT_BOOLEAN_finish:
2213    GET_VREG_R  %ecx rINST
2214    FETCH_INST_OPCODE 2 %edx
2215    movb     %cl,(%eax)
2216    ADVANCE_PC 2
2217    GOTO_NEXT_R %edx
2218
2219
2220/* ------------------------------ */
2221    .balign 64
2222.L_OP_APUT_BYTE: /* 0x4f */
2223/* File: x86/OP_APUT_BYTE.S */
2224/* File: x86/OP_APUT.S */
2225    /*
2226     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2227     *
2228     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2229     */
2230    /* op vAA, vBB, vCC */
2231    movzbl    2(rPC),%eax               # eax<- BB
2232    movzbl    3(rPC),%ecx               # ecx<- CC
2233    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2234    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2235    testl     %eax,%eax                 # null array object?
2236    je        common_errNullObject      # bail if so
2237    cmpl      offArrayObject_length(%eax),%ecx
2238    jae       common_errArrayIndex      # index >= length, bail.  Expects:
2239                                        #   arrayObj in eax
2240                                        #   index in ecx
2241    leal      offArrayObject_contents(%eax,%ecx,1),%eax
2242.LOP_APUT_BYTE_finish:
2243    GET_VREG_R  %ecx rINST
2244    FETCH_INST_OPCODE 2 %edx
2245    movb     %cl,(%eax)
2246    ADVANCE_PC 2
2247    GOTO_NEXT_R %edx
2248
2249
2250/* ------------------------------ */
2251    .balign 64
2252.L_OP_APUT_CHAR: /* 0x50 */
2253/* File: x86/OP_APUT_CHAR.S */
2254/* File: x86/OP_APUT.S */
2255    /*
2256     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2257     *
2258     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2259     */
2260    /* op vAA, vBB, vCC */
2261    movzbl    2(rPC),%eax               # eax<- BB
2262    movzbl    3(rPC),%ecx               # ecx<- CC
2263    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2264    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2265    testl     %eax,%eax                 # null array object?
2266    je        common_errNullObject      # bail if so
2267    cmpl      offArrayObject_length(%eax),%ecx
2268    jae       common_errArrayIndex      # index >= length, bail.  Expects:
2269                                        #   arrayObj in eax
2270                                        #   index in ecx
2271    leal      offArrayObject_contents(%eax,%ecx,2),%eax
2272.LOP_APUT_CHAR_finish:
2273    GET_VREG_R  %ecx rINST
2274    FETCH_INST_OPCODE 2 %edx
2275    movw     %cx,(%eax)
2276    ADVANCE_PC 2
2277    GOTO_NEXT_R %edx
2278
2279
2280/* ------------------------------ */
2281    .balign 64
2282.L_OP_APUT_SHORT: /* 0x51 */
2283/* File: x86/OP_APUT_SHORT.S */
2284/* File: x86/OP_APUT.S */
2285    /*
2286     * Array put, 32 bits or less.  vBB[vCC] <- vAA
2287     *
2288     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
2289     */
2290    /* op vAA, vBB, vCC */
2291    movzbl    2(rPC),%eax               # eax<- BB
2292    movzbl    3(rPC),%ecx               # ecx<- CC
2293    GET_VREG_R  %eax %eax               # eax<- vBB (array object)
2294    GET_VREG_R  %ecx %ecx               # ecs<- vCC (requested index)
2295    testl     %eax,%eax                 # null array object?
2296    je        common_errNullObject      # bail if so
2297    cmpl      offArrayObject_length(%eax),%ecx
2298    jae       common_errArrayIndex      # index >= length, bail.  Expects:
2299                                        #   arrayObj in eax
2300                                        #   index in ecx
2301    leal      offArrayObject_contents(%eax,%ecx,2),%eax
2302.LOP_APUT_SHORT_finish:
2303    GET_VREG_R  %ecx rINST
2304    FETCH_INST_OPCODE 2 %edx
2305    movw     %cx,(%eax)
2306    ADVANCE_PC 2
2307    GOTO_NEXT_R %edx
2308
2309
2310/* ------------------------------ */
2311    .balign 64
2312.L_OP_IGET: /* 0x52 */
2313/* File: x86/OP_IGET.S */
2314    /*
2315     * General 32-bit instance field get.
2316     *
2317     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2318     */
2319    /* op vA, vB, field@CCCC */
2320    movl    rGLUE,%ecx
2321    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2322    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2323    movzbl  rINSTbl,%ecx                        # ecx<- BA
2324    sarl    $4,%ecx                            # ecx<- B
2325    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2326    andb    $0xf,rINSTbl                       # rINST<- A
2327    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2328    movl    (%eax,%edx,4),%eax                  # resolved entry
2329    testl   %eax,%eax                           # is resolved entry null?
2330    jne     .LOP_IGET_finish                  # no, already resolved
2331    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2332    movl    rGLUE,%edx
2333    jmp     .LOP_IGET_resolve
2334
2335/* ------------------------------ */
2336    .balign 64
2337.L_OP_IGET_WIDE: /* 0x53 */
2338/* File: x86/OP_IGET_WIDE.S */
2339    /*
2340     * 64-bit instance field get.
2341     *
2342     */
2343    /* op vA, vB, field@CCCC */
2344    movl    rGLUE,%ecx
2345    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2346    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2347    movzbl  rINSTbl,%ecx                        # ecx<- BA
2348    sarl    $4,%ecx                            # ecx<- B
2349    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2350    andb    $0xf,rINSTbl                       # rINST<- A
2351    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2352    movl    (%eax,%edx,4),%eax                  # resolved entry
2353    testl   %eax,%eax                           # is resolved entry null?
2354    jne     .LOP_IGET_WIDE_finish                  # no, already resolved
2355    movl    %edx,OUT_ARG1(%esp)                 # for dvmResolveInstField
2356    movl    rGLUE,%edx
2357    jmp     .LOP_IGET_WIDE_resolve
2358
2359/* ------------------------------ */
2360    .balign 64
2361.L_OP_IGET_OBJECT: /* 0x54 */
2362/* File: x86/OP_IGET_OBJECT.S */
2363/* File: x86/OP_IGET.S */
2364    /*
2365     * General 32-bit instance field get.
2366     *
2367     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2368     */
2369    /* op vA, vB, field@CCCC */
2370    movl    rGLUE,%ecx
2371    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2372    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2373    movzbl  rINSTbl,%ecx                        # ecx<- BA
2374    sarl    $4,%ecx                            # ecx<- B
2375    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2376    andb    $0xf,rINSTbl                       # rINST<- A
2377    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2378    movl    (%eax,%edx,4),%eax                  # resolved entry
2379    testl   %eax,%eax                           # is resolved entry null?
2380    jne     .LOP_IGET_OBJECT_finish                  # no, already resolved
2381    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2382    movl    rGLUE,%edx
2383    jmp     .LOP_IGET_OBJECT_resolve
2384
2385
2386/* ------------------------------ */
2387    .balign 64
2388.L_OP_IGET_BOOLEAN: /* 0x55 */
2389/* File: x86/OP_IGET_BOOLEAN.S */
2390/* File: x86/OP_IGET.S */
2391    /*
2392     * General 32-bit instance field get.
2393     *
2394     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2395     */
2396    /* op vA, vB, field@CCCC */
2397    movl    rGLUE,%ecx
2398    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2399    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2400    movzbl  rINSTbl,%ecx                        # ecx<- BA
2401    sarl    $4,%ecx                            # ecx<- B
2402    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2403    andb    $0xf,rINSTbl                       # rINST<- A
2404    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2405    movl    (%eax,%edx,4),%eax                  # resolved entry
2406    testl   %eax,%eax                           # is resolved entry null?
2407    jne     .LOP_IGET_BOOLEAN_finish                  # no, already resolved
2408    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2409    movl    rGLUE,%edx
2410    jmp     .LOP_IGET_BOOLEAN_resolve
2411
2412
2413/* ------------------------------ */
2414    .balign 64
2415.L_OP_IGET_BYTE: /* 0x56 */
2416/* File: x86/OP_IGET_BYTE.S */
2417/* File: x86/OP_IGET.S */
2418    /*
2419     * General 32-bit instance field get.
2420     *
2421     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2422     */
2423    /* op vA, vB, field@CCCC */
2424    movl    rGLUE,%ecx
2425    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2426    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2427    movzbl  rINSTbl,%ecx                        # ecx<- BA
2428    sarl    $4,%ecx                            # ecx<- B
2429    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2430    andb    $0xf,rINSTbl                       # rINST<- A
2431    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2432    movl    (%eax,%edx,4),%eax                  # resolved entry
2433    testl   %eax,%eax                           # is resolved entry null?
2434    jne     .LOP_IGET_BYTE_finish                  # no, already resolved
2435    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2436    movl    rGLUE,%edx
2437    jmp     .LOP_IGET_BYTE_resolve
2438
2439
2440/* ------------------------------ */
2441    .balign 64
2442.L_OP_IGET_CHAR: /* 0x57 */
2443/* File: x86/OP_IGET_CHAR.S */
2444/* File: x86/OP_IGET.S */
2445    /*
2446     * General 32-bit instance field get.
2447     *
2448     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2449     */
2450    /* op vA, vB, field@CCCC */
2451    movl    rGLUE,%ecx
2452    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2453    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2454    movzbl  rINSTbl,%ecx                        # ecx<- BA
2455    sarl    $4,%ecx                            # ecx<- B
2456    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2457    andb    $0xf,rINSTbl                       # rINST<- A
2458    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2459    movl    (%eax,%edx,4),%eax                  # resolved entry
2460    testl   %eax,%eax                           # is resolved entry null?
2461    jne     .LOP_IGET_CHAR_finish                  # no, already resolved
2462    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2463    movl    rGLUE,%edx
2464    jmp     .LOP_IGET_CHAR_resolve
2465
2466
2467/* ------------------------------ */
2468    .balign 64
2469.L_OP_IGET_SHORT: /* 0x58 */
2470/* File: x86/OP_IGET_SHORT.S */
2471/* File: x86/OP_IGET.S */
2472    /*
2473     * General 32-bit instance field get.
2474     *
2475     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2476     */
2477    /* op vA, vB, field@CCCC */
2478    movl    rGLUE,%ecx
2479    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2480    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2481    movzbl  rINSTbl,%ecx                        # ecx<- BA
2482    sarl    $4,%ecx                            # ecx<- B
2483    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2484    andb    $0xf,rINSTbl                       # rINST<- A
2485    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2486    movl    (%eax,%edx,4),%eax                  # resolved entry
2487    testl   %eax,%eax                           # is resolved entry null?
2488    jne     .LOP_IGET_SHORT_finish                  # no, already resolved
2489    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
2490    movl    rGLUE,%edx
2491    jmp     .LOP_IGET_SHORT_resolve
2492
2493
2494/* ------------------------------ */
2495    .balign 64
2496.L_OP_IPUT: /* 0x59 */
2497/* File: x86/OP_IPUT.S */
2498
2499    /*
2500     * General 32-bit instance field put.
2501     *
2502     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2503     */
2504    /* op vA, vB, field@CCCC */
2505    movl    rGLUE,%ecx
2506    movzwl  2(rPC),%edx                         # %edx<- 0000CCCC
2507    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2508    movzbl  rINSTbl,%ecx                        # ecx<- BA
2509    sarl    $4,%ecx                            # ecx<- B
2510    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2511    andb    $0xf,rINSTbl                       # rINST<- A
2512    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2513    movl    (%eax,%edx,4),%eax                  # resolved entry
2514    testl   %eax,%eax                           # is resolved entry null?
2515    jne     .LOP_IPUT_finish                  # no, already resolved
2516    movl    %edx,OUT_ARG1(%esp)
2517    movl    rGLUE,%edx
2518    jmp     .LOP_IPUT_resolve
2519
2520/* ------------------------------ */
2521    .balign 64
2522.L_OP_IPUT_WIDE: /* 0x5a */
2523/* File: x86/OP_IPUT_WIDE.S */
2524    /*
2525     * 64-bit instance field put.
2526     *
2527     */
2528    /* op vA, vB, field@CCCC */
2529    movl    rGLUE,%ecx
2530    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2531    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2532    movzbl  rINSTbl,%ecx                        # ecx<- BA
2533    sarl    $4,%ecx                            # ecx<- B
2534    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2535    andb    $0xf,rINSTbl                       # rINST<- A
2536    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2537    movl    (%eax,%edx,4),%eax                  # resolved entry
2538    testl   %eax,%eax                           # is resolved entry null?
2539    jne     .LOP_IPUT_WIDE_finish                  # no, already resolved
2540    movl    %edx,OUT_ARG1(%esp)
2541    movl    rGLUE,%edx
2542    jmp     .LOP_IPUT_WIDE_resolve
2543
2544/* ------------------------------ */
2545    .balign 64
2546.L_OP_IPUT_OBJECT: /* 0x5b */
2547/* File: x86/OP_IPUT_OBJECT.S */
2548    /*
2549     * Object field put.
2550     *
2551     * for: iput-object
2552     */
2553    /* op vA, vB, field@CCCC */
2554    movl    rGLUE,%ecx
2555    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
2556    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2557    movzbl  rINSTbl,%ecx                        # ecx<- BA
2558    sarl    $4,%ecx                            # ecx<- B
2559    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2560    andb    $0xf,rINSTbl                       # rINST<- A
2561    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2562    movl    (%eax,%edx,4),%eax                  # resolved entry
2563    testl   %eax,%eax                           # is resolved entry null?
2564    jne     .LOP_IPUT_OBJECT_finish                  # no, already resolved
2565    movl    %edx,OUT_ARG1(%esp)
2566    movl    rGLUE,%edx
2567    jmp     .LOP_IPUT_OBJECT_resolve
2568
2569/* ------------------------------ */
2570    .balign 64
2571.L_OP_IPUT_BOOLEAN: /* 0x5c */
2572/* File: x86/OP_IPUT_BOOLEAN.S */
2573/* File: x86/OP_IPUT.S */
2574
2575    /*
2576     * General 32-bit instance field put.
2577     *
2578     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2579     */
2580    /* op vA, vB, field@CCCC */
2581    movl    rGLUE,%ecx
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_BOOLEAN_finish                  # no, already resolved
2592    movl    %edx,OUT_ARG1(%esp)
2593    movl    rGLUE,%edx
2594    jmp     .LOP_IPUT_BOOLEAN_resolve
2595
2596
2597/* ------------------------------ */
2598    .balign 64
2599.L_OP_IPUT_BYTE: /* 0x5d */
2600/* File: x86/OP_IPUT_BYTE.S */
2601/* File: x86/OP_IPUT.S */
2602
2603    /*
2604     * General 32-bit instance field put.
2605     *
2606     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2607     */
2608    /* op vA, vB, field@CCCC */
2609    movl    rGLUE,%ecx
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_BYTE_finish                  # no, already resolved
2620    movl    %edx,OUT_ARG1(%esp)
2621    movl    rGLUE,%edx
2622    jmp     .LOP_IPUT_BYTE_resolve
2623
2624
2625/* ------------------------------ */
2626    .balign 64
2627.L_OP_IPUT_CHAR: /* 0x5e */
2628/* File: x86/OP_IPUT_CHAR.S */
2629/* File: x86/OP_IPUT.S */
2630
2631    /*
2632     * General 32-bit instance field put.
2633     *
2634     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2635     */
2636    /* op vA, vB, field@CCCC */
2637    movl    rGLUE,%ecx
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_CHAR_finish                  # no, already resolved
2648    movl    %edx,OUT_ARG1(%esp)
2649    movl    rGLUE,%edx
2650    jmp     .LOP_IPUT_CHAR_resolve
2651
2652
2653/* ------------------------------ */
2654    .balign 64
2655.L_OP_IPUT_SHORT: /* 0x5f */
2656/* File: x86/OP_IPUT_SHORT.S */
2657/* File: x86/OP_IPUT.S */
2658
2659    /*
2660     * General 32-bit instance field put.
2661     *
2662     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2663     */
2664    /* op vA, vB, field@CCCC */
2665    movl    rGLUE,%ecx
2666    movzwl  2(rPC),%edx                         # %edx<- 0000CCCC
2667    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
2668    movzbl  rINSTbl,%ecx                        # ecx<- BA
2669    sarl    $4,%ecx                            # ecx<- B
2670    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
2671    andb    $0xf,rINSTbl                       # rINST<- A
2672    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
2673    movl    (%eax,%edx,4),%eax                  # resolved entry
2674    testl   %eax,%eax                           # is resolved entry null?
2675    jne     .LOP_IPUT_SHORT_finish                  # no, already resolved
2676    movl    %edx,OUT_ARG1(%esp)
2677    movl    rGLUE,%edx
2678    jmp     .LOP_IPUT_SHORT_resolve
2679
2680
2681/* ------------------------------ */
2682    .balign 64
2683.L_OP_SGET: /* 0x60 */
2684/* File: x86/OP_SGET.S */
2685    /*
2686     * General 32-bit SGET handler.
2687     *
2688     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2689     */
2690    /* op vAA, field@BBBB */
2691    movl      rGLUE,%ecx
2692    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2693    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2694    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2695    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2696    testl     %eax,%eax                          # resolved entry null?
2697    je        .LOP_SGET_resolve                # if not, make it so
2698.LOP_SGET_finish:     # field ptr in eax
2699    movl      offStaticField_value(%eax),%eax
2700    FETCH_INST_OPCODE 2 %edx
2701    ADVANCE_PC 2
2702    SET_VREG %eax rINST
2703    GOTO_NEXT_R %edx
2704
2705/* ------------------------------ */
2706    .balign 64
2707.L_OP_SGET_WIDE: /* 0x61 */
2708/* File: x86/OP_SGET_WIDE.S */
2709    /*
2710     * 64-bit SGET handler.
2711     *
2712     */
2713    /* sget-wide vAA, field@BBBB */
2714    movl      rGLUE,%ecx
2715    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2716    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2717    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2718    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2719    testl     %eax,%eax                          # resolved entry null?
2720    je        .LOP_SGET_WIDE_resolve                # if not, make it so
2721.LOP_SGET_WIDE_finish:     # field ptr in eax
2722    movl      offStaticField_value(%eax),%ecx    # ecx<- lsw
2723    movl      4+offStaticField_value(%eax),%eax  # eax<- msw
2724    FETCH_INST_OPCODE 2 %edx
2725    ADVANCE_PC 2
2726    SET_VREG_WORD %ecx rINST 0
2727    SET_VREG_WORD %eax rINST 1
2728    GOTO_NEXT_R %edx
2729
2730/* ------------------------------ */
2731    .balign 64
2732.L_OP_SGET_OBJECT: /* 0x62 */
2733/* File: x86/OP_SGET_OBJECT.S */
2734/* File: x86/OP_SGET.S */
2735    /*
2736     * General 32-bit SGET handler.
2737     *
2738     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2739     */
2740    /* op vAA, field@BBBB */
2741    movl      rGLUE,%ecx
2742    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2743    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2744    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2745    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2746    testl     %eax,%eax                          # resolved entry null?
2747    je        .LOP_SGET_OBJECT_resolve                # if not, make it so
2748.LOP_SGET_OBJECT_finish:     # field ptr in eax
2749    movl      offStaticField_value(%eax),%eax
2750    FETCH_INST_OPCODE 2 %edx
2751    ADVANCE_PC 2
2752    SET_VREG %eax rINST
2753    GOTO_NEXT_R %edx
2754
2755
2756/* ------------------------------ */
2757    .balign 64
2758.L_OP_SGET_BOOLEAN: /* 0x63 */
2759/* File: x86/OP_SGET_BOOLEAN.S */
2760/* File: x86/OP_SGET.S */
2761    /*
2762     * General 32-bit SGET handler.
2763     *
2764     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2765     */
2766    /* op vAA, field@BBBB */
2767    movl      rGLUE,%ecx
2768    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2769    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2770    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2771    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2772    testl     %eax,%eax                          # resolved entry null?
2773    je        .LOP_SGET_BOOLEAN_resolve                # if not, make it so
2774.LOP_SGET_BOOLEAN_finish:     # field ptr in eax
2775    movl      offStaticField_value(%eax),%eax
2776    FETCH_INST_OPCODE 2 %edx
2777    ADVANCE_PC 2
2778    SET_VREG %eax rINST
2779    GOTO_NEXT_R %edx
2780
2781
2782/* ------------------------------ */
2783    .balign 64
2784.L_OP_SGET_BYTE: /* 0x64 */
2785/* File: x86/OP_SGET_BYTE.S */
2786/* File: x86/OP_SGET.S */
2787    /*
2788     * General 32-bit SGET handler.
2789     *
2790     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2791     */
2792    /* op vAA, field@BBBB */
2793    movl      rGLUE,%ecx
2794    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2795    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2796    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2797    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2798    testl     %eax,%eax                          # resolved entry null?
2799    je        .LOP_SGET_BYTE_resolve                # if not, make it so
2800.LOP_SGET_BYTE_finish:     # field ptr in eax
2801    movl      offStaticField_value(%eax),%eax
2802    FETCH_INST_OPCODE 2 %edx
2803    ADVANCE_PC 2
2804    SET_VREG %eax rINST
2805    GOTO_NEXT_R %edx
2806
2807
2808/* ------------------------------ */
2809    .balign 64
2810.L_OP_SGET_CHAR: /* 0x65 */
2811/* File: x86/OP_SGET_CHAR.S */
2812/* File: x86/OP_SGET.S */
2813    /*
2814     * General 32-bit SGET handler.
2815     *
2816     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2817     */
2818    /* op vAA, field@BBBB */
2819    movl      rGLUE,%ecx
2820    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2821    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2822    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2823    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2824    testl     %eax,%eax                          # resolved entry null?
2825    je        .LOP_SGET_CHAR_resolve                # if not, make it so
2826.LOP_SGET_CHAR_finish:     # field ptr in eax
2827    movl      offStaticField_value(%eax),%eax
2828    FETCH_INST_OPCODE 2 %edx
2829    ADVANCE_PC 2
2830    SET_VREG %eax rINST
2831    GOTO_NEXT_R %edx
2832
2833
2834/* ------------------------------ */
2835    .balign 64
2836.L_OP_SGET_SHORT: /* 0x66 */
2837/* File: x86/OP_SGET_SHORT.S */
2838/* File: x86/OP_SGET.S */
2839    /*
2840     * General 32-bit SGET handler.
2841     *
2842     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2843     */
2844    /* op vAA, field@BBBB */
2845    movl      rGLUE,%ecx
2846    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2847    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2848    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2849    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2850    testl     %eax,%eax                          # resolved entry null?
2851    je        .LOP_SGET_SHORT_resolve                # if not, make it so
2852.LOP_SGET_SHORT_finish:     # field ptr in eax
2853    movl      offStaticField_value(%eax),%eax
2854    FETCH_INST_OPCODE 2 %edx
2855    ADVANCE_PC 2
2856    SET_VREG %eax rINST
2857    GOTO_NEXT_R %edx
2858
2859
2860/* ------------------------------ */
2861    .balign 64
2862.L_OP_SPUT: /* 0x67 */
2863/* File: x86/OP_SPUT.S */
2864    /*
2865     * General 32-bit SPUT handler.
2866     *
2867     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2868     */
2869    /* op vAA, field@BBBB */
2870    movl      rGLUE,%ecx
2871    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2872    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2873    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2874    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2875    testl     %eax,%eax                          # resolved entry null?
2876    je        .LOP_SPUT_resolve                # if not, make it so
2877.LOP_SPUT_finish:     # field ptr in eax
2878    GET_VREG_R  %ecx rINST
2879    FETCH_INST_OPCODE 2 %edx
2880    ADVANCE_PC 2
2881    movl      %ecx,offStaticField_value(%eax)
2882    GOTO_NEXT_R %edx
2883
2884/* ------------------------------ */
2885    .balign 64
2886.L_OP_SPUT_WIDE: /* 0x68 */
2887/* File: x86/OP_SPUT_WIDE.S */
2888    /*
2889     * General 32-bit SPUT handler.
2890     *
2891     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2892     */
2893    /* op vAA, field@BBBB */
2894    movl      rGLUE,%ecx
2895    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2896    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2897    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2898    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2899    testl     %eax,%eax                          # resolved entry null?
2900    je        .LOP_SPUT_WIDE_resolve                # if not, make it so
2901.LOP_SPUT_WIDE_finish:     # field ptr in eax
2902    GET_VREG_WORD %ecx rINST 0                  # rINST<- lsw
2903    GET_VREG_WORD rINST rINST 1                 # ecx<- msw
2904    FETCH_INST_OPCODE 2 %edx
2905    ADVANCE_PC 2
2906    movl      %ecx,offStaticField_value(%eax)
2907    movl      rINST,4+offStaticField_value(%eax)
2908    GOTO_NEXT_R %edx
2909
2910/* ------------------------------ */
2911    .balign 64
2912.L_OP_SPUT_OBJECT: /* 0x69 */
2913/* File: x86/OP_SPUT_OBJECT.S */
2914    /*
2915     * SPUT object handler.
2916     */
2917    /* op vAA, field@BBBB */
2918    movl      rGLUE,%ecx
2919    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2920    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2921    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2922    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField
2923    testl     %eax,%eax                          # resolved entry null?
2924    je        .LOP_SPUT_OBJECT_resolve                # if not, make it so
2925.LOP_SPUT_OBJECT_finish:                              # field ptr in eax
2926    movzbl    rINSTbl,%ecx                       # ecx<- AA
2927    GET_VREG_R  %ecx %ecx
2928    jmp       .LOP_SPUT_OBJECT_continue
2929
2930/* ------------------------------ */
2931    .balign 64
2932.L_OP_SPUT_BOOLEAN: /* 0x6a */
2933/* File: x86/OP_SPUT_BOOLEAN.S */
2934/* File: x86/OP_SPUT.S */
2935    /*
2936     * General 32-bit SPUT handler.
2937     *
2938     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2939     */
2940    /* op vAA, field@BBBB */
2941    movl      rGLUE,%ecx
2942    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2943    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2944    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2945    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2946    testl     %eax,%eax                          # resolved entry null?
2947    je        .LOP_SPUT_BOOLEAN_resolve                # if not, make it so
2948.LOP_SPUT_BOOLEAN_finish:     # field ptr in eax
2949    GET_VREG_R  %ecx rINST
2950    FETCH_INST_OPCODE 2 %edx
2951    ADVANCE_PC 2
2952    movl      %ecx,offStaticField_value(%eax)
2953    GOTO_NEXT_R %edx
2954
2955
2956/* ------------------------------ */
2957    .balign 64
2958.L_OP_SPUT_BYTE: /* 0x6b */
2959/* File: x86/OP_SPUT_BYTE.S */
2960/* File: x86/OP_SPUT.S */
2961    /*
2962     * General 32-bit SPUT handler.
2963     *
2964     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2965     */
2966    /* op vAA, field@BBBB */
2967    movl      rGLUE,%ecx
2968    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2969    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2970    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2971    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2972    testl     %eax,%eax                          # resolved entry null?
2973    je        .LOP_SPUT_BYTE_resolve                # if not, make it so
2974.LOP_SPUT_BYTE_finish:     # field ptr in eax
2975    GET_VREG_R  %ecx rINST
2976    FETCH_INST_OPCODE 2 %edx
2977    ADVANCE_PC 2
2978    movl      %ecx,offStaticField_value(%eax)
2979    GOTO_NEXT_R %edx
2980
2981
2982/* ------------------------------ */
2983    .balign 64
2984.L_OP_SPUT_CHAR: /* 0x6c */
2985/* File: x86/OP_SPUT_CHAR.S */
2986/* File: x86/OP_SPUT.S */
2987    /*
2988     * General 32-bit SPUT handler.
2989     *
2990     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2991     */
2992    /* op vAA, field@BBBB */
2993    movl      rGLUE,%ecx
2994    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2995    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2996    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2997    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2998    testl     %eax,%eax                          # resolved entry null?
2999    je        .LOP_SPUT_CHAR_resolve                # if not, make it so
3000.LOP_SPUT_CHAR_finish:     # field ptr in eax
3001    GET_VREG_R  %ecx rINST
3002    FETCH_INST_OPCODE 2 %edx
3003    ADVANCE_PC 2
3004    movl      %ecx,offStaticField_value(%eax)
3005    GOTO_NEXT_R %edx
3006
3007
3008/* ------------------------------ */
3009    .balign 64
3010.L_OP_SPUT_SHORT: /* 0x6d */
3011/* File: x86/OP_SPUT_SHORT.S */
3012/* File: x86/OP_SPUT.S */
3013    /*
3014     * General 32-bit SPUT handler.
3015     *
3016     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3017     */
3018    /* op vAA, field@BBBB */
3019    movl      rGLUE,%ecx
3020    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
3021    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
3022    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
3023    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
3024    testl     %eax,%eax                          # resolved entry null?
3025    je        .LOP_SPUT_SHORT_resolve                # if not, make it so
3026.LOP_SPUT_SHORT_finish:     # field ptr in eax
3027    GET_VREG_R  %ecx rINST
3028    FETCH_INST_OPCODE 2 %edx
3029    ADVANCE_PC 2
3030    movl      %ecx,offStaticField_value(%eax)
3031    GOTO_NEXT_R %edx
3032
3033
3034/* ------------------------------ */
3035    .balign 64
3036.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3037/* File: x86/OP_INVOKE_VIRTUAL.S */
3038
3039    /*
3040     * Handle a virtual method call.
3041     *
3042     * for: invoke-virtual, invoke-virtual/range
3043     */
3044    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3045    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3046    movl      rGLUE,%eax
3047    movzwl    2(rPC),%ecx                 # ecx<- BBBB
3048    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
3049    EXPORT_PC
3050    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
3051    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
3052    testl     %eax,%eax                   # already resolved?
3053    jne       .LOP_INVOKE_VIRTUAL_continue        # yes, continue
3054    movl      rGLUE,%eax
3055    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
3056    movl      offGlue_method(%eax),%eax   # eax<- glue->method
3057    jmp       .LOP_INVOKE_VIRTUAL_more
3058
3059/* ------------------------------ */
3060    .balign 64
3061.L_OP_INVOKE_SUPER: /* 0x6f */
3062/* File: x86/OP_INVOKE_SUPER.S */
3063    /*
3064     * Handle a "super" method call.
3065     *
3066     * for: invoke-super, invoke-super/range
3067     */
3068    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3069    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3070    movl      rGLUE,rINST
3071    movzwl    2(rPC),%eax               # eax<- BBBB
3072    movl      offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex
3073    EXPORT_PC
3074    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3075    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
3076    movl      offGlue_method(rINST),%eax # eax<- method
3077    movzwl    4(rPC),rINST              # rINST<- GFED or CCCC
3078    .if       (!0)
3079    andl      $0xf,rINST               # rINST<- D (or stays CCCC)
3080    .endif
3081    GET_VREG_R  rINST rINST             # rINST<- "this" ptr
3082    testl     rINST,rINST               # null "this"?
3083    je        common_errNullObject      # yes, throw
3084    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
3085    testl     %ecx,%ecx                 # already resolved?
3086    jne       .LOP_INVOKE_SUPER_continue      # yes - go on
3087    jmp       .LOP_INVOKE_SUPER_resolve
3088
3089/* ------------------------------ */
3090    .balign 64
3091.L_OP_INVOKE_DIRECT: /* 0x70 */
3092/* File: x86/OP_INVOKE_DIRECT.S */
3093    /*
3094     * Handle a direct method call.
3095     *
3096     * (We could defer the "is 'this' pointer null" test to the common
3097     * method invocation code, and use a flag to indicate that static
3098     * calls don't count.  If we do this as part of copying the arguments
3099     * out we could avoiding loading the first arg twice.)
3100     *
3101     * for: invoke-direct, invoke-direct/range
3102     */
3103    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3104    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3105    movl      rGLUE,%ecx
3106    movzwl    2(rPC),%eax              # eax<- BBBB
3107    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3108    EXPORT_PC
3109    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
3110    movzwl    4(rPC),%edx              # edx<- GFED or CCCC
3111    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
3112    .if       (!0)
3113    andl      $0xf,%edx               # edx<- D (or stays CCCC)
3114    .endif
3115    testl     %eax,%eax                # already resolved?
3116    GET_VREG_R  %ecx %edx              # ecx<- "this" ptr
3117    je        .LOP_INVOKE_DIRECT_resolve      # not resolved, do it now
3118.LOP_INVOKE_DIRECT_finish:
3119    testl     %ecx,%ecx                # null "this"?
3120    jne       common_invokeMethodNoRange  # no, continue on
3121    jmp       common_errNullObject
3122
3123/* ------------------------------ */
3124    .balign 64
3125.L_OP_INVOKE_STATIC: /* 0x71 */
3126/* File: x86/OP_INVOKE_STATIC.S */
3127    /*
3128     * Handle a static method call.
3129     *
3130     * for: invoke-static, invoke-static/range
3131     */
3132    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3133    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3134    movl      rGLUE,%ecx
3135    movzwl    2(rPC),%eax               # eax<- BBBB
3136    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3137    EXPORT_PC
3138    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
3139    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
3140    testl     %eax,%eax
3141    jne       common_invokeMethodNoRange
3142    movl      rGLUE,%ecx
3143    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
3144    movzwl    2(rPC),%eax
3145    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3146    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
3147    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
3148    jmp       .LOP_INVOKE_STATIC_continue
3149
3150/* ------------------------------ */
3151    .balign 64
3152.L_OP_INVOKE_INTERFACE: /* 0x72 */
3153/* File: x86/OP_INVOKE_INTERFACE.S */
3154    /*
3155     * Handle an interface method call.
3156     *
3157     * for: invoke-interface, invoke-interface/range
3158     */
3159    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3160    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3161    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
3162    movl       rGLUE,%ecx
3163    .if        (!0)
3164    andl       $0xf,%eax               # eax<- C (or stays CCCC)
3165    .endif
3166    GET_VREG_R   %eax %eax              # eax<- "this"
3167    EXPORT_PC
3168    testl      %eax,%eax                # null this?
3169    je         common_errNullObject     # yes, fail
3170    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3171    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
3172    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
3173    movl       offGlue_method(%ecx),%ecx           # ecx<- method
3174    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
3175    movzwl     2(rPC),%eax                         # eax<- BBBB
3176    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
3177    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
3178    jmp        .LOP_INVOKE_INTERFACE_continue
3179
3180/* ------------------------------ */
3181    .balign 64
3182.L_OP_UNUSED_73: /* 0x73 */
3183/* File: x86/OP_UNUSED_73.S */
3184/* File: x86/unused.S */
3185    jmp     common_abort
3186
3187
3188/* ------------------------------ */
3189    .balign 64
3190.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3191/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */
3192/* File: x86/OP_INVOKE_VIRTUAL.S */
3193
3194    /*
3195     * Handle a virtual method call.
3196     *
3197     * for: invoke-virtual, invoke-virtual/range
3198     */
3199    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3200    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3201    movl      rGLUE,%eax
3202    movzwl    2(rPC),%ecx                 # ecx<- BBBB
3203    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
3204    EXPORT_PC
3205    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
3206    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
3207    testl     %eax,%eax                   # already resolved?
3208    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # yes, continue
3209    movl      rGLUE,%eax
3210    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
3211    movl      offGlue_method(%eax),%eax   # eax<- glue->method
3212    jmp       .LOP_INVOKE_VIRTUAL_RANGE_more
3213
3214
3215/* ------------------------------ */
3216    .balign 64
3217.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3218/* File: x86/OP_INVOKE_SUPER_RANGE.S */
3219/* File: x86/OP_INVOKE_SUPER.S */
3220    /*
3221     * Handle a "super" method call.
3222     *
3223     * for: invoke-super, invoke-super/range
3224     */
3225    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3226    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3227    movl      rGLUE,rINST
3228    movzwl    2(rPC),%eax               # eax<- BBBB
3229    movl      offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex
3230    EXPORT_PC
3231    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3232    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
3233    movl      offGlue_method(rINST),%eax # eax<- method
3234    movzwl    4(rPC),rINST              # rINST<- GFED or CCCC
3235    .if       (!1)
3236    andl      $0xf,rINST               # rINST<- D (or stays CCCC)
3237    .endif
3238    GET_VREG_R  rINST rINST             # rINST<- "this" ptr
3239    testl     rINST,rINST               # null "this"?
3240    je        common_errNullObject      # yes, throw
3241    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
3242    testl     %ecx,%ecx                 # already resolved?
3243    jne       .LOP_INVOKE_SUPER_RANGE_continue      # yes - go on
3244    jmp       .LOP_INVOKE_SUPER_RANGE_resolve
3245
3246
3247/* ------------------------------ */
3248    .balign 64
3249.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3250/* File: x86/OP_INVOKE_DIRECT_RANGE.S */
3251/* File: x86/OP_INVOKE_DIRECT.S */
3252    /*
3253     * Handle a direct method call.
3254     *
3255     * (We could defer the "is 'this' pointer null" test to the common
3256     * method invocation code, and use a flag to indicate that static
3257     * calls don't count.  If we do this as part of copying the arguments
3258     * out we could avoiding loading the first arg twice.)
3259     *
3260     * for: invoke-direct, invoke-direct/range
3261     */
3262    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3263    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3264    movl      rGLUE,%ecx
3265    movzwl    2(rPC),%eax              # eax<- BBBB
3266    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3267    EXPORT_PC
3268    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
3269    movzwl    4(rPC),%edx              # edx<- GFED or CCCC
3270    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
3271    .if       (!1)
3272    andl      $0xf,%edx               # edx<- D (or stays CCCC)
3273    .endif
3274    testl     %eax,%eax                # already resolved?
3275    GET_VREG_R  %ecx %edx              # ecx<- "this" ptr
3276    je        .LOP_INVOKE_DIRECT_RANGE_resolve      # not resolved, do it now
3277.LOP_INVOKE_DIRECT_RANGE_finish:
3278    testl     %ecx,%ecx                # null "this"?
3279    jne       common_invokeMethodRange  # no, continue on
3280    jmp       common_errNullObject
3281
3282
3283/* ------------------------------ */
3284    .balign 64
3285.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3286/* File: x86/OP_INVOKE_STATIC_RANGE.S */
3287/* File: x86/OP_INVOKE_STATIC.S */
3288    /*
3289     * Handle a static method call.
3290     *
3291     * for: invoke-static, invoke-static/range
3292     */
3293    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3294    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3295    movl      rGLUE,%ecx
3296    movzwl    2(rPC),%eax               # eax<- BBBB
3297    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3298    EXPORT_PC
3299    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
3300    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
3301    testl     %eax,%eax
3302    jne       common_invokeMethodRange
3303    movl      rGLUE,%ecx
3304    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
3305    movzwl    2(rPC),%eax
3306    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3307    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
3308    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
3309    jmp       .LOP_INVOKE_STATIC_RANGE_continue
3310
3311
3312/* ------------------------------ */
3313    .balign 64
3314.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3315/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */
3316/* File: x86/OP_INVOKE_INTERFACE.S */
3317    /*
3318     * Handle an interface method call.
3319     *
3320     * for: invoke-interface, invoke-interface/range
3321     */
3322    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3323    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3324    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
3325    movl       rGLUE,%ecx
3326    .if        (!1)
3327    andl       $0xf,%eax               # eax<- C (or stays CCCC)
3328    .endif
3329    GET_VREG_R   %eax %eax              # eax<- "this"
3330    EXPORT_PC
3331    testl      %eax,%eax                # null this?
3332    je         common_errNullObject     # yes, fail
3333    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3334    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
3335    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
3336    movl       offGlue_method(%ecx),%ecx           # ecx<- method
3337    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
3338    movzwl     2(rPC),%eax                         # eax<- BBBB
3339    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
3340    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
3341    jmp        .LOP_INVOKE_INTERFACE_RANGE_continue
3342
3343
3344/* ------------------------------ */
3345    .balign 64
3346.L_OP_UNUSED_79: /* 0x79 */
3347/* File: x86/OP_UNUSED_79.S */
3348/* File: x86/unused.S */
3349    jmp     common_abort
3350
3351
3352/* ------------------------------ */
3353    .balign 64
3354.L_OP_UNUSED_7A: /* 0x7a */
3355/* File: x86/OP_UNUSED_7A.S */
3356/* File: x86/unused.S */
3357    jmp     common_abort
3358
3359
3360/* ------------------------------ */
3361    .balign 64
3362.L_OP_NEG_INT: /* 0x7b */
3363/* File: x86/OP_NEG_INT.S */
3364/* File: x86/unop.S */
3365    /*
3366     * Generic 32-bit unary operation.  Provide an "instr" line that
3367     * specifies an instruction that performs "result = op eax".
3368     */
3369    /* unop vA, vB */
3370    movzbl   rINSTbl,%ecx           # ecx<- A+
3371    sarl     $4,rINST             # rINST<- B
3372    GET_VREG_R %eax rINST           # eax<- vB
3373    andb     $0xf,%cl              # ecx<- A
3374    FETCH_INST_OPCODE 1 %edx
3375    ADVANCE_PC 1
3376
3377
3378    negl %eax
3379    SET_VREG %eax %ecx
3380    GOTO_NEXT_R %edx
3381
3382
3383/* ------------------------------ */
3384    .balign 64
3385.L_OP_NOT_INT: /* 0x7c */
3386/* File: x86/OP_NOT_INT.S */
3387/* File: x86/unop.S */
3388    /*
3389     * Generic 32-bit unary operation.  Provide an "instr" line that
3390     * specifies an instruction that performs "result = op eax".
3391     */
3392    /* unop vA, vB */
3393    movzbl   rINSTbl,%ecx           # ecx<- A+
3394    sarl     $4,rINST             # rINST<- B
3395    GET_VREG_R %eax rINST           # eax<- vB
3396    andb     $0xf,%cl              # ecx<- A
3397    FETCH_INST_OPCODE 1 %edx
3398    ADVANCE_PC 1
3399
3400
3401    notl %eax
3402    SET_VREG %eax %ecx
3403    GOTO_NEXT_R %edx
3404
3405
3406/* ------------------------------ */
3407    .balign 64
3408.L_OP_NEG_LONG: /* 0x7d */
3409/* File: x86/OP_NEG_LONG.S */
3410    /* unop vA, vB */
3411    movzbl    rINSTbl,%ecx        # ecx<- BA
3412    sarl      $4,%ecx            # ecx<- B
3413    andb      $0xf,rINSTbl       # rINST<- A
3414    GET_VREG_WORD %eax %ecx 0     # eax<- v[B+0]
3415    GET_VREG_WORD %ecx %ecx 1     # ecx<- v[B+1]
3416    negl      %eax
3417    adcl      $0,%ecx
3418    negl      %ecx
3419    FETCH_INST_OPCODE 1 %edx
3420    SET_VREG_WORD %eax rINST 0    # v[A+0]<- eax
3421    SET_VREG_WORD %ecx rINST 1    # v[A+1]<- ecx
3422    ADVANCE_PC 1
3423    GOTO_NEXT_R %edx
3424
3425/* ------------------------------ */
3426    .balign 64
3427.L_OP_NOT_LONG: /* 0x7e */
3428/* File: x86/OP_NOT_LONG.S */
3429    /* unop vA, vB */
3430    movzbl    rINSTbl,%ecx       # ecx<- BA
3431    sarl      $4,%ecx           # ecx<- B
3432    andb      $0xf,rINSTbl      # rINST<- A
3433    GET_VREG_WORD %eax %ecx 0    # eax<- v[B+0]
3434    GET_VREG_WORD %ecx %ecx 1    # ecx<- v[B+1]
3435    FETCH_INST_OPCODE 1 %edx
3436    notl      %eax
3437    notl      %ecx
3438    SET_VREG_WORD %eax rINST 0   # v[A+0]<- eax
3439    SET_VREG_WORD %ecx rINST 1   # v[A+1]<- ecx
3440    ADVANCE_PC 1
3441    GOTO_NEXT_R %edx
3442
3443/* ------------------------------ */
3444    .balign 64
3445.L_OP_NEG_FLOAT: /* 0x7f */
3446/* File: x86/OP_NEG_FLOAT.S */
3447/* File: x86/fpcvt.S */
3448    /*
3449     * Generic 32-bit FP conversion operation.
3450     */
3451    /* unop vA, vB */
3452    movzbl   rINSTbl,%ecx       # ecx<- A+
3453    sarl     $4,rINST         # rINST<- B
3454    flds    (rFP,rINST,4)      # %st0<- vB
3455    andb     $0xf,%cl          # ecx<- A
3456    FETCH_INST_OPCODE 1 %edx
3457    ADVANCE_PC 1
3458    fchs
3459    fstps  (rFP,%ecx,4)        # vA<- %st0
3460    GOTO_NEXT_R %edx
3461
3462
3463/* ------------------------------ */
3464    .balign 64
3465.L_OP_NEG_DOUBLE: /* 0x80 */
3466/* File: x86/OP_NEG_DOUBLE.S */
3467/* File: x86/fpcvt.S */
3468    /*
3469     * Generic 32-bit FP conversion operation.
3470     */
3471    /* unop vA, vB */
3472    movzbl   rINSTbl,%ecx       # ecx<- A+
3473    sarl     $4,rINST         # rINST<- B
3474    fldl    (rFP,rINST,4)      # %st0<- vB
3475    andb     $0xf,%cl          # ecx<- A
3476    FETCH_INST_OPCODE 1 %edx
3477    ADVANCE_PC 1
3478    fchs
3479    fstpl  (rFP,%ecx,4)        # vA<- %st0
3480    GOTO_NEXT_R %edx
3481
3482
3483/* ------------------------------ */
3484    .balign 64
3485.L_OP_INT_TO_LONG: /* 0x81 */
3486/* File: x86/OP_INT_TO_LONG.S */
3487    /* int to long vA, vB */
3488    movzbl  rINSTbl,%eax                # eax<- +A
3489    sarl    $4,%eax                    # eax<- B
3490    GET_VREG_R %eax %eax                # eax<- vB
3491    andb    $0xf,rINSTbl               # rINST<- A
3492    cltd                                # edx:eax<- sssssssBBBBBBBB
3493    SET_VREG_WORD %edx rINST 1          # v[A+1]<- edx/rPC
3494    FETCH_INST_OPCODE 1 %edx
3495    SET_VREG_WORD %eax rINST 0          # v[A+0]<- %eax
3496    ADVANCE_PC 1
3497    GOTO_NEXT_R %edx
3498
3499/* ------------------------------ */
3500    .balign 64
3501.L_OP_INT_TO_FLOAT: /* 0x82 */
3502/* File: x86/OP_INT_TO_FLOAT.S */
3503/* File: x86/fpcvt.S */
3504    /*
3505     * Generic 32-bit FP conversion operation.
3506     */
3507    /* unop vA, vB */
3508    movzbl   rINSTbl,%ecx       # ecx<- A+
3509    sarl     $4,rINST         # rINST<- B
3510    fildl    (rFP,rINST,4)      # %st0<- vB
3511    andb     $0xf,%cl          # ecx<- A
3512    FETCH_INST_OPCODE 1 %edx
3513    ADVANCE_PC 1
3514
3515    fstps  (rFP,%ecx,4)        # vA<- %st0
3516    GOTO_NEXT_R %edx
3517
3518
3519/* ------------------------------ */
3520    .balign 64
3521.L_OP_INT_TO_DOUBLE: /* 0x83 */
3522/* File: x86/OP_INT_TO_DOUBLE.S */
3523/* File: x86/fpcvt.S */
3524    /*
3525     * Generic 32-bit FP conversion operation.
3526     */
3527    /* unop vA, vB */
3528    movzbl   rINSTbl,%ecx       # ecx<- A+
3529    sarl     $4,rINST         # rINST<- B
3530    fildl    (rFP,rINST,4)      # %st0<- vB
3531    andb     $0xf,%cl          # ecx<- A
3532    FETCH_INST_OPCODE 1 %edx
3533    ADVANCE_PC 1
3534
3535    fstpl  (rFP,%ecx,4)        # vA<- %st0
3536    GOTO_NEXT_R %edx
3537
3538
3539/* ------------------------------ */
3540    .balign 64
3541.L_OP_LONG_TO_INT: /* 0x84 */
3542/* File: x86/OP_LONG_TO_INT.S */
3543/* we ignore the high word, making this equivalent to a 32-bit reg move */
3544/* File: x86/OP_MOVE.S */
3545    /* for move, move-object, long-to-int */
3546    /* op vA, vB */
3547    movzbl rINSTbl,%eax          # eax<- BA
3548    andb   $0xf,%al             # eax<- A
3549    shrl   $4,rINST            # rINST<- B
3550    GET_VREG_R %ecx rINST
3551    FETCH_INST_OPCODE 1 %edx
3552    ADVANCE_PC 1
3553    SET_VREG %ecx %eax           # fp[A]<-fp[B]
3554    GOTO_NEXT_R %edx
3555
3556
3557/* ------------------------------ */
3558    .balign 64
3559.L_OP_LONG_TO_FLOAT: /* 0x85 */
3560/* File: x86/OP_LONG_TO_FLOAT.S */
3561/* File: x86/fpcvt.S */
3562    /*
3563     * Generic 32-bit FP conversion operation.
3564     */
3565    /* unop vA, vB */
3566    movzbl   rINSTbl,%ecx       # ecx<- A+
3567    sarl     $4,rINST         # rINST<- B
3568    fildll    (rFP,rINST,4)      # %st0<- vB
3569    andb     $0xf,%cl          # ecx<- A
3570    FETCH_INST_OPCODE 1 %edx
3571    ADVANCE_PC 1
3572
3573    fstps  (rFP,%ecx,4)        # vA<- %st0
3574    GOTO_NEXT_R %edx
3575
3576
3577/* ------------------------------ */
3578    .balign 64
3579.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3580/* File: x86/OP_LONG_TO_DOUBLE.S */
3581/* File: x86/fpcvt.S */
3582    /*
3583     * Generic 32-bit FP conversion operation.
3584     */
3585    /* unop vA, vB */
3586    movzbl   rINSTbl,%ecx       # ecx<- A+
3587    sarl     $4,rINST         # rINST<- B
3588    fildll    (rFP,rINST,4)      # %st0<- vB
3589    andb     $0xf,%cl          # ecx<- A
3590    FETCH_INST_OPCODE 1 %edx
3591    ADVANCE_PC 1
3592
3593    fstpl  (rFP,%ecx,4)        # vA<- %st0
3594    GOTO_NEXT_R %edx
3595
3596
3597/* ------------------------------ */
3598    .balign 64
3599.L_OP_FLOAT_TO_INT: /* 0x87 */
3600/* File: x86/OP_FLOAT_TO_INT.S */
3601/* File: x86/cvtfp_int.S */
3602/* On fp to int conversions, Java requires that
3603 * if the result > maxint, it should be clamped to maxint.  If it is less
3604 * than minint, it should be clamped to minint.  If it is a nan, the result
3605 * should be zero.  Further, the rounding mode is to truncate.  This model
3606 * differs from what is delivered normally via the x86 fpu, so we have
3607 * to play some games.
3608 */
3609    /* float/double to int/long vA, vB */
3610    movzbl    rINSTbl,%ecx       # ecx<- A+
3611    sarl      $4,rINST         # rINST<- B
3612    .if 0
3613    fldl     (rFP,rINST,4)       # %st0<- vB
3614    .else
3615    flds     (rFP,rINST,4)       # %st0<- vB
3616    .endif
3617    ftst
3618    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3619    movzwl   LOCAL0_OFFSET(%ebp),%eax
3620    movb     $0xc,%ah
3621    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3622    fldcw    LOCAL0_OFFSET+2(%ebp)    # set "to zero" rounding mode
3623    FETCH_INST_OPCODE 1 %edx
3624    andb     $0xf,%cl                # ecx<- A
3625    .if 0
3626    fistpll  (rFP,%ecx,4)             # convert and store
3627    .else
3628    fistpl   (rFP,%ecx,4)             # convert and store
3629    .endif
3630    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3631    jmp      .LOP_FLOAT_TO_INT_continue
3632
3633
3634/* ------------------------------ */
3635    .balign 64
3636.L_OP_FLOAT_TO_LONG: /* 0x88 */
3637/* File: x86/OP_FLOAT_TO_LONG.S */
3638/* File: x86/cvtfp_int.S */
3639/* On fp to int conversions, Java requires that
3640 * if the result > maxint, it should be clamped to maxint.  If it is less
3641 * than minint, it should be clamped to minint.  If it is a nan, the result
3642 * should be zero.  Further, the rounding mode is to truncate.  This model
3643 * differs from what is delivered normally via the x86 fpu, so we have
3644 * to play some games.
3645 */
3646    /* float/double to int/long vA, vB */
3647    movzbl    rINSTbl,%ecx       # ecx<- A+
3648    sarl      $4,rINST         # rINST<- B
3649    .if 0
3650    fldl     (rFP,rINST,4)       # %st0<- vB
3651    .else
3652    flds     (rFP,rINST,4)       # %st0<- vB
3653    .endif
3654    ftst
3655    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3656    movzwl   LOCAL0_OFFSET(%ebp),%eax
3657    movb     $0xc,%ah
3658    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3659    fldcw    LOCAL0_OFFSET+2(%ebp)    # set "to zero" rounding mode
3660    FETCH_INST_OPCODE 1 %edx
3661    andb     $0xf,%cl                # ecx<- A
3662    .if 1
3663    fistpll  (rFP,%ecx,4)             # convert and store
3664    .else
3665    fistpl   (rFP,%ecx,4)             # convert and store
3666    .endif
3667    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3668    jmp      .LOP_FLOAT_TO_LONG_continue
3669
3670
3671/* ------------------------------ */
3672    .balign 64
3673.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3674/* File: x86/OP_FLOAT_TO_DOUBLE.S */
3675/* File: x86/fpcvt.S */
3676    /*
3677     * Generic 32-bit FP conversion operation.
3678     */
3679    /* unop vA, vB */
3680    movzbl   rINSTbl,%ecx       # ecx<- A+
3681    sarl     $4,rINST         # rINST<- B
3682    flds    (rFP,rINST,4)      # %st0<- vB
3683    andb     $0xf,%cl          # ecx<- A
3684    FETCH_INST_OPCODE 1 %edx
3685    ADVANCE_PC 1
3686
3687    fstpl  (rFP,%ecx,4)        # vA<- %st0
3688    GOTO_NEXT_R %edx
3689
3690
3691/* ------------------------------ */
3692    .balign 64
3693.L_OP_DOUBLE_TO_INT: /* 0x8a */
3694/* File: x86/OP_DOUBLE_TO_INT.S */
3695/* File: x86/cvtfp_int.S */
3696/* On fp to int conversions, Java requires that
3697 * if the result > maxint, it should be clamped to maxint.  If it is less
3698 * than minint, it should be clamped to minint.  If it is a nan, the result
3699 * should be zero.  Further, the rounding mode is to truncate.  This model
3700 * differs from what is delivered normally via the x86 fpu, so we have
3701 * to play some games.
3702 */
3703    /* float/double to int/long vA, vB */
3704    movzbl    rINSTbl,%ecx       # ecx<- A+
3705    sarl      $4,rINST         # rINST<- B
3706    .if 1
3707    fldl     (rFP,rINST,4)       # %st0<- vB
3708    .else
3709    flds     (rFP,rINST,4)       # %st0<- vB
3710    .endif
3711    ftst
3712    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3713    movzwl   LOCAL0_OFFSET(%ebp),%eax
3714    movb     $0xc,%ah
3715    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3716    fldcw    LOCAL0_OFFSET+2(%ebp)    # set "to zero" rounding mode
3717    FETCH_INST_OPCODE 1 %edx
3718    andb     $0xf,%cl                # ecx<- A
3719    .if 0
3720    fistpll  (rFP,%ecx,4)             # convert and store
3721    .else
3722    fistpl   (rFP,%ecx,4)             # convert and store
3723    .endif
3724    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3725    jmp      .LOP_DOUBLE_TO_INT_continue
3726
3727
3728/* ------------------------------ */
3729    .balign 64
3730.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3731/* File: x86/OP_DOUBLE_TO_LONG.S */
3732/* File: x86/cvtfp_int.S */
3733/* On fp to int conversions, Java requires that
3734 * if the result > maxint, it should be clamped to maxint.  If it is less
3735 * than minint, it should be clamped to minint.  If it is a nan, the result
3736 * should be zero.  Further, the rounding mode is to truncate.  This model
3737 * differs from what is delivered normally via the x86 fpu, so we have
3738 * to play some games.
3739 */
3740    /* float/double to int/long vA, vB */
3741    movzbl    rINSTbl,%ecx       # ecx<- A+
3742    sarl      $4,rINST         # rINST<- B
3743    .if 1
3744    fldl     (rFP,rINST,4)       # %st0<- vB
3745    .else
3746    flds     (rFP,rINST,4)       # %st0<- vB
3747    .endif
3748    ftst
3749    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3750    movzwl   LOCAL0_OFFSET(%ebp),%eax
3751    movb     $0xc,%ah
3752    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3753    fldcw    LOCAL0_OFFSET+2(%ebp)    # set "to zero" rounding mode
3754    FETCH_INST_OPCODE 1 %edx
3755    andb     $0xf,%cl                # ecx<- A
3756    .if 1
3757    fistpll  (rFP,%ecx,4)             # convert and store
3758    .else
3759    fistpl   (rFP,%ecx,4)             # convert and store
3760    .endif
3761    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3762    jmp      .LOP_DOUBLE_TO_LONG_continue
3763
3764
3765/* ------------------------------ */
3766    .balign 64
3767.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3768/* File: x86/OP_DOUBLE_TO_FLOAT.S */
3769/* File: x86/fpcvt.S */
3770    /*
3771     * Generic 32-bit FP conversion operation.
3772     */
3773    /* unop vA, vB */
3774    movzbl   rINSTbl,%ecx       # ecx<- A+
3775    sarl     $4,rINST         # rINST<- B
3776    fldl    (rFP,rINST,4)      # %st0<- vB
3777    andb     $0xf,%cl          # ecx<- A
3778    FETCH_INST_OPCODE 1 %edx
3779    ADVANCE_PC 1
3780
3781    fstps  (rFP,%ecx,4)        # vA<- %st0
3782    GOTO_NEXT_R %edx
3783
3784
3785/* ------------------------------ */
3786    .balign 64
3787.L_OP_INT_TO_BYTE: /* 0x8d */
3788/* File: x86/OP_INT_TO_BYTE.S */
3789/* File: x86/unop.S */
3790    /*
3791     * Generic 32-bit unary operation.  Provide an "instr" line that
3792     * specifies an instruction that performs "result = op eax".
3793     */
3794    /* unop vA, vB */
3795    movzbl   rINSTbl,%ecx           # ecx<- A+
3796    sarl     $4,rINST             # rINST<- B
3797    GET_VREG_R %eax rINST           # eax<- vB
3798    andb     $0xf,%cl              # ecx<- A
3799    FETCH_INST_OPCODE 1 %edx
3800    ADVANCE_PC 1
3801
3802
3803    movsbl %al,%eax
3804    SET_VREG %eax %ecx
3805    GOTO_NEXT_R %edx
3806
3807
3808/* ------------------------------ */
3809    .balign 64
3810.L_OP_INT_TO_CHAR: /* 0x8e */
3811/* File: x86/OP_INT_TO_CHAR.S */
3812/* File: x86/unop.S */
3813    /*
3814     * Generic 32-bit unary operation.  Provide an "instr" line that
3815     * specifies an instruction that performs "result = op eax".
3816     */
3817    /* unop vA, vB */
3818    movzbl   rINSTbl,%ecx           # ecx<- A+
3819    sarl     $4,rINST             # rINST<- B
3820    GET_VREG_R %eax rINST           # eax<- vB
3821    andb     $0xf,%cl              # ecx<- A
3822    FETCH_INST_OPCODE 1 %edx
3823    ADVANCE_PC 1
3824
3825
3826    movzwl %ax,%eax
3827    SET_VREG %eax %ecx
3828    GOTO_NEXT_R %edx
3829
3830
3831/* ------------------------------ */
3832    .balign 64
3833.L_OP_INT_TO_SHORT: /* 0x8f */
3834/* File: x86/OP_INT_TO_SHORT.S */
3835/* File: x86/unop.S */
3836    /*
3837     * Generic 32-bit unary operation.  Provide an "instr" line that
3838     * specifies an instruction that performs "result = op eax".
3839     */
3840    /* unop vA, vB */
3841    movzbl   rINSTbl,%ecx           # ecx<- A+
3842    sarl     $4,rINST             # rINST<- B
3843    GET_VREG_R %eax rINST           # eax<- vB
3844    andb     $0xf,%cl              # ecx<- A
3845    FETCH_INST_OPCODE 1 %edx
3846    ADVANCE_PC 1
3847
3848
3849    movswl %ax,%eax
3850    SET_VREG %eax %ecx
3851    GOTO_NEXT_R %edx
3852
3853
3854/* ------------------------------ */
3855    .balign 64
3856.L_OP_ADD_INT: /* 0x90 */
3857/* File: x86/OP_ADD_INT.S */
3858/* File: x86/binop.S */
3859    /*
3860     * Generic 32-bit binary operation.  Provide an "instr" line that
3861     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3862     * This could be an x86 instruction or a function call.  (If the result
3863     * comes back in a register other than eax, you can override "result".)
3864     *
3865     * For: add-int, sub-int, and-int, or-int,
3866     *      xor-int, shl-int, shr-int, ushr-int
3867     */
3868    /* binop vAA, vBB, vCC */
3869    movzbl   2(rPC),%eax   # eax<- BB
3870    movzbl   3(rPC),%ecx   # ecx<- CC
3871    GET_VREG_R %eax %eax   # eax<- vBB
3872    addl (rFP,%ecx,4),%eax                 # ex: addl    (rFP,%ecx,4),%eax
3873    FETCH_INST_OPCODE 2 %edx
3874    ADVANCE_PC 2
3875    SET_VREG %eax rINST
3876    GOTO_NEXT_R %edx
3877
3878
3879/* ------------------------------ */
3880    .balign 64
3881.L_OP_SUB_INT: /* 0x91 */
3882/* File: x86/OP_SUB_INT.S */
3883/* File: x86/binop.S */
3884    /*
3885     * Generic 32-bit binary operation.  Provide an "instr" line that
3886     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3887     * This could be an x86 instruction or a function call.  (If the result
3888     * comes back in a register other than eax, you can override "result".)
3889     *
3890     * For: add-int, sub-int, and-int, or-int,
3891     *      xor-int, shl-int, shr-int, ushr-int
3892     */
3893    /* binop vAA, vBB, vCC */
3894    movzbl   2(rPC),%eax   # eax<- BB
3895    movzbl   3(rPC),%ecx   # ecx<- CC
3896    GET_VREG_R %eax %eax   # eax<- vBB
3897    subl   (rFP,%ecx,4),%eax                 # ex: addl    (rFP,%ecx,4),%eax
3898    FETCH_INST_OPCODE 2 %edx
3899    ADVANCE_PC 2
3900    SET_VREG %eax rINST
3901    GOTO_NEXT_R %edx
3902
3903
3904/* ------------------------------ */
3905    .balign 64
3906.L_OP_MUL_INT: /* 0x92 */
3907/* File: x86/OP_MUL_INT.S */
3908    /*
3909     * 32-bit binary multiplication.
3910     */
3911    /* mul vAA, vBB, vCC */
3912    movzbl   2(rPC),%eax            # eax<- BB
3913    movzbl   3(rPC),%ecx            # ecx<- CC
3914    GET_VREG_R %eax %eax            # eax<- vBB
3915    imull    (rFP,%ecx,4),%eax      # trashes edx
3916    FETCH_INST_OPCODE 2 %edx
3917    ADVANCE_PC 2
3918    SET_VREG %eax rINST
3919    GOTO_NEXT_R %edx
3920
3921/* ------------------------------ */
3922    .balign 64
3923.L_OP_DIV_INT: /* 0x93 */
3924/* File: x86/OP_DIV_INT.S */
3925/* File: x86/bindiv.S */
3926
3927    /*
3928     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
3929     * op1=-1.
3930     */
3931    /* binop vAA, vBB, vCC */
3932    movzbl   2(rPC),%eax            # eax<- BB
3933    movzbl   3(rPC),%ecx            # ecx<- CC
3934    GET_VREG_R %eax %eax            # eax<- vBB
3935    GET_VREG_R %ecx %ecx            # eax<- vBB
3936    cmpl     $0,%ecx
3937    je       common_errDivideByZero
3938    cmpl     $-1,%ecx
3939    jne      .LOP_DIV_INT_continue_div
3940    cmpl     $0x80000000,%eax
3941    jne      .LOP_DIV_INT_continue_div
3942    movl     $0x80000000,%eax
3943    jmp      .LOP_DIV_INT_finish_div
3944
3945
3946
3947/* ------------------------------ */
3948    .balign 64
3949.L_OP_REM_INT: /* 0x94 */
3950/* File: x86/OP_REM_INT.S */
3951/* File: x86/bindiv.S */
3952
3953    /*
3954     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
3955     * op1=-1.
3956     */
3957    /* binop vAA, vBB, vCC */
3958    movzbl   2(rPC),%eax            # eax<- BB
3959    movzbl   3(rPC),%ecx            # ecx<- CC
3960    GET_VREG_R %eax %eax            # eax<- vBB
3961    GET_VREG_R %ecx %ecx            # eax<- vBB
3962    cmpl     $0,%ecx
3963    je       common_errDivideByZero
3964    cmpl     $-1,%ecx
3965    jne      .LOP_REM_INT_continue_div
3966    cmpl     $0x80000000,%eax
3967    jne      .LOP_REM_INT_continue_div
3968    movl     $0,%edx
3969    jmp      .LOP_REM_INT_finish_div
3970
3971
3972
3973/* ------------------------------ */
3974    .balign 64
3975.L_OP_AND_INT: /* 0x95 */
3976/* File: x86/OP_AND_INT.S */
3977/* File: x86/binop.S */
3978    /*
3979     * Generic 32-bit binary operation.  Provide an "instr" line that
3980     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3981     * This could be an x86 instruction or a function call.  (If the result
3982     * comes back in a register other than eax, you can override "result".)
3983     *
3984     * For: add-int, sub-int, and-int, or-int,
3985     *      xor-int, shl-int, shr-int, ushr-int
3986     */
3987    /* binop vAA, vBB, vCC */
3988    movzbl   2(rPC),%eax   # eax<- BB
3989    movzbl   3(rPC),%ecx   # ecx<- CC
3990    GET_VREG_R %eax %eax   # eax<- vBB
3991    andl   (rFP,%ecx,4),%eax                 # ex: addl    (rFP,%ecx,4),%eax
3992    FETCH_INST_OPCODE 2 %edx
3993    ADVANCE_PC 2
3994    SET_VREG %eax rINST
3995    GOTO_NEXT_R %edx
3996
3997
3998/* ------------------------------ */
3999    .balign 64
4000.L_OP_OR_INT: /* 0x96 */
4001/* File: x86/OP_OR_INT.S */
4002/* File: x86/binop.S */
4003    /*
4004     * Generic 32-bit binary operation.  Provide an "instr" line that
4005     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
4006     * This could be an x86 instruction or a function call.  (If the result
4007     * comes back in a register other than eax, you can override "result".)
4008     *
4009     * For: add-int, sub-int, and-int, or-int,
4010     *      xor-int, shl-int, shr-int, ushr-int
4011     */
4012    /* binop vAA, vBB, vCC */
4013    movzbl   2(rPC),%eax   # eax<- BB
4014    movzbl   3(rPC),%ecx   # ecx<- CC
4015    GET_VREG_R %eax %eax   # eax<- vBB
4016    orl   (rFP,%ecx,4),%eax                 # ex: addl    (rFP,%ecx,4),%eax
4017    FETCH_INST_OPCODE 2 %edx
4018    ADVANCE_PC 2
4019    SET_VREG %eax rINST
4020    GOTO_NEXT_R %edx
4021
4022
4023/* ------------------------------ */
4024    .balign 64
4025.L_OP_XOR_INT: /* 0x97 */
4026/* File: x86/OP_XOR_INT.S */
4027/* File: x86/binop.S */
4028    /*
4029     * Generic 32-bit binary operation.  Provide an "instr" line that
4030     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
4031     * This could be an x86 instruction or a function call.  (If the result
4032     * comes back in a register other than eax, you can override "result".)
4033     *
4034     * For: add-int, sub-int, and-int, or-int,
4035     *      xor-int, shl-int, shr-int, ushr-int
4036     */
4037    /* binop vAA, vBB, vCC */
4038    movzbl   2(rPC),%eax   # eax<- BB
4039    movzbl   3(rPC),%ecx   # ecx<- CC
4040    GET_VREG_R %eax %eax   # eax<- vBB
4041    xorl   (rFP,%ecx,4),%eax                 # ex: addl    (rFP,%ecx,4),%eax
4042    FETCH_INST_OPCODE 2 %edx
4043    ADVANCE_PC 2
4044    SET_VREG %eax rINST
4045    GOTO_NEXT_R %edx
4046
4047
4048/* ------------------------------ */
4049    .balign 64
4050.L_OP_SHL_INT: /* 0x98 */
4051/* File: x86/OP_SHL_INT.S */
4052/* File: x86/binop1.S */
4053    /*
4054     * Generic 32-bit binary operation in which both operands loaded to
4055     * registers (op0 in eax, op1 in ecx).
4056     */
4057    /* binop vAA, vBB, vCC */
4058    movzbl   2(rPC),%eax            # eax<- BB
4059    movzbl   3(rPC),%ecx            # ecx<- CC
4060    GET_VREG_R %eax %eax            # eax<- vBB
4061    GET_VREG_R %ecx %ecx            # eax<- vBB
4062    sall    %cl,%eax                          # ex: addl    %ecx,%eax
4063    FETCH_INST_OPCODE 2 %edx
4064    ADVANCE_PC 2
4065    SET_VREG %eax rINST
4066    GOTO_NEXT_R %edx
4067
4068
4069/* ------------------------------ */
4070    .balign 64
4071.L_OP_SHR_INT: /* 0x99 */
4072/* File: x86/OP_SHR_INT.S */
4073/* File: x86/binop1.S */
4074    /*
4075     * Generic 32-bit binary operation in which both operands loaded to
4076     * registers (op0 in eax, op1 in ecx).
4077     */
4078    /* binop vAA, vBB, vCC */
4079    movzbl   2(rPC),%eax            # eax<- BB
4080    movzbl   3(rPC),%ecx            # ecx<- CC
4081    GET_VREG_R %eax %eax            # eax<- vBB
4082    GET_VREG_R %ecx %ecx            # eax<- vBB
4083    sarl    %cl,%eax                          # ex: addl    %ecx,%eax
4084    FETCH_INST_OPCODE 2 %edx
4085    ADVANCE_PC 2
4086    SET_VREG %eax rINST
4087    GOTO_NEXT_R %edx
4088
4089
4090/* ------------------------------ */
4091    .balign 64
4092.L_OP_USHR_INT: /* 0x9a */
4093/* File: x86/OP_USHR_INT.S */
4094/* File: x86/binop1.S */
4095    /*
4096     * Generic 32-bit binary operation in which both operands loaded to
4097     * registers (op0 in eax, op1 in ecx).
4098     */
4099    /* binop vAA, vBB, vCC */
4100    movzbl   2(rPC),%eax            # eax<- BB
4101    movzbl   3(rPC),%ecx            # ecx<- CC
4102    GET_VREG_R %eax %eax            # eax<- vBB
4103    GET_VREG_R %ecx %ecx            # eax<- vBB
4104    shrl    %cl,%eax                          # ex: addl    %ecx,%eax
4105    FETCH_INST_OPCODE 2 %edx
4106    ADVANCE_PC 2
4107    SET_VREG %eax rINST
4108    GOTO_NEXT_R %edx
4109
4110
4111/* ------------------------------ */
4112    .balign 64
4113.L_OP_ADD_LONG: /* 0x9b */
4114/* File: x86/OP_ADD_LONG.S */
4115/* File: x86/binopWide.S */
4116    /*
4117     * Generic 64-bit binary operation.
4118     */
4119    /* binop vAA, vBB, vCC */
4120
4121    movzbl    2(rPC),%eax               # eax<- BB
4122    movzbl    3(rPC),%ecx               # ecx<- CC
4123    GET_VREG_WORD %edx %eax 0           # edx<- v[BB+0]
4124    GET_VREG_WORD %eax %eax 1           # eax<- v[BB+1]
4125    addl (rFP,%ecx,4),%edx         # ex: addl   (rFP,%ecx,4),%edx
4126    adcl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4127    SET_VREG_WORD %edx rINST 0          # v[AA+0] <- edx
4128    FETCH_INST_OPCODE 2 %edx
4129    SET_VREG_WORD %eax rINST 1          # v[AA+1] <- eax
4130    ADVANCE_PC 2
4131    GOTO_NEXT_R %edx
4132
4133
4134/* ------------------------------ */
4135    .balign 64
4136.L_OP_SUB_LONG: /* 0x9c */
4137/* File: x86/OP_SUB_LONG.S */
4138/* File: x86/binopWide.S */
4139    /*
4140     * Generic 64-bit binary operation.
4141     */
4142    /* binop vAA, vBB, vCC */
4143
4144    movzbl    2(rPC),%eax               # eax<- BB
4145    movzbl    3(rPC),%ecx               # ecx<- CC
4146    GET_VREG_WORD %edx %eax 0           # edx<- v[BB+0]
4147    GET_VREG_WORD %eax %eax 1           # eax<- v[BB+1]
4148    subl (rFP,%ecx,4),%edx         # ex: addl   (rFP,%ecx,4),%edx
4149    sbbl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4150    SET_VREG_WORD %edx rINST 0          # v[AA+0] <- edx
4151    FETCH_INST_OPCODE 2 %edx
4152    SET_VREG_WORD %eax rINST 1          # v[AA+1] <- eax
4153    ADVANCE_PC 2
4154    GOTO_NEXT_R %edx
4155
4156
4157/* ------------------------------ */
4158    .balign 64
4159.L_OP_MUL_LONG: /* 0x9d */
4160/* File: x86/OP_MUL_LONG.S */
4161    /*
4162     * Signed 64-bit integer multiply.
4163     *
4164     * We could definately use more free registers for
4165     * this code.   We spill rINSTw (ebx),
4166     * giving us eax, ebc, ecx and edx as computational
4167     * temps.  On top of that, we'll spill edi (rFP)
4168     * for use as the vB pointer and esi (rPC) for use
4169     * as the vC pointer.  Yuck.
4170     */
4171    /* mul-long vAA, vBB, vCC */
4172    movzbl    2(rPC),%eax              # eax<- B
4173    movzbl    3(rPC),%ecx              # ecx<- C
4174    SPILL_TMP2(%esi)                   # save Dalvik PC
4175    SPILL(rFP)
4176    SPILL(rINST)
4177    leal      (rFP,%eax,4),%esi        # esi<- &v[B]
4178    leal      (rFP,%ecx,4),rFP         # rFP<- &v[C]
4179    movl      4(%esi),%ecx             # ecx<- Bmsw
4180    imull     (rFP),%ecx               # ecx<- (Bmsw*Clsw)
4181    movl      4(rFP),%eax              # eax<- Cmsw
4182    imull     (%esi),%eax              # eax<- (Cmsw*Blsw)
4183    addl      %eax,%ecx                # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw)
4184    movl      (rFP),%eax               # eax<- Clsw
4185    mull      (%esi)                   # eax<- (Clsw*Alsw)
4186    UNSPILL(rINST)
4187    UNSPILL(rFP)
4188    jmp       .LOP_MUL_LONG_continue
4189
4190/* ------------------------------ */
4191    .balign 64
4192.L_OP_DIV_LONG: /* 0x9e */
4193/* File: x86/OP_DIV_LONG.S */
4194    /* div vAA, vBB, vCC */
4195    movzbl    3(rPC),%eax              # eax<- CC
4196    movzbl    2(rPC),%ecx              # ecx<- BB
4197    GET_VREG_WORD %edx %eax 0
4198    GET_VREG_WORD %eax %eax 1
4199    movl     %edx,OUT_ARG2(%esp)
4200    testl    %eax,%eax
4201    je       .LOP_DIV_LONG_check_zero
4202    cmpl     $-1,%eax
4203    je       .LOP_DIV_LONG_check_neg1
4204.LOP_DIV_LONG_notSpecial:
4205    GET_VREG_WORD %edx %ecx 0
4206    GET_VREG_WORD %ecx %ecx 1
4207.LOP_DIV_LONG_notSpecial1:
4208    movl     %eax,OUT_ARG3(%esp)
4209    movl     %edx,OUT_ARG0(%esp)
4210    movl     %ecx,OUT_ARG1(%esp)
4211    jmp      .LOP_DIV_LONG_continue
4212
4213/* ------------------------------ */
4214    .balign 64
4215.L_OP_REM_LONG: /* 0x9f */
4216/* File: x86/OP_REM_LONG.S */
4217/* File: x86/OP_DIV_LONG.S */
4218    /* div vAA, vBB, vCC */
4219    movzbl    3(rPC),%eax              # eax<- CC
4220    movzbl    2(rPC),%ecx              # ecx<- BB
4221    GET_VREG_WORD %edx %eax 0
4222    GET_VREG_WORD %eax %eax 1
4223    movl     %edx,OUT_ARG2(%esp)
4224    testl    %eax,%eax
4225    je       .LOP_REM_LONG_check_zero
4226    cmpl     $-1,%eax
4227    je       .LOP_REM_LONG_check_neg1
4228.LOP_REM_LONG_notSpecial:
4229    GET_VREG_WORD %edx %ecx 0
4230    GET_VREG_WORD %ecx %ecx 1
4231.LOP_REM_LONG_notSpecial1:
4232    movl     %eax,OUT_ARG3(%esp)
4233    movl     %edx,OUT_ARG0(%esp)
4234    movl     %ecx,OUT_ARG1(%esp)
4235    jmp      .LOP_REM_LONG_continue
4236
4237
4238/* ------------------------------ */
4239    .balign 64
4240.L_OP_AND_LONG: /* 0xa0 */
4241/* File: x86/OP_AND_LONG.S */
4242/* File: x86/binopWide.S */
4243    /*
4244     * Generic 64-bit binary operation.
4245     */
4246    /* binop vAA, vBB, vCC */
4247
4248    movzbl    2(rPC),%eax               # eax<- BB
4249    movzbl    3(rPC),%ecx               # ecx<- CC
4250    GET_VREG_WORD %edx %eax 0           # edx<- v[BB+0]
4251    GET_VREG_WORD %eax %eax 1           # eax<- v[BB+1]
4252    andl (rFP,%ecx,4),%edx         # ex: addl   (rFP,%ecx,4),%edx
4253    andl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4254    SET_VREG_WORD %edx rINST 0          # v[AA+0] <- edx
4255    FETCH_INST_OPCODE 2 %edx
4256    SET_VREG_WORD %eax rINST 1          # v[AA+1] <- eax
4257    ADVANCE_PC 2
4258    GOTO_NEXT_R %edx
4259
4260
4261/* ------------------------------ */
4262    .balign 64
4263.L_OP_OR_LONG: /* 0xa1 */
4264/* File: x86/OP_OR_LONG.S */
4265/* File: x86/binopWide.S */
4266    /*
4267     * Generic 64-bit binary operation.
4268     */
4269    /* binop vAA, vBB, vCC */
4270
4271    movzbl    2(rPC),%eax               # eax<- BB
4272    movzbl    3(rPC),%ecx               # ecx<- CC
4273    GET_VREG_WORD %edx %eax 0           # edx<- v[BB+0]
4274    GET_VREG_WORD %eax %eax 1           # eax<- v[BB+1]
4275    orl (rFP,%ecx,4),%edx         # ex: addl   (rFP,%ecx,4),%edx
4276    orl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4277    SET_VREG_WORD %edx rINST 0          # v[AA+0] <- edx
4278    FETCH_INST_OPCODE 2 %edx
4279    SET_VREG_WORD %eax rINST 1          # v[AA+1] <- eax
4280    ADVANCE_PC 2
4281    GOTO_NEXT_R %edx
4282
4283
4284/* ------------------------------ */
4285    .balign 64
4286.L_OP_XOR_LONG: /* 0xa2 */
4287/* File: x86/OP_XOR_LONG.S */
4288/* File: x86/binopWide.S */
4289    /*
4290     * Generic 64-bit binary operation.
4291     */
4292    /* binop vAA, vBB, vCC */
4293
4294    movzbl    2(rPC),%eax               # eax<- BB
4295    movzbl    3(rPC),%ecx               # ecx<- CC
4296    GET_VREG_WORD %edx %eax 0           # edx<- v[BB+0]
4297    GET_VREG_WORD %eax %eax 1           # eax<- v[BB+1]
4298    xorl (rFP,%ecx,4),%edx         # ex: addl   (rFP,%ecx,4),%edx
4299    xorl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4300    SET_VREG_WORD %edx rINST 0          # v[AA+0] <- edx
4301    FETCH_INST_OPCODE 2 %edx
4302    SET_VREG_WORD %eax rINST 1          # v[AA+1] <- eax
4303    ADVANCE_PC 2
4304    GOTO_NEXT_R %edx
4305
4306
4307/* ------------------------------ */
4308    .balign 64
4309.L_OP_SHL_LONG: /* 0xa3 */
4310/* File: x86/OP_SHL_LONG.S */
4311    /*
4312     * Long integer shift.  This is different from the generic 32/64-bit
4313     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4314     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4315     * 6 bits of the shift distance.  x86 shifts automatically mask off
4316     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4317     * case specially.
4318     */
4319    /* shl-long vAA, vBB, vCC */
4320    /* ecx gets shift count */
4321    /* Need to spill edx */
4322    /* rINSTw gets AA */
4323    movzbl    2(rPC),%eax               # eax<- BB
4324    movzbl    3(rPC),%ecx               # ecx<- CC
4325    GET_VREG_WORD %edx %eax 1           # ecx<- v[BB+1]
4326    GET_VREG_R   %ecx %ecx              # ecx<- vCC
4327    GET_VREG_WORD %eax %eax 0           # eax<- v[BB+0]
4328    shldl     %eax,%edx
4329    sall      %cl,%eax
4330    testb     $32,%cl
4331    je        2f
4332    movl      %eax,%edx
4333    xorl      %eax,%eax
43342:
4335    SET_VREG_WORD %edx rINST 1          # v[AA+1]<- %edx
4336    FETCH_INST_OPCODE 2 %edx
4337    jmp       .LOP_SHL_LONG_finish
4338
4339/* ------------------------------ */
4340    .balign 64
4341.L_OP_SHR_LONG: /* 0xa4 */
4342/* File: x86/OP_SHR_LONG.S */
4343    /*
4344     * Long integer shift.  This is different from the generic 32/64-bit
4345     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4346     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4347     * 6 bits of the shift distance.  x86 shifts automatically mask off
4348     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4349     * case specially.
4350     */
4351    /* shr-long vAA, vBB, vCC */
4352    /* ecx gets shift count */
4353    /* Need to spill edx */
4354    /* rINSTw gets AA */
4355    movzbl    2(rPC),%eax               # eax<- BB
4356    movzbl    3(rPC),%ecx               # ecx<- CC
4357    GET_VREG_WORD %edx %eax 1           # edx<- v[BB+1]
4358    GET_VREG_R   %ecx %ecx              # ecx<- vCC
4359    GET_VREG_WORD %eax %eax 0           # eax<- v[BB+0]
4360    shrdl     %edx,%eax
4361    sarl      %cl,%edx
4362    testb     $32,%cl
4363    je        2f
4364    movl      %edx,%eax
4365    sarl      $31,%edx
43662:
4367    SET_VREG_WORD %edx rINST 1          # v[AA+1]<- edx
4368    FETCH_INST_OPCODE 2 %edx
4369    jmp       .LOP_SHR_LONG_finish
4370
4371/* ------------------------------ */
4372    .balign 64
4373.L_OP_USHR_LONG: /* 0xa5 */
4374/* File: x86/OP_USHR_LONG.S */
4375    /*
4376     * Long integer shift.  This is different from the generic 32/64-bit
4377     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4378     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4379     * 6 bits of the shift distance.  x86 shifts automatically mask off
4380     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4381     * case specially.
4382     */
4383    /* shr-long vAA, vBB, vCC */
4384    /* ecx gets shift count */
4385    /* Need to spill edx */
4386    /* rINSTw gets AA */
4387    movzbl    2(rPC),%eax               # eax<- BB
4388    movzbl    3(rPC),%ecx               # ecx<- CC
4389    GET_VREG_WORD %edx %eax 1           # edx<- v[BB+1]
4390    GET_VREG_R  %ecx %ecx               # ecx<- vCC
4391    GET_VREG_WORD %eax %eax 0           # eax<- v[BB+0]
4392    shrdl     %edx,%eax
4393    shrl      %cl,%edx
4394    testb     $32,%cl
4395    je        2f
4396    movl      %edx,%eax
4397    xorl      %edx,%edx
43982:
4399    SET_VREG_WORD %edx rINST 1          # v[AA+1]<- edx
4400    FETCH_INST_OPCODE 2 %edx
4401    jmp       .LOP_USHR_LONG_finish
4402
4403/* ------------------------------ */
4404    .balign 64
4405.L_OP_ADD_FLOAT: /* 0xa6 */
4406/* File: x86/OP_ADD_FLOAT.S */
4407/* File: x86/binflop.S */
4408    /*
4409     * Generic 32-bit binary float operation.
4410     *
4411     * For: add-fp, sub-fp, mul-fp, div-fp
4412     */
4413    /* binop vAA, vBB, vCC */
4414    movzbl   2(rPC),%eax          # eax<- CC
4415    movzbl   3(rPC),%ecx          # ecx<- BB
4416    flds    (rFP,%eax,4)         # vCC to fp stack
4417    fadds   (rFP,%ecx,4)         # ex: faddp
4418    FETCH_INST_OPCODE 2 %edx
4419    ADVANCE_PC 2
4420    fstps   (rFP,rINST,4)         # %st to vAA
4421    GOTO_NEXT_R %edx
4422
4423
4424/* ------------------------------ */
4425    .balign 64
4426.L_OP_SUB_FLOAT: /* 0xa7 */
4427/* File: x86/OP_SUB_FLOAT.S */
4428/* File: x86/binflop.S */
4429    /*
4430     * Generic 32-bit binary float operation.
4431     *
4432     * For: add-fp, sub-fp, mul-fp, div-fp
4433     */
4434    /* binop vAA, vBB, vCC */
4435    movzbl   2(rPC),%eax          # eax<- CC
4436    movzbl   3(rPC),%ecx          # ecx<- BB
4437    flds    (rFP,%eax,4)         # vCC to fp stack
4438    fsubs   (rFP,%ecx,4)         # ex: faddp
4439    FETCH_INST_OPCODE 2 %edx
4440    ADVANCE_PC 2
4441    fstps   (rFP,rINST,4)         # %st to vAA
4442    GOTO_NEXT_R %edx
4443
4444
4445/* ------------------------------ */
4446    .balign 64
4447.L_OP_MUL_FLOAT: /* 0xa8 */
4448/* File: x86/OP_MUL_FLOAT.S */
4449/* File: x86/binflop.S */
4450    /*
4451     * Generic 32-bit binary float operation.
4452     *
4453     * For: add-fp, sub-fp, mul-fp, div-fp
4454     */
4455    /* binop vAA, vBB, vCC */
4456    movzbl   2(rPC),%eax          # eax<- CC
4457    movzbl   3(rPC),%ecx          # ecx<- BB
4458    flds    (rFP,%eax,4)         # vCC to fp stack
4459    fmuls   (rFP,%ecx,4)         # ex: faddp
4460    FETCH_INST_OPCODE 2 %edx
4461    ADVANCE_PC 2
4462    fstps   (rFP,rINST,4)         # %st to vAA
4463    GOTO_NEXT_R %edx
4464
4465
4466/* ------------------------------ */
4467    .balign 64
4468.L_OP_DIV_FLOAT: /* 0xa9 */
4469/* File: x86/OP_DIV_FLOAT.S */
4470/* File: x86/binflop.S */
4471    /*
4472     * Generic 32-bit binary float operation.
4473     *
4474     * For: add-fp, sub-fp, mul-fp, div-fp
4475     */
4476    /* binop vAA, vBB, vCC */
4477    movzbl   2(rPC),%eax          # eax<- CC
4478    movzbl   3(rPC),%ecx          # ecx<- BB
4479    flds    (rFP,%eax,4)         # vCC to fp stack
4480    fdivs   (rFP,%ecx,4)         # ex: faddp
4481    FETCH_INST_OPCODE 2 %edx
4482    ADVANCE_PC 2
4483    fstps   (rFP,rINST,4)         # %st to vAA
4484    GOTO_NEXT_R %edx
4485
4486
4487/* ------------------------------ */
4488    .balign 64
4489.L_OP_REM_FLOAT: /* 0xaa */
4490/* File: x86/OP_REM_FLOAT.S */
4491    /* rem_float vAA, vBB, vCC */
4492    movzbl   3(rPC),%ecx            # ecx<- BB
4493    movzbl   2(rPC),%eax            # eax<- CC
4494    flds     (rFP,%ecx,4)           # vCC to fp stack
4495    flds     (rFP,%eax,4)           # vCC to fp stack
4496    movzbl   rINSTbl,%ecx           # ecx<- AA
4497    FETCH_INST_OPCODE 2 %edx
44981:
4499    fprem
4500    fstsw     %ax
4501    sahf
4502    jp        1b
4503    fstp      %st(1)
4504    ADVANCE_PC 2
4505    fstps    (rFP,%ecx,4)           # %st to vAA
4506    GOTO_NEXT_R %edx
4507
4508/* ------------------------------ */
4509    .balign 64
4510.L_OP_ADD_DOUBLE: /* 0xab */
4511/* File: x86/OP_ADD_DOUBLE.S */
4512/* File: x86/binflop.S */
4513    /*
4514     * Generic 32-bit binary float operation.
4515     *
4516     * For: add-fp, sub-fp, mul-fp, div-fp
4517     */
4518    /* binop vAA, vBB, vCC */
4519    movzbl   2(rPC),%eax          # eax<- CC
4520    movzbl   3(rPC),%ecx          # ecx<- BB
4521    fldl    (rFP,%eax,4)         # vCC to fp stack
4522    faddl   (rFP,%ecx,4)         # ex: faddp
4523    FETCH_INST_OPCODE 2 %edx
4524    ADVANCE_PC 2
4525    fstpl   (rFP,rINST,4)         # %st to vAA
4526    GOTO_NEXT_R %edx
4527
4528
4529/* ------------------------------ */
4530    .balign 64
4531.L_OP_SUB_DOUBLE: /* 0xac */
4532/* File: x86/OP_SUB_DOUBLE.S */
4533/* File: x86/binflop.S */
4534    /*
4535     * Generic 32-bit binary float operation.
4536     *
4537     * For: add-fp, sub-fp, mul-fp, div-fp
4538     */
4539    /* binop vAA, vBB, vCC */
4540    movzbl   2(rPC),%eax          # eax<- CC
4541    movzbl   3(rPC),%ecx          # ecx<- BB
4542    fldl    (rFP,%eax,4)         # vCC to fp stack
4543    fsubl   (rFP,%ecx,4)         # ex: faddp
4544    FETCH_INST_OPCODE 2 %edx
4545    ADVANCE_PC 2
4546    fstpl   (rFP,rINST,4)         # %st to vAA
4547    GOTO_NEXT_R %edx
4548
4549
4550/* ------------------------------ */
4551    .balign 64
4552.L_OP_MUL_DOUBLE: /* 0xad */
4553/* File: x86/OP_MUL_DOUBLE.S */
4554/* File: x86/binflop.S */
4555    /*
4556     * Generic 32-bit binary float operation.
4557     *
4558     * For: add-fp, sub-fp, mul-fp, div-fp
4559     */
4560    /* binop vAA, vBB, vCC */
4561    movzbl   2(rPC),%eax          # eax<- CC
4562    movzbl   3(rPC),%ecx          # ecx<- BB
4563    fldl    (rFP,%eax,4)         # vCC to fp stack
4564    fmull   (rFP,%ecx,4)         # ex: faddp
4565    FETCH_INST_OPCODE 2 %edx
4566    ADVANCE_PC 2
4567    fstpl   (rFP,rINST,4)         # %st to vAA
4568    GOTO_NEXT_R %edx
4569
4570
4571/* ------------------------------ */
4572    .balign 64
4573.L_OP_DIV_DOUBLE: /* 0xae */
4574/* File: x86/OP_DIV_DOUBLE.S */
4575/* File: x86/binflop.S */
4576    /*
4577     * Generic 32-bit binary float operation.
4578     *
4579     * For: add-fp, sub-fp, mul-fp, div-fp
4580     */
4581    /* binop vAA, vBB, vCC */
4582    movzbl   2(rPC),%eax          # eax<- CC
4583    movzbl   3(rPC),%ecx          # ecx<- BB
4584    fldl    (rFP,%eax,4)         # vCC to fp stack
4585    fdivl   (rFP,%ecx,4)         # ex: faddp
4586    FETCH_INST_OPCODE 2 %edx
4587    ADVANCE_PC 2
4588    fstpl   (rFP,rINST,4)         # %st to vAA
4589    GOTO_NEXT_R %edx
4590
4591
4592/* ------------------------------ */
4593    .balign 64
4594.L_OP_REM_DOUBLE: /* 0xaf */
4595/* File: x86/OP_REM_DOUBLE.S */
4596    /* rem_float vAA, vBB, vCC */
4597    movzbl   3(rPC),%ecx            # ecx<- BB
4598    movzbl   2(rPC),%eax            # eax<- CC
4599    fldl     (rFP,%ecx,4)           # vCC to fp stack
4600    fldl     (rFP,%eax,4)           # vCC to fp stack
4601    movzbl   rINSTbl,%ecx           # ecx<- AA
4602    FETCH_INST_OPCODE 2 %edx
46031:
4604    fprem
4605    fstsw     %ax
4606    sahf
4607    jp        1b
4608    fstp      %st(1)
4609    ADVANCE_PC 2
4610    fstpl    (rFP,%ecx,4)           # %st to vAA
4611    GOTO_NEXT_R %edx
4612
4613/* ------------------------------ */
4614    .balign 64
4615.L_OP_ADD_INT_2ADDR: /* 0xb0 */
4616/* File: x86/OP_ADD_INT_2ADDR.S */
4617/* File: x86/binop2addr.S */
4618    /*
4619     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4620     * that specifies an instruction that performs "result = r0 op r1".
4621     * This could be an ARM instruction or a function call.  (If the result
4622     * comes back in a register other than r0, you can override "result".)
4623     *
4624     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4625     * vCC (r1).  Useful for integer division and modulus.
4626     *
4627     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4628     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4629     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4630     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4631     */
4632    /* binop/2addr vA, vB */
4633    movzx   rINSTbl,%ecx               # ecx<- A+
4634    sarl    $4,rINST                 # rINST<- B
4635    GET_VREG_R %eax rINST              # eax<- vB
4636    FETCH_INST_OPCODE 1 %edx
4637    andb    $0xf,%cl                  # ecx<- A
4638    addl     %eax,(rFP,%ecx,4)                             # for ex: addl   %eax,(rFP,%ecx,4)
4639    ADVANCE_PC 1
4640    GOTO_NEXT_R %edx
4641
4642
4643/* ------------------------------ */
4644    .balign 64
4645.L_OP_SUB_INT_2ADDR: /* 0xb1 */
4646/* File: x86/OP_SUB_INT_2ADDR.S */
4647/* File: x86/binop2addr.S */
4648    /*
4649     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4650     * that specifies an instruction that performs "result = r0 op r1".
4651     * This could be an ARM instruction or a function call.  (If the result
4652     * comes back in a register other than r0, you can override "result".)
4653     *
4654     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4655     * vCC (r1).  Useful for integer division and modulus.
4656     *
4657     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4658     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4659     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4660     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4661     */
4662    /* binop/2addr vA, vB */
4663    movzx   rINSTbl,%ecx               # ecx<- A+
4664    sarl    $4,rINST                 # rINST<- B
4665    GET_VREG_R %eax rINST              # eax<- vB
4666    FETCH_INST_OPCODE 1 %edx
4667    andb    $0xf,%cl                  # ecx<- A
4668    subl     %eax,(rFP,%ecx,4)                             # for ex: addl   %eax,(rFP,%ecx,4)
4669    ADVANCE_PC 1
4670    GOTO_NEXT_R %edx
4671
4672
4673/* ------------------------------ */
4674    .balign 64
4675.L_OP_MUL_INT_2ADDR: /* 0xb2 */
4676/* File: x86/OP_MUL_INT_2ADDR.S */
4677    /* mul vA, vB */
4678    movzx   rINSTbl,%ecx               # ecx<- A+
4679    sarl    $4,rINST                 # rINST<- B
4680    GET_VREG_R %eax rINST              # eax<- vB
4681    andb    $0xf,%cl                  # ecx<- A
4682    imull   (rFP,%ecx,4),%eax
4683    FETCH_INST_OPCODE 1 %edx
4684    SET_VREG %eax %ecx
4685    ADVANCE_PC 1
4686    GOTO_NEXT_R %edx
4687
4688/* ------------------------------ */
4689    .balign 64
4690.L_OP_DIV_INT_2ADDR: /* 0xb3 */
4691/* File: x86/OP_DIV_INT_2ADDR.S */
4692/* File: x86/bindiv2addr.S */
4693    /*
4694     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
4695     * op1=-1.
4696     */
4697    /* div/rem/2addr vA, vB */
4698    movzx    rINSTbl,%ecx          # eax<- BA
4699    sarl     $4,%ecx              # ecx<- B
4700    GET_VREG_R %ecx %ecx           # eax<- vBB
4701    andb     $0xf,rINSTbl         # rINST<- A
4702    GET_VREG_R %eax rINST          # eax<- vBB
4703    cmpl     $0,%ecx
4704    je       common_errDivideByZero
4705    cmpl     $-1,%ecx
4706    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
4707    cmpl     $0x80000000,%eax
4708    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
4709    movl     $0x80000000,%eax
4710    jmp      .LOP_DIV_INT_2ADDR_finish_div2addr
4711
4712
4713
4714/* ------------------------------ */
4715    .balign 64
4716.L_OP_REM_INT_2ADDR: /* 0xb4 */
4717/* File: x86/OP_REM_INT_2ADDR.S */
4718/* File: x86/bindiv2addr.S */
4719    /*
4720     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
4721     * op1=-1.
4722     */
4723    /* div/rem/2addr vA, vB */
4724    movzx    rINSTbl,%ecx          # eax<- BA
4725    sarl     $4,%ecx              # ecx<- B
4726    GET_VREG_R %ecx %ecx           # eax<- vBB
4727    andb     $0xf,rINSTbl         # rINST<- A
4728    GET_VREG_R %eax rINST          # eax<- vBB
4729    cmpl     $0,%ecx
4730    je       common_errDivideByZero
4731    cmpl     $-1,%ecx
4732    jne      .LOP_REM_INT_2ADDR_continue_div2addr
4733    cmpl     $0x80000000,%eax
4734    jne      .LOP_REM_INT_2ADDR_continue_div2addr
4735    movl     $0,%edx
4736    jmp      .LOP_REM_INT_2ADDR_finish_div2addr
4737
4738
4739
4740/* ------------------------------ */
4741    .balign 64
4742.L_OP_AND_INT_2ADDR: /* 0xb5 */
4743/* File: x86/OP_AND_INT_2ADDR.S */
4744/* File: x86/binop2addr.S */
4745    /*
4746     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4747     * that specifies an instruction that performs "result = r0 op r1".
4748     * This could be an ARM instruction or a function call.  (If the result
4749     * comes back in a register other than r0, you can override "result".)
4750     *
4751     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4752     * vCC (r1).  Useful for integer division and modulus.
4753     *
4754     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4755     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4756     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4757     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4758     */
4759    /* binop/2addr vA, vB */
4760    movzx   rINSTbl,%ecx               # ecx<- A+
4761    sarl    $4,rINST                 # rINST<- B
4762    GET_VREG_R %eax rINST              # eax<- vB
4763    FETCH_INST_OPCODE 1 %edx
4764    andb    $0xf,%cl                  # ecx<- A
4765    andl     %eax,(rFP,%ecx,4)                             # for ex: addl   %eax,(rFP,%ecx,4)
4766    ADVANCE_PC 1
4767    GOTO_NEXT_R %edx
4768
4769
4770/* ------------------------------ */
4771    .balign 64
4772.L_OP_OR_INT_2ADDR: /* 0xb6 */
4773/* File: x86/OP_OR_INT_2ADDR.S */
4774/* File: x86/binop2addr.S */
4775    /*
4776     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4777     * that specifies an instruction that performs "result = r0 op r1".
4778     * This could be an ARM instruction or a function call.  (If the result
4779     * comes back in a register other than r0, you can override "result".)
4780     *
4781     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4782     * vCC (r1).  Useful for integer division and modulus.
4783     *
4784     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4785     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4786     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4787     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4788     */
4789    /* binop/2addr vA, vB */
4790    movzx   rINSTbl,%ecx               # ecx<- A+
4791    sarl    $4,rINST                 # rINST<- B
4792    GET_VREG_R %eax rINST              # eax<- vB
4793    FETCH_INST_OPCODE 1 %edx
4794    andb    $0xf,%cl                  # ecx<- A
4795    orl     %eax,(rFP,%ecx,4)                             # for ex: addl   %eax,(rFP,%ecx,4)
4796    ADVANCE_PC 1
4797    GOTO_NEXT_R %edx
4798
4799
4800/* ------------------------------ */
4801    .balign 64
4802.L_OP_XOR_INT_2ADDR: /* 0xb7 */
4803/* File: x86/OP_XOR_INT_2ADDR.S */
4804/* File: x86/binop2addr.S */
4805    /*
4806     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4807     * that specifies an instruction that performs "result = r0 op r1".
4808     * This could be an ARM instruction or a function call.  (If the result
4809     * comes back in a register other than r0, you can override "result".)
4810     *
4811     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4812     * vCC (r1).  Useful for integer division and modulus.
4813     *
4814     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4815     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4816     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4817     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4818     */
4819    /* binop/2addr vA, vB */
4820    movzx   rINSTbl,%ecx               # ecx<- A+
4821    sarl    $4,rINST                 # rINST<- B
4822    GET_VREG_R %eax rINST              # eax<- vB
4823    FETCH_INST_OPCODE 1 %edx
4824    andb    $0xf,%cl                  # ecx<- A
4825    xorl     %eax,(rFP,%ecx,4)                             # for ex: addl   %eax,(rFP,%ecx,4)
4826    ADVANCE_PC 1
4827    GOTO_NEXT_R %edx
4828
4829
4830/* ------------------------------ */
4831    .balign 64
4832.L_OP_SHL_INT_2ADDR: /* 0xb8 */
4833/* File: x86/OP_SHL_INT_2ADDR.S */
4834/* File: x86/shop2addr.S */
4835    /*
4836     * Generic 32-bit "shift/2addr" operation.
4837     */
4838    /* shift/2addr vA, vB */
4839    movzx    rINSTbl,%ecx           # eax<- BA
4840    sarl     $4,%ecx               # ecx<- B
4841    GET_VREG_R %ecx %ecx            # eax<- vBB
4842    andb     $0xf,rINSTbl          # rINST<- A
4843    GET_VREG_R %eax rINST           # eax<- vAA
4844    sall    %cl,%eax                          # ex: sarl %cl,%eax
4845    FETCH_INST_OPCODE 1 %edx
4846    SET_VREG %eax rINST
4847    ADVANCE_PC 1
4848    GOTO_NEXT_R %edx
4849
4850
4851/* ------------------------------ */
4852    .balign 64
4853.L_OP_SHR_INT_2ADDR: /* 0xb9 */
4854/* File: x86/OP_SHR_INT_2ADDR.S */
4855/* File: x86/shop2addr.S */
4856    /*
4857     * Generic 32-bit "shift/2addr" operation.
4858     */
4859    /* shift/2addr vA, vB */
4860    movzx    rINSTbl,%ecx           # eax<- BA
4861    sarl     $4,%ecx               # ecx<- B
4862    GET_VREG_R %ecx %ecx            # eax<- vBB
4863    andb     $0xf,rINSTbl          # rINST<- A
4864    GET_VREG_R %eax rINST           # eax<- vAA
4865    sarl    %cl,%eax                          # ex: sarl %cl,%eax
4866    FETCH_INST_OPCODE 1 %edx
4867    SET_VREG %eax rINST
4868    ADVANCE_PC 1
4869    GOTO_NEXT_R %edx
4870
4871
4872/* ------------------------------ */
4873    .balign 64
4874.L_OP_USHR_INT_2ADDR: /* 0xba */
4875/* File: x86/OP_USHR_INT_2ADDR.S */
4876/* File: x86/shop2addr.S */
4877    /*
4878     * Generic 32-bit "shift/2addr" operation.
4879     */
4880    /* shift/2addr vA, vB */
4881    movzx    rINSTbl,%ecx           # eax<- BA
4882    sarl     $4,%ecx               # ecx<- B
4883    GET_VREG_R %ecx %ecx            # eax<- vBB
4884    andb     $0xf,rINSTbl          # rINST<- A
4885    GET_VREG_R %eax rINST           # eax<- vAA
4886    shrl    %cl,%eax                          # ex: sarl %cl,%eax
4887    FETCH_INST_OPCODE 1 %edx
4888    SET_VREG %eax rINST
4889    ADVANCE_PC 1
4890    GOTO_NEXT_R %edx
4891
4892
4893/* ------------------------------ */
4894    .balign 64
4895.L_OP_ADD_LONG_2ADDR: /* 0xbb */
4896/* File: x86/OP_ADD_LONG_2ADDR.S */
4897/* File: x86/binopWide2addr.S */
4898    /*
4899     * Generic 64-bit binary operation.
4900     */
4901    /* binop/2addr vA, vB */
4902    movzbl    rINSTbl,%ecx              # ecx<- BA
4903    sarl      $4,%ecx                  # ecx<- B
4904    GET_VREG_WORD %eax %ecx 0           # eax<- v[B+0]
4905    GET_VREG_WORD %ecx %ecx 1           # eax<- v[B+1]
4906    andb      $0xF,rINSTbl             # rINST<- A
4907    addl %eax,(rFP,rINST,4)         # example: addl   %eax,(rFP,rINST,4)
4908    adcl %ecx,4(rFP,rINST,4)         # example: adcl   %ecx,4(rFP,rINST,4)
4909    FETCH_INST_OPCODE 1 %edx
4910    ADVANCE_PC 1
4911    GOTO_NEXT_R %edx
4912
4913
4914/* ------------------------------ */
4915    .balign 64
4916.L_OP_SUB_LONG_2ADDR: /* 0xbc */
4917/* File: x86/OP_SUB_LONG_2ADDR.S */
4918/* File: x86/binopWide2addr.S */
4919    /*
4920     * Generic 64-bit binary operation.
4921     */
4922    /* binop/2addr vA, vB */
4923    movzbl    rINSTbl,%ecx              # ecx<- BA
4924    sarl      $4,%ecx                  # ecx<- B
4925    GET_VREG_WORD %eax %ecx 0           # eax<- v[B+0]
4926    GET_VREG_WORD %ecx %ecx 1           # eax<- v[B+1]
4927    andb      $0xF,rINSTbl             # rINST<- A
4928    subl %eax,(rFP,rINST,4)         # example: addl   %eax,(rFP,rINST,4)
4929    sbbl %ecx,4(rFP,rINST,4)         # example: adcl   %ecx,4(rFP,rINST,4)
4930    FETCH_INST_OPCODE 1 %edx
4931    ADVANCE_PC 1
4932    GOTO_NEXT_R %edx
4933
4934
4935/* ------------------------------ */
4936    .balign 64
4937.L_OP_MUL_LONG_2ADDR: /* 0xbd */
4938/* File: x86/OP_MUL_LONG_2ADDR.S */
4939    /*
4940     * Signed 64-bit integer multiply, 2-addr version
4941     *
4942     * We could definately use more free registers for
4943     * this code.  We must spill %edx (edx) because it
4944     * is used by imul.  We'll also spill rINST (ebx),
4945     * giving us eax, ebc, ecx and edx as computational
4946     * temps.  On top of that, we'll spill %esi (edi)
4947     * for use as the vA pointer and rFP (esi) for use
4948     * as the vB pointer.  Yuck.
4949     */
4950    /* mul-long/2addr vA, vB */
4951    movzbl    rINSTbl,%eax             # eax<- BA
4952    andb      $0xf,%al                # eax<- A
4953    sarl      $4,rINST                # rINST<- B
4954    SPILL_TMP2(%esi)
4955    SPILL(rFP)
4956    leal      (rFP,%eax,4),%esi        # %esi<- &v[A]
4957    leal      (rFP,rINST,4),rFP        # rFP<- &v[B]
4958    movl      4(%esi),%ecx             # ecx<- Amsw
4959    imull     (rFP),%ecx               # ecx<- (Amsw*Blsw)
4960    movl      4(rFP),%eax              # eax<- Bmsw
4961    imull     (%esi),%eax              # eax<- (Bmsw*Alsw)
4962    addl      %eax,%ecx                # ecx<- (Amsw*Blsw)+(Bmsw*Alsw)
4963    movl      (rFP),%eax               # eax<- Blsw
4964    mull      (%esi)                   # eax<- (Blsw*Alsw)
4965    jmp       .LOP_MUL_LONG_2ADDR_continue
4966
4967/* ------------------------------ */
4968    .balign 64
4969.L_OP_DIV_LONG_2ADDR: /* 0xbe */
4970/* File: x86/OP_DIV_LONG_2ADDR.S */
4971    /* div/2addr vA, vB */
4972    movzbl    rINSTbl,%eax
4973    shrl      $4,%eax                  # eax<- B
4974    andb      $0xf,rINSTbl             # rINST<- A
4975    GET_VREG_WORD %edx %eax 0
4976    GET_VREG_WORD %eax %eax 1
4977    movl     %edx,OUT_ARG2(%esp)
4978    testl    %eax,%eax
4979    je       .LOP_DIV_LONG_2ADDR_check_zero
4980    cmpl     $-1,%eax
4981    je       .LOP_DIV_LONG_2ADDR_check_neg1
4982.LOP_DIV_LONG_2ADDR_notSpecial:
4983    GET_VREG_WORD %edx rINST 0
4984    GET_VREG_WORD %ecx rINST 1
4985.LOP_DIV_LONG_2ADDR_notSpecial1:
4986    jmp      .LOP_DIV_LONG_2ADDR_continue
4987
4988/* ------------------------------ */
4989    .balign 64
4990.L_OP_REM_LONG_2ADDR: /* 0xbf */
4991/* File: x86/OP_REM_LONG_2ADDR.S */
4992/* File: x86/OP_DIV_LONG_2ADDR.S */
4993    /* div/2addr vA, vB */
4994    movzbl    rINSTbl,%eax
4995    shrl      $4,%eax                  # eax<- B
4996    andb      $0xf,rINSTbl             # rINST<- A
4997    GET_VREG_WORD %edx %eax 0
4998    GET_VREG_WORD %eax %eax 1
4999    movl     %edx,OUT_ARG2(%esp)
5000    testl    %eax,%eax
5001    je       .LOP_REM_LONG_2ADDR_check_zero
5002    cmpl     $-1,%eax
5003    je       .LOP_REM_LONG_2ADDR_check_neg1
5004.LOP_REM_LONG_2ADDR_notSpecial:
5005    GET_VREG_WORD %edx rINST 0
5006    GET_VREG_WORD %ecx rINST 1
5007.LOP_REM_LONG_2ADDR_notSpecial1:
5008    jmp      .LOP_REM_LONG_2ADDR_continue
5009
5010
5011/* ------------------------------ */
5012    .balign 64
5013.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5014/* File: x86/OP_AND_LONG_2ADDR.S */
5015/* File: x86/binopWide2addr.S */
5016    /*
5017     * Generic 64-bit binary operation.
5018     */
5019    /* binop/2addr vA, vB */
5020    movzbl    rINSTbl,%ecx              # ecx<- BA
5021    sarl      $4,%ecx                  # ecx<- B
5022    GET_VREG_WORD %eax %ecx 0           # eax<- v[B+0]
5023    GET_VREG_WORD %ecx %ecx 1           # eax<- v[B+1]
5024    andb      $0xF,rINSTbl             # rINST<- A
5025    andl %eax,(rFP,rINST,4)         # example: addl   %eax,(rFP,rINST,4)
5026    andl %ecx,4(rFP,rINST,4)         # example: adcl   %ecx,4(rFP,rINST,4)
5027    FETCH_INST_OPCODE 1 %edx
5028    ADVANCE_PC 1
5029    GOTO_NEXT_R %edx
5030
5031
5032/* ------------------------------ */
5033    .balign 64
5034.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5035/* File: x86/OP_OR_LONG_2ADDR.S */
5036/* File: x86/binopWide2addr.S */
5037    /*
5038     * Generic 64-bit binary operation.
5039     */
5040    /* binop/2addr vA, vB */
5041    movzbl    rINSTbl,%ecx              # ecx<- BA
5042    sarl      $4,%ecx                  # ecx<- B
5043    GET_VREG_WORD %eax %ecx 0           # eax<- v[B+0]
5044    GET_VREG_WORD %ecx %ecx 1           # eax<- v[B+1]
5045    andb      $0xF,rINSTbl             # rINST<- A
5046    orl %eax,(rFP,rINST,4)         # example: addl   %eax,(rFP,rINST,4)
5047    orl %ecx,4(rFP,rINST,4)         # example: adcl   %ecx,4(rFP,rINST,4)
5048    FETCH_INST_OPCODE 1 %edx
5049    ADVANCE_PC 1
5050    GOTO_NEXT_R %edx
5051
5052
5053/* ------------------------------ */
5054    .balign 64
5055.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5056/* File: x86/OP_XOR_LONG_2ADDR.S */
5057/* File: x86/binopWide2addr.S */
5058    /*
5059     * Generic 64-bit binary operation.
5060     */
5061    /* binop/2addr vA, vB */
5062    movzbl    rINSTbl,%ecx              # ecx<- BA
5063    sarl      $4,%ecx                  # ecx<- B
5064    GET_VREG_WORD %eax %ecx 0           # eax<- v[B+0]
5065    GET_VREG_WORD %ecx %ecx 1           # eax<- v[B+1]
5066    andb      $0xF,rINSTbl             # rINST<- A
5067    xorl %eax,(rFP,rINST,4)         # example: addl   %eax,(rFP,rINST,4)
5068    xorl %ecx,4(rFP,rINST,4)         # example: adcl   %ecx,4(rFP,rINST,4)
5069    FETCH_INST_OPCODE 1 %edx
5070    ADVANCE_PC 1
5071    GOTO_NEXT_R %edx
5072
5073
5074/* ------------------------------ */
5075    .balign 64
5076.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5077/* File: x86/OP_SHL_LONG_2ADDR.S */
5078    /*
5079     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5080     * 32-bit shift distance.
5081     */
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
5092    shldl     %eax,%edx
5093    sall      %cl,%eax
5094    testb     $32,%cl
5095    je        2f
5096    movl      %eax,%edx
5097    xorl      %eax,%eax
50982:
5099    SET_VREG_WORD %edx rINST 1         # v[AA+1]<- edx
5100    jmp       .LOP_SHL_LONG_2ADDR_finish
5101
5102/* ------------------------------ */
5103    .balign 64
5104.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5105/* File: x86/OP_SHR_LONG_2ADDR.S */
5106    /*
5107     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5108     * 32-bit shift distance.
5109     */
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
5120    shrdl     %edx,%eax
5121    sarl      %cl,%edx
5122    testb     $32,%cl
5123    je        2f
5124    movl      %edx,%eax
5125    sarl      $31,%edx
51262:
5127    SET_VREG_WORD %edx rINST 1     # v[AA+1]<- edx
5128    jmp       .LOP_SHR_LONG_2ADDR_finish
5129
5130/* ------------------------------ */
5131    .balign 64
5132.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
5133/* File: x86/OP_USHR_LONG_2ADDR.S */
5134    /*
5135     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5136     * 32-bit shift distance.
5137     */
5138    /* shl-long/2addr vA, vB */
5139    /* ecx gets shift count */
5140    /* Need to spill edx */
5141    /* rINSTw gets AA */
5142    movzbl    rINSTbl,%ecx             # ecx<- BA
5143    andb      $0xf,rINSTbl            # rINST<- A
5144    GET_VREG_WORD %eax rINST 0         # eax<- v[AA+0]
5145    sarl      $4,%ecx                 # ecx<- B
5146    GET_VREG_WORD %edx rINST 1         # edx<- v[AA+1]
5147    GET_VREG_R %ecx %ecx               # ecx<- vBB
5148    shrdl     %edx,%eax
5149    shrl      %cl,%edx
5150    testb     $32,%cl
5151    je        2f
5152    movl      %edx,%eax
5153    xorl      %edx,%edx
51542:
5155    SET_VREG_WORD %edx rINST 1         # v[AA+1]<- edx
5156    jmp       .LOP_USHR_LONG_2ADDR_finish
5157
5158/* ------------------------------ */
5159    .balign 64
5160.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
5161/* File: x86/OP_ADD_FLOAT_2ADDR.S */
5162/* File: x86/binflop2addr.S */
5163    /*
5164     * Generic 32-bit binary float operation.
5165     *
5166     * For: add-fp, sub-fp, mul-fp, div-fp
5167     */
5168
5169    /* binop/2addr vA, vB */
5170    movzx   rINSTbl,%ecx           # ecx<- A+
5171    andb    $0xf,%cl              # ecx<- A
5172    flds    (rFP,%ecx,4)          # vAA to fp stack
5173    sarl    $4,rINST             # rINST<- B
5174    fadds   (rFP,rINST,4)         # ex: faddp
5175    FETCH_INST_OPCODE 1 %edx
5176    ADVANCE_PC 1
5177    fstps    (rFP,%ecx,4)         # %st to vA
5178    GOTO_NEXT_R %edx
5179
5180
5181/* ------------------------------ */
5182    .balign 64
5183.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
5184/* File: x86/OP_SUB_FLOAT_2ADDR.S */
5185/* File: x86/binflop2addr.S */
5186    /*
5187     * Generic 32-bit binary float operation.
5188     *
5189     * For: add-fp, sub-fp, mul-fp, div-fp
5190     */
5191
5192    /* binop/2addr vA, vB */
5193    movzx   rINSTbl,%ecx           # ecx<- A+
5194    andb    $0xf,%cl              # ecx<- A
5195    flds    (rFP,%ecx,4)          # vAA to fp stack
5196    sarl    $4,rINST             # rINST<- B
5197    fsubs   (rFP,rINST,4)         # ex: faddp
5198    FETCH_INST_OPCODE 1 %edx
5199    ADVANCE_PC 1
5200    fstps    (rFP,%ecx,4)         # %st to vA
5201    GOTO_NEXT_R %edx
5202
5203
5204/* ------------------------------ */
5205    .balign 64
5206.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
5207/* File: x86/OP_MUL_FLOAT_2ADDR.S */
5208/* File: x86/binflop2addr.S */
5209    /*
5210     * Generic 32-bit binary float operation.
5211     *
5212     * For: add-fp, sub-fp, mul-fp, div-fp
5213     */
5214
5215    /* binop/2addr vA, vB */
5216    movzx   rINSTbl,%ecx           # ecx<- A+
5217    andb    $0xf,%cl              # ecx<- A
5218    flds    (rFP,%ecx,4)          # vAA to fp stack
5219    sarl    $4,rINST             # rINST<- B
5220    fmuls   (rFP,rINST,4)         # ex: faddp
5221    FETCH_INST_OPCODE 1 %edx
5222    ADVANCE_PC 1
5223    fstps    (rFP,%ecx,4)         # %st to vA
5224    GOTO_NEXT_R %edx
5225
5226
5227/* ------------------------------ */
5228    .balign 64
5229.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
5230/* File: x86/OP_DIV_FLOAT_2ADDR.S */
5231/* File: x86/binflop2addr.S */
5232    /*
5233     * Generic 32-bit binary float operation.
5234     *
5235     * For: add-fp, sub-fp, mul-fp, div-fp
5236     */
5237
5238    /* binop/2addr vA, vB */
5239    movzx   rINSTbl,%ecx           # ecx<- A+
5240    andb    $0xf,%cl              # ecx<- A
5241    flds    (rFP,%ecx,4)          # vAA to fp stack
5242    sarl    $4,rINST             # rINST<- B
5243    fdivs   (rFP,rINST,4)         # ex: faddp
5244    FETCH_INST_OPCODE 1 %edx
5245    ADVANCE_PC 1
5246    fstps    (rFP,%ecx,4)         # %st to vA
5247    GOTO_NEXT_R %edx
5248
5249
5250/* ------------------------------ */
5251    .balign 64
5252.L_OP_REM_FLOAT_2ADDR: /* 0xca */
5253/* File: x86/OP_REM_FLOAT_2ADDR.S */
5254    /* rem_float/2addr vA, vB */
5255    movzx   rINSTbl,%ecx                # ecx<- A+
5256    sarl    $4,rINST                  # rINST<- B
5257    flds     (rFP,rINST,4)              # vBB to fp stack
5258    andb    $0xf,%cl                   # ecx<- A
5259    flds     (rFP,%ecx,4)               # vAA to fp stack
5260    FETCH_INST_OPCODE 1 %edx
52611:
5262    fprem
5263    fstsw     %ax
5264    sahf
5265    jp        1b
5266    fstp      %st(1)
5267    ADVANCE_PC 1
5268    fstps    (rFP,%ecx,4)               # %st to vA
5269    GOTO_NEXT_R %edx
5270
5271/* ------------------------------ */
5272    .balign 64
5273.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
5274/* File: x86/OP_ADD_DOUBLE_2ADDR.S */
5275/* File: x86/binflop2addr.S */
5276    /*
5277     * Generic 32-bit binary float operation.
5278     *
5279     * For: add-fp, sub-fp, mul-fp, div-fp
5280     */
5281
5282    /* binop/2addr vA, vB */
5283    movzx   rINSTbl,%ecx           # ecx<- A+
5284    andb    $0xf,%cl              # ecx<- A
5285    fldl    (rFP,%ecx,4)          # vAA to fp stack
5286    sarl    $4,rINST             # rINST<- B
5287    faddl   (rFP,rINST,4)         # ex: faddp
5288    FETCH_INST_OPCODE 1 %edx
5289    ADVANCE_PC 1
5290    fstpl    (rFP,%ecx,4)         # %st to vA
5291    GOTO_NEXT_R %edx
5292
5293
5294/* ------------------------------ */
5295    .balign 64
5296.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
5297/* File: x86/OP_SUB_DOUBLE_2ADDR.S */
5298/* File: x86/binflop2addr.S */
5299    /*
5300     * Generic 32-bit binary float operation.
5301     *
5302     * For: add-fp, sub-fp, mul-fp, div-fp
5303     */
5304
5305    /* binop/2addr vA, vB */
5306    movzx   rINSTbl,%ecx           # ecx<- A+
5307    andb    $0xf,%cl              # ecx<- A
5308    fldl    (rFP,%ecx,4)          # vAA to fp stack
5309    sarl    $4,rINST             # rINST<- B
5310    fsubl   (rFP,rINST,4)         # ex: faddp
5311    FETCH_INST_OPCODE 1 %edx
5312    ADVANCE_PC 1
5313    fstpl    (rFP,%ecx,4)         # %st to vA
5314    GOTO_NEXT_R %edx
5315
5316
5317/* ------------------------------ */
5318    .balign 64
5319.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
5320/* File: x86/OP_MUL_DOUBLE_2ADDR.S */
5321/* File: x86/binflop2addr.S */
5322    /*
5323     * Generic 32-bit binary float operation.
5324     *
5325     * For: add-fp, sub-fp, mul-fp, div-fp
5326     */
5327
5328    /* binop/2addr vA, vB */
5329    movzx   rINSTbl,%ecx           # ecx<- A+
5330    andb    $0xf,%cl              # ecx<- A
5331    fldl    (rFP,%ecx,4)          # vAA to fp stack
5332    sarl    $4,rINST             # rINST<- B
5333    fmull   (rFP,rINST,4)         # ex: faddp
5334    FETCH_INST_OPCODE 1 %edx
5335    ADVANCE_PC 1
5336    fstpl    (rFP,%ecx,4)         # %st to vA
5337    GOTO_NEXT_R %edx
5338
5339
5340/* ------------------------------ */
5341    .balign 64
5342.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
5343/* File: x86/OP_DIV_DOUBLE_2ADDR.S */
5344/* File: x86/binflop2addr.S */
5345    /*
5346     * Generic 32-bit binary float operation.
5347     *
5348     * For: add-fp, sub-fp, mul-fp, div-fp
5349     */
5350
5351    /* binop/2addr vA, vB */
5352    movzx   rINSTbl,%ecx           # ecx<- A+
5353    andb    $0xf,%cl              # ecx<- A
5354    fldl    (rFP,%ecx,4)          # vAA to fp stack
5355    sarl    $4,rINST             # rINST<- B
5356    fdivl   (rFP,rINST,4)         # ex: faddp
5357    FETCH_INST_OPCODE 1 %edx
5358    ADVANCE_PC 1
5359    fstpl    (rFP,%ecx,4)         # %st to vA
5360    GOTO_NEXT_R %edx
5361
5362
5363/* ------------------------------ */
5364    .balign 64
5365.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
5366/* File: x86/OP_REM_DOUBLE_2ADDR.S */
5367    /* rem_float/2addr vA, vB */
5368    movzx   rINSTbl,%ecx                # ecx<- A+
5369    sarl    $4,rINST                  # rINST<- B
5370    fldl     (rFP,rINST,4)              # vBB to fp stack
5371    andb    $0xf,%cl                   # ecx<- A
5372    fldl     (rFP,%ecx,4)               # vAA to fp stack
5373    FETCH_INST_OPCODE 1 %edx
53741:
5375    fprem
5376    fstsw     %ax
5377    sahf
5378    jp        1b
5379    fstp      %st(1)
5380    ADVANCE_PC 1
5381    fstpl    (rFP,%ecx,4)               # %st to vA
5382    GOTO_NEXT_R %edx
5383
5384/* ------------------------------ */
5385    .balign 64
5386.L_OP_ADD_INT_LIT16: /* 0xd0 */
5387/* File: x86/OP_ADD_INT_LIT16.S */
5388/* File: x86/binopLit16.S */
5389    /*
5390     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5391     * that specifies an instruction that performs "result = eax op ecx".
5392     * This could be an x86 instruction or a function call.  (If the result
5393     * comes back in a register other than eax, you can override "result".)
5394     *
5395     * For: add-int/lit16, rsub-int,
5396     *      and-int/lit16, or-int/lit16, xor-int/lit16
5397     */
5398    /* binop/lit16 vA, vB, #+CCCC */
5399    movzbl   rINSTbl,%eax               # eax<- 000000BA
5400    sarl     $4,%eax                   # eax<- B
5401    GET_VREG_R %eax %eax                # eax<- vB
5402    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5403    andb     $0xf,rINSTbl              # rINST<- A
5404    addl %ecx,%eax                              # for example: addl %ecx, %eax
5405    SET_VREG %eax rINST
5406    FETCH_INST_OPCODE 2 %edx
5407    ADVANCE_PC 2
5408    GOTO_NEXT_R %edx
5409
5410
5411/* ------------------------------ */
5412    .balign 64
5413.L_OP_RSUB_INT: /* 0xd1 */
5414/* File: x86/OP_RSUB_INT.S */
5415/* File: x86/binopLit16.S */
5416    /*
5417     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5418     * that specifies an instruction that performs "result = eax op ecx".
5419     * This could be an x86 instruction or a function call.  (If the result
5420     * comes back in a register other than eax, you can override "result".)
5421     *
5422     * For: add-int/lit16, rsub-int,
5423     *      and-int/lit16, or-int/lit16, xor-int/lit16
5424     */
5425    /* binop/lit16 vA, vB, #+CCCC */
5426    movzbl   rINSTbl,%eax               # eax<- 000000BA
5427    sarl     $4,%eax                   # eax<- B
5428    GET_VREG_R %eax %eax                # eax<- vB
5429    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5430    andb     $0xf,rINSTbl              # rINST<- A
5431    subl %eax,%ecx                              # for example: addl %ecx, %eax
5432    SET_VREG %ecx rINST
5433    FETCH_INST_OPCODE 2 %edx
5434    ADVANCE_PC 2
5435    GOTO_NEXT_R %edx
5436
5437
5438/* ------------------------------ */
5439    .balign 64
5440.L_OP_MUL_INT_LIT16: /* 0xd2 */
5441/* File: x86/OP_MUL_INT_LIT16.S */
5442    /* mul/lit16 vA, vB, #+CCCC */
5443    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5444    movzbl   rINSTbl,%eax               # eax<- 000000BA
5445    sarl     $4,%eax                   # eax<- B
5446    GET_VREG_R %eax %eax                # eax<- vB
5447    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5448    andb     $0xf,rINSTbl              # rINST<- A
5449    imull     %ecx,%eax                 # trashes edx
5450    FETCH_INST_OPCODE 2 %edx
5451    ADVANCE_PC 2
5452    SET_VREG %eax rINST
5453    GOTO_NEXT_R %edx
5454
5455/* ------------------------------ */
5456    .balign 64
5457.L_OP_DIV_INT_LIT16: /* 0xd3 */
5458/* File: x86/OP_DIV_INT_LIT16.S */
5459/* File: x86/bindivLit16.S */
5460    /*
5461     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
5462     * op1=-1.
5463     */
5464    /* div/rem/lit16 vA, vB, #+CCCC */
5465    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5466    movzbl   rINSTbl,%eax         # eax<- 000000BA
5467    sarl     $4,%eax             # eax<- B
5468    GET_VREG_R %eax %eax          # eax<- vB
5469    movswl   2(rPC),%ecx          # ecx<- ssssCCCC
5470    andb     $0xf,rINSTbl        # rINST<- A
5471    cmpl     $0,%ecx
5472    je       common_errDivideByZero
5473    cmpl     $-1,%ecx
5474    jne      .LOP_DIV_INT_LIT16_continue_div
5475    cmpl     $0x80000000,%eax
5476    jne      .LOP_DIV_INT_LIT16_continue_div
5477    movl     $0x80000000,%eax
5478    jmp      .LOP_DIV_INT_LIT16_finish_div
5479
5480
5481
5482/* ------------------------------ */
5483    .balign 64
5484.L_OP_REM_INT_LIT16: /* 0xd4 */
5485/* File: x86/OP_REM_INT_LIT16.S */
5486/* File: x86/bindivLit16.S */
5487    /*
5488     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
5489     * op1=-1.
5490     */
5491    /* div/rem/lit16 vA, vB, #+CCCC */
5492    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
5493    movzbl   rINSTbl,%eax         # eax<- 000000BA
5494    sarl     $4,%eax             # eax<- B
5495    GET_VREG_R %eax %eax          # eax<- vB
5496    movswl   2(rPC),%ecx          # ecx<- ssssCCCC
5497    andb     $0xf,rINSTbl        # rINST<- A
5498    cmpl     $0,%ecx
5499    je       common_errDivideByZero
5500    cmpl     $-1,%ecx
5501    jne      .LOP_REM_INT_LIT16_continue_div
5502    cmpl     $0x80000000,%eax
5503    jne      .LOP_REM_INT_LIT16_continue_div
5504    movl     $0,%edx
5505    jmp      .LOP_REM_INT_LIT16_finish_div
5506
5507
5508
5509/* ------------------------------ */
5510    .balign 64
5511.L_OP_AND_INT_LIT16: /* 0xd5 */
5512/* File: x86/OP_AND_INT_LIT16.S */
5513/* File: x86/binopLit16.S */
5514    /*
5515     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5516     * that specifies an instruction that performs "result = eax op ecx".
5517     * This could be an x86 instruction or a function call.  (If the result
5518     * comes back in a register other than eax, you can override "result".)
5519     *
5520     * For: add-int/lit16, rsub-int,
5521     *      and-int/lit16, or-int/lit16, xor-int/lit16
5522     */
5523    /* binop/lit16 vA, vB, #+CCCC */
5524    movzbl   rINSTbl,%eax               # eax<- 000000BA
5525    sarl     $4,%eax                   # eax<- B
5526    GET_VREG_R %eax %eax                # eax<- vB
5527    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5528    andb     $0xf,rINSTbl              # rINST<- A
5529    andl %ecx,%eax                              # for example: addl %ecx, %eax
5530    SET_VREG %eax rINST
5531    FETCH_INST_OPCODE 2 %edx
5532    ADVANCE_PC 2
5533    GOTO_NEXT_R %edx
5534
5535
5536/* ------------------------------ */
5537    .balign 64
5538.L_OP_OR_INT_LIT16: /* 0xd6 */
5539/* File: x86/OP_OR_INT_LIT16.S */
5540/* File: x86/binopLit16.S */
5541    /*
5542     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5543     * that specifies an instruction that performs "result = eax op ecx".
5544     * This could be an x86 instruction or a function call.  (If the result
5545     * comes back in a register other than eax, you can override "result".)
5546     *
5547     * For: add-int/lit16, rsub-int,
5548     *      and-int/lit16, or-int/lit16, xor-int/lit16
5549     */
5550    /* binop/lit16 vA, vB, #+CCCC */
5551    movzbl   rINSTbl,%eax               # eax<- 000000BA
5552    sarl     $4,%eax                   # eax<- B
5553    GET_VREG_R %eax %eax                # eax<- vB
5554    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5555    andb     $0xf,rINSTbl              # rINST<- A
5556    orl     %ecx,%eax                              # for example: addl %ecx, %eax
5557    SET_VREG %eax rINST
5558    FETCH_INST_OPCODE 2 %edx
5559    ADVANCE_PC 2
5560    GOTO_NEXT_R %edx
5561
5562
5563/* ------------------------------ */
5564    .balign 64
5565.L_OP_XOR_INT_LIT16: /* 0xd7 */
5566/* File: x86/OP_XOR_INT_LIT16.S */
5567/* File: x86/binopLit16.S */
5568    /*
5569     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5570     * that specifies an instruction that performs "result = eax op ecx".
5571     * This could be an x86 instruction or a function call.  (If the result
5572     * comes back in a register other than eax, you can override "result".)
5573     *
5574     * For: add-int/lit16, rsub-int,
5575     *      and-int/lit16, or-int/lit16, xor-int/lit16
5576     */
5577    /* binop/lit16 vA, vB, #+CCCC */
5578    movzbl   rINSTbl,%eax               # eax<- 000000BA
5579    sarl     $4,%eax                   # eax<- B
5580    GET_VREG_R %eax %eax                # eax<- vB
5581    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5582    andb     $0xf,rINSTbl              # rINST<- A
5583    xor    %ecx,%eax                              # for example: addl %ecx, %eax
5584    SET_VREG %eax rINST
5585    FETCH_INST_OPCODE 2 %edx
5586    ADVANCE_PC 2
5587    GOTO_NEXT_R %edx
5588
5589
5590/* ------------------------------ */
5591    .balign 64
5592.L_OP_ADD_INT_LIT8: /* 0xd8 */
5593/* File: x86/OP_ADD_INT_LIT8.S */
5594/* File: x86/binopLit8.S */
5595    /*
5596     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5597     * that specifies an instruction that performs "result = eax op ecx".
5598     * This could be an x86 instruction or a function call.  (If the result
5599     * comes back in a register other than r0, you can override "result".)
5600     *
5601     * For: add-int/lit8, rsub-int/lit8
5602     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5603     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5604     */
5605    /* binop/lit8 vAA, vBB, #+CC */
5606    movzbl    2(rPC),%eax              # eax<- BB
5607    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5608    GET_VREG_R   %eax %eax             # eax<- rBB
5609    addl %ecx,%eax                             # ex: addl %ecx,%eax
5610    FETCH_INST_OPCODE 2 %edx
5611    SET_VREG   %eax rINST
5612    ADVANCE_PC 2
5613    GOTO_NEXT_R %edx
5614
5615
5616/* ------------------------------ */
5617    .balign 64
5618.L_OP_RSUB_INT_LIT8: /* 0xd9 */
5619/* File: x86/OP_RSUB_INT_LIT8.S */
5620/* File: x86/binopLit8.S */
5621    /*
5622     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5623     * that specifies an instruction that performs "result = eax op ecx".
5624     * This could be an x86 instruction or a function call.  (If the result
5625     * comes back in a register other than r0, you can override "result".)
5626     *
5627     * For: add-int/lit8, rsub-int/lit8
5628     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5629     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5630     */
5631    /* binop/lit8 vAA, vBB, #+CC */
5632    movzbl    2(rPC),%eax              # eax<- BB
5633    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5634    GET_VREG_R   %eax %eax             # eax<- rBB
5635    subl  %eax,%ecx                             # ex: addl %ecx,%eax
5636    FETCH_INST_OPCODE 2 %edx
5637    SET_VREG   %ecx rINST
5638    ADVANCE_PC 2
5639    GOTO_NEXT_R %edx
5640
5641
5642/* ------------------------------ */
5643    .balign 64
5644.L_OP_MUL_INT_LIT8: /* 0xda */
5645/* File: x86/OP_MUL_INT_LIT8.S */
5646    /* mul/lit8 vAA, vBB, #+CC */
5647    movzbl    2(rPC),%eax              # eax<- BB
5648    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5649    GET_VREG_R   %eax %eax             # eax<- rBB
5650    imull     %ecx,%eax                # trashes edx
5651    FETCH_INST_OPCODE 2 %edx
5652    ADVANCE_PC 2
5653    SET_VREG  %eax rINST
5654    GOTO_NEXT_R %edx
5655
5656/* ------------------------------ */
5657    .balign 64
5658.L_OP_DIV_INT_LIT8: /* 0xdb */
5659/* File: x86/OP_DIV_INT_LIT8.S */
5660/* File: x86/bindivLit8.S */
5661    /*
5662     * 32-bit div/rem "lit8" binary operation.  Handles special case of
5663     * op0=minint & op1=-1
5664     */
5665    /* div/rem/lit8 vAA, vBB, #+CC */
5666    movzbl    2(rPC),%eax        # eax<- BB
5667    movsbl    3(rPC),%ecx        # ecx<- ssssssCC
5668    GET_VREG_R  %eax %eax        # eax<- rBB
5669    cmpl     $0,%ecx
5670    je       common_errDivideByZero
5671    cmpl     $0x80000000,%eax
5672    jne      .LOP_DIV_INT_LIT8_continue_div
5673    cmpl     $-1,%ecx
5674    jne      .LOP_DIV_INT_LIT8_continue_div
5675    movl     $0x80000000,%eax
5676    jmp      .LOP_DIV_INT_LIT8_finish_div
5677
5678
5679
5680/* ------------------------------ */
5681    .balign 64
5682.L_OP_REM_INT_LIT8: /* 0xdc */
5683/* File: x86/OP_REM_INT_LIT8.S */
5684/* File: x86/bindivLit8.S */
5685    /*
5686     * 32-bit div/rem "lit8" binary operation.  Handles special case of
5687     * op0=minint & op1=-1
5688     */
5689    /* div/rem/lit8 vAA, vBB, #+CC */
5690    movzbl    2(rPC),%eax        # eax<- BB
5691    movsbl    3(rPC),%ecx        # ecx<- ssssssCC
5692    GET_VREG_R  %eax %eax        # eax<- rBB
5693    cmpl     $0,%ecx
5694    je       common_errDivideByZero
5695    cmpl     $0x80000000,%eax
5696    jne      .LOP_REM_INT_LIT8_continue_div
5697    cmpl     $-1,%ecx
5698    jne      .LOP_REM_INT_LIT8_continue_div
5699    movl     $0,%edx
5700    jmp      .LOP_REM_INT_LIT8_finish_div
5701
5702
5703
5704/* ------------------------------ */
5705    .balign 64
5706.L_OP_AND_INT_LIT8: /* 0xdd */
5707/* File: x86/OP_AND_INT_LIT8.S */
5708/* File: x86/binopLit8.S */
5709    /*
5710     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5711     * that specifies an instruction that performs "result = eax op ecx".
5712     * This could be an x86 instruction or a function call.  (If the result
5713     * comes back in a register other than r0, you can override "result".)
5714     *
5715     * For: add-int/lit8, rsub-int/lit8
5716     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5717     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5718     */
5719    /* binop/lit8 vAA, vBB, #+CC */
5720    movzbl    2(rPC),%eax              # eax<- BB
5721    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5722    GET_VREG_R   %eax %eax             # eax<- rBB
5723    andl %ecx,%eax                             # ex: addl %ecx,%eax
5724    FETCH_INST_OPCODE 2 %edx
5725    SET_VREG   %eax rINST
5726    ADVANCE_PC 2
5727    GOTO_NEXT_R %edx
5728
5729
5730/* ------------------------------ */
5731    .balign 64
5732.L_OP_OR_INT_LIT8: /* 0xde */
5733/* File: x86/OP_OR_INT_LIT8.S */
5734/* File: x86/binopLit8.S */
5735    /*
5736     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5737     * that specifies an instruction that performs "result = eax op ecx".
5738     * This could be an x86 instruction or a function call.  (If the result
5739     * comes back in a register other than r0, you can override "result".)
5740     *
5741     * For: add-int/lit8, rsub-int/lit8
5742     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5743     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5744     */
5745    /* binop/lit8 vAA, vBB, #+CC */
5746    movzbl    2(rPC),%eax              # eax<- BB
5747    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5748    GET_VREG_R   %eax %eax             # eax<- rBB
5749    orl     %ecx,%eax                             # ex: addl %ecx,%eax
5750    FETCH_INST_OPCODE 2 %edx
5751    SET_VREG   %eax rINST
5752    ADVANCE_PC 2
5753    GOTO_NEXT_R %edx
5754
5755
5756/* ------------------------------ */
5757    .balign 64
5758.L_OP_XOR_INT_LIT8: /* 0xdf */
5759/* File: x86/OP_XOR_INT_LIT8.S */
5760/* File: x86/binopLit8.S */
5761    /*
5762     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5763     * that specifies an instruction that performs "result = eax op ecx".
5764     * This could be an x86 instruction or a function call.  (If the result
5765     * comes back in a register other than r0, you can override "result".)
5766     *
5767     * For: add-int/lit8, rsub-int/lit8
5768     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5769     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5770     */
5771    /* binop/lit8 vAA, vBB, #+CC */
5772    movzbl    2(rPC),%eax              # eax<- BB
5773    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5774    GET_VREG_R   %eax %eax             # eax<- rBB
5775    xor    %ecx,%eax                             # ex: addl %ecx,%eax
5776    FETCH_INST_OPCODE 2 %edx
5777    SET_VREG   %eax rINST
5778    ADVANCE_PC 2
5779    GOTO_NEXT_R %edx
5780
5781
5782/* ------------------------------ */
5783    .balign 64
5784.L_OP_SHL_INT_LIT8: /* 0xe0 */
5785/* File: x86/OP_SHL_INT_LIT8.S */
5786/* File: x86/binopLit8.S */
5787    /*
5788     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5789     * that specifies an instruction that performs "result = eax op ecx".
5790     * This could be an x86 instruction or a function call.  (If the result
5791     * comes back in a register other than r0, you can override "result".)
5792     *
5793     * For: add-int/lit8, rsub-int/lit8
5794     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5795     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5796     */
5797    /* binop/lit8 vAA, vBB, #+CC */
5798    movzbl    2(rPC),%eax              # eax<- BB
5799    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5800    GET_VREG_R   %eax %eax             # eax<- rBB
5801    sall  %cl,%eax                             # ex: addl %ecx,%eax
5802    FETCH_INST_OPCODE 2 %edx
5803    SET_VREG   %eax rINST
5804    ADVANCE_PC 2
5805    GOTO_NEXT_R %edx
5806
5807
5808/* ------------------------------ */
5809    .balign 64
5810.L_OP_SHR_INT_LIT8: /* 0xe1 */
5811/* File: x86/OP_SHR_INT_LIT8.S */
5812/* File: x86/binopLit8.S */
5813    /*
5814     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5815     * that specifies an instruction that performs "result = eax op ecx".
5816     * This could be an x86 instruction or a function call.  (If the result
5817     * comes back in a register other than r0, you can override "result".)
5818     *
5819     * For: add-int/lit8, rsub-int/lit8
5820     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5821     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5822     */
5823    /* binop/lit8 vAA, vBB, #+CC */
5824    movzbl    2(rPC),%eax              # eax<- BB
5825    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5826    GET_VREG_R   %eax %eax             # eax<- rBB
5827    sarl    %cl,%eax                             # ex: addl %ecx,%eax
5828    FETCH_INST_OPCODE 2 %edx
5829    SET_VREG   %eax rINST
5830    ADVANCE_PC 2
5831    GOTO_NEXT_R %edx
5832
5833
5834/* ------------------------------ */
5835    .balign 64
5836.L_OP_USHR_INT_LIT8: /* 0xe2 */
5837/* File: x86/OP_USHR_INT_LIT8.S */
5838/* File: x86/binopLit8.S */
5839    /*
5840     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5841     * that specifies an instruction that performs "result = eax op ecx".
5842     * This could be an x86 instruction or a function call.  (If the result
5843     * comes back in a register other than r0, you can override "result".)
5844     *
5845     * For: add-int/lit8, rsub-int/lit8
5846     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5847     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5848     */
5849    /* binop/lit8 vAA, vBB, #+CC */
5850    movzbl    2(rPC),%eax              # eax<- BB
5851    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5852    GET_VREG_R   %eax %eax             # eax<- rBB
5853    shrl     %cl,%eax                             # ex: addl %ecx,%eax
5854    FETCH_INST_OPCODE 2 %edx
5855    SET_VREG   %eax rINST
5856    ADVANCE_PC 2
5857    GOTO_NEXT_R %edx
5858
5859
5860/* ------------------------------ */
5861    .balign 64
5862.L_OP_IGET_VOLATILE: /* 0xe3 */
5863/* File: x86/OP_IGET_VOLATILE.S */
5864/* File: x86/OP_IGET.S */
5865    /*
5866     * General 32-bit instance field get.
5867     *
5868     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
5869     */
5870    /* op vA, vB, field@CCCC */
5871    movl    rGLUE,%ecx
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_IGET_VOLATILE_finish                  # no, already resolved
5882    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
5883    movl    rGLUE,%edx
5884    jmp     .LOP_IGET_VOLATILE_resolve
5885
5886
5887/* ------------------------------ */
5888    .balign 64
5889.L_OP_IPUT_VOLATILE: /* 0xe4 */
5890/* File: x86/OP_IPUT_VOLATILE.S */
5891/* File: x86/OP_IPUT.S */
5892
5893    /*
5894     * General 32-bit instance field put.
5895     *
5896     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
5897     */
5898    /* op vA, vB, field@CCCC */
5899    movl    rGLUE,%ecx
5900    movzwl  2(rPC),%edx                         # %edx<- 0000CCCC
5901    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
5902    movzbl  rINSTbl,%ecx                        # ecx<- BA
5903    sarl    $4,%ecx                            # ecx<- B
5904    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
5905    andb    $0xf,rINSTbl                       # rINST<- A
5906    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
5907    movl    (%eax,%edx,4),%eax                  # resolved entry
5908    testl   %eax,%eax                           # is resolved entry null?
5909    jne     .LOP_IPUT_VOLATILE_finish                  # no, already resolved
5910    movl    %edx,OUT_ARG1(%esp)
5911    movl    rGLUE,%edx
5912    jmp     .LOP_IPUT_VOLATILE_resolve
5913
5914
5915/* ------------------------------ */
5916    .balign 64
5917.L_OP_SGET_VOLATILE: /* 0xe5 */
5918/* File: x86/OP_SGET_VOLATILE.S */
5919/* File: x86/OP_SGET.S */
5920    /*
5921     * General 32-bit SGET handler.
5922     *
5923     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
5924     */
5925    /* op vAA, field@BBBB */
5926    movl      rGLUE,%ecx
5927    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
5928    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
5929    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
5930    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
5931    testl     %eax,%eax                          # resolved entry null?
5932    je        .LOP_SGET_VOLATILE_resolve                # if not, make it so
5933.LOP_SGET_VOLATILE_finish:     # field ptr in eax
5934    movl      offStaticField_value(%eax),%eax
5935    FETCH_INST_OPCODE 2 %edx
5936    ADVANCE_PC 2
5937    SET_VREG %eax rINST
5938    GOTO_NEXT_R %edx
5939
5940
5941/* ------------------------------ */
5942    .balign 64
5943.L_OP_SPUT_VOLATILE: /* 0xe6 */
5944/* File: x86/OP_SPUT_VOLATILE.S */
5945/* File: x86/OP_SPUT.S */
5946    /*
5947     * General 32-bit SPUT handler.
5948     *
5949     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
5950     */
5951    /* op vAA, field@BBBB */
5952    movl      rGLUE,%ecx
5953    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
5954    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
5955    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
5956    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
5957    testl     %eax,%eax                          # resolved entry null?
5958    je        .LOP_SPUT_VOLATILE_resolve                # if not, make it so
5959.LOP_SPUT_VOLATILE_finish:     # field ptr in eax
5960    GET_VREG_R  %ecx rINST
5961    FETCH_INST_OPCODE 2 %edx
5962    ADVANCE_PC 2
5963    movl      %ecx,offStaticField_value(%eax)
5964    GOTO_NEXT_R %edx
5965
5966
5967/* ------------------------------ */
5968    .balign 64
5969.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
5970/* File: x86/OP_IGET_OBJECT_VOLATILE.S */
5971/* File: x86/OP_IGET.S */
5972    /*
5973     * General 32-bit instance field get.
5974     *
5975     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
5976     */
5977    /* op vA, vB, field@CCCC */
5978    movl    rGLUE,%ecx
5979    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
5980    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
5981    movzbl  rINSTbl,%ecx                        # ecx<- BA
5982    sarl    $4,%ecx                            # ecx<- B
5983    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
5984    andb    $0xf,rINSTbl                       # rINST<- A
5985    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
5986    movl    (%eax,%edx,4),%eax                  # resolved entry
5987    testl   %eax,%eax                           # is resolved entry null?
5988    jne     .LOP_IGET_OBJECT_VOLATILE_finish                  # no, already resolved
5989    movl    %edx,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
5990    movl    rGLUE,%edx
5991    jmp     .LOP_IGET_OBJECT_VOLATILE_resolve
5992
5993
5994/* ------------------------------ */
5995    .balign 64
5996.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
5997    /* (stub) */
5998    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
5999    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6000    call      dvmMterp_OP_IGET_WIDE_VOLATILE     # do the real work
6001    mov       rGLUE,%ecx
6002    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6003    FETCH_INST
6004    GOTO_NEXT
6005/* ------------------------------ */
6006    .balign 64
6007.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
6008    /* (stub) */
6009    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
6010    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6011    call      dvmMterp_OP_IPUT_WIDE_VOLATILE     # do the real work
6012    mov       rGLUE,%ecx
6013    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6014    FETCH_INST
6015    GOTO_NEXT
6016/* ------------------------------ */
6017    .balign 64
6018.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
6019    /* (stub) */
6020    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
6021    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6022    call      dvmMterp_OP_SGET_WIDE_VOLATILE     # do the real work
6023    mov       rGLUE,%ecx
6024    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6025    FETCH_INST
6026    GOTO_NEXT
6027/* ------------------------------ */
6028    .balign 64
6029.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
6030    /* (stub) */
6031    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
6032    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6033    call      dvmMterp_OP_SPUT_WIDE_VOLATILE     # do the real work
6034    mov       rGLUE,%ecx
6035    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6036    FETCH_INST
6037    GOTO_NEXT
6038/* ------------------------------ */
6039    .balign 64
6040.L_OP_BREAKPOINT: /* 0xec */
6041/* File: x86/OP_BREAKPOINT.S */
6042/* File: x86/unused.S */
6043    jmp     common_abort
6044
6045
6046/* ------------------------------ */
6047    .balign 64
6048.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
6049/* File: x86/OP_THROW_VERIFICATION_ERROR.S */
6050    /*
6051     * Handle a throw-verification-error instruction.  This throws an
6052     * exception for an error discovered during verification.  The
6053     * exception is indicated by AA, with some detail provided by BBBB.
6054     */
6055    /* op AA, ref@BBBB */
6056    movl     rGLUE,%ecx
6057    movzwl   2(rPC),%eax                     # eax<- BBBB
6058    movl     offGlue_method(%ecx),%ecx       # ecx<- glue->method
6059    EXPORT_PC
6060    movl     %eax,OUT_ARG2(%esp)             # arg2<- BBBB
6061    movl     rINST,OUT_ARG1(%esp)            # arg1<- AA
6062    movl     %ecx,OUT_ARG0(%esp)             # arg0<- method
6063    call     dvmThrowVerificationError       # call(method, kind, ref)
6064    jmp      common_exceptionThrown          # handle exception
6065
6066/* ------------------------------ */
6067    .balign 64
6068.L_OP_EXECUTE_INLINE: /* 0xee */
6069/* File: x86/OP_EXECUTE_INLINE.S */
6070    /*
6071     * Execute a "native inline" instruction.
6072     *
6073     * We will be calling through a function table:
6074     *
6075     * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
6076     *
6077     * Ignores argument count - always loads 4.
6078     *
6079     */
6080    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
6081    movl      rGLUE,%ecx
6082    EXPORT_PC
6083    movzwl    2(rPC),%eax               # eax<- BBBB
6084    leal      offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
6085    movl      %ecx,OUT_ARG4(%esp)
6086    call      .LOP_EXECUTE_INLINE_continue      # make call; will return after
6087    testl     %eax,%eax                 # successful?
6088    FETCH_INST_OPCODE 3 %edx
6089    je        common_exceptionThrown    # no, handle exception
6090    ADVANCE_PC 3
6091    GOTO_NEXT_R %edx
6092
6093/* ------------------------------ */
6094    .balign 64
6095.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
6096    /* (stub) */
6097    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
6098    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6099    call      dvmMterp_OP_EXECUTE_INLINE_RANGE     # do the real work
6100    mov       rGLUE,%ecx
6101    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6102    FETCH_INST
6103    GOTO_NEXT
6104/* ------------------------------ */
6105    .balign 64
6106.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
6107/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
6108    /*
6109     * invoke-direct-empty is a no-op in a "standard" interpreter.
6110     */
6111    FETCH_INST_WORD 3
6112    ADVANCE_PC 3
6113    GOTO_NEXT
6114
6115/* ------------------------------ */
6116    .balign 64
6117.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
6118    /* (stub) */
6119    SAVE_PC_FP_TO_GLUE %ecx          # leaves rGLUE in %ecx
6120    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6121    call      dvmMterp_OP_RETURN_VOID_BARRIER     # do the real work
6122    mov       rGLUE,%ecx
6123    LOAD_PC_FP_FROM_GLUE             # retrieve updated values
6124    FETCH_INST
6125    GOTO_NEXT
6126/* ------------------------------ */
6127    .balign 64
6128.L_OP_IGET_QUICK: /* 0xf2 */
6129/* File: x86/OP_IGET_QUICK.S */
6130    /* For: iget-quick, iget-object-quick */
6131    /* op vA, vB, offset@CCCC */
6132    movzbl    rINSTbl,%ecx              # ecx<- BA
6133    sarl      $4,%ecx                  # ecx<- B
6134    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6135    movzwl    2(rPC),%eax               # eax<- field byte offset
6136    cmpl      $0,%ecx                  # is object null?
6137    je        common_errNullObject
6138    movl      (%ecx,%eax,1),%eax
6139    FETCH_INST_OPCODE 2 %edx
6140    ADVANCE_PC 2
6141    andb      $0xf,rINSTbl             # rINST<- A
6142    SET_VREG  %eax rINST                # fp[A]<- result
6143    GOTO_NEXT_R %edx
6144
6145/* ------------------------------ */
6146    .balign 64
6147.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
6148/* File: x86/OP_IGET_WIDE_QUICK.S */
6149    /* For: iget-wide-quick */
6150    /* op vA, vB, offset@CCCC */
6151    movzbl    rINSTbl,%ecx              # ecx<- BA
6152    sarl      $4,%ecx                  # ecx<- B
6153    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6154    movzwl    2(rPC),%eax               # eax<- field byte offset
6155    cmpl      $0,%ecx                  # is object null?
6156    je        common_errNullObject
6157    leal      (%ecx,%eax,1),%eax        # eax<- address of 64-bit source
6158    movl      (%eax),%ecx               # ecx<- lsw
6159    movl      4(%eax),%eax              # eax<- msw
6160    andb      $0xf,rINSTbl             # rINST<- A
6161    FETCH_INST_OPCODE 2 %edx
6162    SET_VREG_WORD %ecx rINST 0          # v[A+0]<- lsw
6163    SET_VREG_WORD %eax rINST 1          # v[A+1]<- msw
6164    ADVANCE_PC 2
6165    GOTO_NEXT_R %edx
6166
6167/* ------------------------------ */
6168    .balign 64
6169.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
6170/* File: x86/OP_IGET_OBJECT_QUICK.S */
6171/* File: x86/OP_IGET_QUICK.S */
6172    /* For: iget-quick, iget-object-quick */
6173    /* op vA, vB, offset@CCCC */
6174    movzbl    rINSTbl,%ecx              # ecx<- BA
6175    sarl      $4,%ecx                  # ecx<- B
6176    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6177    movzwl    2(rPC),%eax               # eax<- field byte offset
6178    cmpl      $0,%ecx                  # is object null?
6179    je        common_errNullObject
6180    movl      (%ecx,%eax,1),%eax
6181    FETCH_INST_OPCODE 2 %edx
6182    ADVANCE_PC 2
6183    andb      $0xf,rINSTbl             # rINST<- A
6184    SET_VREG  %eax rINST                # fp[A]<- result
6185    GOTO_NEXT_R %edx
6186
6187
6188/* ------------------------------ */
6189    .balign 64
6190.L_OP_IPUT_QUICK: /* 0xf5 */
6191/* File: x86/OP_IPUT_QUICK.S */
6192    /* For: iput-quick */
6193    /* op vA, vB, offset@CCCC */
6194    movzbl    rINSTbl,%ecx              # ecx<- BA
6195    sarl      $4,%ecx                  # ecx<- B
6196    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6197    andb      $0xf,rINSTbl             # rINST<- A
6198    GET_VREG_R  rINST,rINST             # rINST<- v[A]
6199    movzwl    2(rPC),%eax               # eax<- field byte offset
6200    testl     %ecx,%ecx                 # is object null?
6201    FETCH_INST_OPCODE 2 %edx
6202    je        common_errNullObject
6203    movl      rINST,(%ecx,%eax,1)
6204    ADVANCE_PC 2
6205    GOTO_NEXT_R %edx
6206
6207/* ------------------------------ */
6208    .balign 64
6209.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
6210/* File: x86/OP_IPUT_WIDE_QUICK.S */
6211    /* For: iput-wide-quick */
6212    /* op vA, vB, offset@CCCC */
6213    movzbl    rINSTbl,%ecx              # ecx<- BA
6214    sarl      $4,%ecx                  # ecx<- B
6215    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6216    movzwl    2(rPC),%eax               # eax<- field byte offset
6217    testl      %ecx,%ecx                # is object null?
6218    je        common_errNullObject
6219    leal      (%ecx,%eax,1),%ecx        # ecx<- Address of 64-bit target
6220    andb      $0xf,rINSTbl             # rINST<- A
6221    GET_VREG_WORD %eax rINST 0          # eax<- lsw
6222    GET_VREG_WORD rINST rINST 1         # rINST<- msw
6223    FETCH_INST_OPCODE 2 %edx
6224    movl      %eax,(%ecx)
6225    movl      rINST,4(%ecx)
6226    ADVANCE_PC 2
6227    GOTO_NEXT_R %edx
6228
6229/* ------------------------------ */
6230    .balign 64
6231.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
6232/* File: x86/OP_IPUT_OBJECT_QUICK.S */
6233    /* For: iput-object-quick */
6234    /* op vA, vB, offset@CCCC */
6235    movzbl    rINSTbl,%ecx              # ecx<- BA
6236    sarl      $4,%ecx                  # ecx<- B
6237    GET_VREG_R  %ecx %ecx               # vB (object we're operating on)
6238    andb      $0xf,rINSTbl             # rINST<- A
6239    GET_VREG_R  rINST rINST             # rINST<- v[A]
6240    movzwl    2(rPC),%eax               # eax<- field byte offset
6241    testl     %ecx,%ecx                 # is object null?
6242    je        common_errNullObject
6243    movl      rINST,(%ecx,%eax,1)
6244    movl      rGLUE,%eax
6245    jmp       .LOP_IPUT_OBJECT_QUICK_finish
6246
6247/* ------------------------------ */
6248    .balign 64
6249.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6250/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6251    /*
6252     * Handle an optimized virtual method call.
6253     *
6254     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6255     */
6256    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6257    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6258    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6259    movzwl    2(rPC),%ecx               # ecx<- BBBB
6260    .if     (!0)
6261    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6262    .endif
6263    GET_VREG_R  %eax %eax               # eax<- vC ("this" ptr)
6264    testl     %eax,%eax                 # null?
6265    je        common_errNullObject      # yep, throw exception
6266    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6267    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6268    EXPORT_PC                           # might throw later - get ready
6269    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6270    jmp       common_invokeMethodNoRange
6271
6272/* ------------------------------ */
6273    .balign 64
6274.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6275/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6276/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6277    /*
6278     * Handle an optimized virtual method call.
6279     *
6280     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6281     */
6282    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6283    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6284    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6285    movzwl    2(rPC),%ecx               # ecx<- BBBB
6286    .if     (!1)
6287    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6288    .endif
6289    GET_VREG_R  %eax %eax               # eax<- vC ("this" ptr)
6290    testl     %eax,%eax                 # null?
6291    je        common_errNullObject      # yep, throw exception
6292    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6293    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6294    EXPORT_PC                           # might throw later - get ready
6295    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6296    jmp       common_invokeMethodRange
6297
6298
6299/* ------------------------------ */
6300    .balign 64
6301.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6302/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6303    /*
6304     * Handle an optimized "super" method call.
6305     *
6306     * for: [opt] invoke-super-quick, invoke-super-quick/range
6307     */
6308    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6309    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6310    movl      rGLUE,%ecx
6311    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6312    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6313    .if       (!0)
6314    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6315    .endif
6316    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6317    GET_VREG_R  %eax %eax               # eax<- "this"
6318    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6319    testl     %eax,%eax                 # null "this"?
6320    je        common_errNullObject      # "this" is null, throw exception
6321    movzwl    2(rPC),%eax               # eax<- BBBB
6322    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6323    EXPORT_PC
6324    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6325    jmp       common_invokeMethodNoRange
6326
6327/* ------------------------------ */
6328    .balign 64
6329.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6330/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6331/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6332    /*
6333     * Handle an optimized "super" method call.
6334     *
6335     * for: [opt] invoke-super-quick, invoke-super-quick/range
6336     */
6337    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6338    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6339    movl      rGLUE,%ecx
6340    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6341    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6342    .if       (!1)
6343    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6344    .endif
6345    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6346    GET_VREG_R  %eax %eax               # eax<- "this"
6347    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6348    testl     %eax,%eax                 # null "this"?
6349    je        common_errNullObject      # "this" is null, throw exception
6350    movzwl    2(rPC),%eax               # eax<- BBBB
6351    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6352    EXPORT_PC
6353    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6354    jmp       common_invokeMethodRange
6355
6356
6357/* ------------------------------ */
6358    .balign 64
6359.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
6360/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */
6361/* File: x86/OP_IPUT_OBJECT.S */
6362    /*
6363     * Object field put.
6364     *
6365     * for: iput-object
6366     */
6367    /* op vA, vB, field@CCCC */
6368    movl    rGLUE,%ecx
6369    movzwl  2(rPC),%edx                         # edx<- 0000CCCC
6370    movl    offGlue_methodClassDex(%ecx),%eax   # eax<- DvmDex
6371    movzbl  rINSTbl,%ecx                        # ecx<- BA
6372    sarl    $4,%ecx                            # ecx<- B
6373    movl    offDvmDex_pResFields(%eax),%eax     # eax<- pDvmDex->pResFields
6374    andb    $0xf,rINSTbl                       # rINST<- A
6375    GET_VREG_R %ecx %ecx                        # ecx<- fp[B], the object ptr
6376    movl    (%eax,%edx,4),%eax                  # resolved entry
6377    testl   %eax,%eax                           # is resolved entry null?
6378    jne     .LOP_IPUT_OBJECT_VOLATILE_finish                  # no, already resolved
6379    movl    %edx,OUT_ARG1(%esp)
6380    movl    rGLUE,%edx
6381    jmp     .LOP_IPUT_OBJECT_VOLATILE_resolve
6382
6383
6384/* ------------------------------ */
6385    .balign 64
6386.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
6387/* File: x86/OP_SGET_OBJECT_VOLATILE.S */
6388/* File: x86/OP_SGET.S */
6389    /*
6390     * General 32-bit SGET handler.
6391     *
6392     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
6393     */
6394    /* op vAA, field@BBBB */
6395    movl      rGLUE,%ecx
6396    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
6397    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
6398    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
6399    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
6400    testl     %eax,%eax                          # resolved entry null?
6401    je        .LOP_SGET_OBJECT_VOLATILE_resolve                # if not, make it so
6402.LOP_SGET_OBJECT_VOLATILE_finish:     # field ptr in eax
6403    movl      offStaticField_value(%eax),%eax
6404    FETCH_INST_OPCODE 2 %edx
6405    ADVANCE_PC 2
6406    SET_VREG %eax rINST
6407    GOTO_NEXT_R %edx
6408
6409
6410/* ------------------------------ */
6411    .balign 64
6412.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
6413/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */
6414/* File: x86/OP_SPUT_OBJECT.S */
6415    /*
6416     * SPUT object handler.
6417     */
6418    /* op vAA, field@BBBB */
6419    movl      rGLUE,%ecx
6420    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
6421    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
6422    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
6423    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField
6424    testl     %eax,%eax                          # resolved entry null?
6425    je        .LOP_SPUT_OBJECT_VOLATILE_resolve                # if not, make it so
6426.LOP_SPUT_OBJECT_VOLATILE_finish:                              # field ptr in eax
6427    movzbl    rINSTbl,%ecx                       # ecx<- AA
6428    GET_VREG_R  %ecx %ecx
6429    jmp       .LOP_SPUT_OBJECT_VOLATILE_continue
6430
6431
6432/* ------------------------------ */
6433    .balign 64
6434.L_OP_UNUSED_FF: /* 0xff */
6435/* File: x86/OP_UNUSED_FF.S */
6436/* File: x86/unused.S */
6437    jmp     common_abort
6438
6439
6440
6441    .balign 64
6442    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
6443    .global dvmAsmInstructionEnd
6444dvmAsmInstructionEnd:
6445
6446/*
6447 * ===========================================================================
6448 *  Sister implementations
6449 * ===========================================================================
6450 */
6451    .global dvmAsmSisterStart
6452    .type   dvmAsmSisterStart, %function
6453    .text
6454    .balign 4
6455dvmAsmSisterStart:
6456
6457/* continuation for OP_CONST_STRING */
6458
6459/* This is the less common path, so we'll redo some work
6460   here rather than force spills on the common path */
6461.LOP_CONST_STRING_resolve:
6462    movl     rGLUE,%eax
6463    movl     %ecx,rINST                # rINST<- AA
6464    EXPORT_PC
6465    movl     offGlue_method(%eax),%eax # eax<- glue->method
6466    movzwl   2(rPC),%ecx               # ecx<- BBBB
6467    movl     offMethod_clazz(%eax),%eax
6468    movl     %ecx,OUT_ARG1(%esp)
6469    movl     %eax,OUT_ARG0(%esp)
6470    call     dvmResolveString          # go resolve
6471    testl    %eax,%eax                 # failed?
6472    je       common_exceptionThrown
6473    SET_VREG %eax rINST
6474    FETCH_INST_OPCODE 2 %edx
6475    ADVANCE_PC 2
6476    GOTO_NEXT_R %edx
6477
6478/* continuation for OP_CONST_STRING_JUMBO */
6479
6480/* This is the less common path, so we'll redo some work
6481   here rather than force spills on the common path */
6482.LOP_CONST_STRING_JUMBO_resolve:
6483    movl     rGLUE,%eax
6484    movl     %ecx,rINST                # rINST<- AA
6485    EXPORT_PC
6486    movl     offGlue_method(%eax),%eax # eax<- glue->method
6487    movl     2(rPC),%ecx               # ecx<- BBBBBBBB
6488    movl     offMethod_clazz(%eax),%eax
6489    movl     %ecx,OUT_ARG1(%esp)
6490    movl     %eax,OUT_ARG0(%esp)
6491    call     dvmResolveString          # go resolve
6492    testl    %eax,%eax                 # failed?
6493    je       common_exceptionThrown
6494    SET_VREG %eax rINST
6495    FETCH_INST_OPCODE 3 %edx
6496    ADVANCE_PC 3
6497    GOTO_NEXT_R %edx
6498
6499/* continuation for OP_CONST_CLASS */
6500
6501/* This is the less common path, so we'll redo some work
6502   here rather than force spills on the common path */
6503.LOP_CONST_CLASS_resolve:
6504    movl     rGLUE,%eax
6505    movl     %ecx,rINST                # rINST<- AA
6506    EXPORT_PC
6507    movl     offGlue_method(%eax),%eax # eax<- glue->method
6508    movl     $1,OUT_ARG2(%esp)        # true
6509    movzwl   2(rPC),%ecx               # ecx<- BBBB
6510    movl     offMethod_clazz(%eax),%eax
6511    movl     %ecx,OUT_ARG1(%esp)
6512    movl     %eax,OUT_ARG0(%esp)
6513    call     dvmResolveClass           # go resolve
6514    testl    %eax,%eax                 # failed?
6515    je       common_exceptionThrown
6516    SET_VREG %eax rINST
6517    FETCH_INST_OPCODE 2 %edx
6518    ADVANCE_PC 2
6519    GOTO_NEXT_R %edx
6520
6521/* continuation for OP_MONITOR_ENTER */
6522
6523.LOP_MONITOR_ENTER_continue:
6524    movl    %ecx,OUT_ARG0(%esp)
6525    movl    %eax,OUT_ARG1(%esp)
6526    call    dvmLockObject               # dvmLockObject(self,object)
6527#ifdef WITH_DEADLOCK_PREDICTION
6528    movl    rGLUE,%ecx
6529    movl    offGlueSelf(%ecx),%ecx      # ecx<- glue->self
6530    movl    offThread_exception(%ecx),%eax
6531    testl   %eax,%eax
6532    jne     common_exceptionThrown
6533#endif
6534    ADVANCE_PC 1
6535    GOTO_NEXT
6536
6537/* continuation for OP_MONITOR_EXIT */
6538
6539.LOP_MONITOR_EXIT_continue:
6540    call    dvmUnlockObject             # unlock(self,obj)
6541    FETCH_INST_OPCODE 1 %edx
6542    testl   %eax,%eax                   # success?
6543    ADVANCE_PC 1
6544    je      common_exceptionThrown      # no, exception pending
6545    GOTO_NEXT_R %edx
6546.LOP_MONITOR_EXIT_errNullObject:
6547    ADVANCE_PC 1                        # advance before throw
6548    jmp     common_errNullObject
6549
6550/* continuation for OP_CHECK_CAST */
6551
6552    /*
6553     * Trivial test failed, need to perform full check.  This is common.
6554     *  ecx holds obj->clazz
6555     *  eax holds class resolved from BBBB
6556     *  rINST holds object
6557     */
6558.LOP_CHECK_CAST_fullcheck:
6559    movl    %eax,OUT_ARG1(%esp)
6560    movl    %ecx,OUT_ARG0(%esp)
6561    call    dvmInstanceofNonTrivial     # eax<- boolean result
6562    testl   %eax,%eax                   # failed?
6563    jne     .LOP_CHECK_CAST_okay            # no, success
6564
6565    # A cast has failed.  We need to throw a ClassCastException with the
6566    # class of the object that failed to be cast.
6567    EXPORT_PC
6568    movl    offObject_clazz(rINST),%ecx  # ecx<- obj->clazz
6569    movl    $.LstrClassCastException,%eax
6570    movl    offClassObject_descriptor(%ecx),%ecx
6571    movl    %eax,OUT_ARG0(%esp)     # arg0<- message
6572    movl    %ecx,OUT_ARG1(%esp)     # arg1<- obj->clazz->descriptor
6573    call    dvmThrowExceptionWithClassMessage
6574    jmp     common_exceptionThrown
6575
6576    /*
6577     * Resolution required.  This is the least-likely path, and we're
6578     * going to have to recreate some data.
6579     *
6580     *  rINST holds object
6581     */
6582.LOP_CHECK_CAST_resolve:
6583    movl    rGLUE,%ecx
6584    EXPORT_PC
6585    movzwl  2(rPC),%eax                # eax<- BBBB
6586    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6587    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
6588    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6589    movl    $0,OUT_ARG2(%esp)         # arg2<- false
6590    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
6591    call    dvmResolveClass            # eax<- resolved ClassObject ptr
6592    testl   %eax,%eax                  # got null?
6593    je      common_exceptionThrown     # yes, handle exception
6594    movl    offObject_clazz(rINST),%ecx  # ecx<- obj->clazz
6595    jmp     .LOP_CHECK_CAST_resolved       # pick up where we left off
6596
6597/* continuation for OP_INSTANCE_OF */
6598
6599    /*
6600     * Trivial test failed, need to perform full check.  This is common.
6601     *  eax holds obj->clazz
6602     *  ecx holds class resolved from BBBB
6603     *  rINST has BA
6604     */
6605.LOP_INSTANCE_OF_fullcheck:
6606    movl    %eax,OUT_ARG0(%esp)
6607    movl    %ecx,OUT_ARG1(%esp)
6608    call    dvmInstanceofNonTrivial     # eax<- boolean result
6609    # fall through to OP_INSTANCE_OF_store
6610
6611    /*
6612     * eax holds boolean result
6613     * rINST holds BA
6614     */
6615.LOP_INSTANCE_OF_store:
6616    FETCH_INST_OPCODE 2 %edx
6617    andb    $0xf,rINSTbl               # <- A
6618    ADVANCE_PC 2
6619    SET_VREG %eax rINST                 # vA<- eax
6620    GOTO_NEXT_R %edx
6621
6622    /*
6623     * Trivial test succeeded, save and bail.
6624     *  r9 holds A
6625     */
6626.LOP_INSTANCE_OF_trivial:
6627    FETCH_INST_OPCODE 2 %edx
6628    andb    $0xf,rINSTbl               # <- A
6629    ADVANCE_PC 2
6630    movl    $1,%eax
6631    SET_VREG %eax rINST                 # vA<- true
6632    GOTO_NEXT_R %edx
6633
6634    /*
6635     * Resolution required.  This is the least-likely path.
6636     *
6637     *  edx holds BBBB
6638     *  rINST holds BA
6639     */
6640.LOP_INSTANCE_OF_resolve:
6641    movl    %edx,OUT_ARG1(%esp)         # arg1<- BBBB
6642    movl    rGLUE,%ecx
6643    movl    offGlue_method(%ecx),%ecx
6644    movl    $1,OUT_ARG2(%esp)          # arg2<- true
6645    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6646    EXPORT_PC
6647    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
6648    call    dvmResolveClass             # eax<- resolved ClassObject ptr
6649    testl   %eax,%eax                   # success?
6650    je      common_exceptionThrown      # no, handle exception
6651/* Now, we need to sync up with fast path.  We need eax to
6652 * hold the obj->clazz, and ecx to hold the resolved class
6653 */
6654    movl    %eax,%ecx                   # ecx<- resolved class
6655    movl    rINST,%eax                # eax<- BA
6656    sarl    $4,%eax                    # eax<- B
6657    GET_VREG_R %eax %eax                # eax<- vB (obj)
6658    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
6659    jmp     .LOP_INSTANCE_OF_resolved
6660
6661/* continuation for OP_NEW_INSTANCE */
6662
6663.LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
6664    /* TODO: remove test for interface/abstract, now done in verifier */
6665    testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6666    movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6667    jne       .LOP_NEW_INSTANCE_abstract
6668.LOP_NEW_INSTANCE_finish: # ecx=class
6669    movl     %ecx,OUT_ARG0(%esp)
6670    call     dvmAllocObject             # eax<- new object
6671    FETCH_INST_OPCODE 2 %edx
6672    testl    %eax,%eax                  # success?
6673    je       common_exceptionThrown     # no, bail out
6674    SET_VREG %eax rINST
6675    ADVANCE_PC 2
6676    GOTO_NEXT_R %edx
6677
6678    /*
6679     * Class initialization required.
6680     *
6681     *  ecx holds class object
6682     */
6683.LOP_NEW_INSTANCE_needinit:
6684    SPILL_TMP1(%ecx)                    # save object
6685    movl    %ecx,OUT_ARG0(%esp)
6686    call    dvmInitClass                # initialize class
6687    UNSPILL_TMP1(%ecx)                  # restore object
6688    testl   %eax,%eax                   # success?
6689    jne     .LOP_NEW_INSTANCE_initialized     # success, continue
6690    jmp     common_exceptionThrown      # go deal with init exception
6691
6692    /*
6693     * Resolution required.  This is the least-likely path.
6694     *
6695     */
6696.LOP_NEW_INSTANCE_resolve:
6697    movl    rGLUE,%ecx
6698    movzwl  2(rPC),%eax
6699    movl    offGlue_method(%ecx),%ecx   # ecx<- glue->method
6700    movl    %eax,OUT_ARG1(%esp)
6701    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6702    movl    $0,OUT_ARG2(%esp)
6703    movl    %ecx,OUT_ARG0(%esp)
6704    call    dvmResolveClass             # call(clazz,off,flags)
6705    movl    %eax,%ecx                   # ecx<- resolved ClassObject ptr
6706    testl   %ecx,%ecx                   # success?
6707    jne     .LOP_NEW_INSTANCE_resolved        # good to go
6708    jmp     common_exceptionThrown      # no, handle exception
6709
6710    /*
6711     * TODO: remove this
6712     * We can't instantiate an abstract class or interface, so throw an
6713     * InstantiationError with the class descriptor as the message.
6714     *
6715     *  ecx holds class object
6716     */
6717.LOP_NEW_INSTANCE_abstract:
6718    movl    offClassObject_descriptor(%ecx),%eax
6719    movl    $.LstrInstantiationError,OUT_ARG0(%esp)
6720    movl    %eax,OUT_ARG1(%esp)
6721    call    dvmThrowExceptionWithClassMessage
6722    jmp     common_exceptionThrown
6723
6724/* continuation for OP_NEW_ARRAY */
6725
6726    /*
6727     * Resolve class.  (This is an uncommon case.)
6728     *  ecx holds class (null here)
6729     *  eax holds array length (vB)
6730     */
6731.LOP_NEW_ARRAY_resolve:
6732    movl    rGLUE,%ecx
6733    SPILL_TMP1(%eax)                   # save array length
6734    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6735    movzwl  2(rPC),%eax                # eax<- CCCC
6736    movl    offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6737    movl    %eax,OUT_ARG1(%esp)
6738    movl    $0,OUT_ARG2(%esp)
6739    movl    %ecx,OUT_ARG0(%esp)
6740    call    dvmResolveClass            # eax<- call(clazz,ref,flag)
6741    movl    %eax,%ecx
6742    UNSPILL_TMP1(%eax)
6743    testl   %ecx,%ecx                  # successful resolution?
6744    je      common_exceptionThrown     # no, bail.
6745# fall through to OP_NEW_ARRAY_finish
6746
6747    /*
6748     * Finish allocation
6749     *
6750     * ecx holds class
6751     * eax holds array length (vB)
6752     */
6753.LOP_NEW_ARRAY_finish:
6754    movl    %ecx,OUT_ARG0(%esp)
6755    movl    %eax,OUT_ARG1(%esp)
6756    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6757    call    dvmAllocArrayByClass    # eax<- call(clazz,length,flags)
6758    FETCH_INST_OPCODE 2 %edx
6759    testl   %eax,%eax               # failed?
6760    je      common_exceptionThrown  # yup - go handle
6761    SET_VREG %eax rINST
6762    ADVANCE_PC 2
6763    GOTO_NEXT_R %edx
6764
6765/* continuation for OP_FILLED_NEW_ARRAY */
6766
6767.LOP_FILLED_NEW_ARRAY_more:
6768    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6769    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6770    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6771    testl   %eax,%eax                         # null?
6772    je      common_exceptionThrown            # yes, handle it
6773
6774       # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6775
6776    /*
6777     * On entry:
6778     *    eax holds array class [r0]
6779     *    rINST holds AA or BB [r10]
6780     *    ecx is scratch
6781     */
6782.LOP_FILLED_NEW_ARRAY_continue:
6783    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6784    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6785    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6786    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6787    movl    rGLUE,%eax
6788    cmpb    $'I',%cl                             # supported?
6789    je      1f
6790    cmpb    $'L',%cl
6791    je      1f
6792    cmpb    $'[',%cl
6793    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
67941:
6795    movl    %ecx,offGlue_retval+4(%eax)           # save type
6796    .if      (!0)
6797    SPILL_TMP1(rINST)                              # save copy, need "B" later
6798    sarl    $4,rINST
6799    .endif
6800    movl    rINST,OUT_ARG1(%esp)                  # arg1<- A or AA (length)
6801    call    dvmAllocArrayByClass     # eax<- call(arrayClass, length, flags)
6802    movl    rGLUE,%ecx
6803    testl   %eax,%eax                             # alloc successful?
6804    je      common_exceptionThrown                # no, handle exception
6805    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6806    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6807    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6808
6809/* at this point:
6810 *     eax is pointer to tgt
6811 *     rINST is length
6812 *     ecx is FEDC or CCCC
6813 *     TMP_SPILL is BA
6814 *  We now need to copy values from registers into the array
6815 */
6816
6817    .if 0
6818    # set up src pointer
6819    SPILL_TMP2(%esi)
6820    SPILL_TMP3(%edi)
6821    movl    %eax,%edi         # set up dst ptr
6822    leal    (rFP,%ecx,4),%esi # set up src ptr
6823    movl    rINST,%ecx        # load count register
6824    rep
6825    movsd
6826    UNSPILL_TMP2(%esi)
6827    UNSPILL_TMP3(%edi)
6828    movl    rGLUE,%ecx
6829    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6830    FETCH_INST_OPCODE 3 %edx
6831    .else
6832    testl  rINST,rINST
6833    je     4f
6834    andl   $0x0f,%edx        # edx<- 0000000A
6835    sall   $16,%edx          # edx<- 000A0000
6836    orl    %ecx,%edx          # edx<- 000AFEDC
68373:
6838    movl   $0xf,%ecx
6839    andl   %edx,%ecx          # ecx<- next reg to load
6840    GET_VREG_R %ecx %ecx
6841    shrl   $4,%edx
6842    leal   4(%eax),%eax
6843    movl   %ecx,-4(%eax)
6844    sub    $1,rINST
6845    jne    3b
68464:
6847    movl   rGLUE,%ecx
6848    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6849    FETCH_INST_OPCODE 3 %edx
6850    .endif
6851
6852    cmpb    $'I',%al                        # Int array?
6853    je      5f                               # skip card mark if so
6854    movl    offGlue_retval(%ecx),%eax        # eax<- object head
6855    movl    offGlue_cardTable(%ecx),%ecx     # card table base
6856    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
6857    movb    %cl,(%ecx,%eax)                  # mark card based on object head
68585:
6859    ADVANCE_PC 3
6860    GOTO_NEXT_R %edx
6861
6862
6863    /*
6864     * Throw an exception indicating that we have not implemented this
6865     * mode of filled-new-array.
6866     */
6867.LOP_FILLED_NEW_ARRAY_notimpl:
6868    movl    $.LstrInternalErrorA,%eax
6869    movl    %eax,OUT_ARG0(%esp)
6870    movl    $.LstrFilledNewArrayNotImplA,%eax
6871    movl    %eax,OUT_ARG1(%esp)
6872    call    dvmThrowException
6873    jmp     common_exceptionThrown
6874
6875/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6876
6877.LOP_FILLED_NEW_ARRAY_RANGE_more:
6878    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6879    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6880    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6881    testl   %eax,%eax                         # null?
6882    je      common_exceptionThrown            # yes, handle it
6883
6884       # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6885
6886    /*
6887     * On entry:
6888     *    eax holds array class [r0]
6889     *    rINST holds AA or BB [r10]
6890     *    ecx is scratch
6891     */
6892.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6893    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6894    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6895    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6896    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6897    movl    rGLUE,%eax
6898    cmpb    $'I',%cl                             # supported?
6899    je      1f
6900    cmpb    $'L',%cl
6901    je      1f
6902    cmpb    $'[',%cl
6903    jne      .LOP_FILLED_NEW_ARRAY_RANGE_notimpl                  # no, not handled yet
69041:
6905    movl    %ecx,offGlue_retval+4(%eax)           # save type
6906    .if      (!1)
6907    SPILL_TMP1(rINST)                              # save copy, need "B" later
6908    sarl    $4,rINST
6909    .endif
6910    movl    rINST,OUT_ARG1(%esp)                  # arg1<- A or AA (length)
6911    call    dvmAllocArrayByClass     # eax<- call(arrayClass, length, flags)
6912    movl    rGLUE,%ecx
6913    testl   %eax,%eax                             # alloc successful?
6914    je      common_exceptionThrown                # no, handle exception
6915    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6916    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6917    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6918
6919/* at this point:
6920 *     eax is pointer to tgt
6921 *     rINST is length
6922 *     ecx is FEDC or CCCC
6923 *     TMP_SPILL is BA
6924 *  We now need to copy values from registers into the array
6925 */
6926
6927    .if 1
6928    # set up src pointer
6929    SPILL_TMP2(%esi)
6930    SPILL_TMP3(%edi)
6931    movl    %eax,%edi         # set up dst ptr
6932    leal    (rFP,%ecx,4),%esi # set up src ptr
6933    movl    rINST,%ecx        # load count register
6934    rep
6935    movsd
6936    UNSPILL_TMP2(%esi)
6937    UNSPILL_TMP3(%edi)
6938    movl    rGLUE,%ecx
6939    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6940    FETCH_INST_OPCODE 3 %edx
6941    .else
6942    testl  rINST,rINST
6943    je     4f
6944    andl   $0x0f,%edx        # edx<- 0000000A
6945    sall   $16,%edx          # edx<- 000A0000
6946    orl    %ecx,%edx          # edx<- 000AFEDC
69473:
6948    movl   $0xf,%ecx
6949    andl   %edx,%ecx          # ecx<- next reg to load
6950    GET_VREG_R %ecx %ecx
6951    shrl   $4,%edx
6952    leal   4(%eax),%eax
6953    movl   %ecx,-4(%eax)
6954    sub    $1,rINST
6955    jne    3b
69564:
6957    movl   rGLUE,%ecx
6958    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6959    FETCH_INST_OPCODE 3 %edx
6960    .endif
6961
6962    cmpb    $'I',%al                        # Int array?
6963    je      5f                               # skip card mark if so
6964    movl    offGlue_retval(%ecx),%eax        # eax<- object head
6965    movl    offGlue_cardTable(%ecx),%ecx     # card table base
6966    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
6967    movb    %cl,(%ecx,%eax)                  # mark card based on object head
69685:
6969    ADVANCE_PC 3
6970    GOTO_NEXT_R %edx
6971
6972
6973    /*
6974     * Throw an exception indicating that we have not implemented this
6975     * mode of filled-new-array.
6976     */
6977.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6978    movl    $.LstrInternalErrorA,%eax
6979    movl    %eax,OUT_ARG0(%esp)
6980    movl    $.LstrFilledNewArrayNotImplA,%eax
6981    movl    %eax,OUT_ARG1(%esp)
6982    call    dvmThrowException
6983    jmp     common_exceptionThrown
6984
6985/* continuation for OP_CMPL_FLOAT */
6986
6987.LOP_CMPL_FLOAT_isNaN:
6988    movl      $-1,%ecx
6989    jmp       .LOP_CMPL_FLOAT_finish
6990
6991/* continuation for OP_CMPG_FLOAT */
6992
6993.LOP_CMPG_FLOAT_isNaN:
6994    movl      $1,%ecx
6995    jmp       .LOP_CMPG_FLOAT_finish
6996
6997/* continuation for OP_CMPL_DOUBLE */
6998
6999.LOP_CMPL_DOUBLE_isNaN:
7000    movl      $-1,%ecx
7001    jmp       .LOP_CMPL_DOUBLE_finish
7002
7003/* continuation for OP_CMPG_DOUBLE */
7004
7005.LOP_CMPG_DOUBLE_isNaN:
7006    movl      $1,%ecx
7007    jmp       .LOP_CMPG_DOUBLE_finish
7008
7009/* continuation for OP_CMP_LONG */
7010
7011.LOP_CMP_LONG_bigger:
7012    movl      $1,%ecx
7013    jmp       .LOP_CMP_LONG_finish
7014.LOP_CMP_LONG_smaller:
7015    movl      $-1,%ecx
7016.LOP_CMP_LONG_finish:
7017    SET_VREG %ecx rINST
7018    FETCH_INST_OPCODE 2 %edx
7019    ADVANCE_PC 2
7020    GOTO_NEXT_R %edx
7021
7022/* continuation for OP_AGET_WIDE */
7023
7024.LOP_AGET_WIDE_finish:
7025    leal      offArrayObject_contents(%eax,%ecx,8),%eax
7026    movl      (%eax),%ecx
7027    movl      4(%eax),%eax
7028    SET_VREG_WORD %ecx rINST 0
7029    SET_VREG_WORD %eax rINST 1
7030    FETCH_INST_OPCODE 2 %edx
7031    ADVANCE_PC 2
7032    GOTO_NEXT_R %edx
7033
7034/* continuation for OP_APUT_WIDE */
7035
7036.LOP_APUT_WIDE_finish:
7037    leal      offArrayObject_contents(%eax,%ecx,8),%eax
7038    GET_VREG_WORD %ecx rINST 0
7039    GET_VREG_WORD rINST rINST 1
7040    movl      rINST,4(%eax)
7041    FETCH_INST_OPCODE 2 %edx
7042    movl      %ecx,(%eax)
7043    ADVANCE_PC 2
7044    GOTO_NEXT_R %edx
7045
7046/* continuation for OP_APUT_OBJECT */
7047
7048    /* On entry:
7049     *   eax<- array object
7050     *   ecx<- index
7051     *   rINST<- vAA
7052     */
7053.LOP_APUT_OBJECT_continue:
7054    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
7055    testl     rINST,rINST                    # storing null reference?
7056    je        .LOP_APUT_OBJECT_skip_check
7057    SPILL_TMP1(%ecx)                         # save target address
7058    SPILL_TMP2(%eax)                         # save object head
7059    movl      offObject_clazz(%eax),%eax     # eax<- arrayObj->clazz
7060    movl      offObject_clazz(rINST),%ecx    # ecx<- obj->clazz
7061    movl      %eax,OUT_ARG1(%esp)
7062    movl      %ecx,OUT_ARG0(%esp)
7063    call      dvmCanPutArrayElement          # test object type vs. array type
7064    UNSPILL_TMP1(%ecx)                       # recover target address
7065    testl     %eax,%eax
7066    movl      rGLUE,%eax
7067    je        common_errArrayStore
7068    movl      offGlue_cardTable(%eax),%eax   # get card table base
7069    movl      rINST,(%ecx)                   # store into array
7070    UNSPILL_TMP2(%ecx)                       # recover object head
7071    FETCH_INST_OPCODE 2 %edx
7072    shrl      $GC_CARD_SHIFT,%ecx           # object head to card number
7073    movb      %al,(%eax,%ecx)                # mark card using object head
7074    ADVANCE_PC 2
7075    GOTO_NEXT_R %edx
7076
7077.LOP_APUT_OBJECT_skip_check:
7078    movl      rINST,(%ecx)
7079    FETCH_INST_OPCODE 2 %edx
7080    ADVANCE_PC 2
7081    GOTO_NEXT_R %edx
7082
7083/* continuation for OP_IGET */
7084
7085
7086.LOP_IGET_resolve:
7087    EXPORT_PC
7088    movl    offGlue_method(%edx),%edx           # edx<- current method
7089    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7090    SPILL_TMP1(%ecx)                            # save obj pointer across call
7091    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7092    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7093    UNSPILL_TMP1(%ecx)
7094    testl   %eax,%eax                           #  returns InstrField ptr
7095    jne     .LOP_IGET_finish
7096    jmp     common_exceptionThrown
7097
7098.LOP_IGET_finish:
7099    /*
7100     * Currently:
7101     *   eax holds resolved field
7102     *   ecx holds object
7103     *   rINST holds A
7104     */
7105    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7106    testl   %ecx,%ecx                           # object null?
7107    je      common_errNullObject                # object was null
7108    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7109    movl    rINST,%eax                          # eax<- A
7110    FETCH_INST_OPCODE 2 %edx
7111    SET_VREG %ecx %eax
7112    ADVANCE_PC 2
7113    GOTO_NEXT_R %edx
7114
7115/* continuation for OP_IGET_WIDE */
7116
7117
7118.LOP_IGET_WIDE_resolve:
7119    EXPORT_PC
7120    movl    offGlue_method(%edx),%edx           # edx<- current method
7121    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7122    SPILL_TMP1(%ecx)                            # save objpointer across call
7123    movl    rPC,OUT_ARG0(%esp)                  # pass in method->clazz
7124    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7125    UNSPILL_TMP1(%ecx)
7126    testl   %eax,%eax                           # returns InstrField ptr
7127    jne     .LOP_IGET_WIDE_finish
7128    jmp     common_exceptionThrown
7129
7130.LOP_IGET_WIDE_finish:
7131    /*
7132     * Currently:
7133     *   eax holds resolved field
7134     *   ecx holds object
7135     *   rINST holds A
7136     */
7137    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7138    testl   %ecx,%ecx                           # object null?
7139    je      common_errNullObject                # object was null
7140    leal    (%ecx,%eax,1),%eax                  # eax<- address of field
7141    movl    (%eax),%ecx                         # ecx<- lsw
7142    movl    4(%eax),%eax                        # eax<- msw
7143    FETCH_INST_OPCODE 2 %edx
7144    SET_VREG_WORD %ecx rINST 0
7145    SET_VREG_WORD %eax rINST 1
7146    ADVANCE_PC 2
7147    GOTO_NEXT_R %edx
7148
7149/* continuation for OP_IGET_OBJECT */
7150
7151
7152.LOP_IGET_OBJECT_resolve:
7153    EXPORT_PC
7154    movl    offGlue_method(%edx),%edx           # edx<- current method
7155    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7156    SPILL_TMP1(%ecx)                            # save obj pointer across call
7157    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7158    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7159    UNSPILL_TMP1(%ecx)
7160    testl   %eax,%eax                           #  returns InstrField ptr
7161    jne     .LOP_IGET_OBJECT_finish
7162    jmp     common_exceptionThrown
7163
7164.LOP_IGET_OBJECT_finish:
7165    /*
7166     * Currently:
7167     *   eax holds resolved field
7168     *   ecx holds object
7169     *   rINST holds A
7170     */
7171    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7172    testl   %ecx,%ecx                           # object null?
7173    je      common_errNullObject                # object was null
7174    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7175    movl    rINST,%eax                          # eax<- A
7176    FETCH_INST_OPCODE 2 %edx
7177    SET_VREG %ecx %eax
7178    ADVANCE_PC 2
7179    GOTO_NEXT_R %edx
7180
7181/* continuation for OP_IGET_BOOLEAN */
7182
7183
7184.LOP_IGET_BOOLEAN_resolve:
7185    EXPORT_PC
7186    movl    offGlue_method(%edx),%edx           # edx<- current method
7187    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7188    SPILL_TMP1(%ecx)                            # save obj pointer across call
7189    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7190    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7191    UNSPILL_TMP1(%ecx)
7192    testl   %eax,%eax                           #  returns InstrField ptr
7193    jne     .LOP_IGET_BOOLEAN_finish
7194    jmp     common_exceptionThrown
7195
7196.LOP_IGET_BOOLEAN_finish:
7197    /*
7198     * Currently:
7199     *   eax holds resolved field
7200     *   ecx holds object
7201     *   rINST holds A
7202     */
7203    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7204    testl   %ecx,%ecx                           # object null?
7205    je      common_errNullObject                # object was null
7206    movzbl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7207    movl    rINST,%eax                          # eax<- A
7208    FETCH_INST_OPCODE 2 %edx
7209    SET_VREG %ecx %eax
7210    ADVANCE_PC 2
7211    GOTO_NEXT_R %edx
7212
7213/* continuation for OP_IGET_BYTE */
7214
7215
7216.LOP_IGET_BYTE_resolve:
7217    EXPORT_PC
7218    movl    offGlue_method(%edx),%edx           # edx<- current method
7219    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7220    SPILL_TMP1(%ecx)                            # save obj pointer across call
7221    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7222    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7223    UNSPILL_TMP1(%ecx)
7224    testl   %eax,%eax                           #  returns InstrField ptr
7225    jne     .LOP_IGET_BYTE_finish
7226    jmp     common_exceptionThrown
7227
7228.LOP_IGET_BYTE_finish:
7229    /*
7230     * Currently:
7231     *   eax holds resolved field
7232     *   ecx holds object
7233     *   rINST holds A
7234     */
7235    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7236    testl   %ecx,%ecx                           # object null?
7237    je      common_errNullObject                # object was null
7238    movsbl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7239    movl    rINST,%eax                          # eax<- A
7240    FETCH_INST_OPCODE 2 %edx
7241    SET_VREG %ecx %eax
7242    ADVANCE_PC 2
7243    GOTO_NEXT_R %edx
7244
7245/* continuation for OP_IGET_CHAR */
7246
7247
7248.LOP_IGET_CHAR_resolve:
7249    EXPORT_PC
7250    movl    offGlue_method(%edx),%edx           # edx<- current method
7251    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7252    SPILL_TMP1(%ecx)                            # save obj pointer across call
7253    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7254    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7255    UNSPILL_TMP1(%ecx)
7256    testl   %eax,%eax                           #  returns InstrField ptr
7257    jne     .LOP_IGET_CHAR_finish
7258    jmp     common_exceptionThrown
7259
7260.LOP_IGET_CHAR_finish:
7261    /*
7262     * Currently:
7263     *   eax holds resolved field
7264     *   ecx holds object
7265     *   rINST holds A
7266     */
7267    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7268    testl   %ecx,%ecx                           # object null?
7269    je      common_errNullObject                # object was null
7270    movzwl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7271    movl    rINST,%eax                          # eax<- A
7272    FETCH_INST_OPCODE 2 %edx
7273    SET_VREG %ecx %eax
7274    ADVANCE_PC 2
7275    GOTO_NEXT_R %edx
7276
7277/* continuation for OP_IGET_SHORT */
7278
7279
7280.LOP_IGET_SHORT_resolve:
7281    EXPORT_PC
7282    movl    offGlue_method(%edx),%edx           # edx<- current method
7283    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7284    SPILL_TMP1(%ecx)                            # save obj pointer across call
7285    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7286    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7287    UNSPILL_TMP1(%ecx)
7288    testl   %eax,%eax                           #  returns InstrField ptr
7289    jne     .LOP_IGET_SHORT_finish
7290    jmp     common_exceptionThrown
7291
7292.LOP_IGET_SHORT_finish:
7293    /*
7294     * Currently:
7295     *   eax holds resolved field
7296     *   ecx holds object
7297     *   rINST holds A
7298     */
7299    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7300    testl   %ecx,%ecx                           # object null?
7301    je      common_errNullObject                # object was null
7302    movswl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7303    movl    rINST,%eax                          # eax<- A
7304    FETCH_INST_OPCODE 2 %edx
7305    SET_VREG %ecx %eax
7306    ADVANCE_PC 2
7307    GOTO_NEXT_R %edx
7308
7309/* continuation for OP_IPUT */
7310
7311
7312.LOP_IPUT_resolve:
7313    EXPORT_PC
7314    movl    offGlue_method(%edx),%edx           # edx<- current method
7315    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7316    SPILL_TMP1(%ecx)                            # save obj pointer across call
7317    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7318    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7319    UNSPILL_TMP1(%ecx)
7320    testl   %eax,%eax                           # returns InstrField ptr
7321    jne     .LOP_IPUT_finish
7322    jmp     common_exceptionThrown
7323
7324.LOP_IPUT_finish:
7325    /*
7326     * Currently:
7327     *   eax holds resolved field
7328     *   ecx holds object
7329     *   rINST holds A
7330     */
7331    GET_VREG_R rINST rINST                       # rINST<- v[A]
7332    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7333    testl   %ecx,%ecx                            # object null?
7334    je      common_errNullObject                 # object was null
7335    FETCH_INST_OPCODE 2 %edx
7336    movl   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7337    ADVANCE_PC 2
7338    GOTO_NEXT_R %edx
7339
7340/* continuation for OP_IPUT_WIDE */
7341
7342
7343.LOP_IPUT_WIDE_resolve:
7344    EXPORT_PC
7345    movl    offGlue_method(%edx),%edx           # edx<- current method
7346    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7347    SPILL_TMP1(%ecx)                            # save obj pointer across call
7348    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7349    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7350    UNSPILL_TMP1(%ecx)
7351    testl   %eax,%eax                           #  ... which returns InstrField ptr
7352    jne     .LOP_IPUT_WIDE_finish
7353    jmp     common_exceptionThrown
7354
7355.LOP_IPUT_WIDE_finish:
7356    /*
7357     * Currently:
7358     *   eax holds resolved field
7359     *   ecx holds object
7360     *   %edx is scratch, but needs to be unspilled
7361     *   rINST holds A
7362     */
7363    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7364    testl   %ecx,%ecx                           # object null?
7365    je      common_errNullObject                # object was null
7366    leal    (%ecx,%eax,1),%eax                  # eax<- address of field
7367    GET_VREG_WORD %ecx rINST 0                  # ecx<- lsw
7368    GET_VREG_WORD rINST rINST 1                 # rINST<- msw
7369    FETCH_INST_OPCODE 2 %edx
7370    movl    rINST,4(%eax)
7371    movl    %ecx,(%eax)
7372    ADVANCE_PC 2
7373    GOTO_NEXT_R %edx
7374
7375/* continuation for OP_IPUT_OBJECT */
7376
7377
7378.LOP_IPUT_OBJECT_resolve:
7379    EXPORT_PC
7380    movl    offGlue_method(%edx),%edx           # edx<- current method
7381    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7382    SPILL_TMP1(%ecx)                            # save obj pointer across call
7383    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7384    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7385    UNSPILL_TMP1(%ecx)
7386    testl   %eax,%eax                           # returns InstrField ptr
7387    jne     .LOP_IPUT_OBJECT_finish
7388    jmp     common_exceptionThrown
7389
7390.LOP_IPUT_OBJECT_finish:
7391    /*
7392     * Currently:
7393     *   eax holds resolved field
7394     *   ecx holds object
7395     *   %edx is scratch, but needs to be unspilled
7396     *   rINST holds A
7397     */
7398    GET_VREG_R rINST rINST                      # rINST<- v[A]
7399    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7400    testl   %ecx,%ecx                           # object null?
7401    je      common_errNullObject                # object was null
7402    movl    rINST,(%ecx,%eax)      # obj.field <- v[A](8/16/32 bits)
7403    movl    rGLUE,%eax
7404    testl   rINST,rINST                         # stored a NULL?
7405    movl    offGlue_cardTable(%eax),%eax        # get card table base
7406    FETCH_INST_OPCODE 2 %edx
7407    je      1f                                  # skip card mark if null store
7408    shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
7409    movb    %al,(%eax,%ecx)                     # mark card using object head
74101:
7411    ADVANCE_PC 2
7412    GOTO_NEXT_R %edx
7413
7414/* continuation for OP_IPUT_BOOLEAN */
7415
7416
7417.LOP_IPUT_BOOLEAN_resolve:
7418    EXPORT_PC
7419    movl    offGlue_method(%edx),%edx           # edx<- current method
7420    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7421    SPILL_TMP1(%ecx)                            # save obj pointer across call
7422    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7423    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7424    UNSPILL_TMP1(%ecx)
7425    testl   %eax,%eax                           # returns InstrField ptr
7426    jne     .LOP_IPUT_BOOLEAN_finish
7427    jmp     common_exceptionThrown
7428
7429.LOP_IPUT_BOOLEAN_finish:
7430    /*
7431     * Currently:
7432     *   eax holds resolved field
7433     *   ecx holds object
7434     *   rINST holds A
7435     */
7436    GET_VREG_R rINST rINST                       # rINST<- v[A]
7437    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7438    testl   %ecx,%ecx                            # object null?
7439    je      common_errNullObject                 # object was null
7440    FETCH_INST_OPCODE 2 %edx
7441    movb   rINSTbl,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7442    ADVANCE_PC 2
7443    GOTO_NEXT_R %edx
7444
7445/* continuation for OP_IPUT_BYTE */
7446
7447
7448.LOP_IPUT_BYTE_resolve:
7449    EXPORT_PC
7450    movl    offGlue_method(%edx),%edx           # edx<- current method
7451    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7452    SPILL_TMP1(%ecx)                            # save obj pointer across call
7453    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7454    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7455    UNSPILL_TMP1(%ecx)
7456    testl   %eax,%eax                           # returns InstrField ptr
7457    jne     .LOP_IPUT_BYTE_finish
7458    jmp     common_exceptionThrown
7459
7460.LOP_IPUT_BYTE_finish:
7461    /*
7462     * Currently:
7463     *   eax holds resolved field
7464     *   ecx holds object
7465     *   rINST holds A
7466     */
7467    GET_VREG_R rINST rINST                       # rINST<- v[A]
7468    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7469    testl   %ecx,%ecx                            # object null?
7470    je      common_errNullObject                 # object was null
7471    FETCH_INST_OPCODE 2 %edx
7472    movb   rINSTbl,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7473    ADVANCE_PC 2
7474    GOTO_NEXT_R %edx
7475
7476/* continuation for OP_IPUT_CHAR */
7477
7478
7479.LOP_IPUT_CHAR_resolve:
7480    EXPORT_PC
7481    movl    offGlue_method(%edx),%edx           # edx<- current method
7482    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7483    SPILL_TMP1(%ecx)                            # save obj pointer across call
7484    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7485    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7486    UNSPILL_TMP1(%ecx)
7487    testl   %eax,%eax                           # returns InstrField ptr
7488    jne     .LOP_IPUT_CHAR_finish
7489    jmp     common_exceptionThrown
7490
7491.LOP_IPUT_CHAR_finish:
7492    /*
7493     * Currently:
7494     *   eax holds resolved field
7495     *   ecx holds object
7496     *   rINST holds A
7497     */
7498    GET_VREG_R rINST rINST                       # rINST<- v[A]
7499    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7500    testl   %ecx,%ecx                            # object null?
7501    je      common_errNullObject                 # object was null
7502    FETCH_INST_OPCODE 2 %edx
7503    movw   rINSTw,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7504    ADVANCE_PC 2
7505    GOTO_NEXT_R %edx
7506
7507/* continuation for OP_IPUT_SHORT */
7508
7509
7510.LOP_IPUT_SHORT_resolve:
7511    EXPORT_PC
7512    movl    offGlue_method(%edx),%edx           # edx<- current method
7513    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7514    SPILL_TMP1(%ecx)                            # save obj pointer across call
7515    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7516    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7517    UNSPILL_TMP1(%ecx)
7518    testl   %eax,%eax                           # returns InstrField ptr
7519    jne     .LOP_IPUT_SHORT_finish
7520    jmp     common_exceptionThrown
7521
7522.LOP_IPUT_SHORT_finish:
7523    /*
7524     * Currently:
7525     *   eax holds resolved field
7526     *   ecx holds object
7527     *   rINST holds A
7528     */
7529    GET_VREG_R rINST rINST                       # rINST<- v[A]
7530    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7531    testl   %ecx,%ecx                            # object null?
7532    je      common_errNullObject                 # object was null
7533    FETCH_INST_OPCODE 2 %edx
7534    movw   rINSTw,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7535    ADVANCE_PC 2
7536    GOTO_NEXT_R %edx
7537
7538/* continuation for OP_SGET */
7539
7540    /*
7541     * Go resolve the field
7542     */
7543.LOP_SGET_resolve:
7544    movl     rGLUE,%ecx
7545    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7546    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7547    EXPORT_PC                                   # could throw, need to export
7548    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7549    movl     %eax,OUT_ARG1(%esp)
7550    movl     %ecx,OUT_ARG0(%esp)
7551    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7552    testl    %eax,%eax
7553    jne      .LOP_SGET_finish                 # success, continue
7554    jmp      common_exceptionThrown             # no, handle exception
7555
7556/* continuation for OP_SGET_WIDE */
7557
7558    /*
7559     * Go resolve the field
7560     */
7561.LOP_SGET_WIDE_resolve:
7562    movl     rGLUE,%ecx
7563    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7564    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7565    EXPORT_PC                                   # could throw, need to export
7566    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7567    movl     %eax,OUT_ARG1(%esp)
7568    movl     %ecx,OUT_ARG0(%esp)
7569    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7570    testl    %eax,%eax
7571    jne      .LOP_SGET_WIDE_finish                 # success, continue
7572    jmp      common_exceptionThrown             # no, handle exception
7573
7574/* continuation for OP_SGET_OBJECT */
7575
7576    /*
7577     * Go resolve the field
7578     */
7579.LOP_SGET_OBJECT_resolve:
7580    movl     rGLUE,%ecx
7581    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7582    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7583    EXPORT_PC                                   # could throw, need to export
7584    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7585    movl     %eax,OUT_ARG1(%esp)
7586    movl     %ecx,OUT_ARG0(%esp)
7587    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7588    testl    %eax,%eax
7589    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7590    jmp      common_exceptionThrown             # no, handle exception
7591
7592/* continuation for OP_SGET_BOOLEAN */
7593
7594    /*
7595     * Go resolve the field
7596     */
7597.LOP_SGET_BOOLEAN_resolve:
7598    movl     rGLUE,%ecx
7599    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7600    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7601    EXPORT_PC                                   # could throw, need to export
7602    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7603    movl     %eax,OUT_ARG1(%esp)
7604    movl     %ecx,OUT_ARG0(%esp)
7605    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7606    testl    %eax,%eax
7607    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7608    jmp      common_exceptionThrown             # no, handle exception
7609
7610/* continuation for OP_SGET_BYTE */
7611
7612    /*
7613     * Go resolve the field
7614     */
7615.LOP_SGET_BYTE_resolve:
7616    movl     rGLUE,%ecx
7617    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7618    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7619    EXPORT_PC                                   # could throw, need to export
7620    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7621    movl     %eax,OUT_ARG1(%esp)
7622    movl     %ecx,OUT_ARG0(%esp)
7623    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7624    testl    %eax,%eax
7625    jne      .LOP_SGET_BYTE_finish                 # success, continue
7626    jmp      common_exceptionThrown             # no, handle exception
7627
7628/* continuation for OP_SGET_CHAR */
7629
7630    /*
7631     * Go resolve the field
7632     */
7633.LOP_SGET_CHAR_resolve:
7634    movl     rGLUE,%ecx
7635    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7636    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7637    EXPORT_PC                                   # could throw, need to export
7638    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7639    movl     %eax,OUT_ARG1(%esp)
7640    movl     %ecx,OUT_ARG0(%esp)
7641    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7642    testl    %eax,%eax
7643    jne      .LOP_SGET_CHAR_finish                 # success, continue
7644    jmp      common_exceptionThrown             # no, handle exception
7645
7646/* continuation for OP_SGET_SHORT */
7647
7648    /*
7649     * Go resolve the field
7650     */
7651.LOP_SGET_SHORT_resolve:
7652    movl     rGLUE,%ecx
7653    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7654    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7655    EXPORT_PC                                   # could throw, need to export
7656    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7657    movl     %eax,OUT_ARG1(%esp)
7658    movl     %ecx,OUT_ARG0(%esp)
7659    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7660    testl    %eax,%eax
7661    jne      .LOP_SGET_SHORT_finish                 # success, continue
7662    jmp      common_exceptionThrown             # no, handle exception
7663
7664/* continuation for OP_SPUT */
7665
7666    /*
7667     * Go resolve the field
7668     */
7669.LOP_SPUT_resolve:
7670    movl     rGLUE,%ecx
7671    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7672    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7673    EXPORT_PC                                   # could throw, need to export
7674    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7675    movl     %eax,OUT_ARG1(%esp)
7676    movl     %ecx,OUT_ARG0(%esp)
7677    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7678    testl    %eax,%eax
7679    jne      .LOP_SPUT_finish                 # success, continue
7680    jmp      common_exceptionThrown             # no, handle exception
7681
7682/* continuation for OP_SPUT_WIDE */
7683
7684    /*
7685     * Go resolve the field
7686     */
7687.LOP_SPUT_WIDE_resolve:
7688    movl     rGLUE,%ecx
7689    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7690    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7691    EXPORT_PC                                   # could throw, need to export
7692    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7693    movl     %eax,OUT_ARG1(%esp)
7694    movl     %ecx,OUT_ARG0(%esp)
7695    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7696    testl    %eax,%eax
7697    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7698    jmp      common_exceptionThrown             # no, handle exception
7699
7700/* continuation for OP_SPUT_OBJECT */
7701
7702
7703.LOP_SPUT_OBJECT_continue:
7704    movl      %ecx,offStaticField_value(%eax)    # do the store
7705    testl     %ecx,%ecx                          # stored null object ptr?
7706    FETCH_INST_OPCODE 2 %edx
7707    je        1f                                 # skip card mark if null
7708    movl      rGLUE,%ecx
7709    movl      offField_clazz(%eax),%eax          # eax<- method->clazz
7710    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
7711    shrl      $GC_CARD_SHIFT,%eax               # head to card number
7712    movb      %cl,(%ecx,%eax)                    # mark card
77131:
7714    ADVANCE_PC 2
7715    GOTO_NEXT_R %edx
7716
7717.LOP_SPUT_OBJECT_resolve:
7718    movl     rGLUE,%ecx
7719    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7720    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7721    EXPORT_PC                                   # could throw, need to export
7722    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7723    movl     %eax,OUT_ARG1(%esp)
7724    movl     %ecx,OUT_ARG0(%esp)
7725    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7726    testl    %eax,%eax
7727    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7728    jmp      common_exceptionThrown             # no, handle exception
7729
7730/* continuation for OP_SPUT_BOOLEAN */
7731
7732    /*
7733     * Go resolve the field
7734     */
7735.LOP_SPUT_BOOLEAN_resolve:
7736    movl     rGLUE,%ecx
7737    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7738    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7739    EXPORT_PC                                   # could throw, need to export
7740    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7741    movl     %eax,OUT_ARG1(%esp)
7742    movl     %ecx,OUT_ARG0(%esp)
7743    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7744    testl    %eax,%eax
7745    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7746    jmp      common_exceptionThrown             # no, handle exception
7747
7748/* continuation for OP_SPUT_BYTE */
7749
7750    /*
7751     * Go resolve the field
7752     */
7753.LOP_SPUT_BYTE_resolve:
7754    movl     rGLUE,%ecx
7755    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7756    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7757    EXPORT_PC                                   # could throw, need to export
7758    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7759    movl     %eax,OUT_ARG1(%esp)
7760    movl     %ecx,OUT_ARG0(%esp)
7761    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7762    testl    %eax,%eax
7763    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7764    jmp      common_exceptionThrown             # no, handle exception
7765
7766/* continuation for OP_SPUT_CHAR */
7767
7768    /*
7769     * Go resolve the field
7770     */
7771.LOP_SPUT_CHAR_resolve:
7772    movl     rGLUE,%ecx
7773    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7774    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7775    EXPORT_PC                                   # could throw, need to export
7776    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7777    movl     %eax,OUT_ARG1(%esp)
7778    movl     %ecx,OUT_ARG0(%esp)
7779    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7780    testl    %eax,%eax
7781    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7782    jmp      common_exceptionThrown             # no, handle exception
7783
7784/* continuation for OP_SPUT_SHORT */
7785
7786    /*
7787     * Go resolve the field
7788     */
7789.LOP_SPUT_SHORT_resolve:
7790    movl     rGLUE,%ecx
7791    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7792    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7793    EXPORT_PC                                   # could throw, need to export
7794    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7795    movl     %eax,OUT_ARG1(%esp)
7796    movl     %ecx,OUT_ARG0(%esp)
7797    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7798    testl    %eax,%eax
7799    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7800    jmp      common_exceptionThrown             # no, handle exception
7801
7802/* continuation for OP_INVOKE_VIRTUAL */
7803
7804
7805.LOP_INVOKE_VIRTUAL_more:
7806    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7807    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7808    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7809    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7810    testl     %eax,%eax                   # got null?
7811    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7812    jmp       common_exceptionThrown      # yes, handle exception
7813
7814    /* At this point:
7815     *   eax = resolved base method
7816     *   ecx = scratch
7817     */
7818.LOP_INVOKE_VIRTUAL_continue:
7819    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7820    .if       (!0)
7821    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7822    .endif
7823    GET_VREG_R  %ecx %ecx               # ecx<- "this"
7824    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7825    testl     %ecx,%ecx                 # null this?
7826    je        common_errNullObject      # go if so
7827    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7828    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7829    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7830    jmp       common_invokeMethodNoRange
7831
7832/* continuation for OP_INVOKE_SUPER */
7833
7834    /*
7835     * At this point:
7836     *  ecx = resolved base method [r0]
7837     *  eax = method->clazz [r9]
7838     */
7839.LOP_INVOKE_SUPER_continue:
7840    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7841    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7842    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7843    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7844    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7845    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7846    jmp     common_invokeMethodNoRange
7847
7848
7849    /* At this point:
7850     * ecx = null (needs to be resolved base method)
7851     * eax = method->clazz
7852    */
7853.LOP_INVOKE_SUPER_resolve:
7854    SPILL_TMP1(%eax)                    # method->clazz
7855    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7856    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7857    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7858    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7859    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7860    testl   %eax,%eax                   # got null?
7861    movl    %eax,%ecx                   # ecx<- resolved base method
7862    UNSPILL_TMP1(%eax)                  # restore method->clazz
7863    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7864    jmp     common_exceptionThrown      # handle exception
7865
7866    /*
7867     * Throw a NoSuchMethodError with the method name as the message.
7868     *  ecx = resolved base method
7869     */
7870.LOP_INVOKE_SUPER_nsm:
7871    movl    offMethod_name(%ecx),%eax
7872    mov     %eax,OUT_ARG1(%esp)
7873    jmp     common_errNoSuchMethod
7874
7875/* continuation for OP_INVOKE_DIRECT */
7876
7877    /*
7878     * On entry:
7879     *   TMP_SPILL  <- "this" register
7880     * Things a bit ugly on this path, but it's the less
7881     * frequent one.  We'll have to do some reloading.
7882     */
7883.LOP_INVOKE_DIRECT_resolve:
7884     SPILL_TMP1(%ecx)
7885     movl     rGLUE,%ecx
7886     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7887     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7888     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7889     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7890     movl     %eax,OUT_ARG1(%esp)
7891     movl     %ecx,OUT_ARG0(%esp)
7892     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7893     UNSPILL_TMP1(%ecx)
7894     testl    %eax,%eax
7895     jne      .LOP_INVOKE_DIRECT_finish
7896     jmp      common_exceptionThrown
7897
7898/* continuation for OP_INVOKE_STATIC */
7899
7900.LOP_INVOKE_STATIC_continue:
7901    movl      $METHOD_STATIC,%eax
7902    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7903    call      dvmResolveMethod          # call(clazz,ref,flags)
7904    testl     %eax,%eax                 # got null?
7905    jne       common_invokeMethodNoRange
7906    jmp       common_exceptionThrown
7907
7908/* continuation for OP_INVOKE_INTERFACE */
7909
7910.LOP_INVOKE_INTERFACE_continue:
7911    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7912    testl      %eax,%eax
7913    je         common_exceptionThrown
7914    jmp        common_invokeMethodNoRange
7915
7916/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7917
7918
7919.LOP_INVOKE_VIRTUAL_RANGE_more:
7920    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7921    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7922    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7923    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7924    testl     %eax,%eax                   # got null?
7925    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7926    jmp       common_exceptionThrown      # yes, handle exception
7927
7928    /* At this point:
7929     *   eax = resolved base method
7930     *   ecx = scratch
7931     */
7932.LOP_INVOKE_VIRTUAL_RANGE_continue:
7933    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7934    .if       (!1)
7935    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7936    .endif
7937    GET_VREG_R  %ecx %ecx               # ecx<- "this"
7938    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7939    testl     %ecx,%ecx                 # null this?
7940    je        common_errNullObject      # go if so
7941    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7942    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7943    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7944    jmp       common_invokeMethodRange
7945
7946/* continuation for OP_INVOKE_SUPER_RANGE */
7947
7948    /*
7949     * At this point:
7950     *  ecx = resolved base method [r0]
7951     *  eax = method->clazz [r9]
7952     */
7953.LOP_INVOKE_SUPER_RANGE_continue:
7954    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7955    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7956    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7957    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7958    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7959    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7960    jmp     common_invokeMethodRange
7961
7962
7963    /* At this point:
7964     * ecx = null (needs to be resolved base method)
7965     * eax = method->clazz
7966    */
7967.LOP_INVOKE_SUPER_RANGE_resolve:
7968    SPILL_TMP1(%eax)                    # method->clazz
7969    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7970    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7971    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7972    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7973    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7974    testl   %eax,%eax                   # got null?
7975    movl    %eax,%ecx                   # ecx<- resolved base method
7976    UNSPILL_TMP1(%eax)                  # restore method->clazz
7977    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7978    jmp     common_exceptionThrown      # handle exception
7979
7980    /*
7981     * Throw a NoSuchMethodError with the method name as the message.
7982     *  ecx = resolved base method
7983     */
7984.LOP_INVOKE_SUPER_RANGE_nsm:
7985    movl    offMethod_name(%ecx),%eax
7986    mov     %eax,OUT_ARG1(%esp)
7987    jmp     common_errNoSuchMethod
7988
7989/* continuation for OP_INVOKE_DIRECT_RANGE */
7990
7991    /*
7992     * On entry:
7993     *   TMP_SPILL  <- "this" register
7994     * Things a bit ugly on this path, but it's the less
7995     * frequent one.  We'll have to do some reloading.
7996     */
7997.LOP_INVOKE_DIRECT_RANGE_resolve:
7998     SPILL_TMP1(%ecx)
7999     movl     rGLUE,%ecx
8000     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
8001     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
8002     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8003     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
8004     movl     %eax,OUT_ARG1(%esp)
8005     movl     %ecx,OUT_ARG0(%esp)
8006     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
8007     UNSPILL_TMP1(%ecx)
8008     testl    %eax,%eax
8009     jne      .LOP_INVOKE_DIRECT_RANGE_finish
8010     jmp      common_exceptionThrown
8011
8012/* continuation for OP_INVOKE_STATIC_RANGE */
8013
8014.LOP_INVOKE_STATIC_RANGE_continue:
8015    movl      $METHOD_STATIC,%eax
8016    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
8017    call      dvmResolveMethod          # call(clazz,ref,flags)
8018    testl     %eax,%eax                 # got null?
8019    jne       common_invokeMethodRange
8020    jmp       common_exceptionThrown
8021
8022/* continuation for OP_INVOKE_INTERFACE_RANGE */
8023
8024.LOP_INVOKE_INTERFACE_RANGE_continue:
8025    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
8026    testl      %eax,%eax
8027    je         common_exceptionThrown
8028    jmp        common_invokeMethodRange
8029
8030/* continuation for OP_FLOAT_TO_INT */
8031
8032
8033.LOP_FLOAT_TO_INT_continue:
8034    .if 0
8035    movl     $0x80000000,%eax
8036    xorl     4(rFP,%ecx,4),%eax
8037    orl      (rFP,%ecx,4),%eax
8038    .else
8039    cmpl     $0x80000000,(rFP,%ecx,4)
8040    .endif
8041    je       .LOP_FLOAT_TO_INT_special_case # fix up result
8042
8043.LOP_FLOAT_TO_INT_finish:
8044    ADVANCE_PC 1
8045    GOTO_NEXT_R %edx
8046
8047.LOP_FLOAT_TO_INT_special_case:
8048    fnstsw   %ax
8049    sahf
8050    jp       .LOP_FLOAT_TO_INT_isNaN
8051    adcl     $-1,(rFP,%ecx,4)
8052    .if 0
8053    adcl     $-1,4(rFP,%ecx,4)
8054    .endif
8055   jmp       .LOP_FLOAT_TO_INT_finish
8056.LOP_FLOAT_TO_INT_isNaN:
8057    movl      $0,(rFP,%ecx,4)
8058    .if 0
8059    movl      $0,4(rFP,%ecx,4)
8060    .endif
8061    jmp       .LOP_FLOAT_TO_INT_finish
8062
8063/* continuation for OP_FLOAT_TO_LONG */
8064
8065
8066.LOP_FLOAT_TO_LONG_continue:
8067    .if 1
8068    movl     $0x80000000,%eax
8069    xorl     4(rFP,%ecx,4),%eax
8070    orl      (rFP,%ecx,4),%eax
8071    .else
8072    cmpl     $0x80000000,(rFP,%ecx,4)
8073    .endif
8074    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
8075
8076.LOP_FLOAT_TO_LONG_finish:
8077    ADVANCE_PC 1
8078    GOTO_NEXT_R %edx
8079
8080.LOP_FLOAT_TO_LONG_special_case:
8081    fnstsw   %ax
8082    sahf
8083    jp       .LOP_FLOAT_TO_LONG_isNaN
8084    adcl     $-1,(rFP,%ecx,4)
8085    .if 1
8086    adcl     $-1,4(rFP,%ecx,4)
8087    .endif
8088   jmp       .LOP_FLOAT_TO_LONG_finish
8089.LOP_FLOAT_TO_LONG_isNaN:
8090    movl      $0,(rFP,%ecx,4)
8091    .if 1
8092    movl      $0,4(rFP,%ecx,4)
8093    .endif
8094    jmp       .LOP_FLOAT_TO_LONG_finish
8095
8096/* continuation for OP_DOUBLE_TO_INT */
8097
8098
8099.LOP_DOUBLE_TO_INT_continue:
8100    .if 0
8101    movl     $0x80000000,%eax
8102    xorl     4(rFP,%ecx,4),%eax
8103    orl      (rFP,%ecx,4),%eax
8104    .else
8105    cmpl     $0x80000000,(rFP,%ecx,4)
8106    .endif
8107    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
8108
8109.LOP_DOUBLE_TO_INT_finish:
8110    ADVANCE_PC 1
8111    GOTO_NEXT_R %edx
8112
8113.LOP_DOUBLE_TO_INT_special_case:
8114    fnstsw   %ax
8115    sahf
8116    jp       .LOP_DOUBLE_TO_INT_isNaN
8117    adcl     $-1,(rFP,%ecx,4)
8118    .if 0
8119    adcl     $-1,4(rFP,%ecx,4)
8120    .endif
8121   jmp       .LOP_DOUBLE_TO_INT_finish
8122.LOP_DOUBLE_TO_INT_isNaN:
8123    movl      $0,(rFP,%ecx,4)
8124    .if 0
8125    movl      $0,4(rFP,%ecx,4)
8126    .endif
8127    jmp       .LOP_DOUBLE_TO_INT_finish
8128
8129/* continuation for OP_DOUBLE_TO_LONG */
8130
8131
8132.LOP_DOUBLE_TO_LONG_continue:
8133    .if 1
8134    movl     $0x80000000,%eax
8135    xorl     4(rFP,%ecx,4),%eax
8136    orl      (rFP,%ecx,4),%eax
8137    .else
8138    cmpl     $0x80000000,(rFP,%ecx,4)
8139    .endif
8140    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8141
8142.LOP_DOUBLE_TO_LONG_finish:
8143    ADVANCE_PC 1
8144    GOTO_NEXT_R %edx
8145
8146.LOP_DOUBLE_TO_LONG_special_case:
8147    fnstsw   %ax
8148    sahf
8149    jp       .LOP_DOUBLE_TO_LONG_isNaN
8150    adcl     $-1,(rFP,%ecx,4)
8151    .if 1
8152    adcl     $-1,4(rFP,%ecx,4)
8153    .endif
8154   jmp       .LOP_DOUBLE_TO_LONG_finish
8155.LOP_DOUBLE_TO_LONG_isNaN:
8156    movl      $0,(rFP,%ecx,4)
8157    .if 1
8158    movl      $0,4(rFP,%ecx,4)
8159    .endif
8160    jmp       .LOP_DOUBLE_TO_LONG_finish
8161
8162/* continuation for OP_DIV_INT */
8163.LOP_DIV_INT_continue_div:
8164    cltd
8165    idivl   %ecx
8166.LOP_DIV_INT_finish_div:
8167    SET_VREG %eax rINST
8168    FETCH_INST_OPCODE 2 %edx
8169    ADVANCE_PC 2
8170    GOTO_NEXT_R %edx
8171
8172/* continuation for OP_REM_INT */
8173.LOP_REM_INT_continue_div:
8174    cltd
8175    idivl   %ecx
8176.LOP_REM_INT_finish_div:
8177    SET_VREG %edx rINST
8178    FETCH_INST_OPCODE 2 %edx
8179    ADVANCE_PC 2
8180    GOTO_NEXT_R %edx
8181
8182/* continuation for OP_MUL_LONG */
8183
8184.LOP_MUL_LONG_continue:
8185    leal      (%ecx,%edx),%edx     # full result now in %edx:%eax
8186    UNSPILL_TMP2(%esi)             # Restore Dalvik PC
8187    FETCH_INST_OPCODE 2 %ecx       # Fetch next instruction
8188    movl      %edx,4(rFP,rINST,4)  # v[B+1]<- %edx
8189    movl      %eax,(rFP,rINST,4)   # v[B]<- %eax
8190    ADVANCE_PC 2
8191    GOTO_NEXT_R %ecx
8192
8193/* continuation for OP_DIV_LONG */
8194
8195.LOP_DIV_LONG_continue:
8196    call     __divdi3
8197.LOP_DIV_LONG_finish:
8198    SET_VREG_WORD %edx rINST 1
8199    SET_VREG_WORD %eax rINST 0
8200    FETCH_INST_OPCODE 2 %edx
8201    ADVANCE_PC 2
8202    GOTO_NEXT_R %edx
8203
8204.LOP_DIV_LONG_check_zero:
8205    testl   %edx,%edx
8206    jne     .LOP_DIV_LONG_notSpecial
8207    jmp     common_errDivideByZero
8208.LOP_DIV_LONG_check_neg1:
8209    testl   %edx,%eax
8210    jne     .LOP_DIV_LONG_notSpecial
8211    GET_VREG_WORD %edx %ecx 0
8212    GET_VREG_WORD %ecx %ecx 1
8213    testl    %edx,%edx
8214    jne      .LOP_DIV_LONG_notSpecial1
8215    cmpl     $0x80000000,%ecx
8216    jne      .LOP_DIV_LONG_notSpecial1
8217    /* minint / -1, return minint on div, 0 on rem */
8218    xorl     %eax,%eax
8219    movl     $0x80000000,%edx
8220    jmp      .LOP_DIV_LONG_finish
8221
8222/* continuation for OP_REM_LONG */
8223
8224.LOP_REM_LONG_continue:
8225    call     __moddi3
8226.LOP_REM_LONG_finish:
8227    SET_VREG_WORD %edx rINST 1
8228    SET_VREG_WORD %eax rINST 0
8229    FETCH_INST_OPCODE 2 %edx
8230    ADVANCE_PC 2
8231    GOTO_NEXT_R %edx
8232
8233.LOP_REM_LONG_check_zero:
8234    testl   %edx,%edx
8235    jne     .LOP_REM_LONG_notSpecial
8236    jmp     common_errDivideByZero
8237.LOP_REM_LONG_check_neg1:
8238    testl   %edx,%eax
8239    jne     .LOP_REM_LONG_notSpecial
8240    GET_VREG_WORD %edx %ecx 0
8241    GET_VREG_WORD %ecx %ecx 1
8242    testl    %edx,%edx
8243    jne      .LOP_REM_LONG_notSpecial1
8244    cmpl     $0x80000000,%ecx
8245    jne      .LOP_REM_LONG_notSpecial1
8246    /* minint / -1, return minint on div, 0 on rem */
8247    xorl     %eax,%eax
8248    movl     $0,%edx
8249    jmp      .LOP_REM_LONG_finish
8250
8251/* continuation for OP_SHL_LONG */
8252
8253.LOP_SHL_LONG_finish:
8254    SET_VREG_WORD %eax rINST 0          # v[AA+0]<- %eax
8255    ADVANCE_PC 2
8256    GOTO_NEXT_R %edx
8257
8258/* continuation for OP_SHR_LONG */
8259
8260
8261.LOP_SHR_LONG_finish:
8262    SET_VREG_WORD %eax rINST 0          # v[AA+0]<- eax
8263    ADVANCE_PC 2
8264    GOTO_NEXT_R %edx
8265
8266/* continuation for OP_USHR_LONG */
8267
8268
8269.LOP_USHR_LONG_finish:
8270    SET_VREG_WORD %eax rINST 0         # v[BB+0]<- eax
8271    ADVANCE_PC 2
8272    GOTO_NEXT_R %edx
8273
8274/* continuation for OP_DIV_INT_2ADDR */
8275.LOP_DIV_INT_2ADDR_continue_div2addr:
8276    cltd
8277    idivl   %ecx
8278.LOP_DIV_INT_2ADDR_finish_div2addr:
8279    SET_VREG %eax rINST
8280    FETCH_INST_OPCODE 1 %edx
8281    ADVANCE_PC 1
8282    GOTO_NEXT_R %edx
8283
8284/* continuation for OP_REM_INT_2ADDR */
8285.LOP_REM_INT_2ADDR_continue_div2addr:
8286    cltd
8287    idivl   %ecx
8288.LOP_REM_INT_2ADDR_finish_div2addr:
8289    SET_VREG %edx rINST
8290    FETCH_INST_OPCODE 1 %edx
8291    ADVANCE_PC 1
8292    GOTO_NEXT_R %edx
8293
8294/* continuation for OP_MUL_LONG_2ADDR */
8295
8296.LOP_MUL_LONG_2ADDR_continue:
8297    leal      (%ecx,%edx),%edx         # full result now in %edx:%eax
8298    movl      %edx,4(%esi)             # v[A+1]<- %edx
8299    movl      %eax,(%esi)              # v[A]<- %eax
8300    UNSPILL_TMP2(%esi)
8301    FETCH_INST_OPCODE 1 %ecx
8302    UNSPILL(rFP)
8303    ADVANCE_PC 1
8304    GOTO_NEXT_R %ecx
8305
8306/* continuation for OP_DIV_LONG_2ADDR */
8307
8308.LOP_DIV_LONG_2ADDR_continue:
8309    movl     %eax,OUT_ARG3(%esp)
8310    movl     %edx,OUT_ARG0(%esp)
8311    movl     %ecx,OUT_ARG1(%esp)
8312    call     __divdi3
8313.LOP_DIV_LONG_2ADDR_finish:
8314    SET_VREG_WORD %edx rINST 1
8315    SET_VREG_WORD %eax rINST 0
8316    FETCH_INST_OPCODE 1 %edx
8317    ADVANCE_PC 1
8318    GOTO_NEXT_R %edx
8319
8320.LOP_DIV_LONG_2ADDR_check_zero:
8321    testl   %edx,%edx
8322    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8323    jmp     common_errDivideByZero
8324.LOP_DIV_LONG_2ADDR_check_neg1:
8325    testl   %edx,%eax
8326    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8327    GET_VREG_WORD %edx rINST 0
8328    GET_VREG_WORD %ecx rINST 1
8329    testl    %edx,%edx
8330    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8331    cmpl     $0x80000000,%ecx
8332    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8333    /* minint / -1, return minint on div, 0 on rem */
8334    xorl     %eax,%eax
8335    movl     $0x80000000,%edx
8336    jmp      .LOP_DIV_LONG_2ADDR_finish
8337
8338/* continuation for OP_REM_LONG_2ADDR */
8339
8340.LOP_REM_LONG_2ADDR_continue:
8341    movl     %eax,OUT_ARG3(%esp)
8342    movl     %edx,OUT_ARG0(%esp)
8343    movl     %ecx,OUT_ARG1(%esp)
8344    call     __moddi3
8345.LOP_REM_LONG_2ADDR_finish:
8346    SET_VREG_WORD %edx rINST 1
8347    SET_VREG_WORD %eax rINST 0
8348    FETCH_INST_OPCODE 1 %edx
8349    ADVANCE_PC 1
8350    GOTO_NEXT_R %edx
8351
8352.LOP_REM_LONG_2ADDR_check_zero:
8353    testl   %edx,%edx
8354    jne     .LOP_REM_LONG_2ADDR_notSpecial
8355    jmp     common_errDivideByZero
8356.LOP_REM_LONG_2ADDR_check_neg1:
8357    testl   %edx,%eax
8358    jne     .LOP_REM_LONG_2ADDR_notSpecial
8359    GET_VREG_WORD %edx rINST 0
8360    GET_VREG_WORD %ecx rINST 1
8361    testl    %edx,%edx
8362    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8363    cmpl     $0x80000000,%ecx
8364    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8365    /* minint / -1, return minint on div, 0 on rem */
8366    xorl     %eax,%eax
8367    movl     $0,%edx
8368    jmp      .LOP_REM_LONG_2ADDR_finish
8369
8370/* continuation for OP_SHL_LONG_2ADDR */
8371
8372
8373.LOP_SHL_LONG_2ADDR_finish:
8374    FETCH_INST_OPCODE 1 %edx
8375    SET_VREG_WORD %eax rINST 0         # v[AA+0]<- eax
8376    ADVANCE_PC 1
8377    GOTO_NEXT_R %edx
8378
8379/* continuation for OP_SHR_LONG_2ADDR */
8380
8381
8382.LOP_SHR_LONG_2ADDR_finish:
8383    FETCH_INST_OPCODE 1 %edx
8384    SET_VREG_WORD %eax rINST 0    # v[AA+0]<- eax
8385    ADVANCE_PC 1
8386    GOTO_NEXT_R %edx
8387
8388/* continuation for OP_USHR_LONG_2ADDR */
8389
8390
8391.LOP_USHR_LONG_2ADDR_finish:
8392    FETCH_INST_OPCODE 1 %edx
8393    SET_VREG_WORD %eax rINST 0         # v[AA+0]<- eax
8394    ADVANCE_PC 1
8395    GOTO_NEXT_R %edx
8396
8397/* continuation for OP_DIV_INT_LIT16 */
8398.LOP_DIV_INT_LIT16_continue_div:
8399    cltd
8400    idivl   %ecx
8401.LOP_DIV_INT_LIT16_finish_div:
8402    SET_VREG %eax rINST
8403    FETCH_INST_OPCODE 2 %edx
8404    ADVANCE_PC 2
8405    GOTO_NEXT_R %edx
8406
8407/* continuation for OP_REM_INT_LIT16 */
8408.LOP_REM_INT_LIT16_continue_div:
8409    cltd
8410    idivl   %ecx
8411.LOP_REM_INT_LIT16_finish_div:
8412    SET_VREG %edx rINST
8413    FETCH_INST_OPCODE 2 %edx
8414    ADVANCE_PC 2
8415    GOTO_NEXT_R %edx
8416
8417/* continuation for OP_DIV_INT_LIT8 */
8418.LOP_DIV_INT_LIT8_continue_div:
8419    cltd
8420    idivl   %ecx
8421.LOP_DIV_INT_LIT8_finish_div:
8422    SET_VREG %eax rINST
8423    FETCH_INST_OPCODE 2 %edx
8424    ADVANCE_PC 2
8425    GOTO_NEXT_R %edx
8426
8427/* continuation for OP_REM_INT_LIT8 */
8428.LOP_REM_INT_LIT8_continue_div:
8429    cltd
8430    idivl   %ecx
8431.LOP_REM_INT_LIT8_finish_div:
8432    SET_VREG %edx rINST
8433    FETCH_INST_OPCODE 2 %edx
8434    ADVANCE_PC 2
8435    GOTO_NEXT_R %edx
8436
8437/* continuation for OP_IGET_VOLATILE */
8438
8439
8440.LOP_IGET_VOLATILE_resolve:
8441    EXPORT_PC
8442    movl    offGlue_method(%edx),%edx           # edx<- current method
8443    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8444    SPILL_TMP1(%ecx)                            # save obj pointer across call
8445    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
8446    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8447    UNSPILL_TMP1(%ecx)
8448    testl   %eax,%eax                           #  returns InstrField ptr
8449    jne     .LOP_IGET_VOLATILE_finish
8450    jmp     common_exceptionThrown
8451
8452.LOP_IGET_VOLATILE_finish:
8453    /*
8454     * Currently:
8455     *   eax holds resolved field
8456     *   ecx holds object
8457     *   rINST holds A
8458     */
8459    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8460    testl   %ecx,%ecx                           # object null?
8461    je      common_errNullObject                # object was null
8462    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
8463    movl    rINST,%eax                          # eax<- A
8464    FETCH_INST_OPCODE 2 %edx
8465    SET_VREG %ecx %eax
8466    ADVANCE_PC 2
8467    GOTO_NEXT_R %edx
8468
8469/* continuation for OP_IPUT_VOLATILE */
8470
8471
8472.LOP_IPUT_VOLATILE_resolve:
8473    EXPORT_PC
8474    movl    offGlue_method(%edx),%edx           # edx<- current method
8475    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8476    SPILL_TMP1(%ecx)                            # save obj pointer across call
8477    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
8478    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8479    UNSPILL_TMP1(%ecx)
8480    testl   %eax,%eax                           # returns InstrField ptr
8481    jne     .LOP_IPUT_VOLATILE_finish
8482    jmp     common_exceptionThrown
8483
8484.LOP_IPUT_VOLATILE_finish:
8485    /*
8486     * Currently:
8487     *   eax holds resolved field
8488     *   ecx holds object
8489     *   rINST holds A
8490     */
8491    GET_VREG_R rINST rINST                       # rINST<- v[A]
8492    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8493    testl   %ecx,%ecx                            # object null?
8494    je      common_errNullObject                 # object was null
8495    FETCH_INST_OPCODE 2 %edx
8496    movl   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
8497    ADVANCE_PC 2
8498    GOTO_NEXT_R %edx
8499
8500/* continuation for OP_SGET_VOLATILE */
8501
8502    /*
8503     * Go resolve the field
8504     */
8505.LOP_SGET_VOLATILE_resolve:
8506    movl     rGLUE,%ecx
8507    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8508    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8509    EXPORT_PC                                   # could throw, need to export
8510    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8511    movl     %eax,OUT_ARG1(%esp)
8512    movl     %ecx,OUT_ARG0(%esp)
8513    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8514    testl    %eax,%eax
8515    jne      .LOP_SGET_VOLATILE_finish                 # success, continue
8516    jmp      common_exceptionThrown             # no, handle exception
8517
8518/* continuation for OP_SPUT_VOLATILE */
8519
8520    /*
8521     * Go resolve the field
8522     */
8523.LOP_SPUT_VOLATILE_resolve:
8524    movl     rGLUE,%ecx
8525    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8526    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8527    EXPORT_PC                                   # could throw, need to export
8528    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8529    movl     %eax,OUT_ARG1(%esp)
8530    movl     %ecx,OUT_ARG0(%esp)
8531    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8532    testl    %eax,%eax
8533    jne      .LOP_SPUT_VOLATILE_finish                 # success, continue
8534    jmp      common_exceptionThrown             # no, handle exception
8535
8536/* continuation for OP_IGET_OBJECT_VOLATILE */
8537
8538
8539.LOP_IGET_OBJECT_VOLATILE_resolve:
8540    EXPORT_PC
8541    movl    offGlue_method(%edx),%edx           # edx<- current method
8542    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8543    SPILL_TMP1(%ecx)                            # save obj pointer across call
8544    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
8545    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8546    UNSPILL_TMP1(%ecx)
8547    testl   %eax,%eax                           #  returns InstrField ptr
8548    jne     .LOP_IGET_OBJECT_VOLATILE_finish
8549    jmp     common_exceptionThrown
8550
8551.LOP_IGET_OBJECT_VOLATILE_finish:
8552    /*
8553     * Currently:
8554     *   eax holds resolved field
8555     *   ecx holds object
8556     *   rINST holds A
8557     */
8558    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8559    testl   %ecx,%ecx                           # object null?
8560    je      common_errNullObject                # object was null
8561    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
8562    movl    rINST,%eax                          # eax<- A
8563    FETCH_INST_OPCODE 2 %edx
8564    SET_VREG %ecx %eax
8565    ADVANCE_PC 2
8566    GOTO_NEXT_R %edx
8567
8568/* continuation for OP_EXECUTE_INLINE */
8569
8570.LOP_EXECUTE_INLINE_continue:
8571    /*
8572     * Extract args, call function.
8573     *  ecx = #of args (0-4)
8574     *  eax = call index
8575     *  @esp = return addr
8576     *  esp is -4 from normal
8577     *
8578     *  Go ahead and load all 4 args, even if not used.
8579     */
8580    movzwl    4(rPC),%edx
8581
8582    movl      $0xf,%ecx
8583    andl      %edx,%ecx
8584    GET_VREG_R  %ecx %ecx
8585    sarl      $4,%edx
8586    movl      %ecx,4+OUT_ARG0(%esp)
8587
8588    movl      $0xf,%ecx
8589    andl      %edx,%ecx
8590    GET_VREG_R  %ecx %ecx
8591    sarl      $4,%edx
8592    movl      %ecx,4+OUT_ARG1(%esp)
8593
8594    movl      $0xf,%ecx
8595    andl      %edx,%ecx
8596    GET_VREG_R  %ecx %ecx
8597    sarl      $4,%edx
8598    movl      %ecx,4+OUT_ARG2(%esp)
8599
8600    movl      $0xf,%ecx
8601    andl      %edx,%ecx
8602    GET_VREG_R  %ecx %ecx
8603    sarl      $4,%edx
8604    movl      %ecx,4+OUT_ARG3(%esp)
8605
8606    sall      $4,%eax      # index *= sizeof(table entry)
8607    jmp       *gDvmInlineOpsTable(%eax)
8608    # will return to caller of .LOP_EXECUTE_INLINE_continue
8609
8610/* continuation for OP_IPUT_OBJECT_QUICK */
8611
8612.LOP_IPUT_OBJECT_QUICK_finish:
8613    testl     rINST,rINST               # did we store null?
8614    FETCH_INST_OPCODE 2 %edx
8615    movl      offGlue_cardTable(%eax),%eax  # get card table base
8616    je        1f                            # skip card mark if null store
8617    shrl      $GC_CARD_SHIFT,%ecx          # object head to card number
8618    movb      %al,(%eax,%ecx)               # mark card based on object head
86191:
8620    ADVANCE_PC 2
8621    GOTO_NEXT_R %edx
8622
8623/* continuation for OP_IPUT_OBJECT_VOLATILE */
8624
8625
8626.LOP_IPUT_OBJECT_VOLATILE_resolve:
8627    EXPORT_PC
8628    movl    offGlue_method(%edx),%edx           # edx<- current method
8629    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8630    SPILL_TMP1(%ecx)                            # save obj pointer across call
8631    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
8632    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8633    UNSPILL_TMP1(%ecx)
8634    testl   %eax,%eax                           # returns InstrField ptr
8635    jne     .LOP_IPUT_OBJECT_VOLATILE_finish
8636    jmp     common_exceptionThrown
8637
8638.LOP_IPUT_OBJECT_VOLATILE_finish:
8639    /*
8640     * Currently:
8641     *   eax holds resolved field
8642     *   ecx holds object
8643     *   %edx is scratch, but needs to be unspilled
8644     *   rINST holds A
8645     */
8646    GET_VREG_R rINST rINST                      # rINST<- v[A]
8647    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8648    testl   %ecx,%ecx                           # object null?
8649    je      common_errNullObject                # object was null
8650    movl    rINST,(%ecx,%eax)      # obj.field <- v[A](8/16/32 bits)
8651    movl    rGLUE,%eax
8652    testl   rINST,rINST                         # stored a NULL?
8653    movl    offGlue_cardTable(%eax),%eax        # get card table base
8654    FETCH_INST_OPCODE 2 %edx
8655    je      1f                                  # skip card mark if null store
8656    shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
8657    movb    %al,(%eax,%ecx)                     # mark card using object head
86581:
8659    ADVANCE_PC 2
8660    GOTO_NEXT_R %edx
8661
8662/* continuation for OP_SGET_OBJECT_VOLATILE */
8663
8664    /*
8665     * Go resolve the field
8666     */
8667.LOP_SGET_OBJECT_VOLATILE_resolve:
8668    movl     rGLUE,%ecx
8669    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8670    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8671    EXPORT_PC                                   # could throw, need to export
8672    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8673    movl     %eax,OUT_ARG1(%esp)
8674    movl     %ecx,OUT_ARG0(%esp)
8675    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8676    testl    %eax,%eax
8677    jne      .LOP_SGET_OBJECT_VOLATILE_finish                 # success, continue
8678    jmp      common_exceptionThrown             # no, handle exception
8679
8680/* continuation for OP_SPUT_OBJECT_VOLATILE */
8681
8682
8683.LOP_SPUT_OBJECT_VOLATILE_continue:
8684    movl      %ecx,offStaticField_value(%eax)    # do the store
8685    testl     %ecx,%ecx                          # stored null object ptr?
8686    FETCH_INST_OPCODE 2 %edx
8687    je        1f                                 # skip card mark if null
8688    movl      rGLUE,%ecx
8689    movl      offField_clazz(%eax),%eax          # eax<- method->clazz
8690    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
8691    shrl      $GC_CARD_SHIFT,%eax               # head to card number
8692    movb      %cl,(%ecx,%eax)                    # mark card
86931:
8694    ADVANCE_PC 2
8695    GOTO_NEXT_R %edx
8696
8697.LOP_SPUT_OBJECT_VOLATILE_resolve:
8698    movl     rGLUE,%ecx
8699    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8700    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8701    EXPORT_PC                                   # could throw, need to export
8702    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8703    movl     %eax,OUT_ARG1(%esp)
8704    movl     %ecx,OUT_ARG0(%esp)
8705    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8706    testl    %eax,%eax
8707    jne      .LOP_SPUT_OBJECT_VOLATILE_finish                 # success, continue
8708    jmp      common_exceptionThrown             # no, handle exception
8709
8710    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8711    .global dvmAsmSisterEnd
8712dvmAsmSisterEnd:
8713
8714/* File: x86/entry.S */
8715/*
8716 * Copyright (C) 2008 The Android Open Source Project
8717 *
8718 * Licensed under the Apache License, Version 2.0 (the "License");
8719 * you may not use this file except in compliance with the License.
8720 * You may obtain a copy of the License at
8721 *
8722 *      http://www.apache.org/licenses/LICENSE-2.0
8723 *
8724 * Unless required by applicable law or agreed to in writing, software
8725 * distributed under the License is distributed on an "AS IS" BASIS,
8726 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8727 * See the License for the specific language governing permissions and
8728 * limitations under the License.
8729 */
8730
8731
8732    .text
8733    .global dvmMterpStdRun
8734    .type   dvmMterpStdRun, %function
8735/*
8736 * bool dvmMterpStdRun(MterpGlue* glue)
8737 *
8738 * Interpreter entry point.  Returns changeInterp.
8739 *
8740 */
8741dvmMterpStdRun:
8742    movl    4(%esp), %ecx        # get incoming rGLUE
8743    push    %ebp                 # save caller base pointer
8744    push    %ecx                 # save rGLUE at (%ebp)
8745    movl    %esp, %ebp           # set our %ebp
8746/*
8747 * At this point we've allocated two slots on the stack
8748 * via push and stack is 8-byte aligned.  Allocate space
8749 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for
8750 * padding to bring us to 16-byte alignment
8751 */
8752    subl    $(FRAME_SIZE-8), %esp
8753
8754/* Spill callee save regs */
8755    movl    %edi,EDI_SPILL(%ebp)
8756    movl    %esi,ESI_SPILL(%ebp)
8757    movl    %ebx,EBX_SPILL(%ebp)
8758
8759/* Set up "named" registers */
8760    movl    offGlue_pc(%ecx),rPC
8761    movl    offGlue_fp(%ecx),rFP
8762
8763/* Remember %esp for future "longjmp" */
8764    movl    %esp,offGlue_bailPtr(%ecx)
8765
8766/* How to start? */
8767    movb    offGlue_entryPoint(%ecx),%al
8768
8769/* Normal start? */
8770    cmpb    $kInterpEntryInstr,%al
8771    jne     .Lnot_instr
8772
8773   /* Normal case: start executing the instruction at rPC */
8774    FETCH_INST
8775    GOTO_NEXT
8776
8777.Lnot_instr:
8778    /* Reset to normal case */
8779    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8780    cmpb   $kInterpEntryReturn,%al
8781    je     common_returnFromMethod
8782    cmpb   $kInterpEntryThrow,%al
8783    je     common_exceptionThrown
8784    movzx  %al,%eax
8785    movl   %eax,OUT_ARG1(%esp)
8786    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8787    call   printf
8788    call   dvmAbort
8789    /* Not reached */
8790
8791
8792    .global dvmMterpStdBail
8793    .type   dvmMterpStdBail, %function
8794/*
8795 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8796 *
8797 * Restore the stack pointer and PC from the save point established on entry.
8798 * This is essentially the same as a longjmp, but should be cheaper.  The
8799 * last instruction causes us to return to whoever called dvmMterpStdRun.
8800 *
8801 * We're not going to build a standard frame here, so the arg accesses will
8802 * look a little strange.
8803 *
8804 * On entry:
8805 *  esp+4 (arg0)  MterpGlue* glue
8806 *  esp+8 (arg1)  bool changeInterp
8807 */
8808dvmMterpStdBail:
8809    movl    4(%esp),%ecx                 # grab glue
8810    movl    8(%esp),%eax                 # changeInterp to return reg
8811    movl    offGlue_bailPtr(%ecx),%esp   # Restore "setjmp" esp
8812    movl    %esp,%ebp
8813    addl    $(FRAME_SIZE-8), %ebp       # Restore %ebp at point of setjmp
8814    movl    EDI_SPILL(%ebp),%edi
8815    movl    ESI_SPILL(%ebp),%esi
8816    movl    EBX_SPILL(%ebp),%ebx
8817    movl    PREV_FP(%ebp),%ebp           # restore caller's ebp
8818    addl    $FRAME_SIZE,%esp                    # strip frame
8819    ret                                  # return to dvmMterpStdRun's caller
8820
8821
8822/*
8823 * Strings
8824 */
8825    .section    .rodata
8826.LstrBadEntryPoint:
8827    .asciz  "Bad entry point %d\n"
8828
8829
8830/*
8831 * FIXME: Should have the config/rebuild mechanism generate this
8832 * for targets that need it.
8833 */
8834
8835/* Jump table */
8836dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable
8837.LdvmAsmInstructionJmpTable:
8838.long .L_OP_NOP
8839.long .L_OP_MOVE
8840.long .L_OP_MOVE_FROM16
8841.long .L_OP_MOVE_16
8842.long .L_OP_MOVE_WIDE
8843.long .L_OP_MOVE_WIDE_FROM16
8844.long .L_OP_MOVE_WIDE_16
8845.long .L_OP_MOVE_OBJECT
8846.long .L_OP_MOVE_OBJECT_FROM16
8847.long .L_OP_MOVE_OBJECT_16
8848.long .L_OP_MOVE_RESULT
8849.long .L_OP_MOVE_RESULT_WIDE
8850.long .L_OP_MOVE_RESULT_OBJECT
8851.long .L_OP_MOVE_EXCEPTION
8852.long .L_OP_RETURN_VOID
8853.long .L_OP_RETURN
8854.long .L_OP_RETURN_WIDE
8855.long .L_OP_RETURN_OBJECT
8856.long .L_OP_CONST_4
8857.long .L_OP_CONST_16
8858.long .L_OP_CONST
8859.long .L_OP_CONST_HIGH16
8860.long .L_OP_CONST_WIDE_16
8861.long .L_OP_CONST_WIDE_32
8862.long .L_OP_CONST_WIDE
8863.long .L_OP_CONST_WIDE_HIGH16
8864.long .L_OP_CONST_STRING
8865.long .L_OP_CONST_STRING_JUMBO
8866.long .L_OP_CONST_CLASS
8867.long .L_OP_MONITOR_ENTER
8868.long .L_OP_MONITOR_EXIT
8869.long .L_OP_CHECK_CAST
8870.long .L_OP_INSTANCE_OF
8871.long .L_OP_ARRAY_LENGTH
8872.long .L_OP_NEW_INSTANCE
8873.long .L_OP_NEW_ARRAY
8874.long .L_OP_FILLED_NEW_ARRAY
8875.long .L_OP_FILLED_NEW_ARRAY_RANGE
8876.long .L_OP_FILL_ARRAY_DATA
8877.long .L_OP_THROW
8878.long .L_OP_GOTO
8879.long .L_OP_GOTO_16
8880.long .L_OP_GOTO_32
8881.long .L_OP_PACKED_SWITCH
8882.long .L_OP_SPARSE_SWITCH
8883.long .L_OP_CMPL_FLOAT
8884.long .L_OP_CMPG_FLOAT
8885.long .L_OP_CMPL_DOUBLE
8886.long .L_OP_CMPG_DOUBLE
8887.long .L_OP_CMP_LONG
8888.long .L_OP_IF_EQ
8889.long .L_OP_IF_NE
8890.long .L_OP_IF_LT
8891.long .L_OP_IF_GE
8892.long .L_OP_IF_GT
8893.long .L_OP_IF_LE
8894.long .L_OP_IF_EQZ
8895.long .L_OP_IF_NEZ
8896.long .L_OP_IF_LTZ
8897.long .L_OP_IF_GEZ
8898.long .L_OP_IF_GTZ
8899.long .L_OP_IF_LEZ
8900.long .L_OP_UNUSED_3E
8901.long .L_OP_UNUSED_3F
8902.long .L_OP_UNUSED_40
8903.long .L_OP_UNUSED_41
8904.long .L_OP_UNUSED_42
8905.long .L_OP_UNUSED_43
8906.long .L_OP_AGET
8907.long .L_OP_AGET_WIDE
8908.long .L_OP_AGET_OBJECT
8909.long .L_OP_AGET_BOOLEAN
8910.long .L_OP_AGET_BYTE
8911.long .L_OP_AGET_CHAR
8912.long .L_OP_AGET_SHORT
8913.long .L_OP_APUT
8914.long .L_OP_APUT_WIDE
8915.long .L_OP_APUT_OBJECT
8916.long .L_OP_APUT_BOOLEAN
8917.long .L_OP_APUT_BYTE
8918.long .L_OP_APUT_CHAR
8919.long .L_OP_APUT_SHORT
8920.long .L_OP_IGET
8921.long .L_OP_IGET_WIDE
8922.long .L_OP_IGET_OBJECT
8923.long .L_OP_IGET_BOOLEAN
8924.long .L_OP_IGET_BYTE
8925.long .L_OP_IGET_CHAR
8926.long .L_OP_IGET_SHORT
8927.long .L_OP_IPUT
8928.long .L_OP_IPUT_WIDE
8929.long .L_OP_IPUT_OBJECT
8930.long .L_OP_IPUT_BOOLEAN
8931.long .L_OP_IPUT_BYTE
8932.long .L_OP_IPUT_CHAR
8933.long .L_OP_IPUT_SHORT
8934.long .L_OP_SGET
8935.long .L_OP_SGET_WIDE
8936.long .L_OP_SGET_OBJECT
8937.long .L_OP_SGET_BOOLEAN
8938.long .L_OP_SGET_BYTE
8939.long .L_OP_SGET_CHAR
8940.long .L_OP_SGET_SHORT
8941.long .L_OP_SPUT
8942.long .L_OP_SPUT_WIDE
8943.long .L_OP_SPUT_OBJECT
8944.long .L_OP_SPUT_BOOLEAN
8945.long .L_OP_SPUT_BYTE
8946.long .L_OP_SPUT_CHAR
8947.long .L_OP_SPUT_SHORT
8948.long .L_OP_INVOKE_VIRTUAL
8949.long .L_OP_INVOKE_SUPER
8950.long .L_OP_INVOKE_DIRECT
8951.long .L_OP_INVOKE_STATIC
8952.long .L_OP_INVOKE_INTERFACE
8953.long .L_OP_UNUSED_73
8954.long .L_OP_INVOKE_VIRTUAL_RANGE
8955.long .L_OP_INVOKE_SUPER_RANGE
8956.long .L_OP_INVOKE_DIRECT_RANGE
8957.long .L_OP_INVOKE_STATIC_RANGE
8958.long .L_OP_INVOKE_INTERFACE_RANGE
8959.long .L_OP_UNUSED_79
8960.long .L_OP_UNUSED_7A
8961.long .L_OP_NEG_INT
8962.long .L_OP_NOT_INT
8963.long .L_OP_NEG_LONG
8964.long .L_OP_NOT_LONG
8965.long .L_OP_NEG_FLOAT
8966.long .L_OP_NEG_DOUBLE
8967.long .L_OP_INT_TO_LONG
8968.long .L_OP_INT_TO_FLOAT
8969.long .L_OP_INT_TO_DOUBLE
8970.long .L_OP_LONG_TO_INT
8971.long .L_OP_LONG_TO_FLOAT
8972.long .L_OP_LONG_TO_DOUBLE
8973.long .L_OP_FLOAT_TO_INT
8974.long .L_OP_FLOAT_TO_LONG
8975.long .L_OP_FLOAT_TO_DOUBLE
8976.long .L_OP_DOUBLE_TO_INT
8977.long .L_OP_DOUBLE_TO_LONG
8978.long .L_OP_DOUBLE_TO_FLOAT
8979.long .L_OP_INT_TO_BYTE
8980.long .L_OP_INT_TO_CHAR
8981.long .L_OP_INT_TO_SHORT
8982.long .L_OP_ADD_INT
8983.long .L_OP_SUB_INT
8984.long .L_OP_MUL_INT
8985.long .L_OP_DIV_INT
8986.long .L_OP_REM_INT
8987.long .L_OP_AND_INT
8988.long .L_OP_OR_INT
8989.long .L_OP_XOR_INT
8990.long .L_OP_SHL_INT
8991.long .L_OP_SHR_INT
8992.long .L_OP_USHR_INT
8993.long .L_OP_ADD_LONG
8994.long .L_OP_SUB_LONG
8995.long .L_OP_MUL_LONG
8996.long .L_OP_DIV_LONG
8997.long .L_OP_REM_LONG
8998.long .L_OP_AND_LONG
8999.long .L_OP_OR_LONG
9000.long .L_OP_XOR_LONG
9001.long .L_OP_SHL_LONG
9002.long .L_OP_SHR_LONG
9003.long .L_OP_USHR_LONG
9004.long .L_OP_ADD_FLOAT
9005.long .L_OP_SUB_FLOAT
9006.long .L_OP_MUL_FLOAT
9007.long .L_OP_DIV_FLOAT
9008.long .L_OP_REM_FLOAT
9009.long .L_OP_ADD_DOUBLE
9010.long .L_OP_SUB_DOUBLE
9011.long .L_OP_MUL_DOUBLE
9012.long .L_OP_DIV_DOUBLE
9013.long .L_OP_REM_DOUBLE
9014.long .L_OP_ADD_INT_2ADDR
9015.long .L_OP_SUB_INT_2ADDR
9016.long .L_OP_MUL_INT_2ADDR
9017.long .L_OP_DIV_INT_2ADDR
9018.long .L_OP_REM_INT_2ADDR
9019.long .L_OP_AND_INT_2ADDR
9020.long .L_OP_OR_INT_2ADDR
9021.long .L_OP_XOR_INT_2ADDR
9022.long .L_OP_SHL_INT_2ADDR
9023.long .L_OP_SHR_INT_2ADDR
9024.long .L_OP_USHR_INT_2ADDR
9025.long .L_OP_ADD_LONG_2ADDR
9026.long .L_OP_SUB_LONG_2ADDR
9027.long .L_OP_MUL_LONG_2ADDR
9028.long .L_OP_DIV_LONG_2ADDR
9029.long .L_OP_REM_LONG_2ADDR
9030.long .L_OP_AND_LONG_2ADDR
9031.long .L_OP_OR_LONG_2ADDR
9032.long .L_OP_XOR_LONG_2ADDR
9033.long .L_OP_SHL_LONG_2ADDR
9034.long .L_OP_SHR_LONG_2ADDR
9035.long .L_OP_USHR_LONG_2ADDR
9036.long .L_OP_ADD_FLOAT_2ADDR
9037.long .L_OP_SUB_FLOAT_2ADDR
9038.long .L_OP_MUL_FLOAT_2ADDR
9039.long .L_OP_DIV_FLOAT_2ADDR
9040.long .L_OP_REM_FLOAT_2ADDR
9041.long .L_OP_ADD_DOUBLE_2ADDR
9042.long .L_OP_SUB_DOUBLE_2ADDR
9043.long .L_OP_MUL_DOUBLE_2ADDR
9044.long .L_OP_DIV_DOUBLE_2ADDR
9045.long .L_OP_REM_DOUBLE_2ADDR
9046.long .L_OP_ADD_INT_LIT16
9047.long .L_OP_RSUB_INT
9048.long .L_OP_MUL_INT_LIT16
9049.long .L_OP_DIV_INT_LIT16
9050.long .L_OP_REM_INT_LIT16
9051.long .L_OP_AND_INT_LIT16
9052.long .L_OP_OR_INT_LIT16
9053.long .L_OP_XOR_INT_LIT16
9054.long .L_OP_ADD_INT_LIT8
9055.long .L_OP_RSUB_INT_LIT8
9056.long .L_OP_MUL_INT_LIT8
9057.long .L_OP_DIV_INT_LIT8
9058.long .L_OP_REM_INT_LIT8
9059.long .L_OP_AND_INT_LIT8
9060.long .L_OP_OR_INT_LIT8
9061.long .L_OP_XOR_INT_LIT8
9062.long .L_OP_SHL_INT_LIT8
9063.long .L_OP_SHR_INT_LIT8
9064.long .L_OP_USHR_INT_LIT8
9065.long .L_OP_IGET_VOLATILE
9066.long .L_OP_IPUT_VOLATILE
9067.long .L_OP_SGET_VOLATILE
9068.long .L_OP_SPUT_VOLATILE
9069.long .L_OP_IGET_OBJECT_VOLATILE
9070.long .L_OP_IGET_WIDE_VOLATILE
9071.long .L_OP_IPUT_WIDE_VOLATILE
9072.long .L_OP_SGET_WIDE_VOLATILE
9073.long .L_OP_SPUT_WIDE_VOLATILE
9074.long .L_OP_BREAKPOINT
9075.long .L_OP_THROW_VERIFICATION_ERROR
9076.long .L_OP_EXECUTE_INLINE
9077.long .L_OP_EXECUTE_INLINE_RANGE
9078.long .L_OP_INVOKE_DIRECT_EMPTY
9079.long .L_OP_RETURN_VOID_BARRIER
9080.long .L_OP_IGET_QUICK
9081.long .L_OP_IGET_WIDE_QUICK
9082.long .L_OP_IGET_OBJECT_QUICK
9083.long .L_OP_IPUT_QUICK
9084.long .L_OP_IPUT_WIDE_QUICK
9085.long .L_OP_IPUT_OBJECT_QUICK
9086.long .L_OP_INVOKE_VIRTUAL_QUICK
9087.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE
9088.long .L_OP_INVOKE_SUPER_QUICK
9089.long .L_OP_INVOKE_SUPER_QUICK_RANGE
9090.long .L_OP_IPUT_OBJECT_VOLATILE
9091.long .L_OP_SGET_OBJECT_VOLATILE
9092.long .L_OP_SPUT_OBJECT_VOLATILE
9093.long .L_OP_UNUSED_FF
9094
9095
9096/* File: x86/footer.S */
9097/*
9098 * Copyright (C) 2008 The Android Open Source Project
9099 *
9100 * Licensed under the Apache License, Version 2.0 (the "License");
9101 * you may not use this file except in compliance with the License.
9102 * You may obtain a copy of the License at
9103 *
9104 *      http://www.apache.org/licenses/LICENSE-2.0
9105 *
9106 * Unless required by applicable law or agreed to in writing, software
9107 * distributed under the License is distributed on an "AS IS" BASIS,
9108 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9109 * See the License for the specific language governing permissions and
9110 * limitations under the License.
9111 */
9112/*
9113 * Common subroutines and data.
9114 */
9115
9116#if defined(WITH_JIT)
9117/*
9118 * Placeholder entries for x86 JIT
9119 */
9120    .global dvmJitToInterpPunt
9121dvmJitToInterpPunt:
9122    .global dvmJitToInterpSingleStep
9123dvmJitToInterpSingleStep:
9124    .global dvmJitToInterpNoChainNoProfile
9125dvmJitToInterpNoChainNoProfile:
9126    .global dvmJitToInterpTraceSelectNoChain
9127dvmJitToInterpTraceSelectNoChain:
9128    .global dvmJitToInterpTraceSelect
9129dvmJitToInterpTraceSelect:
9130    .global dvmJitToInterpBackwardBranch
9131dvmJitToInterpBackwardBranch:
9132    .global dvmJitToInterpNormal
9133dvmJitToInterpNormal:
9134    .global dvmJitToInterpNoChain
9135dvmJitToInterpNoChain:
9136    jmp  common_abort
9137#endif
9138
9139/*
9140 * Common code when a backwards branch is taken
9141 *
9142 * On entry:
9143 *   ebx (a.k.a. rINST) -> PC adjustment in 16-bit words
9144 */
9145common_backwardBranch:
9146    movl    rGLUE,%ecx
9147    call   common_periodicChecks  # Note: expects rPC to be preserved
9148    ADVANCE_PC_INDEXED rINST
9149    FETCH_INST
9150    GOTO_NEXT
9151
9152
9153
9154/*
9155 * Common code for method invocation with range.
9156 *
9157 * On entry:
9158 *   eax = Method* methodToCall
9159 *   rINSTw trashed, must reload
9160 */
9161
9162common_invokeMethodRange:
9163.LinvokeNewRange:
9164
9165   /*
9166    * prepare to copy args to "outs" area of current frame
9167    */
9168
9169    movzbl      1(rPC),rINST       # rINST<- AA
9170    movzwl      4(rPC), %ecx            # %ecx<- CCCC
9171    SAVEAREA_FROM_FP %edx               # %edx<- &StackSaveArea
9172    test        rINST, rINST
9173    movl        rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
9174    jz          .LinvokeArgsDone        # no args; jump to args done
9175
9176
9177   /*
9178    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
9179    * (very few methods have > 10 args; could unroll for common cases)
9180    */
9181
9182    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
9183    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
9184    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
9185    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
9186    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
91871:
9188    movl        (%ecx), %ebx            # %ebx<- vCCCC
9189    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
9190    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
9191    movl        %ebx, (%edx)            # *outs<- vCCCC
9192    lea         4(%edx), %edx           # outs++
9193    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
9194    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
9195    jmp         .LinvokeArgsDone        # continue
9196
9197   /*
9198    * %eax is "Method* methodToCall", the method we're trying to call
9199    * prepare to copy args to "outs" area of current frame
9200    */
9201
9202common_invokeMethodNoRange:
9203.LinvokeNewNoRange:
9204    movzbl      1(rPC),rINST       # rINST<- BA
9205    movl        rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
9206    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
9207    je          .LinvokeArgsDone        # no args; jump to args done
9208    movzwl      4(rPC), %ecx            # %ecx<- GFED
9209    SAVEAREA_FROM_FP %edx               # %edx<- &StackSaveArea
9210
9211   /*
9212    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
9213    */
9214
9215.LinvokeNonRange:
9216    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
9217    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
9218    jl          1f                      # handle 1 arg
9219    je          2f                      # handle 2 args
9220    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
9221    jl          3f                      # handle 3 args
9222    je          4f                      # handle 4 args
92235:
9224    andl        $15, rINST             # rINSTw<- A
9225    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9226    movl        (rFP, rINST, 4), %ecx   # %ecx<- vA
9227    movl        %ecx, (%edx)            # *outs<- vA
9228    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92294:
9230    shr         $12, %ecx              # %ecx<- G
9231    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9232    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
9233    movl        %ecx, (%edx)            # *outs<- vG
9234    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92353:
9236    and         $0x0f00, %ecx          # %ecx<- 0F00
9237    shr         $8, %ecx               # %ecx<- F
9238    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9239    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
9240    movl        %ecx, (%edx)            # *outs<- vF
9241    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92422:
9243    and         $0x00f0, %ecx          # %ecx<- 00E0
9244    shr         $4, %ecx               # %ecx<- E
9245    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9246    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
9247    movl        %ecx, (%edx)            # *outs<- vE
9248    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92491:
9250    and         $0x000f, %ecx          # %ecx<- 000D
9251    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
9252    movl        %ecx, -4(%edx)          # *--outs<- vD
92530:
9254
9255   /*
9256    * %eax is "Method* methodToCall", the method we're trying to call
9257    * find space for the new stack frame, check for overflow
9258    */
9259
9260.LinvokeArgsDone:
9261    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
9262    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
9263    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
9264    shl         $2, %edx               # %edx<- update offset
9265    SAVEAREA_FROM_FP %eax               # %eax<- &StackSaveArea
9266    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
9267    movl        rGLUE,%edx              # %edx<- pMterpGlue
9268    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
9269    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
9270    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
9271    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
9272    shl         $2, %ecx               # %ecx<- update offset for outsSize
9273    movl        %eax, %edx              # %edx<- newSaveArea
9274    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
9275    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
9276    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
9277    jl          .LstackOverflow         # handle frame overflow
9278
9279   /*
9280    * set up newSaveArea
9281    */
9282
9283#ifdef EASY_GDB
9284    SAVEAREA_FROM_FP %ecx               # %ecx<- &StackSaveArea
9285    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
9286#endif
9287    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
9288    movl        rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
9289    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
9290    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
9291    jne         .LinvokeNative          # handle native call
9292
9293   /*
9294    * Update "glue" values for the new method
9295    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
9296    */
9297
9298    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
9299    movl        rGLUE,%ecx                  # %ecx<- pMterpGlue
9300    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
9301    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
9302    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
9303    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
9304    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
9305    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
9306    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
9307    FETCH_INST
9308    GOTO_NEXT                           # jump to methodToCall->insns
9309
9310   /*
9311    * Prep for the native call
9312    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
9313    */
9314
9315.LinvokeNative:
9316    movl        rGLUE,%ecx              # %ecx<- pMterpGlue
9317    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9318    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
9319    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
9320    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
9321    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
9322    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
9323    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
9324    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
9325    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
9326    movl        rGLUE,%ecx              # %ecx<- pMterpGlue
9327    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
9328    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
9329    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
9330    push        %edx                    # push parameter newFP
9331
9332    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
9333    lea         4(%esp), %esp
9334    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
9335    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
9336    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
9337    cmp         $0, offThread_exception(%eax) # check for exception
9338    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
9339    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
9340    jne         common_exceptionThrown  # handle exception
9341    FETCH_INST_OPCODE 3 %edx
9342    ADVANCE_PC 3
9343    GOTO_NEXT_R %edx                    # jump to next instruction
9344
9345.LstackOverflow:    # eax=methodToCall
9346    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9347    movl        rGLUE,%eax              # %eax<- pMterpGlue
9348    movl        offGlue_self(%eax), %eax # %eax<- glue->self
9349    movl        %eax, OUT_ARG0(%esp)    # push parameter self
9350    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
9351    jmp         common_exceptionThrown  # handle exception
9352
9353
9354/*
9355 * Do we need the thread to be suspended or have debugger/profiling activity?
9356 *
9357 * On entry:
9358 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
9359 *   ecx  -> GLUE pointer
9360 *   reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint
9361 *
9362 * Note: A call will normally kill %eax and %ecx.  To
9363 *       streamline the normal case, this routine will preserve
9364 *       %ecx in addition to the normal caller save regs.  The save/restore
9365 *       is a bit ugly, but will happen in the relatively uncommon path.
9366 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
9367 *       the suspendCount check so we can get both in 1 shot.
9368 */
9369common_periodicChecks:
9370    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
9371    cmpl    $0,(%eax)
9372    jne     1f
9373
93746:
9375    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
9376    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
9377    testl  %eax,%eax               # debugger enabled?
9378    je     2f
9379    movzbl (%eax),%eax             # get active count
93802:
9381    orl    (%ecx),%eax             # eax <- debuggerActive | activeProfilers
9382    movl   rGLUE,%ecx              # restore rGLUE
9383    jne    3f                      # one or both active - switch interp
9384
93855:
9386    ret
9387
9388    /* Check for suspend */
93891:
9390    /*  At this point, the return pointer to the caller of
9391     *  common_periodicChecks is on the top of stack.  We need to preserve
9392     *  GLUE(ecx).
9393     *  The outgoing profile is:
9394     *      bool dvmCheckSuspendPending(Thread* self)
9395     *  Because we reached here via a call, go ahead and build a new frame.
9396     */
9397    EXPORT_PC                         # need for precise GC
9398    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
9399    push    %ebp
9400    movl    %esp,%ebp
9401    subl    $24,%esp
9402    movl    %eax,OUT_ARG0(%esp)
9403    call    dvmCheckSuspendPending
9404    addl    $24,%esp
9405    pop     %ebp
9406    movl    rGLUE,%ecx
9407
9408    /*
9409     * Need to check to see if debugger or profiler flags got set
9410     * while we were suspended.
9411     */
9412    jmp    6b
9413
9414    /* Switch interpreters */
9415    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
9416     * "complete" the interpretation of backwards branches.  In effect, we
9417     * are completing the interpretation of the branch instruction here,
9418     * and the new interpreter will resume interpretation at the branch
9419     * target. However, a switch request recognized during the handling
9420     * of a return from method instruction results in an immediate abort,
9421     * and the new interpreter will resume by re-interpreting the return
9422     * instruction.
9423     */
94243:
9425    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
9426    movl    rGLUE,%ecx             # bail expect GLUE already loaded
9427    movl    $1,rINST              # set changeInterp to true
9428    jmp     common_gotoBail
9429
9430
9431/*
9432 * Common code for handling a return instruction
9433 */
9434common_returnFromMethod:
9435    movl    rGLUE,%ecx
9436    /* Set entry mode in case we bail */
9437    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
9438    xorl    rINST,rINST   # zero offset in case we switch interps
9439    call    common_periodicChecks   # Note: expects %ecx to be preserved
9440
9441    SAVEAREA_FROM_FP %eax                         # eax<- saveArea (old)
9442    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
9443    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST
9444    cmpl    $0,rINST                             # break?
9445    je      common_gotoBail    # break frame, bail out completely
9446
9447    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
9448    movl    offGlue_self(%ecx),%eax               # eax<- self
9449    movl    rINST,offGlue_method(%ecx)  # glue->method = newSave->meethod
9450    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
9451    movl    offMethod_clazz(rINST),%eax      # eax<- method->clazz
9452    FETCH_INST_OPCODE 3 %edx
9453    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
9454    ADVANCE_PC 3
9455    movl    %eax,offGlue_methodClassDex(%ecx)
9456    /* not bailing - restore entry mode to default */
9457    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
9458    GOTO_NEXT_R %edx
9459
9460/*
9461 * Prepare to strip the current frame and "longjump" back to caller of
9462 * dvmMterpStdRun.
9463 *
9464 * on entry:
9465 *    rINST holds changeInterp
9466 *    ecx holds glue pointer
9467 *
9468 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
9469 */
9470common_gotoBail:
9471    movl   rPC,offGlue_pc(%ecx)     # export state to glue
9472    movl   rFP,offGlue_fp(%ecx)
9473    movl   %ecx,OUT_ARG0(%esp)      # glue in arg0
9474    movl   rINST,OUT_ARG1(%esp)     # changeInterp in arg1
9475    call   dvmMterpStdBail          # bail out....
9476
9477
9478/*
9479 * After returning from a "glued" function, pull out the updated values
9480 * and start executing at the next instruction.
9481 */
9482 common_resumeAfterGlueCall:
9483     LOAD_PC_FP_FROM_GLUE
9484     FETCH_INST
9485     GOTO_NEXT
9486
9487/*
9488 * Integer divide or mod by zero
9489 */
9490common_errDivideByZero:
9491    EXPORT_PC
9492    movl    $.LstrArithmeticException,%eax
9493    movl    %eax,OUT_ARG0(%esp)
9494    movl    $.LstrDivideByZero,%eax
9495    movl    %eax,OUT_ARG1(%esp)
9496    call    dvmThrowException
9497    jmp     common_exceptionThrown
9498
9499/*
9500 * Attempt to allocate an array with a negative size.
9501 */
9502common_errNegativeArraySize:
9503    EXPORT_PC
9504    movl    $.LstrNegativeArraySizeException,%eax
9505    movl    %eax,OUT_ARG0(%esp)
9506    xorl    %eax,%eax
9507    movl    %eax,OUT_ARG1(%esp)
9508    call    dvmThrowException
9509    jmp     common_exceptionThrown
9510
9511/*
9512 * Attempt to allocate an array with a negative size.
9513 */
9514common_errNoSuchMethod:
9515
9516    EXPORT_PC
9517    movl    $.LstrNoSuchMethodError,%eax
9518    movl    %eax,OUT_ARG0(%esp)
9519    xorl    %eax,%eax
9520    movl    %eax,OUT_ARG1(%esp)
9521    call    dvmThrowException
9522    jmp     common_exceptionThrown
9523
9524/*
9525 * Hit a null object when we weren't expecting one.  Export the PC, throw a
9526 * NullPointerException and goto the exception processing code.
9527 */
9528common_errNullObject:
9529    EXPORT_PC
9530    movl    $.LstrNullPointerException,%eax
9531    movl    %eax,OUT_ARG0(%esp)
9532    xorl    %eax,%eax
9533    movl    %eax,OUT_ARG1(%esp)
9534    call    dvmThrowException
9535    jmp     common_exceptionThrown
9536
9537/*
9538 * Array index exceeds max.
9539 * On entry:
9540 *    eax <- array object
9541 *    ecx <- index
9542 */
9543common_errArrayIndex:
9544    EXPORT_PC
9545    movl    offArrayObject_length(%eax), %eax
9546    movl    %ecx,OUT_ARG0(%esp)
9547    movl    %eax,OUT_ARG1(%esp)
9548    call    dvmThrowAIOOBE        # dvmThrowAIOO(index, length)
9549    jmp     common_exceptionThrown
9550/*
9551 * Invalid array value.
9552 */
9553common_errArrayStore:
9554    EXPORT_PC
9555    movl    $.LstrArrayStoreException,%eax
9556    movl    %eax,OUT_ARG0(%esp)
9557    xorl    %eax,%eax
9558    movl    %eax,OUT_ARG1(%esp)
9559    call    dvmThrowException
9560    jmp     common_exceptionThrown
9561
9562/*
9563 * Somebody has thrown an exception.  Handle it.
9564 *
9565 * If the exception processing code returns to us (instead of falling
9566 * out of the interpreter), continue with whatever the next instruction
9567 * now happens to be.
9568 *
9569 * This does not return.
9570 */
9571common_exceptionThrown:
9572    movl    rGLUE,%ecx
9573    movl    rPC,offGlue_pc(%ecx)
9574    movl    rFP,offGlue_fp(%ecx)
9575    movl    %ecx,OUT_ARG0(%esp)
9576    call    dvmMterp_exceptionThrown
9577    jmp     common_resumeAfterGlueCall
9578
9579common_abort:
9580    movl    $0xdeadf00d,%eax
9581    call     *%eax
9582
9583
9584/*
9585 * Strings
9586 */
9587
9588    .section     .rodata
9589.LstrNullPointerException:
9590    .asciz    "Ljava/lang/NullPointerException;"
9591.LstrArithmeticException:
9592    .asciz  "Ljava/lang/ArithmeticException;"
9593.LstrDivideByZero:
9594    .asciz  "divide by zero"
9595.LstrArrayStoreException:
9596    .asciz  "Ljava/lang/ArrayStoreException;"
9597.LstrNegativeArraySizeException:
9598    .asciz  "Ljava/lang/NegativeArraySizeException;"
9599.LstrInstantiationError:
9600    .asciz  "Ljava/lang/InstantiationError;"
9601.LstrClassCastException:
9602    .asciz  "Ljava/lang/ClassCastException;"
9603.LstrNoSuchMethodError:
9604    .asciz  "Ljava/lang/NoSuchMethodError;"
9605.LstrInternalErrorA:
9606    .asciz  "Ljava/lang/InternalError;"
9607.LstrFilledNewArrayNotImplA:
9608    .asciz  "filled-new-array only implemented for 'int'"
9609
9610